]> git.sur5r.net Git - freertos/commitdiff
Added +TCP code to main repo.
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 17 Aug 2017 12:18:14 +0000 (12:18 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 17 Aug 2017 12:18:14 +0000 (12:18 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2517 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

114 files changed:
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/SimpleUDPClientAndServer.c [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/TCPEchoClient_SingleTasks.c [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/include/SimpleUDPClientAndServer.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/include/TCPEchoClient_SingleTasks.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOSConfig.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOSIPConfig.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOS_Plus_TCP_Minimal.sln [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOS_Plus_TCP_Minimal.suo [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/ReadMe.txt [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/Read_Me_Build_Instructions.url [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WIN32.vcxproj [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WIN32.vcxproj.filters [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/Packet32.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/PacketData.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/Win32-Extensions.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/arch.c [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/bittypes.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/ip6_misc.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/netif.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap-bpf.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap-namedb.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap-stdinc.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/bluetooth.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/bpf.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/namedb.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/pcap.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/sll.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/usb.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/vlan.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/remote-ext.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/wpcap.lib [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/demo_logging.c [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/demo_logging.h [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/main.c [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/printf-stdarg.c [new file with mode: 0644]
FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC/.cproject
FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC/CLI-commands.c
FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC/FreeRTOSConfig.h
FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC/trcConfig.h
FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC/trcSnapshotConfig.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/History.txt [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/ReadMe.url [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_end.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_start.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_end.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_start.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_end.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_start.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_end.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_start.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/component/gmac.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/ethernet_phy.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/ethernet_phy.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/instance/gmac.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/ReadMe.txt [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/README_DRIVER_DISCLAIMER.txt [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/FaultInjection.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_topology.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/Common/FreeRTOS_TCP_server.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/FTP/FreeRTOS_FTP_commands.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/FTP/FreeRTOS_FTP_server.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/HTTP/FreeRTOS_HTTP_commands.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/HTTP/FreeRTOS_HTTP_server.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/NTP/NTPDemo.c [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_FTP_commands.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_HTTP_commands.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_TCP_server.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_server_private.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/NTPClient.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/NTPDemo.h [new file with mode: 0644]
FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/readme.txt [new file with mode: 0644]

diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/SimpleUDPClientAndServer.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/SimpleUDPClientAndServer.c
new file mode 100644 (file)
index 0000000..9e67c9a
--- /dev/null
@@ -0,0 +1,397 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+\r
+/*\r
+ * Creates two transmitting tasks and two receiving tasks.  The transmitting\r
+ * tasks send values that are received by the receiving tasks.  One set of tasks\r
+ * uses the standard API.  The other set of tasks uses the zero copy API.\r
+ *\r
+ * See the following web page for essential demo usage and configuration\r
+ * details:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+\r
+#define simpTINY_DELAY ( ( TickType_t ) 2 )\r
+\r
+/*\r
+ * Uses a socket to send data without using the zero copy option.\r
+ * prvSimpleServerTask() will receive the data.\r
+ */\r
+static void prvSimpleClientTask( void *pvParameters );\r
+\r
+/*\r
+ * Uses a socket to receive the data sent by the prvSimpleClientTask() task.\r
+ * Does not use the zero copy option.\r
+ */\r
+static void prvSimpleServerTask( void *pvParameters );\r
+\r
+/*\r
+ * Uses a socket to send data using the zero copy option.\r
+ * prvSimpleZeroCopyServerTask() will receive the data.\r
+ */\r
+static void prvSimpleZeroCopyUDPClientTask( void *pvParameters );\r
+\r
+/*\r
+ * Uses a socket to receive the data sent by the prvSimpleZeroCopyUDPClientTask()\r
+ * task.  Uses the zero copy option.\r
+ */\r
+static void prvSimpleZeroCopyServerTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartSimpleUDPClientServerTasks( uint16_t usStackSize, uint32_t ulPort, UBaseType_t uxPriority )\r
+{\r
+       /* Create the client and server tasks that do not use the zero copy\r
+       interface. */\r
+       xTaskCreate( prvSimpleClientTask, "SimpCpyClnt", usStackSize, ( void * ) ulPort, uxPriority, NULL );\r
+       xTaskCreate( prvSimpleServerTask, "SimpCpySrv", usStackSize, ( void * ) ulPort, uxPriority + 1, NULL );\r
+\r
+       /* Create the client and server tasks that do use the zero copy interface. */\r
+       xTaskCreate( prvSimpleZeroCopyUDPClientTask, "SimpZCpyClnt", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority, NULL );\r
+       xTaskCreate( prvSimpleZeroCopyServerTask, "SimpZCpySrv", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority + 1, NULL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSimpleClientTask( void *pvParameters )\r
+{\r
+Socket_t xClientSocket;\r
+struct freertos_sockaddr xDestinationAddress;\r
+uint8_t cString[ 50 ];\r
+BaseType_t lReturned;\r
+uint32_t ulCount = 0UL, ulIPAddress;\r
+const uint32_t ulLoopsPerSocket = 10UL;\r
+const TickType_t x150ms = 150UL / portTICK_PERIOD_MS;\r
+\r
+       /* Remove compiler warning about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       /* It is assumed that this task is not created until the network is up,\r
+       so the IP address can be obtained immediately.  store the IP address being\r
+       used in ulIPAddress.  This is done so the socket can send to a different\r
+       port on the same IP address. */\r
+       FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );\r
+\r
+       /* This test sends to itself, so data sent from here is received by a server\r
+       socket on the same IP address.  Setup the freertos_sockaddr structure with\r
+       this nodes IP address, and the port number being sent to.  The strange\r
+       casting is to try and remove compiler warnings on 32 bit machines. */\r
+       xDestinationAddress.sin_addr = ulIPAddress;\r
+       xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;\r
+       xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );\r
+\r
+       for( ;; )\r
+       {\r
+               /* Create the socket. */\r
+               xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
+               configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET );\r
+\r
+               /* The count is used to differentiate between different messages sent to\r
+               the server, and to break out of the do while loop below. */\r
+               ulCount = 0UL;\r
+\r
+               do\r
+               {\r
+                       /* Create the string that is sent to the server. */\r
+                       sprintf( ( char * ) cString, "Server received (not zero copy): Message number %lu\r\n", ulCount );\r
+\r
+                       /* Send the string to the socket.  ulFlags is set to 0, so the zero\r
+                       copy option is not selected.  That means the data from cString[] is\r
+                       copied into a network buffer inside FreeRTOS_sendto(), and cString[]\r
+                       can be reused as soon as FreeRTOS_sendto() has returned. */\r
+                       lReturned = FreeRTOS_sendto( xClientSocket, ( void * ) cString, strlen( ( const char * ) cString ), 0, &xDestinationAddress, sizeof( xDestinationAddress ) );\r
+\r
+                       ulCount++;\r
+\r
+               } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) );\r
+\r
+               FreeRTOS_closesocket( xClientSocket );\r
+\r
+               /* A short delay to prevent the messages printed by the server task\r
+               scrolling off the screen too quickly, and to prevent reduce the network\r
+               loading. */\r
+               vTaskDelay( x150ms );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSimpleServerTask( void *pvParameters )\r
+{\r
+int32_t lBytes;\r
+uint8_t cReceivedString[ 60 ];\r
+struct freertos_sockaddr xClient, xBindAddress;\r
+uint32_t xClientLength = sizeof( xClient );\r
+Socket_t xListeningSocket;\r
+\r
+       /* Just to prevent compiler warnings. */\r
+       ( void ) pvParameters;\r
+\r
+       /* Attempt to open the socket. */\r
+       xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
+       configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );\r
+\r
+       /* This test receives data sent from a different port on the same IP\r
+       address.  Configure the freertos_sockaddr structure with the address being\r
+       bound to.  The strange casting is to try and remove     compiler warnings on 32\r
+       bit machines.  Note that this task is only created after the network is up,\r
+       so the IP address is valid here. */\r
+       xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;\r
+       xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );\r
+\r
+       /* Bind the socket to the port that the client task will send to. */\r
+       FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );\r
+\r
+       for( ;; )\r
+       {\r
+               /* Zero out the receive array so there is NULL at the end of the string\r
+               when it is printed out. */\r
+               memset( cReceivedString, 0x00, sizeof( cReceivedString ) );\r
+\r
+               /* Receive data on the socket.  ulFlags is zero, so the zero copy option\r
+               is not set and the received data is copied into the buffer pointed to by\r
+               cReceivedString.  By default the block time is portMAX_DELAY.\r
+               xClientLength is not actually used by FreeRTOS_recvfrom(), but is set\r
+               appropriately in case future versions do use it. */\r
+               lBytes = FreeRTOS_recvfrom( xListeningSocket, cReceivedString, sizeof( cReceivedString ), 0, &xClient, &xClientLength );\r
+\r
+               /* Error check. */\r
+               configASSERT( lBytes == ( BaseType_t ) strlen( ( const char * ) cReceivedString ) );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSimpleZeroCopyUDPClientTask( void *pvParameters )\r
+{\r
+Socket_t xClientSocket;\r
+uint8_t *pucUDPPayloadBuffer;\r
+struct freertos_sockaddr xDestinationAddress;\r
+BaseType_t lReturned;\r
+uint32_t ulCount = 0UL, ulIPAddress;\r
+const uint32_t ulLoopsPerSocket = 10UL;\r
+const char *pcStringToSend = "Server received (using zero copy): Message number ";\r
+const TickType_t x150ms = 150UL / portTICK_PERIOD_MS;\r
+/* 15 is added to ensure the number, \r\n and terminating zero fit. */\r
+const size_t xStringLength = strlen( pcStringToSend ) + 15;\r
+\r
+       /* Remove compiler warning about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       /* It is assumed that this task is not created until the network is up,\r
+       so the IP address can be obtained immediately.  store the IP address being\r
+       used in ulIPAddress.  This is done so the socket can send to a different\r
+       port on the same IP address. */\r
+       FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );\r
+\r
+       /* This test sends to itself, so data sent from here is received by a server\r
+       socket on the same IP address.  Setup the freertos_sockaddr structure with\r
+       this nodes IP address, and the port number being sent to.  The strange\r
+       casting is to try and remove compiler warnings on 32 bit machines. */\r
+       xDestinationAddress.sin_addr = ulIPAddress;\r
+       xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;\r
+       xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );\r
+\r
+       for( ;; )\r
+       {\r
+               /* Create the socket. */\r
+               xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
+               configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET );\r
+\r
+               /* The count is used to differentiate between different messages sent to\r
+               the server, and to break out of the do while loop below. */\r
+               ulCount = 0UL;\r
+\r
+               do\r
+               {\r
+                       /* This task is going to send using the zero copy interface.  The\r
+                       data being sent is therefore written directly into a buffer that is\r
+                       passed into, rather than copied into, the FreeRTOS_sendto()\r
+                       function.\r
+\r
+                       First obtain a buffer of adequate length from the IP stack into which\r
+                       the string will be written.  Although a max delay is used, the actual\r
+                       delay will be capped to ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence\r
+                       the do while loop is used to ensure a buffer is obtained. */\r
+                       do\r
+                       {\r
+                       } while( ( pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xStringLength, portMAX_DELAY ) ) == NULL );\r
+\r
+                       /* A buffer was successfully obtained.  Create the string that is\r
+                       sent to the server.  First the string is filled with zeros as this will\r
+                       effectively be the null terminator when the string is received at the other\r
+                       end.  Note that the string is being written directly into the buffer\r
+                       obtained from the IP stack above. */\r
+                       memset( ( void * ) pucUDPPayloadBuffer, 0x00, xStringLength );\r
+                       sprintf( ( char * ) pucUDPPayloadBuffer, "%s%lu\r\n", pcStringToSend, ulCount );\r
+\r
+                       /* Pass the buffer into the send function.  ulFlags has the\r
+                       FREERTOS_ZERO_COPY bit set so the IP stack will take control of the\r
+                       buffer rather than copy data out of the buffer. */\r
+                       lReturned = FreeRTOS_sendto( xClientSocket,                             /* The socket being sent to. */\r
+                                                                               ( void * ) pucUDPPayloadBuffer, /* A pointer to the the data being sent. */\r
+                                                                               strlen( ( const char * ) pucUDPPayloadBuffer ) + 1, /* The length of the data being sent - including the string's null terminator. */\r
+                                                                               FREERTOS_ZERO_COPY,                     /* ulFlags with the FREERTOS_ZERO_COPY bit set. */\r
+                                                                               &xDestinationAddress,                   /* Where the data is being sent. */\r
+                                                                               sizeof( xDestinationAddress ) );\r
+\r
+                       if( lReturned == 0 )\r
+                       {\r
+                               /* The send operation failed, so this task is still responsible\r
+                               for the buffer obtained from the IP stack.  To ensure the buffer\r
+                               is not lost it must either be used again, or, as in this case,\r
+                               returned to the IP stack using FreeRTOS_ReleaseUDPPayloadBuffer().\r
+                               pucUDPPayloadBuffer can be safely re-used after this call. */\r
+                               FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* The send was successful so the IP stack is now managing the\r
+                               buffer pointed to by pucUDPPayloadBuffer, and the IP stack will\r
+                               return the buffer once it has been sent.  pucUDPPayloadBuffer can\r
+                               be safely re-used. */\r
+                       }\r
+\r
+                       ulCount++;\r
+\r
+               } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) );\r
+\r
+               FreeRTOS_closesocket( xClientSocket );\r
+\r
+               /* A short delay to prevent the messages scrolling off the screen too\r
+               quickly. */\r
+               vTaskDelay( x150ms );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSimpleZeroCopyServerTask( void *pvParameters )\r
+{\r
+int32_t lBytes;\r
+uint8_t *pucUDPPayloadBuffer;\r
+struct freertos_sockaddr xClient, xBindAddress;\r
+uint32_t xClientLength = sizeof( xClient ), ulIPAddress;\r
+Socket_t xListeningSocket;\r
+\r
+       /* Just to prevent compiler warnings. */\r
+       ( void ) pvParameters;\r
+\r
+       /* Attempt to open the socket. */\r
+       xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
+       configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );\r
+\r
+       /* This test receives data sent from a different port on the same IP address.\r
+       Obtain the nodes IP address.  Configure the freertos_sockaddr structure with\r
+       the address being bound to.  The strange casting is to try and remove\r
+       compiler warnings on 32 bit machines.  Note that this task is only created\r
+       after the network is up, so the IP address is valid here. */\r
+       FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );\r
+       xBindAddress.sin_addr = ulIPAddress;\r
+       xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;\r
+       xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );\r
+\r
+       /* Bind the socket to the port that the client task will send to. */\r
+       FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );\r
+\r
+       for( ;; )\r
+       {\r
+               /* Receive data on the socket.  ulFlags has the zero copy bit set\r
+               (FREERTOS_ZERO_COPY) indicating to the stack that a reference to the\r
+               received data should be passed out to this task using the second\r
+               parameter to the FreeRTOS_recvfrom() call.  When this is done the\r
+               IP stack is no longer responsible for releasing the buffer, and\r
+               the task *must* return the buffer to the stack when it is no longer\r
+               needed.  By default the block time is portMAX_DELAY. */\r
+               lBytes = FreeRTOS_recvfrom( xListeningSocket, ( void * ) &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xClient, &xClientLength );\r
+\r
+               /* Print the received characters. */\r
+               if( lBytes > 0 )\r
+               {\r
+                       /* It is expected to receive one more byte than the string length as\r
+                       the NULL terminator is also transmitted. */\r
+                       configASSERT( lBytes == ( ( BaseType_t ) strlen( ( const char * ) pucUDPPayloadBuffer ) + 1 ) );\r
+               }\r
+\r
+               if( lBytes >= 0 )\r
+               {\r
+                       /* The buffer *must* be freed once it is no longer needed. */\r
+                       FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );\r
+               }\r
+       }\r
+}\r
+\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/TCPEchoClient_SingleTasks.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/TCPEchoClient_SingleTasks.c
new file mode 100644 (file)
index 0000000..4ebd6e3
--- /dev/null
@@ -0,0 +1,400 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+\r
+/*\r
+ * A set of tasks are created that send TCP echo requests to the standard echo\r
+ * port (port 7) on the IP address set by the configECHO_SERVER_ADDR0 to\r
+ * configECHO_SERVER_ADDR3 constants, then wait for and verify the reply\r
+ * (another demo is avilable that demonstrates the reception being performed in\r
+ * a task other than that from with the request was made).\r
+ *\r
+ * See the following web page for essential demo usage and configuration\r
+ * details:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+\r
+/* Exclude the whole file if FreeRTOSIPConfig.h is configured to use UDP only. */\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+/* The echo tasks create a socket, send out a number of echo requests, listen\r
+for the echo reply, then close the socket again before starting over.  This\r
+delay is used between each iteration to ensure the network does not get too\r
+congested. */\r
+#define echoLOOP_DELAY ( ( TickType_t ) 150 / portTICK_PERIOD_MS )\r
+\r
+/* The echo server is assumed to be on port 7, which is the standard echo\r
+protocol port. */\r
+#define echoECHO_PORT  ( 7 )\r
+\r
+/* The size of the buffers is a multiple of the MSS - the length of the data\r
+sent is a pseudo random size between 20 and echoBUFFER_SIZES. */\r
+#define echoBUFFER_SIZE_MULTIPLIER     ( 3 )\r
+#define echoBUFFER_SIZES                       ( ipconfigTCP_MSS * echoBUFFER_SIZE_MULTIPLIER )\r
+\r
+/* The number of instances of the echo client task to create. */\r
+#define echoNUM_ECHO_CLIENTS           ( 5 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Uses a socket to send data to, then receive data from, the standard echo\r
+ * port number 7.\r
+ */\r
+static void prvEchoClientTask( void *pvParameters );\r
+\r
+/*\r
+ * Creates a pseudo random sized buffer of data to send to the echo server.\r
+ */\r
+static BaseType_t prvCreateTxData( char *ucBuffer, uint32_t ulBufferLength );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Rx and Tx time outs are used to ensure the sockets do not wait too long for\r
+missing data. */\r
+static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 4000 );\r
+static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 2000 );\r
+\r
+/* Counters for each created task - for inspection only. */\r
+static uint32_t ulTxRxCycles[ echoNUM_ECHO_CLIENTS ]  = { 0 },\r
+                               ulTxRxFailures[ echoNUM_ECHO_CLIENTS ] = { 0 },\r
+                               ulConnections[ echoNUM_ECHO_CLIENTS ] = { 0 };\r
+\r
+/* Rx and Tx buffers for each created task. */\r
+static char cTxBuffers[ echoNUM_ECHO_CLIENTS ][ echoBUFFER_SIZES ],\r
+                       cRxBuffers[ echoNUM_ECHO_CLIENTS ][ echoBUFFER_SIZES ];\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartTCPEchoClientTasks_SingleTasks( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority )\r
+{\r
+BaseType_t x;\r
+\r
+       /* Create the echo client tasks. */\r
+       for( x = 0; x < echoNUM_ECHO_CLIENTS; x++ )\r
+       {\r
+               xTaskCreate(    prvEchoClientTask,      /* The function that implements the task. */\r
+                                               "Echo0",                        /* Just a text name for the task to aid debugging. */\r
+                                               usTaskStackSize,        /* The stack size is defined in FreeRTOSIPConfig.h. */\r
+                                               ( void * ) x,           /* The task parameter, not used in this case. */\r
+                                               uxTaskPriority,         /* The priority assigned to the task is defined in FreeRTOSConfig.h. */\r
+                                               NULL );                         /* The task handle is not used. */\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEchoClientTask( void *pvParameters )\r
+{\r
+Socket_t xSocket;\r
+struct freertos_sockaddr xEchoServerAddress;\r
+int32_t lLoopCount = 0UL;\r
+const int32_t lMaxLoopCount = 1;\r
+volatile uint32_t ulTxCount = 0UL;\r
+BaseType_t xReceivedBytes, xReturned, xInstance;\r
+BaseType_t lTransmitted, lStringLength;\r
+char *pcTransmittedString, *pcReceivedString;\r
+WinProperties_t xWinProps;\r
+TickType_t xTimeOnEntering;\r
+\r
+       /* Fill in the buffer and window sizes that will be used by the socket. */\r
+       xWinProps.lTxBufSize = 6 * ipconfigTCP_MSS;\r
+       xWinProps.lTxWinSize = 3;\r
+       xWinProps.lRxBufSize = 6 * ipconfigTCP_MSS;\r
+       xWinProps.lRxWinSize = 3;\r
+\r
+       /* This task can be created a number of times.  Each instance is numbered\r
+       to enable each instance to use a different Rx and Tx buffer.  The number is\r
+       passed in as the task's parameter. */\r
+       xInstance = ( BaseType_t ) pvParameters;\r
+\r
+       /* Point to the buffers to be used by this instance of this task. */\r
+       pcTransmittedString = &( cTxBuffers[ xInstance ][ 0 ] );\r
+       pcReceivedString = &( cRxBuffers[ xInstance ][ 0 ] );\r
+\r
+       /* Echo requests are sent to the echo server.  The address of the echo\r
+       server is configured by the constants configECHO_SERVER_ADDR0 to\r
+       configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */\r
+       xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT );\r
+       xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0,\r
+                                                                                                                       configECHO_SERVER_ADDR1,\r
+                                                                                                                       configECHO_SERVER_ADDR2,\r
+                                                                                                                       configECHO_SERVER_ADDR3 );\r
+\r
+       for( ;; )\r
+       {\r
+               /* Create a TCP socket. */\r
+               xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );\r
+               configASSERT( xSocket != FREERTOS_INVALID_SOCKET );\r
+\r
+               /* Set a time out so a missing reply does not cause the task to block\r
+               indefinitely. */\r
+               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );\r
+               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) );\r
+\r
+               /* Set the window and buffer sizes. */\r
+               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps,     sizeof( xWinProps ) );\r
+\r
+               /* Connect to the echo server. */\r
+               if( FreeRTOS_connect( xSocket, &xEchoServerAddress, sizeof( xEchoServerAddress ) ) == 0 )\r
+               {\r
+                       ulConnections[ xInstance ]++;\r
+\r
+                       /* Send a number of echo requests. */\r
+                       for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ )\r
+                       {\r
+                               /* Create the string that is sent to the echo server. */\r
+                               lStringLength = prvCreateTxData( pcTransmittedString, echoBUFFER_SIZES );\r
+\r
+                               /* Add in some unique text at the front of the string. */\r
+                               sprintf( pcTransmittedString, "TxRx message number %u", ulTxCount );\r
+                               ulTxCount++;\r
+\r
+                               /* Send the string to the socket. */\r
+                               lTransmitted = FreeRTOS_send(   xSocket,                                                /* The socket being sent to. */\r
+                                                                                               ( void * ) pcTransmittedString, /* The data being sent. */\r
+                                                                                               lStringLength,                                  /* The length of the data being sent. */\r
+                                                                                               0 );                                                    /* No flags. */\r
+\r
+                               if( lTransmitted < 0 )\r
+                               {\r
+                                       /* Error? */\r
+                                       break;\r
+                               }\r
+\r
+                               /* Clear the buffer into which the echoed string will be\r
+                               placed. */\r
+                               memset( ( void * ) pcReceivedString, 0x00, echoBUFFER_SIZES );\r
+                               xReceivedBytes = 0;\r
+\r
+                               /* Receive data echoed back to the socket. */\r
+                               while( xReceivedBytes < lTransmitted )\r
+                               {\r
+                                       xReturned = FreeRTOS_recv( xSocket,                                                             /* The socket being received from. */\r
+                                                                                       &( pcReceivedString[ xReceivedBytes ] ),/* The buffer into which the received data will be written. */\r
+                                                                                        lStringLength - xReceivedBytes,                /* The size of the buffer provided to receive the data. */\r
+                                                                                        0 );                                                                   /* No flags. */\r
+\r
+                                       if( xReturned < 0 )\r
+                                       {\r
+                                               /* Error occurred.  Latch it so it can be detected\r
+                                               below. */\r
+                                               xReceivedBytes = xReturned;\r
+                                               break;\r
+                                       }\r
+                                       else if( xReturned == 0 )\r
+                                       {\r
+                                               /* Timed out. */\r
+                                               break;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               /* Keep a count of the bytes received so far. */\r
+                                               xReceivedBytes += xReturned;\r
+                                       }\r
+                               }\r
+\r
+                               /* If an error occurred it will be latched in xReceivedBytes,\r
+                               otherwise xReceived bytes will be just that - the number of\r
+                               bytes received from the echo server. */\r
+                               if( xReceivedBytes > 0 )\r
+                               {\r
+                                       /* Compare the transmitted string to the received string. */\r
+                                       configASSERT( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 );\r
+                                       if( strncmp( pcReceivedString, pcTransmittedString, lTransmitted ) == 0 )\r
+                                       {\r
+                                               /* The echo reply was received without error. */\r
+                                               ulTxRxCycles[ xInstance ]++;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               /* The received string did not match the transmitted\r
+                                               string. */\r
+                                               ulTxRxFailures[ xInstance ]++;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               else if( xReceivedBytes < 0 )\r
+                               {\r
+                                       /* FreeRTOS_recv() returned an error. */\r
+                                       break;\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Timed out without receiving anything? */\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       /* Finished using the connected socket, initiate a graceful close:\r
+                       FIN, FIN+ACK, ACK. */\r
+                       FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );\r
+\r
+                       /* Expect FreeRTOS_recv() to return an error once the shutdown is\r
+                       complete. */\r
+                       xTimeOnEntering = xTaskGetTickCount();\r
+                       do\r
+                       {\r
+                               xReturned = FreeRTOS_recv( xSocket,     /* The socket being received from. */\r
+                                       &( pcReceivedString[ 0 ] ),             /* The buffer into which the received data will be written. */\r
+                                       echoBUFFER_SIZES,                               /* The size of the buffer provided to receive the data. */\r
+                                       0 );\r
+\r
+                               if( xReturned < 0 )\r
+                               {\r
+                                       break;\r
+                               }\r
+\r
+                       } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xReceiveTimeOut );\r
+               }\r
+\r
+               /* Close this socket before looping back to create another. */\r
+               FreeRTOS_closesocket( xSocket );\r
+\r
+               /* Pause for a short while to ensure the network is not too\r
+               congested. */\r
+               vTaskDelay( echoLOOP_DELAY );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvCreateTxData( char *cBuffer, uint32_t ulBufferLength )\r
+{\r
+BaseType_t lCharactersToAdd, lCharacter;\r
+char cChar = '0';\r
+const BaseType_t lMinimumLength = 60;\r
+\r
+       /* Randomise the number of characters that will be sent in the echo\r
+       request. */\r
+       do\r
+       {\r
+               lCharactersToAdd = ipconfigRAND32() % ( ulBufferLength - 20UL );\r
+       } while ( ( lCharactersToAdd == 0 ) || ( lCharactersToAdd < lMinimumLength ) ); /* Must be at least enough to add the unique text to the start of the string later. */\r
+\r
+       /* Fill the buffer. */\r
+       for( lCharacter = 0; lCharacter < lCharactersToAdd; lCharacter++ )\r
+       {\r
+               cBuffer[ lCharacter ] = cChar;\r
+               cChar++;\r
+\r
+               if( cChar > '~' )\r
+               {\r
+                       cChar = '0';\r
+               }\r
+       }\r
+\r
+       return lCharactersToAdd;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xAreSingleTaskTCPEchoClientsStillRunning( void )\r
+{\r
+static uint32_t ulLastEchoSocketCount[ echoNUM_ECHO_CLIENTS ] = { 0 }, ulLastConnections[ echoNUM_ECHO_CLIENTS ] = { 0 };\r
+BaseType_t xReturn = pdPASS, x;\r
+\r
+       /* Return fail is the number of cycles does not increment between\r
+       consecutive calls. */\r
+       for( x = 0; x < echoNUM_ECHO_CLIENTS; x++ )\r
+       {\r
+               if( ulTxRxCycles[ x ] == ulLastEchoSocketCount[ x ] )\r
+               {\r
+                       xReturn = pdFAIL;\r
+               }\r
+               else\r
+               {\r
+                       ulLastEchoSocketCount[ x ] = ulTxRxCycles[ x ];\r
+               }\r
+\r
+               if( ulConnections[ x ] == ulLastConnections[ x ] )\r
+               {\r
+                       xReturn = pdFAIL;\r
+               }\r
+               else\r
+               {\r
+                       ulConnections[ x ] = ulLastConnections[ x ];\r
+               }\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/include/SimpleUDPClientAndServer.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/include/SimpleUDPClientAndServer.h
new file mode 100644 (file)
index 0000000..daeec49
--- /dev/null
@@ -0,0 +1,75 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+\r
+#ifndef SIMPLE_UDP_CLIENT_AND_SERVER_H\r
+#define SIMPLE_UDPCLIENT_AND_SERVER_H\r
+\r
+void vStartSimpleUDPClientServerTasks( uint16_t usStackSize, uint32_t ulsPort, UBaseType_t uxPriority );\r
+\r
+#endif /* SIMPLE_UDPCLIENT_AND_SERVER_H */\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/include/TCPEchoClient_SingleTasks.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/include/TCPEchoClient_SingleTasks.h
new file mode 100644 (file)
index 0000000..03dae2f
--- /dev/null
@@ -0,0 +1,82 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+\r
+#ifndef SINGLE_TASK_TCP_ECHO_CLIENTS_H\r
+#define SINGLE_TASK_TCP_ECHO_CLIENTS_H\r
+\r
+/*\r
+ * Create the TCP echo client tasks.  This is the version where an echo request\r
+ * is made from the same task that listens for the echo reply.\r
+ */\r
+void vStartTCPEchoClientTasks_SingleTasks( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority );\r
+BaseType_t xAreSingleTaskTCPEchoClientsStillRunning( void );\r
+\r
+#endif /* SINGLE_TASK_TCP_ECHO_CLIENTS_H */\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOSConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOSConfig.h
new file mode 100644 (file)
index 0000000..8f62f5a
--- /dev/null
@@ -0,0 +1,261 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+\r
+#ifndef FREERTOS_CONFIG_H\r
+#define FREERTOS_CONFIG_H\r
+\r
+/*-----------------------------------------------------------\r
+ * Application specific definitions.\r
+ *\r
+ * These definitions should be adjusted for your particular hardware and\r
+ * application requirements.\r
+ *\r
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE\r
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.\r
+ * http://www.freertos.org/a00110.html\r
+ *\r
+ * The bottom of this file contains some constants specific to running the UDP\r
+ * stack in this demo.  Constants specific to FreeRTOS+TCP itself (rather than\r
+ * the demo) are contained in FreeRTOSIPConfig.h.\r
+ *----------------------------------------------------------*/\r
+#define configENABLE_BACKWARD_COMPATIBILITY            0\r
+#define configUSE_PREEMPTION                                   1\r
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION        1\r
+#define configMAX_PRIORITIES                                   ( 7 )\r
+#define configTICK_RATE_HZ                                             ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */\r
+#define configMINIMAL_STACK_SIZE                               ( ( unsigned short ) 60 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the Win32 thread. */\r
+#define configTOTAL_HEAP_SIZE                                  ( ( size_t ) ( 2048U * 1024U ) )\r
+#define configMAX_TASK_NAME_LEN                                        ( 15 )\r
+#define configUSE_TRACE_FACILITY                               1\r
+#define configUSE_16_BIT_TICKS                                 0\r
+#define configIDLE_SHOULD_YIELD                                        1\r
+#define configUSE_CO_ROUTINES                                  0\r
+#define configUSE_MUTEXES                                              1\r
+#define configUSE_RECURSIVE_MUTEXES                            1\r
+#define configQUEUE_REGISTRY_SIZE                              0\r
+#define configUSE_APPLICATION_TASK_TAG                 0\r
+#define configUSE_COUNTING_SEMAPHORES                  1\r
+#define configUSE_ALTERNATIVE_API                              0\r
+#define configNUM_THREAD_LOCAL_STORAGE_POINTERS        3 /* FreeRTOS+FAT requires 2 pointers if a CWD is supported. */\r
+\r
+/* Hook function related definitions. */\r
+#define configUSE_TICK_HOOK                            0\r
+#define configUSE_IDLE_HOOK                            1\r
+#define configUSE_MALLOC_FAILED_HOOK   1\r
+#define configCHECK_FOR_STACK_OVERFLOW 0 /* Not applicable to the Win32 port. */\r
+\r
+/* Software timer related definitions. */\r
+#define configUSE_TIMERS                               1\r
+#define configTIMER_TASK_PRIORITY              ( configMAX_PRIORITIES - 1 )\r
+#define configTIMER_QUEUE_LENGTH               5\r
+#define configTIMER_TASK_STACK_DEPTH   ( configMINIMAL_STACK_SIZE * 2 )\r
+\r
+/* Event group related definitions. */\r
+#define configUSE_EVENT_GROUPS                 1\r
+\r
+/* Run time stats gathering definitions. */\r
+#define configGENERATE_RUN_TIME_STATS  0\r
+\r
+/* Co-routine definitions. */\r
+#define configUSE_CO_ROUTINES                  0\r
+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )\r
+\r
+/* Set the following definitions to 1 to include the API function, or zero\r
+to exclude the API function. */\r
+#define INCLUDE_vTaskPrioritySet                               1\r
+#define INCLUDE_uxTaskPriorityGet                              1\r
+#define INCLUDE_vTaskDelete                                            1\r
+#define INCLUDE_vTaskCleanUpResources                  0\r
+#define INCLUDE_vTaskSuspend                                   1\r
+#define INCLUDE_vTaskDelayUntil                                        1\r
+#define INCLUDE_vTaskDelay                                             1\r
+#define INCLUDE_uxTaskGetStackHighWaterMark            1\r
+#define INCLUDE_xTaskGetSchedulerState                 1\r
+#define INCLUDE_xTimerGetTimerTaskHandle               0\r
+#define INCLUDE_xTaskGetIdleTaskHandle                 0\r
+#define INCLUDE_xQueueGetMutexHolder                   1\r
+#define INCLUDE_eTaskGetState                                  1\r
+#define INCLUDE_xEventGroupSetBitsFromISR              1\r
+#define INCLUDE_xTimerPendFunctionCall                 1\r
+#define INCLUDE_pcTaskGetTaskName                              1\r
+\r
+/* This demo makes use of one or more example stats formatting functions.  These\r
+format the raw data provided by the uxTaskGetSystemState() function in to human\r
+readable ASCII form.  See the notes in the implementation of vTaskList() within\r
+FreeRTOS/Source/tasks.c for limitations.  configUSE_STATS_FORMATTING_FUNCTIONS\r
+is set to 2 so the formatting functions are included without the stdio.h being\r
+included in tasks.c.  That is because this project defines its own sprintf()\r
+functions. */\r
+#define configUSE_STATS_FORMATTING_FUNCTIONS   1\r
+\r
+/* Assert call defined for debug builds. */\r
+#ifdef _DEBUG\r
+       extern void vAssertCalled( const char *pcFile, uint32_t ulLine );\r
+       #define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )\r
+#endif /* _DEBUG */\r
+\r
+\r
+\r
+/* Application specific definitions follow. **********************************/\r
+\r
+/* If configINCLUDE_DEMO_DEBUG_STATS is set to one, then a few basic IP trace\r
+macros are defined to gather some UDP stack statistics that can then be viewed\r
+through the CLI interface. */\r
+#define configINCLUDE_DEMO_DEBUG_STATS 1\r
+\r
+/* The size of the global output buffer that is available for use when there\r
+are multiple command interpreters running at once (for example, one on a UART\r
+and one on TCP/IP).  This is done to prevent an output buffer being defined by\r
+each implementation - which would waste RAM.  In this case, there is only one\r
+command interpreter running, and it has its own local output buffer, so the\r
+global buffer is just set to be one byte long as it is not used and should not\r
+take up unnecessary RAM. */\r
+#define configCOMMAND_INT_MAX_OUTPUT_SIZE 1\r
+\r
+/* Only used when running in the FreeRTOS Windows simulator.  Defines the\r
+priority of the task used to simulate Ethernet interrupts. */\r
+#define configMAC_ISR_SIMULATOR_PRIORITY       ( configMAX_PRIORITIES - 1 )\r
+\r
+/* This demo creates a virtual network connection by accessing the raw Ethernet\r
+or WiFi data to and from a real network connection.  Many computers have more\r
+than one real network port, and configNETWORK_INTERFACE_TO_USE is used to tell\r
+the demo which real port should be used to create the virtual port.  The ports\r
+available are displayed on the console when the application is executed.  For\r
+example, on my development laptop setting configNETWORK_INTERFACE_TO_USE to 4\r
+results in the wired network being used, while setting\r
+configNETWORK_INTERFACE_TO_USE to 2 results in the wireless network being\r
+used. */\r
+#define configNETWORK_INTERFACE_TO_USE 4L\r
+\r
+/* The address of an echo server that will be used by the two demo echo client\r
+tasks.\r
+http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_Echo_Clients.html\r
+http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/UDP_Echo_Clients.html */\r
+#define configECHO_SERVER_ADDR0        192\r
+#define configECHO_SERVER_ADDR1 168\r
+#define configECHO_SERVER_ADDR2 0\r
+#define configECHO_SERVER_ADDR3 11\r
+\r
+/* Default MAC address configuration.  The demo creates a virtual network\r
+connection that uses this MAC address by accessing the raw Ethernet/WiFi data\r
+to and from a real network connection on the host PC.  See the\r
+configNETWORK_INTERFACE_TO_USE definition above for information on how to\r
+configure the real network connection to use. */\r
+#define configMAC_ADDR0                0x00\r
+#define configMAC_ADDR1                0x11\r
+#define configMAC_ADDR2                0x22\r
+#define configMAC_ADDR3                0x33\r
+#define configMAC_ADDR4                0x44\r
+#define configMAC_ADDR5                0x41\r
+\r
+/* Default IP address configuration.  Used in ipconfigUSE_DNS is set to 0, or\r
+ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */\r
+#define configIP_ADDR0         172\r
+#define configIP_ADDR1         25\r
+#define configIP_ADDR2         218\r
+#define configIP_ADDR3         200\r
+\r
+/* Default gateway IP address configuration.  Used in ipconfigUSE_DNS is set to\r
+0, or ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */\r
+#define configGATEWAY_ADDR0    172\r
+#define configGATEWAY_ADDR1    25\r
+#define configGATEWAY_ADDR2    218\r
+#define configGATEWAY_ADDR3    1\r
+\r
+/* Default DNS server configuration.  OpenDNS addresses are 208.67.222.222 and\r
+208.67.220.220.  Used in ipconfigUSE_DNS is set to 0, or ipconfigUSE_DNS is set\r
+to 1 but a DNS server cannot be contacted.*/\r
+#define configDNS_SERVER_ADDR0         208\r
+#define configDNS_SERVER_ADDR1         67\r
+#define configDNS_SERVER_ADDR2         222\r
+#define configDNS_SERVER_ADDR3         222\r
+\r
+/* Default netmask configuration.  Used in ipconfigUSE_DNS is set to 0, or\r
+ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */\r
+#define configNET_MASK0                255\r
+#define configNET_MASK1                255\r
+#define configNET_MASK2                0\r
+#define configNET_MASK3                0\r
+\r
+/* The UDP port to which print messages are sent. */\r
+#define configPRINT_PORT       ( 15000 )\r
+\r
+#if( defined( _MSC_VER ) && ( _MSC_VER <= 1600 ) && !defined( snprintf ) )\r
+       /* Map to Windows names. */\r
+       #define snprintf        _snprintf\r
+       #define vsnprintf       _vsnprintf\r
+#endif\r
+\r
+/* Visual studio does not have an implementation of strcasecmp(). */\r
+#define strcasecmp _stricmp\r
+#define strncasecmp _strnicmp\r
+#define strcmpi _strcmpi\r
+\r
+#endif /* FREERTOS_CONFIG_H */\r
+\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOSIPConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOSIPConfig.h
new file mode 100644 (file)
index 0000000..9be333e
--- /dev/null
@@ -0,0 +1,349 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+\r
+\r
+/*****************************************************************************\r
+ *\r
+ * See the following URL for configuration information.\r
+ * http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html\r
+ *\r
+ *****************************************************************************/\r
+\r
+#ifndef FREERTOS_IP_CONFIG_H\r
+#define FREERTOS_IP_CONFIG_H\r
+\r
+/* Prototype for the function used to print out.  In this case it prints to the\r
+console before the network is connected then a UDP port after the network has\r
+connected. */\r
+extern void vLoggingPrintf( const char *pcFormatString, ... );\r
+\r
+/* Set to 1 to print out debug messages.  If ipconfigHAS_DEBUG_PRINTF is set to\r
+1 then FreeRTOS_debug_printf should be defined to the function used to print\r
+out the debugging messages. */\r
+#define ipconfigHAS_DEBUG_PRINTF       0\r
+#if( ipconfigHAS_DEBUG_PRINTF == 1 )\r
+       #define FreeRTOS_debug_printf(X)        vLoggingPrintf X\r
+#endif\r
+\r
+/* Set to 1 to print out non debugging messages, for example the output of the\r
+FreeRTOS_netstat() command, and ping replies.  If ipconfigHAS_PRINTF is set to 1\r
+then FreeRTOS_printf should be set to the function used to print out the\r
+messages. */\r
+#define ipconfigHAS_PRINTF                     1\r
+#if( ipconfigHAS_PRINTF == 1 )\r
+       #define FreeRTOS_printf(X)                      vLoggingPrintf X\r
+#endif\r
+\r
+/* Define the byte order of the target MCU (the MCU FreeRTOS+TCP is executing\r
+on).  Valid options are pdFREERTOS_BIG_ENDIAN and pdFREERTOS_LITTLE_ENDIAN. */\r
+#define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN\r
+\r
+/* If the network card/driver includes checksum offloading (IP/TCP/UDP checksums)\r
+then set ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM to 1 to prevent the software\r
+stack repeating the checksum calculations. */\r
+#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM   1\r
+\r
+/* Several API's will block until the result is known, or the action has been\r
+performed, for example FreeRTOS_send() and FreeRTOS_recv().  The timeouts can be\r
+set per socket, using setsockopt().  If not set, the times below will be\r
+used as defaults. */\r
+#define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME        ( 5000 )\r
+#define        ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME    ( 5000 )\r
+\r
+/* Include support for LLMNR: Link-local Multicast Name Resolution\r
+(non-Microsoft) */\r
+#define ipconfigUSE_LLMNR                                      ( 1 )\r
+\r
+/* Include support for NBNS: NetBIOS Name Service (Microsoft) */\r
+#define ipconfigUSE_NBNS                                       ( 1 )\r
+\r
+/* Include support for DNS caching.  For TCP, having a small DNS cache is very\r
+useful.  When a cache is present, ipconfigDNS_REQUEST_ATTEMPTS can be kept low\r
+and also DNS may use small timeouts.  If a DNS reply comes in after the DNS\r
+socket has been destroyed, the result will be stored into the cache.  The next\r
+call to FreeRTOS_gethostbyname() will return immediately, without even creating\r
+a socket. */\r
+#define ipconfigUSE_DNS_CACHE                          ( 1 )\r
+#define ipconfigDNS_CACHE_NAME_LENGTH          ( 16 )\r
+#define ipconfigDNS_CACHE_ENTRIES                      ( 4 )\r
+#define ipconfigDNS_REQUEST_ATTEMPTS           ( 2 )\r
+\r
+/* The IP stack executes it its own task (although any application task can make\r
+use of its services through the published sockets API). ipconfigUDP_TASK_PRIORITY\r
+sets the priority of the task that executes the IP stack.  The priority is a\r
+standard FreeRTOS task priority so can take any value from 0 (the lowest\r
+priority) to (configMAX_PRIORITIES - 1) (the highest priority).\r
+configMAX_PRIORITIES is a standard FreeRTOS configuration parameter defined in\r
+FreeRTOSConfig.h, not FreeRTOSIPConfig.h. Consideration needs to be given as to\r
+the priority assigned to the task executing the IP stack relative to the\r
+priority assigned to tasks that use the IP stack. */\r
+#define ipconfigIP_TASK_PRIORITY                       ( configMAX_PRIORITIES - 2 )\r
+\r
+/* The size, in words (not bytes), of the stack allocated to the FreeRTOS+TCP\r
+task.  This setting is less important when the FreeRTOS Win32 simulator is used\r
+as the Win32 simulator only stores a fixed amount of information on the task\r
+stack.  FreeRTOS includes optional stack overflow detection, see:\r
+http://www.freertos.org/Stacks-and-stack-overflow-checking.html */\r
+#define ipconfigIP_TASK_STACK_SIZE_WORDS       ( configMINIMAL_STACK_SIZE * 5 )\r
+\r
+/* ipconfigRAND32() is called by the IP stack to generate random numbers for\r
+things such as a DHCP transaction number or initial sequence number.  Random\r
+number generation is performed via this macro to allow applications to use their\r
+own random number generation method.  For example, it might be possible to\r
+generate a random number by sampling noise on an analogue input. */\r
+extern UBaseType_t uxRand();\r
+#define ipconfigRAND32()       uxRand()\r
+\r
+/* If ipconfigUSE_NETWORK_EVENT_HOOK is set to 1 then FreeRTOS+TCP will call the\r
+network event hook at the appropriate times.  If ipconfigUSE_NETWORK_EVENT_HOOK\r
+is not set to 1 then the network event hook will never be called.  See\r
+http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/API/vApplicationIPNetworkEventHook.shtml\r
+*/\r
+#define ipconfigUSE_NETWORK_EVENT_HOOK 1\r
+\r
+/* Sockets have a send block time attribute.  If FreeRTOS_sendto() is called but\r
+a network buffer cannot be obtained then the calling task is held in the Blocked\r
+state (so other tasks can continue to executed) until either a network buffer\r
+becomes available or the send block time expires.  If the send block time expires\r
+then the send operation is aborted.  The maximum allowable send block time is\r
+capped to the value set by ipconfigMAX_SEND_BLOCK_TIME_TICKS.  Capping the\r
+maximum allowable send block time prevents prevents a deadlock occurring when\r
+all the network buffers are in use and the tasks that process (and subsequently\r
+free) the network buffers are themselves blocked waiting for a network buffer.\r
+ipconfigMAX_SEND_BLOCK_TIME_TICKS is specified in RTOS ticks.  A time in\r
+milliseconds can be converted to a time in ticks by dividing the time in\r
+milliseconds by portTICK_PERIOD_MS. */\r
+#define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( 5000 / portTICK_PERIOD_MS )\r
+\r
+/* If ipconfigUSE_DHCP is 1 then FreeRTOS+TCP will attempt to retrieve an IP\r
+address, netmask, DNS server address and gateway address from a DHCP server.  If\r
+ipconfigUSE_DHCP is 0 then FreeRTOS+TCP will use a static IP address.  The\r
+stack will revert to using the static IP address even when ipconfigUSE_DHCP is\r
+set to 1 if a valid configuration cannot be obtained from a DHCP server for any\r
+reason.  The static configuration used is that passed into the stack by the\r
+FreeRTOS_IPInit() function call. */\r
+#define ipconfigUSE_DHCP       1\r
+\r
+/* When ipconfigUSE_DHCP is set to 1, DHCP requests will be sent out at\r
+increasing time intervals until either a reply is received from a DHCP server\r
+and accepted, or the interval between transmissions reaches\r
+ipconfigMAXIMUM_DISCOVER_TX_PERIOD.  The IP stack will revert to using the\r
+static IP address passed as a parameter to FreeRTOS_IPInit() if the\r
+re-transmission time interval reaches ipconfigMAXIMUM_DISCOVER_TX_PERIOD without\r
+a DHCP reply being received. */\r
+#define ipconfigMAXIMUM_DISCOVER_TX_PERIOD             ( 120000 / portTICK_PERIOD_MS )\r
+\r
+/* The ARP cache is a table that maps IP addresses to MAC addresses.  The IP\r
+stack can only send a UDP message to a remove IP address if it knowns the MAC\r
+address associated with the IP address, or the MAC address of the router used to\r
+contact the remote IP address.  When a UDP message is received from a remote IP\r
+address the MAC address and IP address are added to the ARP cache.  When a UDP\r
+message is sent to a remote IP address that does not already appear in the ARP\r
+cache then the UDP message is replaced by a ARP message that solicits the\r
+required MAC address information.  ipconfigARP_CACHE_ENTRIES defines the maximum\r
+number of entries that can exist in the ARP table at any one time. */\r
+#define ipconfigARP_CACHE_ENTRIES              6\r
+\r
+/* ARP requests that do not result in an ARP response will be re-transmitted a\r
+maximum of ipconfigMAX_ARP_RETRANSMISSIONS times before the ARP request is\r
+aborted. */\r
+#define ipconfigMAX_ARP_RETRANSMISSIONS ( 5 )\r
+\r
+/* ipconfigMAX_ARP_AGE defines the maximum time between an entry in the ARP\r
+table being created or refreshed and the entry being removed because it is stale.\r
+New ARP requests are sent for ARP cache entries that are nearing their maximum\r
+age.  ipconfigMAX_ARP_AGE is specified in tens of seconds, so a value of 150 is\r
+equal to 1500 seconds (or 25 minutes). */\r
+#define ipconfigMAX_ARP_AGE                    150\r
+\r
+/* Implementing FreeRTOS_inet_addr() necessitates the use of string handling\r
+routines, which are relatively large.  To save code space the full\r
+FreeRTOS_inet_addr() implementation is made optional, and a smaller and faster\r
+alternative called FreeRTOS_inet_addr_quick() is provided.  FreeRTOS_inet_addr()\r
+takes an IP in decimal dot format (for example, "192.168.0.1") as its parameter.\r
+FreeRTOS_inet_addr_quick() takes an IP address as four separate numerical octets\r
+(for example, 192, 168, 0, 1) as its parameters.  If\r
+ipconfigINCLUDE_FULL_INET_ADDR is set to 1 then both FreeRTOS_inet_addr() and\r
+FreeRTOS_indet_addr_quick() are available.  If ipconfigINCLUDE_FULL_INET_ADDR is\r
+not set to 1 then only FreeRTOS_indet_addr_quick() is available. */\r
+#define ipconfigINCLUDE_FULL_INET_ADDR 1\r
+\r
+/* ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS defines the total number of network buffer that\r
+are available to the IP stack.  The total number of network buffers is limited\r
+to ensure the total amount of RAM that can be consumed by the IP stack is capped\r
+to a pre-determinable value. */\r
+#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS         60\r
+\r
+/* A FreeRTOS queue is used to send events from application tasks to the IP\r
+stack.  ipconfigEVENT_QUEUE_LENGTH sets the maximum number of events that can\r
+be queued for processing at any one time.  The event queue must be a minimum of\r
+5 greater than the total number of network buffers. */\r
+#define ipconfigEVENT_QUEUE_LENGTH             ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 )\r
+\r
+/* The address of a socket is the combination of its IP address and its port\r
+number.  FreeRTOS_bind() is used to manually allocate a port number to a socket\r
+(to 'bind' the socket to a port), but manual binding is not normally necessary\r
+for client sockets (those sockets that initiate outgoing connections rather than\r
+wait for incoming connections on a known port number).  If\r
+ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 1 then calling\r
+FreeRTOS_sendto() on a socket that has not yet been bound will result in the IP\r
+stack automatically binding the socket to a port number from the range\r
+socketAUTO_PORT_ALLOCATION_START_NUMBER to 0xffff.  If\r
+ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is set to 0 then calling FreeRTOS_sendto()\r
+on a socket that has not yet been bound will result in the send operation being\r
+aborted. */\r
+#define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1\r
+\r
+/* Defines the Time To Live (TTL) values used in outgoing UDP packets. */\r
+#define ipconfigUDP_TIME_TO_LIVE               128\r
+#define ipconfigTCP_TIME_TO_LIVE               128 /* also defined in FreeRTOSIPConfigDefaults.h */\r
+\r
+/* USE_TCP: Use TCP and all its features */\r
+#define ipconfigUSE_TCP                                ( 1 )\r
+\r
+/* USE_WIN: Let TCP use windowing mechanism. */\r
+#define ipconfigUSE_TCP_WIN                    ( 1 )\r
+\r
+/* The MTU is the maximum number of bytes the payload of a network frame can\r
+contain.  For normal Ethernet V2 frames the maximum MTU is 1500.  Setting a\r
+lower value can save RAM, depending on the buffer management scheme used.  If\r
+ipconfigCAN_FRAGMENT_OUTGOING_PACKETS is 1 then (ipconfigNETWORK_MTU - 28) must\r
+be divisible by 8. */\r
+#define ipconfigNETWORK_MTU            1200\r
+\r
+/* Set ipconfigUSE_DNS to 1 to include a basic DNS client/resolver.  DNS is used\r
+through the FreeRTOS_gethostbyname() API function. */\r
+#define ipconfigUSE_DNS                        1\r
+\r
+/* If ipconfigREPLY_TO_INCOMING_PINGS is set to 1 then the IP stack will\r
+generate replies to incoming ICMP echo (ping) requests. */\r
+#define ipconfigREPLY_TO_INCOMING_PINGS                                1\r
+\r
+/* If ipconfigSUPPORT_OUTGOING_PINGS is set to 1 then the\r
+FreeRTOS_SendPingRequest() API function is available. */\r
+#define ipconfigSUPPORT_OUTGOING_PINGS                         0\r
+\r
+/* If ipconfigSUPPORT_SELECT_FUNCTION is set to 1 then the FreeRTOS_select()\r
+(and associated) API function is available. */\r
+#define ipconfigSUPPORT_SELECT_FUNCTION                                1\r
+\r
+/* If ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES is set to 1 then Ethernet frames\r
+that are not in Ethernet II format will be dropped.  This option is included for\r
+potential future IP stack developments. */\r
+#define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES  1\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1 then it is the\r
+responsibility of the Ethernet interface to filter out packets that are of no\r
+interest.  If the Ethernet interface does not implement this functionality, then\r
+set ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES to 0 to have the IP stack\r
+perform the filtering instead (it is much less efficient for the stack to do it\r
+because the packet will already have been passed into the stack).  If the\r
+Ethernet driver does all the necessary filtering in hardware then software\r
+filtering can be removed by using a value other than 1 or 0. */\r
+#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES    1\r
+\r
+/* The windows simulator cannot really simulate MAC interrupts, and needs to\r
+block occasionally to allow other tasks to run. */\r
+#define configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY ( 20 / portTICK_PERIOD_MS )\r
+\r
+/* Advanced only: in order to access 32-bit fields in the IP packets with\r
+32-bit memory instructions, all packets will be stored 32-bit-aligned, plus 16-bits.\r
+This has to do with the contents of the IP-packets: all 32-bit fields are\r
+32-bit-aligned, plus 16-bit(!) */\r
+#define ipconfigPACKET_FILLER_SIZE 2\r
+\r
+/* Define the size of the pool of TCP window descriptors.  On the average, each\r
+TCP socket will use up to 2 x 6 descriptors, meaning that it can have 2 x 6\r
+outstanding packets (for Rx and Tx).  When using up to 10 TP sockets\r
+simultaneously, one could define TCP_WIN_SEG_COUNT as 120. */\r
+#define ipconfigTCP_WIN_SEG_COUNT              240\r
+\r
+/* Each TCP socket has a circular buffers for Rx and Tx, which have a fixed\r
+maximum size.  Define the size of Rx buffer for TCP sockets. */\r
+#define ipconfigTCP_RX_BUFFER_LENGTH                   ( 1000 )\r
+\r
+/* Define the size of Tx buffer for TCP sockets. */\r
+#define ipconfigTCP_TX_BUFFER_LENGTH                   ( 1000 )\r
+\r
+/* When using call-back handlers, the driver may check if the handler points to\r
+real program memory (RAM or flash) or just has a random non-zero value. */\r
+#define ipconfigIS_VALID_PROG_ADDRESS(x) ( (x) != NULL )\r
+\r
+/* Include support for TCP hang protection.  All sockets in a connecting or\r
+disconnecting stage will timeout after a period of non-activity. */\r
+#define ipconfigTCP_HANG_PROTECTION                    ( 1 )\r
+#define ipconfigTCP_HANG_PROTECTION_TIME       ( 30 )\r
+\r
+/* Include support for TCP keep-alive messages. */\r
+#define ipconfigTCP_KEEP_ALIVE                         ( 1 )\r
+#define ipconfigTCP_KEEP_ALIVE_INTERVAL                ( 20 ) /* in seconds */\r
+\r
+#define portINLINE __inline\r
+\r
+#endif /* FREERTOS_IP_CONFIG_H */\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOS_Plus_TCP_Minimal.sln b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOS_Plus_TCP_Minimal.sln
new file mode 100644 (file)
index 0000000..b362f36
--- /dev/null
@@ -0,0 +1,23 @@
+\r
+Microsoft Visual Studio Solution File, Format Version 11.00\r
+# Visual Studio 2010\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RTOSDemo", "WIN32.vcxproj", "{C686325E-3261-42F7-AEB1-DDE5280E1CEB}"\r
+EndProject\r
+Global\r
+       GlobalSection(TestCaseManagementSettings) = postSolution\r
+               CategoryFile = FreeRTOS_Plus_TCP_Minimal.vsmdi\r
+       EndGlobalSection\r
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+               Debug|Win32 = Debug|Win32\r
+               Release|Win32 = Release|Win32\r
+       EndGlobalSection\r
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+               {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Debug|Win32.ActiveCfg = Debug|Win32\r
+               {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Debug|Win32.Build.0 = Debug|Win32\r
+               {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Release|Win32.ActiveCfg = Release|Win32\r
+               {C686325E-3261-42F7-AEB1-DDE5280E1CEB}.Release|Win32.Build.0 = Release|Win32\r
+       EndGlobalSection\r
+       GlobalSection(SolutionProperties) = preSolution\r
+               HideSolutionNode = FALSE\r
+       EndGlobalSection\r
+EndGlobal\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOS_Plus_TCP_Minimal.suo b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOS_Plus_TCP_Minimal.suo
new file mode 100644 (file)
index 0000000..6a1e0eb
Binary files /dev/null and b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/FreeRTOS_Plus_TCP_Minimal.suo differ
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/ReadMe.txt b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/ReadMe.txt
new file mode 100644 (file)
index 0000000..682a18c
--- /dev/null
@@ -0,0 +1,34 @@
+The FreeRTOS+TCP source code and example projects are currently provided in\r
+their own .zip file download, but using the directory structure of the official\r
+FreeRTOS .zip file download.  This allow the projects to be seamlessly moved\r
+from one download to the other, but can seem strange when the files are viewed\r
+in isolation.\r
+\r
+The minimal FreeRTOS+TCP Visual Studio project file is in the following directory:\r
+FreeRTOS-Plus\Demo\FreeRTOS_Plus_TCP_Minimal_Windows_Simulator\r
+\r
+The minimal project is a cut down version of the full Windows demo that only\r
+includes examples of simple TCP and UDP clients.  The instructions for the full \r
+Windows demo are still relevant though as they describe how to set up the \r
+WinPCap development environment, how to set the IP address, and other such \r
+items.  Note that, as delivered, configUSE_DHCP is set to 0, so a static IP \r
+address is used.  The instructions are provided on the following URL:\r
+http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html\r
+\r
+The UDP client example included in the minimal project is described on the \r
+following URL:\r
+http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/UDP_client_server.html\r
+\r
+The TCP client example included in the minimal project is described on the\r
+following URL:\r
+http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_Echo_Clients.html\r
+\r
+A description of the FreeRTOS+TCP source code directory is provided on the\r
+following URL:\r
+http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_Networking_Tutorial_Source_Code_Organisation.html\r
+\r
+A description of the way the main FreeRTOS .zip file download source code is\r
+organised is provided on the following URL:\r
+http://www.freertos.org/a00017.html\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/Read_Me_Build_Instructions.url b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/Read_Me_Build_Instructions.url
new file mode 100644 (file)
index 0000000..3ceab76
--- /dev/null
@@ -0,0 +1,6 @@
+[{000214A0-0000-0000-C000-000000000046}]\r
+Prop3=19,2\r
+[InternetShortcut]\r
+URL=http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html\r
+IDList=\r
+HotKey=0\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WIN32.vcxproj b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WIN32.vcxproj
new file mode 100644 (file)
index 0000000..14a8d8a
--- /dev/null
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup Label="ProjectConfigurations">\r
+    <ProjectConfiguration Include="Debug|Win32">\r
+      <Configuration>Debug</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+    <ProjectConfiguration Include="Release|Win32">\r
+      <Configuration>Release</Configuration>\r
+      <Platform>Win32</Platform>\r
+    </ProjectConfiguration>\r
+  </ItemGroup>\r
+  <PropertyGroup Label="Globals">\r
+    <ProjectGuid>{C686325E-3261-42F7-AEB1-DDE5280E1CEB}</ProjectGuid>\r
+    <ProjectName>RTOSDemo</ProjectName>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">\r
+    <ConfigurationType>Application</ConfigurationType>\r
+    <UseOfMfc>false</UseOfMfc>\r
+    <CharacterSet>MultiByte</CharacterSet>\r
+    <PlatformToolset>v140</PlatformToolset>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">\r
+    <ConfigurationType>Application</ConfigurationType>\r
+    <UseOfMfc>false</UseOfMfc>\r
+    <CharacterSet>MultiByte</CharacterSet>\r
+    <PlatformToolset>v140</PlatformToolset>\r
+  </PropertyGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\r
+  <ImportGroup Label="ExtensionSettings">\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
+  </ImportGroup>\r
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">\r
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />\r
+    <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />\r
+  </ImportGroup>\r
+  <PropertyGroup Label="UserMacros" />\r
+  <PropertyGroup>\r
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>\r
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>\r
+    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>\r
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>\r
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>\r
+    <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>\r
+  </PropertyGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">\r
+    <Midl>\r
+      <TypeLibraryName>.\Debug/WIN32.tlb</TypeLibraryName>\r
+      <HeaderFileName>\r
+      </HeaderFileName>\r
+    </Midl>\r
+    <ClCompile>\r
+      <Optimization>Disabled</Optimization>\r
+      <AdditionalIncludeDirectories>..\..\Source\FreeRTOS-Plus-FAT\include;..\..\Source\FreeRTOS-Plus-FAT\portable\common;..\..\Source\FreeRTOS-Plus-TCP\protocols\include;..\..\Source\FreeRTOS-Plus-TCP\portable\BufferManagement;.\DemoTasks\include;..\..\Source\FreeRTOS-Plus-TCP\portable\Compiler\MSVC;.\WinPCap;..\..\..\FreeRTOS\Source\include;..\..\..\FreeRTOS\Source\portable\MSVC-MingW;..\..\Source\FreeRTOS-Plus-CLI;.\TraceMacros\Example1;..\..\Source\FreeRTOS-Plus-TCP\include;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0500;WINVER=0x400;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <MinimalRebuild>true</MinimalRebuild>\r
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
+      <PrecompiledHeaderOutputFile>.\Debug/WIN32.pch</PrecompiledHeaderOutputFile>\r
+      <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>\r
+      <ObjectFileName>.\Debug/</ObjectFileName>\r
+      <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>\r
+      <WarningLevel>Level4</WarningLevel>\r
+      <SuppressStartupBanner>true</SuppressStartupBanner>\r
+      <DisableLanguageExtensions>false</DisableLanguageExtensions>\r
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
+      <AdditionalOptions>/wd4210 /wd4127 /wd4214 /wd4201 /wd4244  /wd4310 %(AdditionalOptions)</AdditionalOptions>\r
+      <BrowseInformation>true</BrowseInformation>\r
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
+      <ExceptionHandling>false</ExceptionHandling>\r
+      <CompileAs>CompileAsC</CompileAs>\r
+    </ClCompile>\r
+    <ResourceCompile>\r
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <Culture>0x0c09</Culture>\r
+    </ResourceCompile>\r
+    <Link>\r
+      <OutputFile>.\Debug/RTOSDemo.exe</OutputFile>\r
+      <SuppressStartupBanner>true</SuppressStartupBanner>\r
+      <GenerateDebugInformation>true</GenerateDebugInformation>\r
+      <ProgramDatabaseFile>.\Debug/WIN32.pdb</ProgramDatabaseFile>\r
+      <SubSystem>Console</SubSystem>\r
+      <TargetMachine>MachineX86</TargetMachine>\r
+      <AdditionalDependencies>wpcap.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+      <AdditionalLibraryDirectories>.\WinPCap</AdditionalLibraryDirectories>\r
+      <Profile>false</Profile>\r
+    </Link>\r
+    <Bscmake>\r
+      <SuppressStartupBanner>true</SuppressStartupBanner>\r
+      <OutputFile>.\Debug/WIN32.bsc</OutputFile>\r
+    </Bscmake>\r
+  </ItemDefinitionGroup>\r
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
+    <Midl>\r
+      <TypeLibraryName>.\Release/WIN32.tlb</TypeLibraryName>\r
+      <HeaderFileName>\r
+      </HeaderFileName>\r
+    </Midl>\r
+    <ClCompile>\r
+      <Optimization>MaxSpeed</Optimization>\r
+      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>\r
+      <PreprocessorDefinitions>_WINSOCKAPI_;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <StringPooling>true</StringPooling>\r
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
+      <FunctionLevelLinking>true</FunctionLevelLinking>\r
+      <PrecompiledHeaderOutputFile>.\Release/WIN32.pch</PrecompiledHeaderOutputFile>\r
+      <AssemblerListingLocation>.\Release/</AssemblerListingLocation>\r
+      <ObjectFileName>.\Release/</ObjectFileName>\r
+      <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>\r
+      <WarningLevel>Level3</WarningLevel>\r
+      <SuppressStartupBanner>true</SuppressStartupBanner>\r
+      <AdditionalIncludeDirectories>..\Common\Utils;..\Common\ethernet\lwip-1.4.0\ports\win32\WinPCap;..\Common\ethernet\lwip-1.4.0\src\include\ipv4;..\Common\ethernet\lwip-1.4.0\src\include;..\..\Source\include;..\..\Source\portable\MSVC-MingW;..\Common\ethernet\lwip-1.4.0\ports\win32\include;..\Common\Include;.\lwIP_Apps;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+    </ClCompile>\r
+    <ResourceCompile>\r
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <Culture>0x0c09</Culture>\r
+    </ResourceCompile>\r
+    <Link>\r
+      <OutputFile>.\Release/RTOSDemo.exe</OutputFile>\r
+      <SuppressStartupBanner>true</SuppressStartupBanner>\r
+      <ProgramDatabaseFile>.\Release/WIN32.pdb</ProgramDatabaseFile>\r
+      <SubSystem>Console</SubSystem>\r
+      <TargetMachine>MachineX86</TargetMachine>\r
+      <AdditionalLibraryDirectories>..\Common\ethernet\lwip-1.4.0\ports\win32\WinPCap</AdditionalLibraryDirectories>\r
+      <AdditionalDependencies>wpcap.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
+    </Link>\r
+    <Bscmake>\r
+      <SuppressStartupBanner>true</SuppressStartupBanner>\r
+      <OutputFile>.\Release/WIN32.bsc</OutputFile>\r
+    </Bscmake>\r
+  </ItemDefinitionGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\event_groups.c" />\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\list.c" />\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\portable\MemMang\heap_4.c" />\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\portable\MSVC-MingW\port.c" />\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\queue.c" />\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\tasks.c" />\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\timers.c" />\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_ARP.c" />\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_DHCP.c" />\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_DNS.c" />\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_IP.c" />\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_Sockets.c" />\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_Stream_Buffer.c" />\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_TCP_IP.c" />\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_TCP_WIN.c" />\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_UDP_IP.c" />\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\portable\BufferManagement\BufferAllocation_2.c" />\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\portable\NetworkInterface\WinPCap\NetworkInterface.c" />\r
+    <ClCompile Include="DemoTasks\TCPEchoClient_SingleTasks.c" />\r
+    <ClCompile Include="DemoTasks\SimpleUDPClientAndServer.c" />\r
+    <ClCompile Include="demo_logging.c" />\r
+    <ClCompile Include="main.c">\r
+      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\event_groups.h" />\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\FreeRTOS.h" />\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\portable.h" />\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\projdefs.h" />\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\queue.h" />\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\semphr.h" />\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\task.h" />\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\timers.h" />\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\portable\MSVC-MingW\portmacro.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOSIPConfigDefaults.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_ARP.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_DHCP.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_DNS.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_IP.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_IP_Private.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_Sockets.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_Stream_Buffer.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_TCP_IP.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_TCP_WIN.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_UDP_IP.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\IPTraceMacroDefaults.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\NetworkBufferManagement.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\NetworkInterface.h" />\r
+    <ClInclude Include="FreeRTOSConfig.h" />\r
+    <ClInclude Include="FreeRTOSIPConfig.h" />\r
+  </ItemGroup>\r
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
+  <ImportGroup Label="ExtensionTargets">\r
+  </ImportGroup>\r
+</Project>
\ No newline at end of file
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WIN32.vcxproj.filters b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WIN32.vcxproj.filters
new file mode 100644 (file)
index 0000000..4884971
--- /dev/null
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="Resource Files">\r
+      <UniqueIdentifier>{38712199-cebf-4124-bf15-398f7c3419ea}</UniqueIdentifier>\r
+      <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>\r
+    </Filter>\r
+    <Filter Include="FreeRTOS">\r
+      <UniqueIdentifier>{af3445a1-4908-4170-89ed-39345d90d30c}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="FreeRTOS\Source">\r
+      <UniqueIdentifier>{f32be356-4763-4cae-9020-974a2638cb08}</UniqueIdentifier>\r
+      <Extensions>*.c</Extensions>\r
+    </Filter>\r
+    <Filter Include="FreeRTOS\Source\Portable">\r
+      <UniqueIdentifier>{88f409e6-d396-4ac5-94bd-7a99c914be46}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="FreeRTOS+">\r
+      <UniqueIdentifier>{e5ad4ec7-23dc-4295-8add-2acaee488f5a}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="FreeRTOS\Source\include">\r
+      <UniqueIdentifier>{d2dcd641-8d91-492b-852f-5563ffadaec6}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="FreeRTOS+\FreeRTOS+TCP">\r
+      <UniqueIdentifier>{8672fa26-b119-481f-8b8d-086419c01a3e}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="FreeRTOS+\FreeRTOS+TCP\portable">\r
+      <UniqueIdentifier>{4570be11-ec96-4b55-ac58-24b50ada980a}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="FreeRTOS+\FreeRTOS+TCP\include">\r
+      <UniqueIdentifier>{5d93ed51-023a-41ad-9243-8d230165d34b}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="DemoTasks">\r
+      <UniqueIdentifier>{b71e974a-9f28-4815-972b-d930ba8a34d0}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\portable\MSVC-MingW\port.c">\r
+      <Filter>FreeRTOS\Source\Portable</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\timers.c">\r
+      <Filter>FreeRTOS\Source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\list.c">\r
+      <Filter>FreeRTOS\Source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\queue.c">\r
+      <Filter>FreeRTOS\Source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\tasks.c">\r
+      <Filter>FreeRTOS\Source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="DemoTasks\SimpleUDPClientAndServer.c">\r
+      <Filter>DemoTasks</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_UDP_IP.c">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_DHCP.c">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_DNS.c">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_Sockets.c">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\portable\BufferManagement\BufferAllocation_2.c">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\portable</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\portable\NetworkInterface\WinPCap\NetworkInterface.c">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\portable</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_ARP.c">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_IP.c">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_TCP_IP.c">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_TCP_WIN.c">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\event_groups.c">\r
+      <Filter>FreeRTOS\Source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\FreeRTOS\Source\portable\MemMang\heap_4.c">\r
+      <Filter>FreeRTOS\Source\Portable</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="main.c" />\r
+    <ClCompile Include="DemoTasks\TCPEchoClient_SingleTasks.c">\r
+      <Filter>DemoTasks</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\Source\FreeRTOS-Plus-TCP\FreeRTOS_Stream_Buffer.c">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="demo_logging.c" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\NetworkInterface.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_DNS.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_Sockets.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_UDP_IP.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\timers.h">\r
+      <Filter>FreeRTOS\Source\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\event_groups.h">\r
+      <Filter>FreeRTOS\Source\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\FreeRTOS.h">\r
+      <Filter>FreeRTOS\Source\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\queue.h">\r
+      <Filter>FreeRTOS\Source\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\semphr.h">\r
+      <Filter>FreeRTOS\Source\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\task.h">\r
+      <Filter>FreeRTOS\Source\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\portable\MSVC-MingW\portmacro.h">\r
+      <Filter>FreeRTOS\Source\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_IP_Private.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\NetworkBufferManagement.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_ARP.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_DHCP.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_IP.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_TCP_IP.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_TCP_WIN.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOSIPConfigDefaults.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\IPTraceMacroDefaults.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="FreeRTOSConfig.h" />\r
+    <ClInclude Include="FreeRTOSIPConfig.h" />\r
+    <ClInclude Include="..\..\Source\FreeRTOS-Plus-TCP\include\FreeRTOS_Stream_Buffer.h">\r
+      <Filter>FreeRTOS+\FreeRTOS+TCP\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\portable.h">\r
+      <Filter>FreeRTOS\Source\include</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\FreeRTOS\Source\include\projdefs.h">\r
+      <Filter>FreeRTOS\Source\include</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/Packet32.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/Packet32.h
new file mode 100644 (file)
index 0000000..1e0eacd
--- /dev/null
@@ -0,0 +1,359 @@
+/*\r
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)\r
+ * Copyright (c) 2005 - 2007 CACE Technologies, Davis (California)\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies \r
+ * nor the names of its contributors may be used to endorse or promote \r
+ * products derived from this software without specific prior written \r
+ * permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ */\r
+\r
+/** @ingroup packetapi\r
+ *  @{ \r
+ */\r
+\r
+/** @defgroup packet32h Packet.dll definitions and data structures\r
+ *  Packet32.h contains the data structures and the definitions used by packet.dll.\r
+ *  The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included\r
+ *  by the applications that use the functions of this library\r
+ *  @{\r
+ */\r
+\r
+#ifndef __PACKET32\r
+#define __PACKET32\r
+\r
+#include <winsock2.h>\r
+\r
+#ifdef HAVE_AIRPCAP_API\r
+#include <airpcap.h>\r
+#else\r
+#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_)\r
+#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_\r
+typedef struct _AirpcapHandle *PAirpcapHandle;\r
+#endif /* AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_ */\r
+#endif /* HAVE_AIRPCAP_API */\r
+\r
+#ifdef HAVE_DAG_API\r
+#include <dagc.h>\r
+#endif /* HAVE_DAG_API */\r
+\r
+// Working modes\r
+#define PACKET_MODE_CAPT 0x0 ///< Capture mode\r
+#define PACKET_MODE_STAT 0x1 ///< Statistical mode\r
+#define PACKET_MODE_MON 0x2 ///< Monitoring mode\r
+#define PACKET_MODE_DUMP 0x10 ///< Dump mode\r
+#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode\r
+\r
+\r
+/// Alignment macro. Defines the alignment size.\r
+#define Packet_ALIGNMENT sizeof(int)\r
+/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT. \r
+#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))\r
+\r
+#define NdisMediumNull -1              ///< Custom linktype: NDIS doesn't provide an equivalent\r
+#define NdisMediumCHDLC        -2              ///< Custom linktype: NDIS doesn't provide an equivalent\r
+#define NdisMediumPPPSerial    -3      ///< Custom linktype: NDIS doesn't provide an equivalent\r
+#define NdisMediumBare80211    -4      ///< Custom linktype: NDIS doesn't provide an equivalent\r
+#define NdisMediumRadio80211   -5      ///< Custom linktype: NDIS doesn't provide an equivalent\r
+#define NdisMediumPpi          -6      ///< Custom linktype: NDIS doesn't provide an equivalent\r
+\r
+// Loopback behaviour definitions\r
+#define NPF_DISABLE_LOOPBACK   1       ///< Drop the packets sent by the NPF driver\r
+#define NPF_ENABLE_LOOPBACK            2       ///< Capture the packets sent by the NPF driver\r
+\r
+/*!\r
+  \brief Network type structure.\r
+\r
+  This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed.\r
+*/\r
+typedef struct NetType\r
+{\r
+       UINT LinkType;  ///< The MAC of the current network adapter (see function PacketGetNetType() for more information)\r
+       ULONGLONG LinkSpeed;    ///< The speed of the network in bits per second\r
+}NetType;\r
+\r
+\r
+//some definitions stolen from libpcap\r
+\r
+#ifndef BPF_MAJOR_VERSION\r
+\r
+/*!\r
+  \brief A BPF pseudo-assembly program.\r
+\r
+  The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet. \r
+*/\r
+struct bpf_program \r
+{\r
+       UINT bf_len;                            ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow.\r
+       struct bpf_insn *bf_insns;      ///< A pointer to the first instruction of the program.\r
+};\r
+\r
+/*!\r
+  \brief A single BPF pseudo-instruction.\r
+\r
+  bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver.\r
+*/\r
+struct bpf_insn \r
+{\r
+       USHORT  code;           ///< Instruction type and addressing mode.\r
+       UCHAR   jt;                     ///< Jump if true\r
+       UCHAR   jf;                     ///< Jump if false\r
+       int k;                          ///< Generic field used for various purposes.\r
+};\r
+\r
+/*!\r
+  \brief Structure that contains a couple of statistics values on the current capture.\r
+\r
+  It is used by packet.dll to return statistics about a capture session.\r
+*/\r
+struct bpf_stat \r
+{\r
+       UINT bs_recv;           ///< Number of packets that the driver received from the network adapter \r
+                                               ///< from the beginning of the current capture. This value includes the packets \r
+                                               ///< lost by the driver.\r
+       UINT bs_drop;           ///< number of packets that the driver lost from the beginning of a capture. \r
+                                               ///< Basically, a packet is lost when the the buffer of the driver is full. \r
+                                               ///< In this situation the packet cannot be stored and the driver rejects it.\r
+       UINT ps_ifdrop;         ///< drops by interface. XXX not yet supported\r
+       UINT bs_capt;           ///< number of packets that pass the filter, find place in the kernel buffer and\r
+                                               ///< thus reach the application.\r
+};\r
+\r
+/*!\r
+  \brief Packet header.\r
+\r
+  This structure defines the header associated with every packet delivered to the application.\r
+*/\r
+struct bpf_hdr \r
+{\r
+       struct timeval  bh_tstamp;      ///< The timestamp associated with the captured packet. \r
+                                                               ///< It is stored in a TimeVal structure.\r
+       UINT    bh_caplen;                      ///< Length of captured portion. The captured portion <b>can be different</b>\r
+                                                               ///< from the original packet, because it is possible (with a proper filter)\r
+                                                               ///< to instruct the driver to capture only a portion of the packets.\r
+       UINT    bh_datalen;                     ///< Original length of packet\r
+       USHORT          bh_hdrlen;              ///< Length of bpf header (this struct plus alignment padding). In some cases,\r
+                                                               ///< a padding could be added between the end of this structure and the packet\r
+                                                               ///< data for performance reasons. This filed can be used to retrieve the actual data \r
+                                                               ///< of the packet.\r
+};\r
+\r
+/*!\r
+  \brief Dump packet header.\r
+\r
+  This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets().\r
+  It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a\r
+  packet in a dump file. This makes straightforward sending WinPcap dump files to the network.\r
+*/\r
+struct dump_bpf_hdr{\r
+    struct timeval     ts;                     ///< Time stamp of the packet\r
+    UINT                       caplen;         ///< Length of captured portion. The captured portion can smaller than the \r
+                                                               ///< the original packet, because it is possible (with a proper filter) to \r
+                                                               ///< instruct the driver to capture only a portion of the packets. \r
+    UINT                       len;            ///< Length of the original packet (off wire).\r
+};\r
+\r
+\r
+#endif\r
+\r
+struct bpf_stat;\r
+\r
+#define        DOSNAMEPREFIX   TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices\r
+#define        MAX_LINK_NAME_LENGTH    64                      //< Maximum length of the devices symbolic links\r
+#define        NMAX_PACKET 65535\r
+\r
+/*!\r
+  \brief Addresses of a network adapter.\r
+\r
+  This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with \r
+  an adapter.\r
+*/\r
+typedef struct npf_if_addr {\r
+       struct sockaddr_storage IPAddress;      ///< IP address.\r
+       struct sockaddr_storage SubnetMask;     ///< Netmask for that address.\r
+       struct sockaddr_storage Broadcast;      ///< Broadcast address.\r
+}npf_if_addr;\r
+\r
+\r
+#define ADAPTER_NAME_LENGTH 256 + 12   ///<  Maximum length for the name of an adapter. The value is the same used by the IP Helper API.\r
+#define ADAPTER_DESC_LENGTH 128                        ///<  Maximum length for the description of an adapter. The value is the same used by the IP Helper API.\r
+#define MAX_MAC_ADDR_LENGTH 8                  ///<  Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.\r
+#define MAX_NETWORK_ADDRESSES 16               ///<  Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.\r
+\r
+\r
+typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API\r
+typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API\r
+\r
+#define INFO_FLAG_NDIS_ADAPTER         0       ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter\r
+#define INFO_FLAG_NDISWAN_ADAPTER      1       ///< Flag for ADAPTER_INFO: this is a NdisWan adapter, and it's managed by WANPACKET\r
+#define INFO_FLAG_DAG_CARD                     2       ///< Flag for ADAPTER_INFO: this is a DAG card\r
+#define INFO_FLAG_DAG_FILE                     6       ///< Flag for ADAPTER_INFO: this is a DAG file\r
+#define INFO_FLAG_DONT_EXPORT          8       ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones.\r
+#define INFO_FLAG_AIRPCAP_CARD         16      ///< Flag for ADAPTER_INFO: this is an airpcap card\r
+#define INFO_FLAG_NPFIM_DEVICE         32\r
+\r
+/*!\r
+  \brief Describes an opened network adapter.\r
+\r
+  This structure is the most important for the functioning of packet.dll, but the great part of its fields\r
+  should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters\r
+*/\r
+typedef struct _ADAPTER  { \r
+       HANDLE hFile;                           ///< \internal Handle to an open instance of the NPF driver.\r
+       CHAR  SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened.\r
+       int NumWrites;                          ///< \internal Number of times a packets written on this adapter will be repeated \r
+                                                               ///< on the wire.\r
+       HANDLE ReadEvent;                       ///< A notification event associated with the read calls on the adapter.\r
+                                                               ///< It can be passed to standard Win32 functions (like WaitForSingleObject\r
+                                                               ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some \r
+                                                               ///< data. It is particularly useful in GUI applications that need to wait \r
+                                                               ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy()\r
+                                                               ///< function can be used to define the minimum amount of data in the kernel buffer\r
+                                                               ///< that will cause the event to be signalled. \r
+       \r
+       UINT ReadTimeOut;                       ///< \internal The amount of time after which a read on the driver will be released and \r
+                                                               ///< ReadEvent will be signaled, also if no packets were captured\r
+       CHAR Name[ADAPTER_NAME_LENGTH];\r
+       PWAN_ADAPTER pWanAdapter;\r
+       UINT Flags;                                     ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API.\r
+\r
+#ifdef HAVE_AIRPCAP_API\r
+       PAirpcapHandle  AirpcapAd;\r
+#endif // HAVE_AIRPCAP_API\r
+\r
+#ifdef HAVE_NPFIM_API\r
+       void* NpfImHandle;\r
+#endif // HAVE_NPFIM_API\r
+\r
+#ifdef HAVE_DAG_API\r
+       dagc_t *pDagCard;                       ///< Pointer to the dagc API adapter descriptor for this adapter\r
+       PCHAR DagBuffer;                        ///< Pointer to the buffer with the packets that is received from the DAG card\r
+       struct timeval DagReadTimeout;  ///< Read timeout. The dagc API requires a timeval structure\r
+       unsigned DagFcsLen;                     ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry\r
+       DWORD DagFastProcess;           ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps).\r
+#endif // HAVE_DAG_API\r
+}  ADAPTER, *LPADAPTER;\r
+\r
+/*!\r
+  \brief Structure that contains a group of packets coming from the driver.\r
+\r
+  This structure defines the header associated with every packet delivered to the application.\r
+*/\r
+typedef struct _PACKET {  \r
+       HANDLE       hEvent;            ///< \deprecated Still present for compatibility with old applications.\r
+       OVERLAPPED   OverLapped;        ///< \deprecated Still present for compatibility with old applications.\r
+       PVOID        Buffer;            ///< Buffer with containing the packets. See the PacketReceivePacket() for\r
+                                                               ///< details about the organization of the data in this buffer\r
+       UINT         Length;            ///< Length of the buffer\r
+       DWORD        ulBytesReceived;   ///< Number of valid bytes present in the buffer, i.e. amount of data\r
+                                                                       ///< received by the last call to PacketReceivePacket()\r
+       BOOLEAN      bIoComplete;       ///< \deprecated Still present for compatibility with old applications.\r
+}  PACKET, *LPPACKET;\r
+\r
+/*!\r
+  \brief Structure containing an OID request.\r
+\r
+  It is used by the PacketRequest() function to send an OID to the interface card driver. \r
+  It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address, \r
+  the list of the multicast groups defined on it, and so on.\r
+*/\r
+struct _PACKET_OID_DATA {\r
+    ULONG Oid;                                 ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h\r
+                                                               ///< for a complete list of valid codes.\r
+    ULONG Length;                              ///< Length of the data field\r
+    UCHAR Data[1];                             ///< variable-lenght field that contains the information passed to or received \r
+                                                               ///< from the adapter.\r
+}; \r
+typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/**\r
+ *  @}\r
+ */\r
+\r
+/*\r
+BOOLEAN QueryWinPcapRegistryStringA(CHAR *SubKeyName,\r
+                                                                CHAR *Value,\r
+                                                                UINT *pValueLen,\r
+                                                                CHAR *DefaultVal);\r
+\r
+BOOLEAN QueryWinPcapRegistryStringW(WCHAR *SubKeyName,\r
+                                                                WCHAR *Value,\r
+                                                                UINT *pValueLen,\r
+                                                                WCHAR *DefaultVal);\r
+*/\r
+                                                                \r
+//---------------------------------------------------------------------------\r
+// EXPORTED FUNCTIONS\r
+//---------------------------------------------------------------------------\r
+\r
+PCHAR PacketGetVersion();\r
+PCHAR PacketGetDriverVersion();\r
+BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes);\r
+BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites);\r
+BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode);\r
+BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout);\r
+BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp);\r
+BOOLEAN PacketSetLoopbackBehavior(LPADAPTER  AdapterObject, UINT LoopbackBehavior);\r
+INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen);\r
+BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s);\r
+BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s);\r
+BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim);\r
+BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type);\r
+LPADAPTER PacketOpenAdapter(PCHAR AdapterName);\r
+BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync);\r
+INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync);\r
+LPPACKET PacketAllocatePacket(void);\r
+VOID PacketInitPacket(LPPACKET lpPacket,PVOID  Buffer,UINT  Length);\r
+VOID PacketFreePacket(LPPACKET lpPacket);\r
+BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync);\r
+BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter);\r
+BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG  BufferSize);\r
+BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries);\r
+BOOLEAN PacketRequest(LPADAPTER  AdapterObject,BOOLEAN Set,PPACKET_OID_DATA  OidData);\r
+HANDLE PacketGetReadEvent(LPADAPTER AdapterObject);\r
+BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len);\r
+BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks);\r
+BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync);\r
+BOOL PacketStopDriver();\r
+VOID PacketCloseAdapter(LPADAPTER lpAdapter);\r
+BOOLEAN PacketStartOem(PCHAR errorString, UINT errorStringLength);\r
+BOOLEAN PacketStartOemEx(PCHAR errorString, UINT errorStringLength, ULONG flags);\r
+PAirpcapHandle PacketGetAirPcapHandle(LPADAPTER AdapterObject);\r
+\r
+//\r
+// Used by PacketStartOemEx\r
+//\r
+#define PACKET_START_OEM_NO_NETMON     0x00000001\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif \r
+\r
+#endif //__PACKET32\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/PacketData.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/PacketData.h
new file mode 100644 (file)
index 0000000..8124db6
--- /dev/null
@@ -0,0 +1,267 @@
+char pkt1[] = {\r
+0x00, 0x01, 0x02, 0x45, 0x09, 0x11, 0x00, 0x14,\r
+0x22, 0xcb, 0x18, 0x2d, 0x08, 0x00, 0x45, 0x00,\r
+0x00, 0x30, 0x09, 0x9c, 0x40, 0x00, 0x80, 0x06,\r
+0x6f, 0x07, 0xc0, 0xa8, 0x00, 0xc8, 0xc0, 0xa8,\r
+0x00, 0x0c, 0x0f, 0xe2, 0x00, 0x50, 0x09, 0xe7,\r
+0xc7, 0x35, 0x00, 0x00, 0x00, 0x00, 0x70, 0x02,\r
+0x40, 0x00, 0xdf, 0xab, 0x00, 0x00, 0x02, 0x04,\r
+0x05, 0xb4, 0x01, 0x01, 0x04, 0x02 };\r
+\r
+char pkt2[] = {\r
+0x00, 0x14, 0x22, 0xcb, 0x18, 0x2d, 0x00, 0x01,\r
+0x02, 0x45, 0x09, 0x11, 0x08, 0x00, 0x45, 0x00,\r
+0x00, 0x2c, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,\r
+0xf8, 0xa6, 0xc0, 0xa8, 0x00, 0x0c, 0xc0, 0xa8,\r
+0x00, 0xc8, 0x00, 0x50, 0x0f, 0xe2, 0x00, 0x00,\r
+0x06, 0x68, 0x09, 0xe7, 0xc7, 0x36, 0x60, 0x12,\r
+0x05, 0x92, 0x28, 0xca, 0x00, 0x00, 0x02, 0x04,\r
+0x05, 0x92 };\r
+\r
+char pkt3[] = {\r
+0x00, 0x01, 0x02, 0x45, 0x09, 0x11, 0x00, 0x14,\r
+0x22, 0xcb, 0x18, 0x2d, 0x08, 0x00, 0x45, 0x00,\r
+0x00, 0x28, 0x09, 0x9e, 0x40, 0x00, 0x80, 0x06,\r
+0x6f, 0x0d, 0xc0, 0xa8, 0x00, 0xc8, 0xc0, 0xa8,\r
+0x00, 0x0c, 0x0f, 0xe2, 0x00, 0x50, 0x09, 0xe7,\r
+0xc7, 0x36, 0x00, 0x00, 0x06, 0x69, 0x50, 0x10,\r
+0x42, 0xd8, 0x82, 0x3f, 0x00, 0x00 };\r
+\r
+char pkt4[] = {\r
+0x00, 0x01, 0x02, 0x45, 0x09, 0x11, 0x00, 0x14,\r
+0x22, 0xcb, 0x18, 0x2d, 0x08, 0x00, 0x45, 0x00,\r
+0x02, 0x27, 0x09, 0x9f, 0x40, 0x00, 0x80, 0x06,\r
+0x6d, 0x0d, 0xc0, 0xa8, 0x00, 0xc8, 0xc0, 0xa8,\r
+0x00, 0x0c, 0x0f, 0xe2, 0x00, 0x50, 0x09, 0xe7,\r
+0xc7, 0x36, 0x00, 0x00, 0x06, 0x69, 0x50, 0x18,\r
+0x42, 0xd8, 0x84, 0x3e, 0x00, 0x00, 0x47, 0x45,\r
+0x54, 0x20, 0x2f, 0x20, 0x48, 0x54, 0x54, 0x50,\r
+0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x41, 0x63,\r
+0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x69, 0x6d,\r
+0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0x2c,\r
+0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78,\r
+0x2d, 0x78, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70,\r
+0x2c, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f,\r
+0x6a, 0x70, 0x65, 0x67, 0x2c, 0x20, 0x69, 0x6d,\r
+0x61, 0x67, 0x65, 0x2f, 0x70, 0x6a, 0x70, 0x65,\r
+0x67, 0x2c, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69,\r
+0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76,\r
+0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x65, 0x78,\r
+0x63, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x70, 0x70,\r
+0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,\r
+0x2f, 0x6d, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x2c,\r
+0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61,\r
+0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64,\r
+0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6f, 0x77, 0x65,\r
+0x72, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2c, 0x20,\r
+0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74,\r
+0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73,\r
+0x2d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61,\r
+0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x70,\r
+0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,\r
+0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x78,\r
+0x62, 0x61, 0x70, 0x2c, 0x20, 0x61, 0x70, 0x70,\r
+0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,\r
+0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d,\r
+0x78, 0x70, 0x73, 0x64, 0x6f, 0x63, 0x75, 0x6d,\r
+0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x70, 0x70,\r
+0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,\r
+0x2f, 0x78, 0x61, 0x6d, 0x6c, 0x2b, 0x78, 0x6d,\r
+0x6c, 0x2c, 0x20, 0x2a, 0x2f, 0x2a, 0x0d, 0x0a,\r
+0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x4c,\r
+0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x3a,\r
+0x20, 0x65, 0x6e, 0x2d, 0x67, 0x62, 0x0d, 0x0a,\r
+0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x45,\r
+0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a,\r
+0x20, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x20, 0x64,\r
+0x65, 0x66, 0x6c, 0x61, 0x74, 0x65, 0x0d, 0x0a,\r
+0x55, 0x73, 0x65, 0x72, 0x2d, 0x41, 0x67, 0x65,\r
+0x6e, 0x74, 0x3a, 0x20, 0x4d, 0x6f, 0x7a, 0x69,\r
+0x6c, 0x6c, 0x61, 0x2f, 0x34, 0x2e, 0x30, 0x20,\r
+0x28, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69,\r
+0x62, 0x6c, 0x65, 0x3b, 0x20, 0x4d, 0x53, 0x49,\r
+0x45, 0x20, 0x36, 0x2e, 0x30, 0x3b, 0x20, 0x57,\r
+0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x4e,\r
+0x54, 0x20, 0x35, 0x2e, 0x31, 0x3b, 0x20, 0x53,\r
+0x56, 0x31, 0x3b, 0x20, 0x47, 0x6f, 0x6f, 0x67,\r
+0x6c, 0x65, 0x54, 0x35, 0x3b, 0x20, 0x2e, 0x4e,\r
+0x45, 0x54, 0x20, 0x43, 0x4c, 0x52, 0x20, 0x32,\r
+0x2e, 0x30, 0x2e, 0x35, 0x30, 0x37, 0x32, 0x37,\r
+0x3b, 0x20, 0x2e, 0x4e, 0x45, 0x54, 0x20, 0x43,\r
+0x4c, 0x52, 0x20, 0x33, 0x2e, 0x30, 0x2e, 0x30,\r
+0x34, 0x35, 0x30, 0x36, 0x2e, 0x36, 0x34, 0x38,\r
+0x3b, 0x20, 0x2e, 0x4e, 0x45, 0x54, 0x20, 0x43,\r
+0x4c, 0x52, 0x20, 0x33, 0x2e, 0x35, 0x2e, 0x32,\r
+0x31, 0x30, 0x32, 0x32, 0x29, 0x0d, 0x0a, 0x48,\r
+0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x39, 0x32,\r
+0x2e, 0x31, 0x36, 0x38, 0x2e, 0x30, 0x2e, 0x31,\r
+0x32, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,\r
+0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x4b,\r
+0x65, 0x65, 0x70, 0x2d, 0x41, 0x6c, 0x69, 0x76,\r
+0x65, 0x0d, 0x0a, 0x0d, 0x0a };\r
+\r
+char pkt5[] = {\r
+0x00, 0x14, 0x22, 0xcb, 0x18, 0x2d, 0x00, 0x01,\r
+0x02, 0x45, 0x09, 0x11, 0x08, 0x00, 0x45, 0x00,\r
+0x00, 0x2c, 0x00, 0x02, 0x00, 0x00, 0x40, 0x06,\r
+0xf8, 0xa5, 0xc0, 0xa8, 0x00, 0x0c, 0xc0, 0xa8,\r
+0x00, 0xc8, 0x00, 0x50, 0x0f, 0xe2, 0x00, 0x00,\r
+0x06, 0x68, 0x09, 0xe7, 0xc7, 0x36, 0x60, 0x12,\r
+0x05, 0x92, 0x28, 0xca, 0x00, 0x00, 0x02, 0x04,\r
+0x05, 0x92 };\r
+\r
+char pkt6[] = {\r
+0x00, 0x01, 0x02, 0x45, 0x09, 0x11, 0x00, 0x14,\r
+0x22, 0xcb, 0x18, 0x2d, 0x08, 0x00, 0x45, 0x00,\r
+0x00, 0x28, 0x09, 0xa1, 0x40, 0x00, 0x80, 0x06,\r
+0x6f, 0x0a, 0xc0, 0xa8, 0x00, 0xc8, 0xc0, 0xa8,\r
+0x00, 0x0c, 0x0f, 0xe2, 0x00, 0x50, 0x09, 0xe7,\r
+0xc9, 0x35, 0x00, 0x00, 0x06, 0x69, 0x50, 0x10,\r
+0x42, 0xd8, 0x82, 0x3f, 0x00, 0x00 };\r
+\r
+char pkt7[] = {\r
+0x00, 0x01, 0x02, 0x45, 0x09, 0x11, 0x00, 0x14,\r
+0x22, 0xcb, 0x18, 0x2d, 0x08, 0x00, 0x45, 0x00,\r
+0x02, 0x27, 0x09, 0xa2, 0x40, 0x00, 0x80, 0x06,\r
+0x6d, 0x0a, 0xc0, 0xa8, 0x00, 0xc8, 0xc0, 0xa8,\r
+0x00, 0x0c, 0x0f, 0xe2, 0x00, 0x50, 0x09, 0xe7,\r
+0xc7, 0x36, 0x00, 0x00, 0x06, 0x69, 0x50, 0x18,\r
+0x42, 0xd8, 0x84, 0x3e, 0x00, 0x00, 0x47, 0x45,\r
+0x54, 0x20, 0x2f, 0x20, 0x48, 0x54, 0x54, 0x50,\r
+0x2f, 0x31, 0x2e, 0x31, 0x0d, 0x0a, 0x41, 0x63,\r
+0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x69, 0x6d,\r
+0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0x2c,\r
+0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x78,\r
+0x2d, 0x78, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x70,\r
+0x2c, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f,\r
+0x6a, 0x70, 0x65, 0x67, 0x2c, 0x20, 0x69, 0x6d,\r
+0x61, 0x67, 0x65, 0x2f, 0x70, 0x6a, 0x70, 0x65,\r
+0x67, 0x2c, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69,\r
+0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76,\r
+0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d, 0x65, 0x78,\r
+0x63, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x70, 0x70,\r
+0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,\r
+0x2f, 0x6d, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x2c,\r
+0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61,\r
+0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x6e, 0x64,\r
+0x2e, 0x6d, 0x73, 0x2d, 0x70, 0x6f, 0x77, 0x65,\r
+0x72, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2c, 0x20,\r
+0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74,\r
+0x69, 0x6f, 0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73,\r
+0x2d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61,\r
+0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x70,\r
+0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,\r
+0x6e, 0x2f, 0x78, 0x2d, 0x6d, 0x73, 0x2d, 0x78,\r
+0x62, 0x61, 0x70, 0x2c, 0x20, 0x61, 0x70, 0x70,\r
+0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,\r
+0x2f, 0x76, 0x6e, 0x64, 0x2e, 0x6d, 0x73, 0x2d,\r
+0x78, 0x70, 0x73, 0x64, 0x6f, 0x63, 0x75, 0x6d,\r
+0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x70, 0x70,\r
+0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,\r
+0x2f, 0x78, 0x61, 0x6d, 0x6c, 0x2b, 0x78, 0x6d,\r
+0x6c, 0x2c, 0x20, 0x2a, 0x2f, 0x2a, 0x0d, 0x0a,\r
+0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x4c,\r
+0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x3a,\r
+0x20, 0x65, 0x6e, 0x2d, 0x67, 0x62, 0x0d, 0x0a,\r
+0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x45,\r
+0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3a,\r
+0x20, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x20, 0x64,\r
+0x65, 0x66, 0x6c, 0x61, 0x74, 0x65, 0x0d, 0x0a,\r
+0x55, 0x73, 0x65, 0x72, 0x2d, 0x41, 0x67, 0x65,\r
+0x6e, 0x74, 0x3a, 0x20, 0x4d, 0x6f, 0x7a, 0x69,\r
+0x6c, 0x6c, 0x61, 0x2f, 0x34, 0x2e, 0x30, 0x20,\r
+0x28, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69,\r
+0x62, 0x6c, 0x65, 0x3b, 0x20, 0x4d, 0x53, 0x49,\r
+0x45, 0x20, 0x36, 0x2e, 0x30, 0x3b, 0x20, 0x57,\r
+0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x4e,\r
+0x54, 0x20, 0x35, 0x2e, 0x31, 0x3b, 0x20, 0x53,\r
+0x56, 0x31, 0x3b, 0x20, 0x47, 0x6f, 0x6f, 0x67,\r
+0x6c, 0x65, 0x54, 0x35, 0x3b, 0x20, 0x2e, 0x4e,\r
+0x45, 0x54, 0x20, 0x43, 0x4c, 0x52, 0x20, 0x32,\r
+0x2e, 0x30, 0x2e, 0x35, 0x30, 0x37, 0x32, 0x37,\r
+0x3b, 0x20, 0x2e, 0x4e, 0x45, 0x54, 0x20, 0x43,\r
+0x4c, 0x52, 0x20, 0x33, 0x2e, 0x30, 0x2e, 0x30,\r
+0x34, 0x35, 0x30, 0x36, 0x2e, 0x36, 0x34, 0x38,\r
+0x3b, 0x20, 0x2e, 0x4e, 0x45, 0x54, 0x20, 0x43,\r
+0x4c, 0x52, 0x20, 0x33, 0x2e, 0x35, 0x2e, 0x32,\r
+0x31, 0x30, 0x32, 0x32, 0x29, 0x0d, 0x0a, 0x48,\r
+0x6f, 0x73, 0x74, 0x3a, 0x20, 0x31, 0x39, 0x32,\r
+0x2e, 0x31, 0x36, 0x38, 0x2e, 0x30, 0x2e, 0x31,\r
+0x32, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,\r
+0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x4b,\r
+0x65, 0x65, 0x70, 0x2d, 0x41, 0x6c, 0x69, 0x76,\r
+0x65, 0x0d, 0x0a, 0x0d, 0x0a };\r
+\r
+char pkt8[] = {\r
+0x00, 0x14, 0x22, 0xcb, 0x18, 0x2d, 0x00, 0x01,\r
+0x02, 0x45, 0x09, 0x11, 0x08, 0x00, 0x45, 0x00,\r
+0x00, 0x2c, 0x00, 0x03, 0x00, 0x00, 0x40, 0x06,\r
+0xf8, 0xa4, 0xc0, 0xa8, 0x00, 0x0c, 0xc0, 0xa8,\r
+0x00, 0xc8, 0x00, 0x50, 0x0f, 0xe2, 0x00, 0x00,\r
+0x06, 0x68, 0x09, 0xe7, 0xc7, 0x36, 0x60, 0x12,\r
+0x05, 0x92, 0x28, 0xca, 0x00, 0x00, 0x02, 0x04,\r
+0x05, 0x92 };\r
+\r
+char pkt9[] = {\r
+0x00, 0x01, 0x02, 0x45, 0x09, 0x11, 0x00, 0x14,\r
+0x22, 0xcb, 0x18, 0x2d, 0x08, 0x00, 0x45, 0x00,\r
+0x00, 0x28, 0x09, 0xa3, 0x40, 0x00, 0x80, 0x06,\r
+0x6f, 0x08, 0xc0, 0xa8, 0x00, 0xc8, 0xc0, 0xa8,\r
+0x00, 0x0c, 0x0f, 0xe2, 0x00, 0x50, 0x09, 0xe7,\r
+0xc9, 0x35, 0x00, 0x00, 0x06, 0x69, 0x50, 0x10,\r
+0x42, 0xd8, 0x82, 0x3f, 0x00, 0x00 };\r
+\r
+char pkt10[] = {\r
+0x00, 0x14, 0x22, 0xcb, 0x18, 0x2d, 0x00, 0x01,\r
+0x02, 0x45, 0x09, 0x11, 0x08, 0x00, 0x45, 0x00,\r
+0x00, 0x2c, 0x00, 0x04, 0x00, 0x00, 0x40, 0x06,\r
+0xf8, 0xa3, 0xc0, 0xa8, 0x00, 0x0c, 0xc0, 0xa8,\r
+0x00, 0xc8, 0x00, 0x50, 0x0f, 0xe2, 0x00, 0x00,\r
+0x06, 0x68, 0x09, 0xe7, 0xc7, 0x36, 0x60, 0x12,\r
+0x05, 0x92, 0x28, 0xca, 0x00, 0x00, 0x02, 0x04,\r
+0x05, 0x92 };\r
+\r
+char pkt11[] = {\r
+0x00, 0x01, 0x02, 0x45, 0x09, 0x11, 0x00, 0x14,\r
+0x22, 0xcb, 0x18, 0x2d, 0x08, 0x00, 0x45, 0x00,\r
+0x00, 0x28, 0x09, 0xa6, 0x40, 0x00, 0x80, 0x06,\r
+0x6f, 0x05, 0xc0, 0xa8, 0x00, 0xc8, 0xc0, 0xa8,\r
+0x00, 0x0c, 0x0f, 0xe2, 0x00, 0x50, 0x09, 0xe7,\r
+0xc9, 0x35, 0x00, 0x00, 0x06, 0x69, 0x50, 0x10,\r
+0x42, 0xd8, 0x82, 0x3f, 0x00, 0x00 };\r
+\r
+char pkt12[] = {\r
+0x00, 0x01, 0x02, 0x45, 0x09, 0x11, 0x00, 0x14,\r
+0x22, 0xcb, 0x18, 0x2d, 0x08, 0x00, 0x45, 0x00,\r
+0x00, 0x28, 0x09, 0xa7, 0x40, 0x00, 0x80, 0x06,\r
+0x6f, 0x04, 0xc0, 0xa8, 0x00, 0xc8, 0xc0, 0xa8,\r
+0x00, 0x0c, 0x0f, 0xe2, 0x00, 0x50, 0x09, 0xe7,\r
+0xc9, 0x35, 0x00, 0x00, 0x06, 0x69, 0x50, 0x14,\r
+0x00, 0x00, 0x43, 0xf4, 0x00, 0x00 };\r
+\r
+\r
+typedef struct\r
+{\r
+       char *pcData;\r
+       int iDataLen;\r
+} xPacketData;\r
+\r
+xPacketData xAllPackets[] =\r
+{\r
+       { pkt1, sizeof( pkt1 ) },\r
+//     { pkt2, sizeof( pkt2 ) },\r
+       { pkt3, sizeof( pkt3 ) },\r
+       { pkt4, sizeof( pkt4 ) },\r
+//     { pkt5, sizeof( pkt5 ) },\r
+       { pkt6, sizeof( pkt6 ) },\r
+       { pkt7, sizeof( pkt7 ) },\r
+       { pkt8, sizeof( pkt8 ) },\r
+       { pkt9, sizeof( pkt9 ) },\r
+       { pkt10, sizeof( pkt10 ) },\r
+//     { pkt11, sizeof( pkt11 ) },\r
+//     { pkt12, sizeof( pkt12 ) },\r
+//     { pkt13, sizeof( pkt13 ) },\r
+//     { pkt14, sizeof( pkt14 ) },\r
+//     { pkt15, sizeof( pkt15 ) },\r
+//     { pkt16, sizeof( pkt16 ) },\r
+};\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/Win32-Extensions.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/Win32-Extensions.h
new file mode 100644 (file)
index 0000000..be71c85
--- /dev/null
@@ -0,0 +1,114 @@
+/*\r
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)\r
+ * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies \r
+ * nor the names of its contributors may be used to endorse or promote \r
+ * products derived from this software without specific prior written \r
+ * permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ */\r
+\r
+\r
+#ifndef __WIN32_EXTENSIONS_H__\r
+#define __WIN32_EXTENSIONS_H__\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* Definitions */\r
+\r
+/*!\r
+  \brief A queue of raw packets that will be sent to the network with pcap_sendqueue_transmit().\r
+*/\r
+struct pcap_send_queue\r
+{\r
+       u_int maxlen;           ///< Maximum size of the the queue, in bytes. This variable contains the size of the buffer field.\r
+       u_int len;                      ///< Current size of the queue, in bytes.\r
+       char *buffer;           ///< Buffer containing the packets to be sent.\r
+};\r
+\r
+typedef struct pcap_send_queue pcap_send_queue;\r
+\r
+/*!\r
+  \brief This typedef is a support for the pcap_get_airpcap_handle() function\r
+*/\r
+#if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_)\r
+#define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_\r
+typedef struct _AirpcapHandle *PAirpcapHandle;\r
+#endif\r
+\r
+#define                BPF_MEM_EX_IMM  0xc0\r
+#define                BPF_MEM_EX_IND  0xe0\r
+\r
+/*used for ST*/\r
+#define                BPF_MEM_EX              0xc0\r
+#define                BPF_TME                                 0x08\r
+\r
+#define                BPF_LOOKUP                              0x90   \r
+#define                BPF_EXECUTE                             0xa0\r
+#define                BPF_INIT                                0xb0\r
+#define                BPF_VALIDATE                    0xc0\r
+#define                BPF_SET_ACTIVE                  0xd0\r
+#define                BPF_RESET                               0xe0\r
+#define                BPF_SET_MEMORY                  0x80\r
+#define                BPF_GET_REGISTER_VALUE  0x70\r
+#define                BPF_SET_REGISTER_VALUE  0x60\r
+#define                BPF_SET_WORKING                 0x50\r
+#define                BPF_SET_ACTIVE_READ             0x40\r
+#define                BPF_SET_AUTODELETION    0x30\r
+#define                BPF_SEPARATION                  0xff\r
+\r
+/* Prototypes */\r
+pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);\r
+\r
+void pcap_sendqueue_destroy(pcap_send_queue* queue);\r
+\r
+int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);\r
+\r
+u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync);\r
+\r
+HANDLE pcap_getevent(pcap_t *p);\r
+\r
+struct pcap_stat *pcap_stats_ex(pcap_t *p, int *pcap_stat_size);\r
+\r
+int pcap_setuserbuffer(pcap_t *p, int size);\r
+\r
+int pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks);\r
+\r
+int pcap_live_dump_ended(pcap_t *p, int sync);\r
+\r
+int pcap_offline_filter(struct bpf_program *prog, const struct pcap_pkthdr *header, const u_char *pkt_data);\r
+\r
+int pcap_start_oem(char* err_str, int flags);\r
+\r
+PAirpcapHandle pcap_get_airpcap_handle(pcap_t *p);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif //__WIN32_EXTENSIONS_H__\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/arch.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/arch.c
new file mode 100644 (file)
index 0000000..c90f030
--- /dev/null
@@ -0,0 +1,378 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\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
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/bittypes.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/bittypes.h
new file mode 100644 (file)
index 0000000..f55fcec
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 1999 WIDE Project.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _BITTYPES_H
+#define _BITTYPES_H
+
+#ifndef HAVE_U_INT8_T
+
+#if SIZEOF_CHAR == 1
+typedef unsigned char u_int8_t;
+typedef signed char _int8_t;
+#elif SIZEOF_INT == 1
+typedef unsigned int u_int8_t;
+typedef signed int int8_t;
+#else  /* XXX */
+#error "there's no appropriate type for u_int8_t"
+#endif
+#define HAVE_U_INT8_T 1
+#define HAVE_INT8_T 1
+
+#endif /* HAVE_U_INT8_T */
+
+#ifndef HAVE_U_INT16_T 
+
+#if SIZEOF_SHORT == 2
+typedef unsigned short u_int16_t;
+typedef signed short _int16_t;
+#elif SIZEOF_INT == 2
+typedef unsigned int u_int16_t;
+typedef signed int int16_t;
+#elif SIZEOF_CHAR == 2
+typedef unsigned char u_int16_t;
+typedef signed char int16_t;
+#else  /* XXX */
+#error "there's no appropriate type for u_int16_t"
+#endif
+#define HAVE_U_INT16_T 1
+#define HAVE_INT16_T 1
+
+#endif /* HAVE_U_INT16_T */
+
+#ifndef HAVE_U_INT32_T
+
+#if SIZEOF_INT == 4
+typedef unsigned int u_int32_t;
+typedef signed int _int32_t;
+#elif SIZEOF_LONG == 4
+typedef unsigned long u_int32_t;
+typedef signed long int32_t;
+#elif SIZEOF_SHORT == 4
+typedef unsigned short u_int32_t;
+typedef signed short int32_t;
+#else  /* XXX */
+#error "there's no appropriate type for u_int32_t"
+#endif
+#define HAVE_U_INT32_T 1
+#define HAVE_INT32_T 1
+
+#endif /* HAVE_U_INT32_T */
+
+#ifndef HAVE_U_INT64_T
+#if SIZEOF_LONG_LONG == 8
+typedef unsigned long long u_int64_t;
+typedef long long int64_t;
+#elif defined(_MSC_EXTENSIONS)
+typedef unsigned _int64 u_int64_t;
+typedef _int64 int64_t;
+#elif SIZEOF_INT == 8
+typedef unsigned int u_int64_t;
+#elif SIZEOF_LONG == 8
+typedef unsigned long u_int64_t;
+#elif SIZEOF_SHORT == 8
+typedef unsigned short u_int64_t;
+#else  /* XXX */
+#error "there's no appropriate type for u_int64_t"
+#endif
+
+#endif /* HAVE_U_INT64_T */
+
+#ifndef PRId64
+#ifdef _MSC_EXTENSIONS
+#define PRId64 "I64d"
+#else /* _MSC_EXTENSIONS */
+#define PRId64 "lld"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRId64 */
+
+#ifndef PRIo64
+#ifdef _MSC_EXTENSIONS
+#define PRIo64 "I64o"
+#else /* _MSC_EXTENSIONS */
+#define PRIo64 "llo"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRIo64 */
+
+#ifndef PRIx64
+#ifdef _MSC_EXTENSIONS
+#define PRIx64 "I64x"
+#else /* _MSC_EXTENSIONS */
+#define PRIx64 "llx"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRIx64 */
+
+#ifndef PRIu64
+#ifdef _MSC_EXTENSIONS
+#define PRIu64 "I64u"
+#else /* _MSC_EXTENSIONS */
+#define PRIu64 "llu"
+#endif /* _MSC_EXTENSIONS */
+#endif /* PRIu64 */
+
+#endif /* _BITTYPES_H */
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/ip6_misc.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/ip6_misc.h
new file mode 100644 (file)
index 0000000..562fa61
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 1993, 1994, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/Win32/Include/ip6_misc.h,v 1.5 2006-01-22 18:02:18 gianluca Exp $ (LBL)
+ */
+
+/*
+ * This file contains a collage of declarations for IPv6 from FreeBSD not present in Windows
+ */
+
+#include <winsock2.h>
+
+#include <ws2tcpip.h>
+
+#ifndef __MINGW32__
+#define        IN_MULTICAST(a)         IN_CLASSD(a)
+#endif
+
+#define        IN_EXPERIMENTAL(a)      ((((u_int32_t) (a)) & 0xf0000000) == 0xf0000000)
+
+#define        IN_LOOPBACKNET          127
+
+#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+/* IPv6 address */
+struct in6_addr
+  {
+    union
+      {
+       u_int8_t                u6_addr8[16];
+       u_int16_t       u6_addr16[8];
+       u_int32_t       u6_addr32[4];
+      } in6_u;
+#define s6_addr                        in6_u.u6_addr8
+#define s6_addr16              in6_u.u6_addr16
+#define s6_addr32              in6_u.u6_addr32
+#define s6_addr64              in6_u.u6_addr64
+  };
+
+#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
+#endif /* __MINGW32__ */
+
+
+#if (defined _MSC_VER) || (defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF))
+typedef unsigned short sa_family_t;
+#endif
+
+
+#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+
+#define        __SOCKADDR_COMMON(sa_prefix) \
+  sa_family_t sa_prefix##family
+
+/* Ditto, for IPv6.  */
+struct sockaddr_in6
+  {
+    __SOCKADDR_COMMON (sin6_);
+    u_int16_t sin6_port;               /* Transport layer port # */
+    u_int32_t sin6_flowinfo;   /* IPv6 flow information */
+    struct in6_addr sin6_addr; /* IPv6 address */
+  };
+
+#define IN6_IS_ADDR_V4MAPPED(a) \
+       ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
+        (((u_int32_t *) (a))[2] == htonl (0xffff)))
+
+#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff)
+
+#define IN6_IS_ADDR_LINKLOCAL(a) \
+       ((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000))
+
+#define IN6_IS_ADDR_LOOPBACK(a) \
+       (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \
+        ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1))
+#endif /* __MINGW32__ */
+
+#define ip6_vfc   ip6_ctlun.ip6_un2_vfc
+#define ip6_flow  ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen  ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt   ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim  ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops  ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+#define nd_rd_type               nd_rd_hdr.icmp6_type
+#define nd_rd_code               nd_rd_hdr.icmp6_code
+#define nd_rd_cksum              nd_rd_hdr.icmp6_cksum
+#define nd_rd_reserved           nd_rd_hdr.icmp6_data32[0]
+
+/*
+ *     IPV6 extension headers
+ */
+#define IPPROTO_HOPOPTS                0       /* IPv6 hop-by-hop options      */
+#define IPPROTO_IPV6           41  /* IPv6 header.  */
+#define IPPROTO_ROUTING                43      /* IPv6 routing header          */
+#define IPPROTO_FRAGMENT       44      /* IPv6 fragmentation header    */
+#define IPPROTO_ESP            50      /* encapsulating security payload */
+#define IPPROTO_AH             51      /* authentication header        */
+#define IPPROTO_ICMPV6         58      /* ICMPv6                       */
+#define IPPROTO_NONE           59      /* IPv6 no next header          */
+#define IPPROTO_DSTOPTS                60      /* IPv6 destination options     */
+#define IPPROTO_PIM                    103 /* Protocol Independent Multicast.  */
+
+#define         IPV6_RTHDR_TYPE_0 0
+
+/* Option types and related macros */
+#define IP6OPT_PAD1            0x00    /* 00 0 00000 */
+#define IP6OPT_PADN            0x01    /* 00 0 00001 */
+#define IP6OPT_JUMBO           0xC2    /* 11 0 00010 = 194 */
+#define IP6OPT_JUMBO_LEN       6
+#define IP6OPT_ROUTER_ALERT    0x05    /* 00 0 00101 */
+
+#define IP6OPT_RTALERT_LEN     4
+#define IP6OPT_RTALERT_MLD     0       /* Datagram contains an MLD message */
+#define IP6OPT_RTALERT_RSVP    1       /* Datagram contains an RSVP message */
+#define IP6OPT_RTALERT_ACTNET  2       /* contains an Active Networks msg */
+#define IP6OPT_MINLEN          2
+
+#define IP6OPT_BINDING_UPDATE  0xc6    /* 11 0 00110 */
+#define IP6OPT_BINDING_ACK     0x07    /* 00 0 00111 */
+#define IP6OPT_BINDING_REQ     0x08    /* 00 0 01000 */
+#define IP6OPT_HOME_ADDRESS    0xc9    /* 11 0 01001 */
+#define IP6OPT_EID             0x8a    /* 10 0 01010 */
+
+#define IP6OPT_TYPE(o)         ((o) & 0xC0)
+#define IP6OPT_TYPE_SKIP       0x00
+#define IP6OPT_TYPE_DISCARD    0x40
+#define IP6OPT_TYPE_FORCEICMP  0x80
+#define IP6OPT_TYPE_ICMP       0xC0
+
+#define IP6OPT_MUTABLE         0x20
+
+
+#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+#ifndef EAI_ADDRFAMILY
+struct addrinfo {
+       int     ai_flags;       /* AI_PASSIVE, AI_CANONNAME */
+       int     ai_family;      /* PF_xxx */
+       int     ai_socktype;    /* SOCK_xxx */
+       int     ai_protocol;    /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+       size_t  ai_addrlen;     /* length of ai_addr */
+       char    *ai_canonname;  /* canonical name for hostname */
+       struct sockaddr *ai_addr;       /* binary address */
+       struct addrinfo *ai_next;       /* next structure in linked list */
+};
+#endif
+#endif /* __MINGW32__ */
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/netif.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/netif.h
new file mode 100644 (file)
index 0000000..6982ca0
--- /dev/null
@@ -0,0 +1,94 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+\r
+#ifndef NET_IF_H\r
+#define NET_IF_H\r
+\r
+/*\r
+ * Send uip_len bytes from uip_buf to the network interface selected by the \r
+ * configNETWORK_INTERFACE_TO_USE constant (defined in FreeRTOSConfig.h). \r
+ */\r
+void vNetifTx( void );\r
+\r
+/*\r
+ * Receive bytes from the network interface selected by the \r
+ * configNETWORK_INTERFACE_TO_USE constant (defined in FreeRTOSConfig.h).  The\r
+ * bytes are placed in uip_buf.  The number of bytes copied into uip_buf is\r
+ * returned.\r
+ */\r
+UBaseType_t uxNetifRx( void );\r
+\r
+/*\r
+ * Prepare a packet capture session.  This will print out all the network \r
+ * interfaces available, and the one actually used is set by the \r
+ * configNETWORK_INTERFACE_TO_USE constant that is defined in \r
+ * FreeRTOSConfig.h. */\r
+BaseType_t xNetifInit( void );\r
+\r
+#endif /* NET_IF_H */\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap-bpf.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap-bpf.h
new file mode 100644 (file)
index 0000000..5fe129d
--- /dev/null
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.50 2007/04/01 21:43:55 guy Exp $ (LBL)
+ */
+
+/*
+ * For backwards compatibility.
+ *
+ * Note to OS vendors: do NOT get rid of this file!  Some applications
+ * might expect to be able to include <pcap-bpf.h>.
+ */
+#include <pcap/bpf.h>
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap-namedb.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap-namedb.h
new file mode 100644 (file)
index 0000000..80a2f00
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1994, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.13 2006/10/04 18:13:32 guy Exp $ (LBL)
+ */
+
+/*
+ * For backwards compatibility.
+ *
+ * Note to OS vendors: do NOT get rid of this file!  Some applications
+ * might expect to be able to include <pcap-namedb.h>.
+ */
+#include <pcap/namedb.h>
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap-stdinc.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap-stdinc.h
new file mode 100644 (file)
index 0000000..cbd62d1
--- /dev/null
@@ -0,0 +1,93 @@
+/*\r
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)\r
+ * Copyright (c) 2005 - 2009 CACE Technologies, Inc. Davis (California)\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ * notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ * notice, this list of conditions and the following disclaimer in the\r
+ * documentation and/or other materials provided with the distribution.\r
+ * 3. Neither the name of the Politecnico di Torino nor the names of its\r
+ * contributors may be used to endorse or promote products derived from\r
+ * this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-stdinc.h,v 1.10.2.1 2008-10-06 15:38:39 gianluca Exp $ (LBL)\r
+ */\r
+\r
+#define SIZEOF_CHAR 1\r
+#define SIZEOF_SHORT 2\r
+#define SIZEOF_INT 4\r
+#ifndef _MSC_EXTENSIONS\r
+#define SIZEOF_LONG_LONG 8\r
+#endif\r
+\r
+/*\r
+ * Avoids a compiler warning in case this was already defined      \r
+ * (someone defined _WINSOCKAPI_ when including 'windows.h', in order\r
+ * to prevent it from including 'winsock.h')\r
+ */\r
+#ifdef _WINSOCKAPI_\r
+#undef _WINSOCKAPI_\r
+#endif\r
+#include <winsock2.h>\r
+\r
+#include <fcntl.h>\r
+\r
+#include "bittypes.h"\r
+#include <time.h>\r
+#include <io.h>\r
+\r
+#ifndef __MINGW32__\r
+#include "IP6_misc.h"\r
+#endif\r
+\r
+#define caddr_t char*\r
+\r
+#if _MSC_VER < 1500\r
+#define snprintf _snprintf\r
+#define vsnprintf _vsnprintf\r
+#define strdup _strdup\r
+#endif\r
+\r
+#define inline __inline \r
+\r
+#ifdef __MINGW32__\r
+#include <stdint.h>\r
+#else /*__MINGW32__*/\r
+/* MSVC compiler */\r
+#ifndef _UINTPTR_T_DEFINED\r
+#ifdef  _WIN64\r
+typedef unsigned __int64    uintptr_t;\r
+#else\r
+typedef _W64 unsigned int   uintptr_t;\r
+#endif\r
+#define _UINTPTR_T_DEFINED\r
+#endif\r
+\r
+#ifndef _INTPTR_T_DEFINED\r
+#ifdef  _WIN64\r
+typedef __int64    intptr_t;\r
+#else\r
+typedef _W64 int   intptr_t;\r
+#endif\r
+#define _INTPTR_T_DEFINED\r
+#endif \r
+\r
+#endif /*__MINGW32__*/\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap.h
new file mode 100644 (file)
index 0000000..935f949
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.59 2006/10/04 18:09:22 guy Exp $ (LBL)
+ */
+
+/*
+ * For backwards compatibility.
+ *
+ * Note to OS vendors: do NOT get rid of this file!  Many applications
+ * expect to be able to include <pcap.h>, and at least some of them
+ * go through contortions in their configure scripts to try to detect
+ * OSes that have "helpfully" moved pcap.h to <pcap/pcap.h> without
+ * leaving behind a <pcap.h> file.
+ */
+#include <pcap/pcap.h>
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/bluetooth.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/bluetooth.h
new file mode 100644 (file)
index 0000000..7bf65df
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * bluetooth data struct
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/bluetooth.h,v 1.1 2007/09/22 02:10:17 guy Exp $
+ */
+#ifndef _PCAP_BLUETOOTH_STRUCTS_H__
+#define _PCAP_BLUETOOTH_STRUCTS_H__
+
+/*
+ * Header prepended libpcap to each bluetooth h:4 frame.
+ * fields are in network byte order
+ */
+typedef struct _pcap_bluetooth_h4_header {
+       u_int32_t direction; /* if first bit is set direction is incoming */
+} pcap_bluetooth_h4_header;
+
+
+#endif
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/bpf.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/bpf.h
new file mode 100644 (file)
index 0000000..9f4ca33
--- /dev/null
@@ -0,0 +1,934 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      @(#)bpf.h       7.1 (Berkeley) 5/7/91
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.19.2.8 2008-09-22 20:16:01 guy Exp $ (LBL)
+ */
+
+/*
+ * This is libpcap's cut-down version of bpf.h; it includes only
+ * the stuff needed for the code generator and the userland BPF
+ * interpreter, and the libpcap APIs for setting filters, etc..
+ *
+ * "pcap-bpf.c" will include the native OS version, as it deals with
+ * the OS's BPF implementation.
+ *
+ * XXX - should this all just be moved to "pcap.h"?
+ */
+
+#ifndef BPF_MAJOR_VERSION
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+#ifdef MSDOS /* must be 32-bit */
+typedef long          bpf_int32;
+typedef unsigned long bpf_u_int32;
+#else
+typedef        int bpf_int32;
+typedef        u_int bpf_u_int32;
+#endif
+
+/*
+ * Alignment macros.  BPF_WORDALIGN rounds up to the next 
+ * even multiple of BPF_ALIGNMENT. 
+ */
+#ifndef __NetBSD__
+#define BPF_ALIGNMENT sizeof(bpf_int32)
+#else
+#define BPF_ALIGNMENT sizeof(long)
+#endif
+#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
+
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+/*
+ * Structure for "pcap_compile()", "pcap_setfilter()", etc..
+ */
+struct bpf_program {
+       u_int bf_len;
+       struct bpf_insn *bf_insns;
+};
+/*
+ * Struct return by BIOCVERSION.  This represents the version number of 
+ * the filter language described by the instruction encodings below.
+ * bpf understands a program iff kernel_major == filter_major &&
+ * kernel_minor >= filter_minor, that is, if the value returned by the
+ * running kernel has the same major number and a minor number equal
+ * equal to or less than the filter being downloaded.  Otherwise, the
+ * results are undefined, meaning an error may be returned or packets
+ * may be accepted haphazardly.
+ * It has nothing to do with the source code version.
+ */
+struct bpf_version {
+       u_short bv_major;
+       u_short bv_minor;
+};
+/* Current version number of filter architecture. */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+/*
+ * Data-link level type codes.
+ *
+ * Do *NOT* add new values to this list without asking
+ * "tcpdump-workers@lists.tcpdump.org" for a value.  Otherwise, you run
+ * the risk of using a value that's already being used for some other
+ * purpose, and of having tools that read libpcap-format captures not
+ * being able to handle captures with your new DLT_ value, with no hope
+ * that they will ever be changed to do so (as that would destroy their
+ * ability to read captures using that value for that other purpose).
+ */
+
+/*
+ * These are the types that are the same on all platforms, and that
+ * have been defined by <net/bpf.h> for ages.
+ */
+#define DLT_NULL       0       /* BSD loopback encapsulation */
+#define DLT_EN10MB     1       /* Ethernet (10Mb) */
+#define DLT_EN3MB      2       /* Experimental Ethernet (3Mb) */
+#define DLT_AX25       3       /* Amateur Radio AX.25 */
+#define DLT_PRONET     4       /* Proteon ProNET Token Ring */
+#define DLT_CHAOS      5       /* Chaos */
+#define DLT_IEEE802    6       /* 802.5 Token Ring */
+#define DLT_ARCNET     7       /* ARCNET, with BSD-style header */
+#define DLT_SLIP       8       /* Serial Line IP */
+#define DLT_PPP                9       /* Point-to-point Protocol */
+#define DLT_FDDI       10      /* FDDI */
+
+/*
+ * These are types that are different on some platforms, and that
+ * have been defined by <net/bpf.h> for ages.  We use #ifdefs to
+ * detect the BSDs that define them differently from the traditional
+ * libpcap <net/bpf.h>
+ *
+ * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
+ * but I don't know what the right #define is for BSD/OS.
+ */
+#define DLT_ATM_RFC1483        11      /* LLC-encapsulated ATM */
+
+#ifdef __OpenBSD__
+#define DLT_RAW                14      /* raw IP */
+#else
+#define DLT_RAW                12      /* raw IP */
+#endif
+
+/*
+ * Given that the only OS that currently generates BSD/OS SLIP or PPP
+ * is, well, BSD/OS, arguably everybody should have chosen its values
+ * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
+ * didn't.  So it goes.
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#ifndef DLT_SLIP_BSDOS
+#define DLT_SLIP_BSDOS 13      /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS  14      /* BSD/OS Point-to-point Protocol */
+#endif
+#else
+#define DLT_SLIP_BSDOS 15      /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS  16      /* BSD/OS Point-to-point Protocol */
+#endif
+
+/*
+ * 17 is used for DLT_OLD_PFLOG in OpenBSD;
+ *     OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below.
+ * 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else.
+ */
+
+#define DLT_ATM_CLIP   19      /* Linux Classical-IP over ATM */
+
+/*
+ * Apparently Redback uses this for its SmartEdge 400/800.  I hope
+ * nobody else decided to use it, too.
+ */
+#define DLT_REDBACK_SMARTEDGE  32
+
+/*
+ * These values are defined by NetBSD; other platforms should refrain from
+ * using them for other purposes, so that NetBSD savefiles with link
+ * types of 50 or 51 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50      /* PPP over serial with HDLC encapsulation */
+#define DLT_PPP_ETHER  51      /* PPP over Ethernet */
+
+/*
+ * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
+ * a link-layer type of 99 for the tcpdump it supplies.  The link-layer
+ * header has 6 bytes of unknown data, something that appears to be an
+ * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
+ * I've seen.
+ */
+#define DLT_SYMANTEC_FIREWALL  99
+
+/*
+ * Values between 100 and 103 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC     104     /* Cisco HDLC */
+#define DLT_CHDLC      DLT_C_HDLC
+
+#define DLT_IEEE802_11 105     /* IEEE 802.11 wireless */
+
+/*
+ * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
+ * except when it isn't.  (I.e., sometimes it's just raw IP, and
+ * sometimes it isn't.)  We currently handle it as DLT_LINUX_SLL,
+ * so that we don't have to worry about the link-layer header.)
+ */
+
+/*
+ * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
+ * with other values.
+ * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
+ * (DLCI, etc.).
+ */
+#define DLT_FRELAY     107
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
+ * we don't use 12 for it in OSes other than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_LOOP       12
+#else
+#define DLT_LOOP       108
+#endif
+
+/*
+ * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
+ * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
+ * than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_ENC                13
+#else
+#define DLT_ENC                109
+#endif
+
+/*
+ * Values between 110 and 112 are reserved for use in capture file headers
+ * as link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ types
+ * other than the corresponding DLT_ types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL  113
+
+/*
+ * Apple LocalTalk hardware.
+ */
+#define DLT_LTALK      114
+
+/*
+ * Acorn Econet.
+ */
+#define DLT_ECONET     115
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define DLT_IPFILTER   116
+
+/*
+ * OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023
+ * in SuSE 6.3, so we can't use 17 for it in capture-file headers.
+ *
+ * XXX: is there a conflict with DLT_PFSYNC 18 as well?
+ */
+#ifdef __OpenBSD__
+#define DLT_OLD_PFLOG  17
+#define DLT_PFSYNC     18
+#endif
+#define DLT_PFLOG      117
+
+/*
+ * Registered for Cisco-internal use.
+ */
+#define DLT_CISCO_IOS  118
+
+/*
+ * For 802.11 cards using the Prism II chips, with a link-layer
+ * header including Prism monitor mode information plus an 802.11
+ * header.
+ */
+#define DLT_PRISM_HEADER       119
+
+/*
+ * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
+ * (see Doug Ambrisko's FreeBSD patches).
+ */
+#define DLT_AIRONET_HEADER     120
+
+/*
+ * Reserved for Siemens HiPath HDLC.
+ */
+#define DLT_HHDLC              121
+
+/*
+ * This is for RFC 2625 IP-over-Fibre Channel.
+ *
+ * This is not for use with raw Fibre Channel, where the link-layer
+ * header starts with a Fibre Channel frame header; it's for IP-over-FC,
+ * where the link-layer header starts with an RFC 2625 Network_Header
+ * field.
+ */
+#define DLT_IP_OVER_FC         122
+
+/*
+ * This is for Full Frontal ATM on Solaris with SunATM, with a
+ * pseudo-header followed by an AALn PDU.
+ *
+ * There may be other forms of Full Frontal ATM on other OSes,
+ * with different pseudo-headers.
+ *
+ * If ATM software returns a pseudo-header with VPI/VCI information
+ * (and, ideally, packet type information, e.g. signalling, ILMI,
+ * LANE, LLC-multiplexed traffic, etc.), it should not use
+ * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
+ * and the like don't have to infer the presence or absence of a
+ * pseudo-header and the form of the pseudo-header.
+ */
+#define DLT_SUNATM             123     /* Solaris+SunATM */
+
+/* 
+ * Reserved as per request from Kent Dahlgren <kent@praesum.com>
+ * for private use.
+ */
+#define DLT_RIO                 124     /* RapidIO */
+#define DLT_PCI_EXP             125     /* PCI Express */
+#define DLT_AURORA              126     /* Xilinx Aurora link layer */
+
+/*
+ * Header for 802.11 plus a number of bits of link-layer information
+ * including radio information, used by some recent BSD drivers as
+ * well as the madwifi Atheros driver for Linux.
+ */
+#define DLT_IEEE802_11_RADIO   127     /* 802.11 plus radiotap radio header */
+
+/*
+ * Reserved for the TZSP encapsulation, as per request from
+ * Chris Waters <chris.waters@networkchemistry.com>
+ * TZSP is a generic encapsulation for any other link type,
+ * which includes a means to include meta-information
+ * with the packet, e.g. signal strength and channel
+ * for 802.11 packets.
+ */
+#define DLT_TZSP                128     /* Tazmen Sniffer Protocol */
+
+/*
+ * BSD's ARCNET headers have the source host, destination host,
+ * and type at the beginning of the packet; that's what's handed
+ * up to userland via BPF.
+ *
+ * Linux's ARCNET headers, however, have a 2-byte offset field
+ * between the host IDs and the type; that's what's handed up
+ * to userland via PF_PACKET sockets.
+ *
+ * We therefore have to have separate DLT_ values for them.
+ */
+#define DLT_ARCNET_LINUX       129     /* ARCNET */
+
+/*
+ * Juniper-private data link types, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MLPPP       130
+#define DLT_JUNIPER_MLFR        131
+#define DLT_JUNIPER_ES          132
+#define DLT_JUNIPER_GGSN        133
+#define DLT_JUNIPER_MFR         134
+#define DLT_JUNIPER_ATM2        135
+#define DLT_JUNIPER_SERVICES    136
+#define DLT_JUNIPER_ATM1        137
+
+/*
+ * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
+ * <dieter@apple.com>.  The header that's presented is an Ethernet-like
+ * header:
+ *
+ *     #define FIREWIRE_EUI64_LEN      8
+ *     struct firewire_header {
+ *             u_char  firewire_dhost[FIREWIRE_EUI64_LEN];
+ *             u_char  firewire_shost[FIREWIRE_EUI64_LEN];
+ *             u_short firewire_type;
+ *     };
+ *
+ * with "firewire_type" being an Ethernet type value, rather than,
+ * for example, raw GASP frames being handed up.
+ */
+#define DLT_APPLE_IP_OVER_IEEE1394     138
+
+/*
+ * Various SS7 encapsulations, as per a request from Jeff Morriss
+ * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
+ */
+#define DLT_MTP2_WITH_PHDR     139     /* pseudo-header with various info, followed by MTP2 */
+#define DLT_MTP2               140     /* MTP2, without pseudo-header */
+#define DLT_MTP3               141     /* MTP3, without pseudo-header or MTP2 */
+#define DLT_SCCP               142     /* SCCP, without pseudo-header or MTP2 or MTP3 */
+
+/*
+ * DOCSIS MAC frames.
+ */
+#define DLT_DOCSIS             143
+
+/*
+ * Linux-IrDA packets. Protocol defined at http://www.irda.org.
+ * Those packets include IrLAP headers and above (IrLMP...), but
+ * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
+ * framing can be handled by the hardware and depend on the bitrate.
+ * This is exactly the format you would get capturing on a Linux-IrDA
+ * interface (irdaX), but not on a raw serial port.
+ * Note the capture is done in "Linux-cooked" mode, so each packet include
+ * a fake packet header (struct sll_header). This is because IrDA packet
+ * decoding is dependant on the direction of the packet (incomming or
+ * outgoing).
+ * When/if other platform implement IrDA capture, we may revisit the
+ * issue and define a real DLT_IRDA...
+ * Jean II
+ */
+#define DLT_LINUX_IRDA         144
+
+/*
+ * Reserved for IBM SP switch and IBM Next Federation switch.
+ */
+#define DLT_IBM_SP             145
+#define DLT_IBM_SN             146
+
+/*
+ * Reserved for private use.  If you have some link-layer header type
+ * that you want to use within your organization, with the capture files
+ * using that link-layer header type not ever be sent outside your
+ * organization, you can use these values.
+ *
+ * No libpcap release will use these for any purpose, nor will any
+ * tcpdump release use them, either.
+ *
+ * Do *NOT* use these in capture files that you expect anybody not using
+ * your private versions of capture-file-reading tools to read; in
+ * particular, do *NOT* use them in products, otherwise you may find that
+ * people won't be able to use tcpdump, or snort, or Ethereal, or... to
+ * read capture files from your firewall/intrusion detection/traffic
+ * monitoring/etc. appliance, or whatever product uses that DLT_ value,
+ * and you may also find that the developers of those applications will
+ * not accept patches to let them read those files.
+ *
+ * Also, do not use them if somebody might send you a capture using them
+ * for *their* private type and tools using them for *your* private type
+ * would have to read them.
+ *
+ * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value,
+ * as per the comment above, and use the type you're given.
+ */
+#define DLT_USER0              147
+#define DLT_USER1              148
+#define DLT_USER2              149
+#define DLT_USER3              150
+#define DLT_USER4              151
+#define DLT_USER5              152
+#define DLT_USER6              153
+#define DLT_USER7              154
+#define DLT_USER8              155
+#define DLT_USER9              156
+#define DLT_USER10             157
+#define DLT_USER11             158
+#define DLT_USER12             159
+#define DLT_USER13             160
+#define DLT_USER14             161
+#define DLT_USER15             162
+
+/*
+ * For future use with 802.11 captures - defined by AbsoluteValue
+ * Systems to store a number of bits of link-layer information
+ * including radio information:
+ *
+ *     http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ *
+ * but it might be used by some non-AVS drivers now or in the
+ * future.
+ */
+#define DLT_IEEE802_11_RADIO_AVS 163   /* 802.11 plus AVS radio header */
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MONITOR     164
+
+/*
+ * Reserved for BACnet MS/TP.
+ */
+#define DLT_BACNET_MS_TP       165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define DLT_PPP_PPPD           166
+
+/*
+ * Names for backwards compatibility with older versions of some PPP
+ * software; new software should use DLT_PPP_PPPD.
+ */
+#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
+#define DLT_LINUX_PPP_WITHDIRECTION    DLT_PPP_PPPD
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define DLT_JUNIPER_PPPOE       167
+#define DLT_JUNIPER_PPPOE_ATM   168
+
+#define DLT_GPRS_LLC           169     /* GPRS LLC */
+#define DLT_GPF_T              170     /* GPF-T (ITU-T G.7041/Y.1303) */
+#define DLT_GPF_F              171     /* GPF-F (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define DLT_GCOM_T1E1          172
+#define DLT_GCOM_SERIAL                173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.  The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define DLT_JUNIPER_PIC_PEER    174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems.  They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define DLT_ERF_ETH            175     /* Ethernet */
+#define DLT_ERF_POS            176     /* Packet-over-SONET */
+
+/*
+ * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
+ * for vISDN (http://www.orlandi.com/visdn/).  Its link-layer header
+ * includes additional information before the LAPD header, so it's
+ * not necessarily a generic LAPD header.
+ */
+#define DLT_LINUX_LAPD         177
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The DLT_ are used for prepending meta-information
+ * like interface index, interface name
+ * before standard Ethernet, PPP, Frelay & C-HDLC Frames
+ */
+#define DLT_JUNIPER_ETHER       178
+#define DLT_JUNIPER_PPP         179
+#define DLT_JUNIPER_FRELAY      180
+#define DLT_JUNIPER_CHDLC       181
+
+/*
+ * Multi Link Frame Relay (FRF.16)
+ */
+#define DLT_MFR                 182
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The DLT_ is used for internal communication with a
+ * voice Adapter Card (PIC)
+ */
+#define DLT_JUNIPER_VP          183
+
+/*
+ * Arinc 429 frames.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Every frame contains a 32bit A429 label.
+ * More documentation on Arinc 429 can be found at
+ * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ */
+#define DLT_A429                184
+
+/*
+ * Arinc 653 Interpartition Communication messages.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Please refer to the A653-1 standard for more information.
+ */
+#define DLT_A653_ICM            185
+
+/*
+ * USB packets, beginning with a USB setup header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define DLT_USB                        186
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4); requested by
+ * Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4   187
+
+/*
+ * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
+ * <cruz_petagay@bah.com>.
+ */
+#define DLT_IEEE802_16_MAC_CPS 188
+
+/*
+ * USB packets, beginning with a Linux USB header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define DLT_USB_LINUX          189
+
+/*
+ * Controller Area Network (CAN) v. 2.0B packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Used to dump CAN packets coming from a CAN Vector board.
+ * More documentation on the CAN v2.0B frames can be found at
+ * http://www.can-cia.org/downloads/?269
+ */
+#define DLT_CAN20B              190
+
+/*
+ * IEEE 802.15.4, with address fields padded, as is done by Linux
+ * drivers; requested by Juergen Schimmer.
+ */
+#define DLT_IEEE802_15_4_LINUX 191
+
+/*
+ * Per Packet Information encapsulated packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ */
+#define DLT_PPI                        192
+
+/*
+ * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
+ * requested by Charles Clancy.
+ */
+#define DLT_IEEE802_16_MAC_CPS_RADIO   193
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The DLT_ is used for internal communication with a
+ * integrated service module (ISM).
+ */
+#define DLT_JUNIPER_ISM         194
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
+ */
+#define DLT_IEEE802_15_4       195
+
+/*
+ * Various link-layer types, with a pseudo-header, for SITA
+ * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
+ */
+#define DLT_SITA               196
+
+/*
+ * Various link-layer types, with a pseudo-header, for Endace DAG cards;
+ * encapsulates Endace ERF records.  Requested by Stephen Donnelly
+ * <stephen@endace.com>.
+ */
+#define DLT_ERF                        197
+
+/*
+ * Special header prepended to Ethernet packets when capturing from a
+ * u10 Networks board.  Requested by Phil Mulholland
+ * <phil@u10networks.com>.
+ */
+#define DLT_RAIF1              198
+
+/*
+ * IPMB packet for IPMI, beginning with the I2C slave address, followed
+ * by the netFn and LUN, etc..  Requested by Chanthy Toeung
+ * <chanthy.toeung@ca.kontron.com>.
+ */
+#define DLT_IPMB               199
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. 
+ * The DLT_ is used for capturing data on a secure tunnel interface.
+ */
+#define DLT_JUNIPER_ST          200
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
+ * that includes direction information; requested by Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
+
+/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ *     http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
+ */
+#define DLT_AX25_KISS          202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <varunax@gmail.com>.
+ */
+#define DLT_LAPD               203
+
+/*
+ * Variants of various link-layer headers, with a one-byte direction
+ * pseudo-header prepended - zero means "received by this host",
+ * non-zero (any non-zero value) means "sent by this host" - as per
+ * Will Barker <w.barker@zen.co.uk>.
+ */
+#define DLT_PPP_WITH_DIR       204     /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
+#define DLT_C_HDLC_WITH_DIR    205     /* Cisco HDLC */
+#define DLT_FRELAY_WITH_DIR    206     /* Frame Relay */
+#define DLT_LAPB_WITH_DIR      207     /* LAPB */
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ * <avn@pigeonpoint.com>.
+ */
+#define DLT_IPMB_LINUX         209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_FLEXRAY            210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_MOST               211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ * <hannes.kaelber@x2e.de>.
+ */
+#define DLT_LIN                        212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_SERIAL         213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_XORAYA         214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <jcmvbkbc@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NONASK_PHY    215
+
+
+/*
+ * DLT and savefile link type values are split into a class and
+ * a member of that class.  A class value of 0 indicates a regular
+ * DLT_/LINKTYPE_ value.
+ */
+#define DLT_CLASS(x)           ((x) & 0x03ff0000)
+
+/*
+ * NetBSD-specific generic "raw" link type.  The class value indicates
+ * that this is the generic raw type, and the lower 16 bits are the
+ * address family we're dealing with.  Those values are NetBSD-specific;
+ * do not assume that they correspond to AF_ values for your operating
+ * system.
+ */
+#define        DLT_CLASS_NETBSD_RAWAF  0x02240000
+#define        DLT_NETBSD_RAWAF(af)    (DLT_CLASS_NETBSD_RAWAF | (af))
+#define        DLT_NETBSD_RAWAF_AF(x)  ((x) & 0x0000ffff)
+#define        DLT_IS_NETBSD_RAWAF(x)  (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
+
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define                BPF_LD          0x00
+#define                BPF_LDX         0x01
+#define                BPF_ST          0x02
+#define                BPF_STX         0x03
+#define                BPF_ALU         0x04
+#define                BPF_JMP         0x05
+#define                BPF_RET         0x06
+#define                BPF_MISC        0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define                BPF_W           0x00
+#define                BPF_H           0x08
+#define                BPF_B           0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define                BPF_IMM         0x00
+#define                BPF_ABS         0x20
+#define                BPF_IND         0x40
+#define                BPF_MEM         0x60
+#define                BPF_LEN         0x80
+#define                BPF_MSH         0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code)   ((code) & 0xf0)
+#define                BPF_ADD         0x00
+#define                BPF_SUB         0x10
+#define                BPF_MUL         0x20
+#define                BPF_DIV         0x30
+#define                BPF_OR          0x40
+#define                BPF_AND         0x50
+#define                BPF_LSH         0x60
+#define                BPF_RSH         0x70
+#define                BPF_NEG         0x80
+#define                BPF_JA          0x00
+#define                BPF_JEQ         0x10
+#define                BPF_JGT         0x20
+#define                BPF_JGE         0x30
+#define                BPF_JSET        0x40
+#define BPF_SRC(code)  ((code) & 0x08)
+#define                BPF_K           0x00
+#define                BPF_X           0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define                BPF_A           0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define                BPF_TAX         0x00
+#define                BPF_TXA         0x80
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+       u_short code;
+       u_char  jt;
+       u_char  jf;
+       bpf_u_int32 k;
+};
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+#if __STDC__ || defined(__cplusplus)
+extern int bpf_validate(const struct bpf_insn *, int);
+extern u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+#else
+extern int bpf_validate();
+extern u_int bpf_filter();
+#endif
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/namedb.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/namedb.h
new file mode 100644 (file)
index 0000000..9002c75
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1994, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/namedb.h,v 1.1 2006/10/04 18:09:22 guy Exp $ (LBL)
+ */
+
+#ifndef lib_pcap_namedb_h
+#define lib_pcap_namedb_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * As returned by the pcap_next_etherent()
+ * XXX this stuff doesn't belong in this interface, but this
+ * library already must do name to address translation, so
+ * on systems that don't have support for /etc/ethers, we
+ * export these hooks since they'll
+ */
+struct pcap_etherent {
+       u_char addr[6];
+       char name[122];
+};
+#ifndef PCAP_ETHERS_FILE
+#define PCAP_ETHERS_FILE "/etc/ethers"
+#endif
+struct pcap_etherent *pcap_next_etherent(FILE *);
+u_char *pcap_ether_hostton(const char*);
+u_char *pcap_ether_aton(const char *);
+
+bpf_u_int32 **pcap_nametoaddr(const char *);
+#ifdef INET6
+struct addrinfo *pcap_nametoaddrinfo(const char *);
+#endif
+bpf_u_int32 pcap_nametonetaddr(const char *);
+
+int    pcap_nametoport(const char *, int *, int *);
+int    pcap_nametoportrange(const char *, int *, int *, int *);
+int    pcap_nametoproto(const char *);
+int    pcap_nametoeproto(const char *);
+int    pcap_nametollc(const char *);
+/*
+ * If a protocol is unknown, PROTO_UNDEF is returned.
+ * Also, pcap_nametoport() returns the protocol along with the port number.
+ * If there are ambiguous entried in /etc/services (i.e. domain
+ * can be either tcp or udp) PROTO_UNDEF is returned.
+ */
+#define PROTO_UNDEF            -1
+
+/* XXX move these to pcap-int.h? */
+int __pcap_atodn(const char *, bpf_u_int32 *);
+int __pcap_atoin(const char *, bpf_u_int32 *);
+u_short        __pcap_nametodnaddr(const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/pcap.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/pcap.h
new file mode 100644 (file)
index 0000000..ad8fc40
--- /dev/null
@@ -0,0 +1,407 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the Computer Systems
+ *     Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.4.2.11 2008-10-06 15:38:39 gianluca Exp $ (LBL)
+ */
+
+#ifndef lib_pcap_pcap_h
+#define lib_pcap_pcap_h
+
+#if defined(WIN32)
+  #include <pcap-stdinc.h>
+#elif defined(MSDOS)
+  #include <sys/types.h>
+  #include <sys/socket.h>  /* u_int, u_char etc. */
+#else /* UN*X */
+  #include <sys/types.h>
+  #include <sys/time.h>
+#endif /* WIN32/MSDOS/UN*X */
+
+#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <pcap/bpf.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_REMOTE
+       // We have to define the SOCKET here, although it has been defined in sockutils.h
+       // This is to avoid the distribution of the 'sockutils.h' file around
+       // (for example in the WinPcap developer's pack)
+       #ifndef SOCKET
+               #ifdef WIN32
+                       #define SOCKET unsigned int
+               #else
+                       #define SOCKET int
+               #endif
+       #endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PCAP_VERSION_MAJOR 2
+#define PCAP_VERSION_MINOR 4
+
+#define PCAP_ERRBUF_SIZE 256
+
+/*
+ * Compatibility for systems that have a bpf.h that
+ * predates the bpf typedefs for 64-bit support.
+ */
+#if BPF_RELEASE - 0 < 199406
+typedef        int bpf_int32;
+typedef        u_int bpf_u_int32;
+#endif
+
+typedef struct pcap pcap_t;
+typedef struct pcap_dumper pcap_dumper_t;
+typedef struct pcap_if pcap_if_t;
+typedef struct pcap_addr pcap_addr_t;
+
+/*
+ * The first record in the file contains saved values for some
+ * of the flags used in the printout phases of tcpdump.
+ * Many fields here are 32 bit ints so compilers won't insert unwanted
+ * padding; these files need to be interchangeable across architectures.
+ *
+ * Do not change the layout of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure).
+ *
+ * Also, do not change the interpretation of any of the members of this
+ * structure, in any way (this includes using values other than
+ * LINKTYPE_ values, as defined in "savefile.c", in the "linktype"
+ * field).
+ *
+ * Instead:
+ *
+ *     introduce a new structure for the new format, if the layout
+ *     of the structure changed;
+ *
+ *     send mail to "tcpdump-workers@lists.tcpdump.org", requesting
+ *     a new magic number for your new capture file format, and, when
+ *     you get the new magic number, put it in "savefile.c";
+ *
+ *     use that magic number for save files with the changed file
+ *     header;
+ *
+ *     make the code in "savefile.c" capable of reading files with
+ *     the old file header as well as files with the new file header
+ *     (using the magic number to determine the header format).
+ *
+ * Then supply the changes as a patch at
+ *
+ *     http://sourceforge.net/projects/libpcap/
+ *
+ * so that future versions of libpcap and programs that use it (such as
+ * tcpdump) will be able to read your new capture file format.
+ */
+struct pcap_file_header {
+       bpf_u_int32 magic;
+       u_short version_major;
+       u_short version_minor;
+       bpf_int32 thiszone;     /* gmt to local correction */
+       bpf_u_int32 sigfigs;    /* accuracy of timestamps */
+       bpf_u_int32 snaplen;    /* max length saved portion of each pkt */
+       bpf_u_int32 linktype;   /* data link type (LINKTYPE_*) */
+};
+
+/*
+ * Macros for the value returned by pcap_datalink_ext().
+ * 
+ * If LT_FCS_LENGTH_PRESENT(x) is true, the LT_FCS_LENGTH(x) macro
+ * gives the FCS length of packets in the capture.
+ */
+#define LT_FCS_LENGTH_PRESENT(x)       ((x) & 0x04000000)
+#define LT_FCS_LENGTH(x)               (((x) & 0xF0000000) >> 28)
+#define LT_FCS_DATALINK_EXT(x)         ((((x) & 0xF) << 28) | 0x04000000)
+
+typedef enum {
+       PCAP_D_INOUT = 0,
+       PCAP_D_IN,
+       PCAP_D_OUT
+} pcap_direction_t;
+
+/*
+ * Generic per-packet information, as supplied by libpcap.
+ *
+ * The time stamp can and should be a "struct timeval", regardless of
+ * whether your system supports 32-bit tv_sec in "struct timeval",
+ * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit
+ * and 64-bit applications.  The on-disk format of savefiles uses 32-bit
+ * tv_sec (and tv_usec); this structure is irrelevant to that.  32-bit
+ * and 64-bit versions of libpcap, even if they're on the same platform,
+ * should supply the appropriate version of "struct timeval", even if
+ * that's not what the underlying packet capture mechanism supplies.
+ */
+struct pcap_pkthdr {
+       struct timeval ts;      /* time stamp */
+       bpf_u_int32 caplen;     /* length of portion present */
+       bpf_u_int32 len;        /* length this packet (off wire) */
+};
+
+/*
+ * As returned by the pcap_stats()
+ */
+struct pcap_stat {
+       u_int ps_recv;          /* number of packets received */
+       u_int ps_drop;          /* number of packets dropped */
+       u_int ps_ifdrop;        /* drops by interface XXX not yet supported */
+#ifdef HAVE_REMOTE
+       u_int ps_capt;          /* number of packets that are received by the application; please get rid off the Win32 ifdef */
+       u_int ps_sent;          /* number of packets sent by the server on the network */
+       u_int ps_netdrop;       /* number of packets lost on the network */
+#endif /* HAVE_REMOTE */
+};
+
+#ifdef MSDOS
+/*
+ * As returned by the pcap_stats_ex()
+ */
+struct pcap_stat_ex {
+       u_long  rx_packets;        /* total packets received       */
+       u_long  tx_packets;        /* total packets transmitted    */
+       u_long  rx_bytes;          /* total bytes received         */
+       u_long  tx_bytes;          /* total bytes transmitted      */
+       u_long  rx_errors;         /* bad packets received         */
+       u_long  tx_errors;         /* packet transmit problems     */
+       u_long  rx_dropped;        /* no space in Rx buffers       */
+       u_long  tx_dropped;        /* no space available for Tx    */
+       u_long  multicast;         /* multicast packets received   */
+       u_long  collisions;
+
+       /* detailed rx_errors: */
+       u_long  rx_length_errors;
+       u_long  rx_over_errors;    /* receiver ring buff overflow  */
+       u_long  rx_crc_errors;     /* recv'd pkt with crc error    */
+       u_long  rx_frame_errors;   /* recv'd frame alignment error */
+       u_long  rx_fifo_errors;    /* recv'r fifo overrun          */
+       u_long  rx_missed_errors;  /* recv'r missed packet         */
+
+       /* detailed tx_errors */
+       u_long  tx_aborted_errors;
+       u_long  tx_carrier_errors;
+       u_long  tx_fifo_errors;
+       u_long  tx_heartbeat_errors;
+       u_long  tx_window_errors;
+     };
+#endif
+
+/*
+ * Item in a list of interfaces.
+ */
+struct pcap_if {
+       struct pcap_if *next;
+       char *name;             /* name to hand to "pcap_open_live()" */
+       char *description;      /* textual description of interface, or NULL */
+       struct pcap_addr *addresses;
+       bpf_u_int32 flags;      /* PCAP_IF_ interface flags */
+};
+
+#define PCAP_IF_LOOPBACK       0x00000001      /* interface is loopback */
+
+/*
+ * Representation of an interface address.
+ */
+struct pcap_addr {
+       struct pcap_addr *next;
+       struct sockaddr *addr;          /* address */
+       struct sockaddr *netmask;       /* netmask for that address */
+       struct sockaddr *broadaddr;     /* broadcast address for that address */
+       struct sockaddr *dstaddr;       /* P2P destination address for that address */
+};
+
+typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
+                            const u_char *);
+
+/*
+ * Error codes for the pcap API.
+ * These will all be negative, so you can check for the success or
+ * failure of a call that returns these codes by checking for a
+ * negative value.
+ */
+#define PCAP_ERROR                     -1      /* generic error code */
+#define PCAP_ERROR_BREAK               -2      /* loop terminated by pcap_breakloop */
+#define PCAP_ERROR_NOT_ACTIVATED       -3      /* the capture needs to be activated */
+#define PCAP_ERROR_ACTIVATED           -4      /* the operation can't be performed on already activated captures */
+#define PCAP_ERROR_NO_SUCH_DEVICE      -5      /* no such device exists */
+#define PCAP_ERROR_RFMON_NOTSUP                -6      /* this device doesn't support rfmon (monitor) mode */
+#define PCAP_ERROR_NOT_RFMON           -7      /* operation supported only in monitor mode */
+#define PCAP_ERROR_PERM_DENIED         -8      /* no permission to open the device */
+#define PCAP_ERROR_IFACE_NOT_UP                -9      /* interface isn't up */
+
+/*
+ * Warning codes for the pcap API.
+ * These will all be positive and non-zero, so they won't look like
+ * errors.
+ */
+#define PCAP_WARNING                   1       /* generic warning code */
+#define PCAP_WARNING_PROMISC_NOTSUP    2       /* this device doesn't support promiscuous mode */
+
+char   *pcap_lookupdev(char *);
+int    pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+
+pcap_t *pcap_create(const char *, char *);
+int    pcap_set_snaplen(pcap_t *, int);
+int    pcap_set_promisc(pcap_t *, int);
+int    pcap_can_set_rfmon(pcap_t *);
+int    pcap_set_rfmon(pcap_t *, int);
+int    pcap_set_timeout(pcap_t *, int);
+int    pcap_set_buffer_size(pcap_t *, int);
+int    pcap_activate(pcap_t *);
+
+pcap_t *pcap_open_live(const char *, int, int, int, char *);
+pcap_t *pcap_open_dead(int, int);
+pcap_t *pcap_open_offline(const char *, char *);
+#if defined(WIN32)
+pcap_t  *pcap_hopen_offline(intptr_t, char *);
+#if !defined(LIBPCAP_EXPORTS)
+#define pcap_fopen_offline(f,b) \
+       pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
+#else /*LIBPCAP_EXPORTS*/
+static pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif
+#else /*WIN32*/
+pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif /*WIN32*/
+
+void   pcap_close(pcap_t *);
+int    pcap_loop(pcap_t *, int, pcap_handler, u_char *);
+int    pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
+const u_char*
+       pcap_next(pcap_t *, struct pcap_pkthdr *);
+int    pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
+void   pcap_breakloop(pcap_t *);
+int    pcap_stats(pcap_t *, struct pcap_stat *);
+int    pcap_setfilter(pcap_t *, struct bpf_program *);
+int    pcap_setdirection(pcap_t *, pcap_direction_t);
+int    pcap_getnonblock(pcap_t *, char *);
+int    pcap_setnonblock(pcap_t *, int, char *);
+int    pcap_inject(pcap_t *, const void *, size_t);
+int    pcap_sendpacket(pcap_t *, const u_char *, int);
+const char *pcap_statustostr(int);
+const char *pcap_strerror(int);
+char   *pcap_geterr(pcap_t *);
+void   pcap_perror(pcap_t *, char *);
+int    pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
+           bpf_u_int32);
+int    pcap_compile_nopcap(int, int, struct bpf_program *,
+           const char *, int, bpf_u_int32);
+void   pcap_freecode(struct bpf_program *);
+int    pcap_offline_filter(struct bpf_program *, const struct pcap_pkthdr *,
+           const u_char *);
+int    pcap_datalink(pcap_t *);
+int    pcap_datalink_ext(pcap_t *);
+int    pcap_list_datalinks(pcap_t *, int **);
+int    pcap_set_datalink(pcap_t *, int);
+void   pcap_free_datalinks(int *);
+int    pcap_datalink_name_to_val(const char *);
+const char *pcap_datalink_val_to_name(int);
+const char *pcap_datalink_val_to_description(int);
+int    pcap_snapshot(pcap_t *);
+int    pcap_is_swapped(pcap_t *);
+int    pcap_major_version(pcap_t *);
+int    pcap_minor_version(pcap_t *);
+
+/* XXX */
+FILE   *pcap_file(pcap_t *);
+int    pcap_fileno(pcap_t *);
+
+pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
+FILE   *pcap_dump_file(pcap_dumper_t *);
+long   pcap_dump_ftell(pcap_dumper_t *);
+int    pcap_dump_flush(pcap_dumper_t *);
+void   pcap_dump_close(pcap_dumper_t *);
+void   pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+
+int    pcap_findalldevs(pcap_if_t **, char *);
+void   pcap_freealldevs(pcap_if_t *);
+
+const char *pcap_lib_version(void);
+
+/* XXX this guy lives in the bpf tree */
+u_int  bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+int    bpf_validate(const struct bpf_insn *f, int len);
+char   *bpf_image(const struct bpf_insn *, int);
+void   bpf_dump(const struct bpf_program *, int);
+
+#if defined(WIN32)
+
+/*
+ * Win32 definitions
+ */
+
+int pcap_setbuff(pcap_t *p, int dim);
+int pcap_setmode(pcap_t *p, int mode);
+int pcap_setmintocopy(pcap_t *p, int size);
+
+#ifdef WPCAP
+/* Include file with the wpcap-specific extensions */
+#include <Win32-Extensions.h>
+#endif /* WPCAP */
+
+#define MODE_CAPT 0
+#define MODE_STAT 1
+#define MODE_MON 2
+
+#elif defined(MSDOS)
+
+/*
+ * MS-DOS definitions
+ */
+
+int  pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
+void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
+u_long pcap_mac_packets (void);
+
+#else /* UN*X */
+
+/*
+ * UN*X definitions
+ */
+
+int    pcap_get_selectable_fd(pcap_t *);
+
+#endif /* WIN32/MSDOS/UN*X */
+
+#ifdef HAVE_REMOTE
+/* Includes most of the public stuff that is needed for the remote capture */
+#include <remote-ext.h>
+#endif  /* HAVE_REMOTE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/sll.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/sll.h
new file mode 100644 (file)
index 0000000..e9d5452
--- /dev/null
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/sll.h,v 1.2.2.1 2008-05-30 01:36:06 guy Exp $ (LBL)
+ */
+
+/*
+ * For captures on Linux cooked sockets, we construct a fake header
+ * that includes:
+ *
+ *     a 2-byte "packet type" which is one of:
+ *
+ *             LINUX_SLL_HOST          packet was sent to us
+ *             LINUX_SLL_BROADCAST     packet was broadcast
+ *             LINUX_SLL_MULTICAST     packet was multicast
+ *             LINUX_SLL_OTHERHOST     packet was sent to somebody else
+ *             LINUX_SLL_OUTGOING      packet was sent *by* us;
+ *
+ *     a 2-byte Ethernet protocol field;
+ *
+ *     a 2-byte link-layer type;
+ *
+ *     a 2-byte link-layer address length;
+ *
+ *     an 8-byte source link-layer address, whose actual length is
+ *     specified by the previous value.
+ *
+ * All fields except for the link-layer address are in network byte order.
+ *
+ * DO NOT change the layout of this structure, or change any of the
+ * LINUX_SLL_ values below.  If you must change the link-layer header
+ * for a "cooked" Linux capture, introduce a new DLT_ type (ask
+ * "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it
+ * a value that collides with a value already being used), and use the
+ * new header in captures of that type, so that programs that can
+ * handle DLT_LINUX_SLL captures will continue to handle them correctly
+ * without any change, and so that capture files with different headers
+ * can be told apart and programs that read them can dissect the
+ * packets in them.
+ */
+
+#ifndef lib_pcap_sll_h
+#define lib_pcap_sll_h
+
+/*
+ * A DLT_LINUX_SLL fake link-layer header.
+ */
+#define SLL_HDR_LEN    16              /* total header length */
+#define SLL_ADDRLEN    8               /* length of address field */
+
+struct sll_header {
+       u_int16_t sll_pkttype;          /* packet type */
+       u_int16_t sll_hatype;           /* link-layer address type */
+       u_int16_t sll_halen;            /* link-layer address length */
+       u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */
+       u_int16_t sll_protocol;         /* protocol */
+};
+
+/*
+ * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
+ * PACKET_ values on Linux, but are defined here so that they're
+ * available even on systems other than Linux, and so that they
+ * don't change even if the PACKET_ values change.
+ */
+#define LINUX_SLL_HOST         0
+#define LINUX_SLL_BROADCAST    1
+#define LINUX_SLL_MULTICAST    2
+#define LINUX_SLL_OTHERHOST    3
+#define LINUX_SLL_OUTGOING     4
+
+/*
+ * The LINUX_SLL_ values for "sll_protocol"; these correspond to the
+ * ETH_P_ values on Linux, but are defined here so that they're
+ * available even on systems other than Linux.  We assume, for now,
+ * that the ETH_P_ values won't change in Linux; if they do, then:
+ *
+ *     if we don't translate them in "pcap-linux.c", capture files
+ *     won't necessarily be readable if captured on a system that
+ *     defines ETH_P_ values that don't match these values;
+ *
+ *     if we do translate them in "pcap-linux.c", that makes life
+ *     unpleasant for the BPF code generator, as the values you test
+ *     for in the kernel aren't the values that you test for when
+ *     reading a capture file, so the fixup code run on BPF programs
+ *     handed to the kernel ends up having to do more work.
+ *
+ * Add other values here as necessary, for handling packet types that
+ * might show up on non-Ethernet, non-802.x networks.  (Not all the ones
+ * in the Linux "if_ether.h" will, I suspect, actually show up in
+ * captures.)
+ */
+#define LINUX_SLL_P_802_3      0x0001  /* Novell 802.3 frames without 802.2 LLC header */
+#define LINUX_SLL_P_802_2      0x0004  /* 802.2 frames (not D/I/X Ethernet) */
+
+#endif
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/usb.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/usb.h
new file mode 100644 (file)
index 0000000..adcd19c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote 
+ * products derived from this software without specific prior written 
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Basic USB data struct
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/usb.h,v 1.6 2007/09/22 02:06:08 guy Exp $
+ */
+#ifndef _PCAP_USB_STRUCTS_H__
+#define _PCAP_USB_STRUCTS_H__
+
+/* 
+ * possible transfer mode
+ */
+#define URB_TRANSFER_IN   0x80
+#define URB_ISOCHRONOUS   0x0
+#define URB_INTERRUPT     0x1
+#define URB_CONTROL       0x2
+#define URB_BULK          0x3
+
+/*
+ * possible event type
+ */
+#define URB_SUBMIT        'S'
+#define URB_COMPLETE      'C'
+#define URB_ERROR         'E'
+
+/*
+ * USB setup header as defined in USB specification.
+ * Appears at the front of each packet in DLT_USB captures.
+ */
+typedef struct _usb_setup {
+       u_int8_t bmRequestType;
+       u_int8_t bRequest;
+       u_int16_t wValue;
+       u_int16_t wIndex;
+       u_int16_t wLength;
+} pcap_usb_setup;
+
+
+/*
+ * Header prepended by linux kernel to each event.
+ * Appears at the front of each packet in DLT_USB_LINUX captures.
+ */
+typedef struct _usb_header {
+       u_int64_t id;
+       u_int8_t event_type;
+       u_int8_t transfer_type;
+       u_int8_t endpoint_number;
+       u_int8_t device_address;
+       u_int16_t bus_id;
+       char setup_flag;/*if !=0 the urb setup header is not present*/
+       char data_flag; /*if !=0 no urb data is present*/
+       int64_t ts_sec;
+       int32_t ts_usec;
+       int32_t status;
+       u_int32_t urb_len;
+       u_int32_t data_len; /* amount of urb data really present in this event*/
+       pcap_usb_setup setup;
+} pcap_usb_header;
+
+
+#endif
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/vlan.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/pcap/vlan.h
new file mode 100644 (file)
index 0000000..b0cb794
--- /dev/null
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/vlan.h,v 1.1.2.2 2008-08-06 07:45:59 guy Exp $
+ */
+
+#ifndef lib_pcap_vlan_h
+#define lib_pcap_vlan_h
+
+struct vlan_tag {
+       u_int16_t       vlan_tpid;              /* ETH_P_8021Q */
+       u_int16_t       vlan_tci;               /* VLAN TCI */
+};
+
+#define VLAN_TAG_LEN   4
+
+#endif
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/remote-ext.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/remote-ext.h
new file mode 100644 (file)
index 0000000..9f54d69
--- /dev/null
@@ -0,0 +1,444 @@
+/*\r
+ * Copyright (c) 2002 - 2003\r
+ * NetGroup, Politecnico di Torino (Italy)\r
+ * All rights reserved.\r
+ * \r
+ * Redistribution and use in source and binary forms, with or without \r
+ * modification, are permitted provided that the following conditions \r
+ * are met:\r
+ * \r
+ * 1. Redistributions of source code must retain the above copyright \r
+ * notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright \r
+ * notice, this list of conditions and the following disclaimer in the \r
+ * documentation and/or other materials provided with the distribution. \r
+ * 3. Neither the name of the Politecnico di Torino nor the names of its \r
+ * contributors may be used to endorse or promote products derived from \r
+ * this software without specific prior written permission. \r
+ * \r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR \r
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, \r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY \r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ * \r
+ */\r
+\r
+\r
+#ifndef __REMOTE_EXT_H__\r
+#define __REMOTE_EXT_H__\r
+\r
+\r
+#ifndef HAVE_REMOTE\r
+#error Please do not include this file directly. Just define HAVE_REMOTE and then include pcap.h\r
+#endif\r
+\r
+// Definition for Microsoft Visual Studio\r
+#if _MSC_VER > 1000\r
+#pragma once\r
+#endif\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*!\r
+       \file remote-ext.h\r
+\r
+       The goal of this file it to include most of the new definitions that should be\r
+       placed into the pcap.h file.\r
+\r
+       It includes all new definitions (structures and functions like pcap_open().\r
+    Some of the functions are not really a remote feature, but, right now, \r
+       they are placed here.\r
+*/\r
+\r
+\r
+\r
+// All this stuff is public\r
+/*! \addtogroup remote_struct\r
+       \{\r
+*/\r
+\r
+\r
+\r
+\r
+/*!\r
+       \brief Defines the maximum buffer size in which address, port, interface names are kept.\r
+\r
+       In case the adapter name or such is larger than this value, it is truncated.\r
+       This is not used by the user; however it must be aware that an hostname / interface\r
+       name longer than this value will be truncated.\r
+*/\r
+#define PCAP_BUF_SIZE 1024\r
+\r
+\r
+/*! \addtogroup remote_source_ID\r
+       \{\r
+*/\r
+\r
+\r
+/*!\r
+       \brief Internal representation of the type of source in use (file, \r
+       remote/local interface).\r
+\r
+       This indicates a file, i.e. the user want to open a capture from a local file.\r
+*/\r
+#define PCAP_SRC_FILE 2\r
+/*!\r
+       \brief Internal representation of the type of source in use (file, \r
+       remote/local interface).\r
+\r
+       This indicates a local interface, i.e. the user want to open a capture from \r
+       a local interface. This does not involve the RPCAP protocol.\r
+*/\r
+#define PCAP_SRC_IFLOCAL 3\r
+/*!\r
+       \brief Internal representation of the type of source in use (file, \r
+       remote/local interface).\r
+\r
+       This indicates a remote interface, i.e. the user want to open a capture from \r
+       an interface on a remote host. This does involve the RPCAP protocol.\r
+*/\r
+#define PCAP_SRC_IFREMOTE 4\r
+\r
+/*!\r
+       \}\r
+*/\r
+\r
+\r
+\r
+/*! \addtogroup remote_source_string\r
+\r
+       The formats allowed by the pcap_open() are the following:\r
+       - file://path_and_filename [opens a local file]\r
+       - rpcap://devicename [opens the selected device devices available on the local host, without using the RPCAP protocol]\r
+       - rpcap://host/devicename [opens the selected device available on a remote host]\r
+       - rpcap://host:port/devicename [opens the selected device available on a remote host, using a non-standard port for RPCAP]\r
+       - adaptername [to open a local adapter; kept for compability, but it is strongly discouraged]\r
+       - (NULL) [to open the first local adapter; kept for compability, but it is strongly discouraged]\r
+\r
+       The formats allowed by the pcap_findalldevs_ex() are the following:\r
+       - file://folder/ [lists all the files in the given folder]\r
+       - rpcap:// [lists all local adapters]\r
+       - rpcap://host:port/ [lists the devices available on a remote host]\r
+\r
+       Referring to the 'host' and 'port' paramters, they can be either numeric or literal. Since\r
+       IPv6 is fully supported, these are the allowed formats:\r
+\r
+       - host (literal): e.g. host.foo.bar\r
+       - host (numeric IPv4): e.g. 10.11.12.13\r
+       - host (numeric IPv4, IPv6 style): e.g. [10.11.12.13]\r
+       - host (numeric IPv6): e.g. [1:2:3::4]\r
+       - port: can be either numeric (e.g. '80') or literal (e.g. 'http')\r
+\r
+       Here you find some allowed examples:\r
+       - rpcap://host.foo.bar/devicename [everything literal, no port number]\r
+       - rpcap://host.foo.bar:1234/devicename [everything literal, with port number]\r
+       - rpcap://10.11.12.13/devicename [IPv4 numeric, no port number]\r
+       - rpcap://10.11.12.13:1234/devicename [IPv4 numeric, with port number]\r
+       - rpcap://[10.11.12.13]:1234/devicename [IPv4 numeric with IPv6 format, with port number]\r
+       - rpcap://[1:2:3::4]/devicename [IPv6 numeric, no port number]\r
+       - rpcap://[1:2:3::4]:1234/devicename [IPv6 numeric, with port number]\r
+       - rpcap://[1:2:3::4]:http/devicename [IPv6 numeric, with literal port number]\r
+       \r
+       \{\r
+*/\r
+\r
+\r
+/*!\r
+       \brief String that will be used to determine the type of source in use (file,\r
+       remote/local interface).\r
+\r
+       This string will be prepended to the interface name in order to create a string\r
+       that contains all the information required to open the source.\r
+\r
+       This string indicates that the user wants to open a capture from a local file.\r
+*/\r
+#define PCAP_SRC_FILE_STRING "file://"\r
+/*!\r
+       \brief String that will be used to determine the type of source in use (file,\r
+       remote/local interface).\r
+\r
+       This string will be prepended to the interface name in order to create a string\r
+       that contains all the information required to open the source.\r
+\r
+       This string indicates that the user wants to open a capture from a network interface.\r
+       This string does not necessarily involve the use of the RPCAP protocol. If the\r
+       interface required resides on the local host, the RPCAP protocol is not involved\r
+       and the local functions are used.\r
+*/\r
+#define PCAP_SRC_IF_STRING "rpcap://"\r
+\r
+/*!\r
+       \}\r
+*/\r
+\r
+\r
+\r
+\r
+\r
+/*!\r
+       \addtogroup remote_open_flags\r
+       \{\r
+*/\r
+\r
+/*!\r
+       \brief Defines if the adapter has to go in promiscuous mode.\r
+\r
+       It is '1' if you have to open the adapter in promiscuous mode, '0' otherwise.\r
+       Note that even if this parameter is false, the interface could well be in promiscuous\r
+       mode for some other reason (for example because another capture process with \r
+       promiscuous mode enabled is currently using that interface).\r
+       On on Linux systems with 2.2 or later kernels (that have the "any" device), this\r
+       flag does not work on the "any" device; if an argument of "any" is supplied,\r
+       the 'promisc' flag is ignored.\r
+*/\r
+#define PCAP_OPENFLAG_PROMISCUOUS              1\r
+\r
+/*!\r
+       \brief Defines if the data trasfer (in case of a remote\r
+       capture) has to be done with UDP protocol.\r
+\r
+       If it is '1' if you want a UDP data connection, '0' if you want\r
+       a TCP data connection; control connection is always TCP-based.\r
+       A UDP connection is much lighter, but it does not guarantee that all\r
+       the captured packets arrive to the client workstation. Moreover, \r
+       it could be harmful in case of network congestion.\r
+       This flag is meaningless if the source is not a remote interface.\r
+       In that case, it is simply ignored.\r
+*/\r
+#define PCAP_OPENFLAG_DATATX_UDP                       2\r
+\r
+\r
+/*!\r
+       \brief Defines if the remote probe will capture its own generated traffic.\r
+\r
+       In case the remote probe uses the same interface to capture traffic and to send\r
+       data back to the caller, the captured traffic includes the RPCAP traffic as well.\r
+       If this flag is turned on, the RPCAP traffic is excluded from the capture, so that\r
+       the trace returned back to the collector is does not include this traffic.\r
+*/\r
+#define PCAP_OPENFLAG_NOCAPTURE_RPCAP  4\r
+\r
+/*!\r
+       \brief Defines if the local adapter will capture its own generated traffic.\r
+\r
+       This flag tells the underlying capture driver to drop the packets that were sent by itself. \r
+       This is usefult when building applications like bridges, that should ignore the traffic\r
+       they just sent.\r
+*/\r
+#define PCAP_OPENFLAG_NOCAPTURE_LOCAL  8\r
+\r
+/*!\r
+       \brief This flag configures the adapter for maximum responsiveness.\r
+\r
+       In presence of a large value for nbytes, WinPcap waits for the arrival of several packets before \r
+       copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage, \r
+       i.e. better performance, which is good for applications like sniffers. If the user sets the \r
+       PCAP_OPENFLAG_MAX_RESPONSIVENESS flag, the capture driver will copy the packets as soon as the application \r
+       is ready to receive them. This is suggested for real time applications (like, for example, a bridge) \r
+       that need the best responsiveness.*/\r
+#define PCAP_OPENFLAG_MAX_RESPONSIVENESS       16\r
+\r
+/*!\r
+       \}\r
+*/\r
+\r
+\r
+/*!\r
+       \addtogroup remote_samp_methods\r
+       \{\r
+*/\r
+\r
+/*!\r
+       \brief No sampling has to be done on the current capture.\r
+\r
+       In this case, no sampling algorithms are applied to the current capture.\r
+*/\r
+#define PCAP_SAMP_NOSAMP       0\r
+\r
+/*!\r
+       \brief It defines that only 1 out of N packets must be returned to the user.\r
+\r
+       In this case, the 'value' field of the 'pcap_samp' structure indicates the\r
+       number of packets (minus 1) that must be discarded before one packet got accepted.\r
+       In other words, if 'value = 10', the first packet is returned to the caller, while\r
+       the following 9 are discarded.\r
+*/\r
+#define PCAP_SAMP_1_EVERY_N    1\r
+\r
+/*!\r
+       \brief It defines that we have to return 1 packet every N milliseconds.\r
+\r
+       In this case, the 'value' field of the 'pcap_samp' structure indicates the 'waiting\r
+       time' in milliseconds before one packet got accepted.\r
+       In other words, if 'value = 10', the first packet is returned to the caller; the next \r
+       returned one will be the first packet that arrives when 10ms have elapsed. \r
+*/\r
+#define PCAP_SAMP_FIRST_AFTER_N_MS 2\r
+\r
+/*!\r
+       \}\r
+*/\r
+\r
+\r
+/*!\r
+       \addtogroup remote_auth_methods\r
+       \{\r
+*/\r
+\r
+/*!\r
+       \brief It defines the NULL authentication.\r
+\r
+       This value has to be used within the 'type' member of the pcap_rmtauth structure.\r
+       The 'NULL' authentication has to be equal to 'zero', so that old applications\r
+       can just put every field of struct pcap_rmtauth to zero, and it does work.\r
+*/\r
+#define RPCAP_RMTAUTH_NULL 0\r
+/*!\r
+       \brief It defines the username/password authentication.\r
+\r
+       With this type of authentication, the RPCAP protocol will use the username/\r
+       password provided to authenticate the user on the remote machine. If the\r
+       authentication is successful (and the user has the right to open network devices)\r
+       the RPCAP connection will continue; otherwise it will be dropped.\r
+\r
+       This value has to be used within the 'type' member of the pcap_rmtauth structure.\r
+*/\r
+#define RPCAP_RMTAUTH_PWD 1\r
+\r
+/*!\r
+       \}\r
+*/\r
+\r
+\r
+\r
+\r
+/*!\r
+\r
+       \brief This structure keeps the information needed to autheticate\r
+       the user on a remote machine.\r
+       \r
+       The remote machine can either grant or refuse the access according \r
+       to the information provided.\r
+       In case the NULL authentication is required, both 'username' and\r
+       'password' can be NULL pointers.\r
+       \r
+       This structure is meaningless if the source is not a remote interface;\r
+       in that case, the functions which requires such a structure can accept\r
+       a NULL pointer as well.\r
+*/\r
+struct pcap_rmtauth\r
+{\r
+       /*!\r
+               \brief Type of the authentication required.\r
+\r
+               In order to provide maximum flexibility, we can support different types\r
+               of authentication based on the value of this 'type' variable. The currently \r
+               supported authentication methods are defined into the\r
+               \link remote_auth_methods Remote Authentication Methods Section\endlink.\r
+\r
+       */\r
+       int type;\r
+       /*!\r
+               \brief Zero-terminated string containing the username that has to be \r
+               used on the remote machine for authentication.\r
+               \r
+               This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication\r
+               and it can be NULL.\r
+       */\r
+       char *username;\r
+       /*!\r
+               \brief Zero-terminated string containing the password that has to be \r
+               used on the remote machine for authentication.\r
+               \r
+               This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication\r
+               and it can be NULL.\r
+       */\r
+       char *password;\r
+};\r
+\r
+\r
+/*!\r
+       \brief This structure defines the information related to sampling.\r
+\r
+       In case the sampling is requested, the capturing device should read\r
+       only a subset of the packets coming from the source. The returned packets depend\r
+       on the sampling parameters.\r
+\r
+       \warning The sampling process is applied <strong>after</strong> the filtering process.\r
+       In other words, packets are filtered first, then the sampling process selects a\r
+       subset of the 'filtered' packets and it returns them to the caller.\r
+*/\r
+struct pcap_samp\r
+{\r
+       /*!\r
+               Method used for sampling. Currently, the supported methods are listed in the\r
+               \link remote_samp_methods Sampling Methods Section\endlink.\r
+       */\r
+       int method;\r
+\r
+       /*!\r
+               This value depends on the sampling method defined. For its meaning, please check\r
+               at the \link remote_samp_methods Sampling Methods Section\endlink.\r
+       */\r
+       int value;\r
+};\r
+\r
+\r
+\r
+\r
+//! Maximum lenght of an host name (needed for the RPCAP active mode)\r
+#define RPCAP_HOSTLIST_SIZE 1024\r
+\r
+\r
+/*!\r
+       \}\r
+*/ // end of public documentation\r
+\r
+\r
+// Exported functions\r
+\r
+\r
+\r
+/** \name New WinPcap functions\r
+\r
+       This section lists the new functions that are able to help considerably in writing\r
+       WinPcap programs because of their easiness of use.\r
+ */\r
+//\{\r
+pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf);\r
+int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf);\r
+int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf);\r
+int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);\r
+struct pcap_samp *pcap_setsampling(pcap_t *p);\r
+\r
+//\}\r
+// End of new winpcap functions\r
+\r
+\r
+\r
+/** \name Remote Capture functions\r
+ */\r
+//\{ \r
+SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf);\r
+int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf);\r
+int pcap_remoteact_close(const char *host, char *errbuf);\r
+void pcap_remoteact_cleanup();\r
+//\}\r
+// End of remote capture functions\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+\r
+#endif\r
+\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/wpcap.lib b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/wpcap.lib
new file mode 100644 (file)
index 0000000..f832e04
Binary files /dev/null and b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/WinPCap/wpcap.lib differ
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/demo_logging.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/demo_logging.c
new file mode 100644 (file)
index 0000000..6646fc7
--- /dev/null
@@ -0,0 +1,568 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+\r
+/*\r
+ * Logging utility that allows FreeRTOS tasks to log to a UDP port, stdout, and\r
+ * disk file without making any Win32 system calls themselves.\r
+ *\r
+ * Messages logged to a UDP port are sent directly (using FreeRTOS+TCP), but as\r
+ * FreeRTOS tasks cannot make Win32 system calls messages sent to stdout or a\r
+ * disk file are sent via a stream buffer to a Win32 thread which then performs\r
+ * the actual output.\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdio.h>\r
+#include <stdint.h>\r
+#include <stdarg.h>\r
+#include <io.h>\r
+#include <ctype.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include <FreeRTOS.h>\r
+#include "task.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_Stream_Buffer.h"\r
+\r
+/* Demo includes. */\r
+#include "demo_logging.h"\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The maximum size to which the log file may grow, before being renamed\r
+to .ful. */\r
+#define dlLOGGING_FILE_SIZE            ( 40ul * 1024ul * 1024ul )\r
+\r
+/* Dimensions the arrays into which print messages are created. */\r
+#define dlMAX_PRINT_STRING_LENGTH      255\r
+\r
+/* The size of the stream buffer used to pass messages from FreeRTOS tasks to\r
+the Win32 thread that is responsible for making any Win32 system calls that are\r
+necessary for the selected logging method. */\r
+#define dlLOGGING_STREAM_BUFFER_SIZE  32768\r
+\r
+/* A block time of zero simply means don't block. */\r
+#define dlDONT_BLOCK   0\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Called from vLoggingInit() to start a new disk log file.\r
+ */\r
+static void prvFileLoggingInit( void );\r
+\r
+/*\r
+ * Attempt to write a message to the file.\r
+ */\r
+static void prvLogToFile( const char *pcMessage, size_t xLength );\r
+\r
+/*\r
+ * Simply close the logging file, if it is open.\r
+ */\r
+static void prvFileClose( void );\r
+\r
+/*\r
+ * Before the scheduler is started this function is called directly.  After the\r
+ * scheduler has started it is called from the Windows thread dedicated to\r
+ * outputting log messages.  Only the windows thread actually performs the\r
+ * writing so as not to disrupt the simulation by making Windows system calls\r
+ * from FreeRTOS tasks.\r
+ */\r
+static void prvLoggingFlushBuffer( void );\r
+\r
+/*\r
+ * The windows thread that performs the actual writing of messages that require\r
+ * Win32 system calls.  Only the windows thread can make system calls so as not\r
+ * to disrupt the simulation by making Windows calls from FreeRTOS tasks.\r
+ */\r
+static DWORD WINAPI prvWin32LoggingThread( void *pvParam );\r
+\r
+/*\r
+ * Creates the socket to which UDP messages are sent.  This function is not\r
+ * called directly to prevent the print socket being created from within the IP\r
+ * task - which could result in a deadlock.  Instead the function call is\r
+ * deferred to run in the RTOS daemon task - hence it prototype.\r
+ */\r
+static void prvCreatePrintSocket( void *pvParameter1, uint32_t ulParameter2 );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Windows event used to wake the Win32 thread which performs any logging that\r
+needs Win32 system calls. */\r
+static void *pvLoggingThreadEvent = NULL;\r
+\r
+/* Stores the selected logging targets passed in as parameters to the\r
+vLoggingInit() function. */\r
+BaseType_t xStdoutLoggingUsed = pdFALSE, xDiskFileLoggingUsed = pdFALSE, xUDPLoggingUsed = pdFALSE;\r
+\r
+/* Circular buffer used to pass messages from the FreeRTOS tasks to the Win32\r
+thread that is responsible for making Win32 calls (when stdout or a disk log is\r
+used). */\r
+static StreamBuffer_t *xLogStreamBuffer = NULL;\r
+\r
+/* Handle to the file used for logging.  This is left open while there are\r
+messages waiting to be logged, then closed again in between logs. */\r
+static FILE *pxLoggingFileHandle = NULL;\r
+\r
+/* When true prints are performed directly.  After start up xDirectPrint is set\r
+to pdFALSE - at which time prints that require Win32 system calls are done by\r
+the Win32 thread responsible for logging. */\r
+BaseType_t xDirectPrint = pdTRUE;\r
+\r
+/* File names for the in use and complete (full) log files. */\r
+static const char *pcLogFileName = "RTOSDemo.log";\r
+static const char *pcFullLogFileName = "RTOSDemo.ful";\r
+\r
+/* Keep the current file size in a variable, as an optimisation. */\r
+static size_t ulSizeOfLoggingFile = 0ul;\r
+\r
+/* The UDP socket and address on/to which print messages are sent. */\r
+Socket_t xPrintSocket = FREERTOS_INVALID_SOCKET;\r
+struct freertos_sockaddr xPrintUDPAddress;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vLoggingInit( BaseType_t xLogToStdout, BaseType_t xLogToFile, BaseType_t xLogToUDP, uint32_t ulRemoteIPAddress, uint16_t usRemotePort )\r
+{\r
+       /* Can only be called before the scheduler has started. */\r
+       configASSERT( xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED );\r
+\r
+       #if( ( ipconfigHAS_DEBUG_PRINTF == 1 ) || ( ipconfigHAS_PRINTF == 1 ) )\r
+       {\r
+               HANDLE Win32Thread;\r
+\r
+               /* Record which output methods are to be used. */\r
+               xStdoutLoggingUsed = xLogToStdout;\r
+               xDiskFileLoggingUsed = xLogToFile;\r
+               xUDPLoggingUsed = xLogToUDP;\r
+\r
+               /* If a disk file is used then initialise it now. */\r
+               if( xDiskFileLoggingUsed != pdFALSE )\r
+               {\r
+                       prvFileLoggingInit();\r
+               }\r
+\r
+               /* If UDP logging is used then store the address to which the log data\r
+               will be sent - but don't create the socket yet because the network is\r
+               not initialised. */\r
+               if( xUDPLoggingUsed != pdFALSE )\r
+               {\r
+                       /* Set the address to which the print messages are sent. */\r
+                       xPrintUDPAddress.sin_port = FreeRTOS_htons( usRemotePort );\r
+                       xPrintUDPAddress.sin_addr = ulRemoteIPAddress;\r
+               }\r
+\r
+               /* If a disk file or stdout are to be used then Win32 system calls will\r
+               have to be made.  Such system calls cannot be made from FreeRTOS tasks\r
+               so create a stream buffer to pass the messages to a Win32 thread, then\r
+               create the thread itself, along with a Win32 event that can be used to\r
+               unblock the thread. */\r
+               if( ( xStdoutLoggingUsed != pdFALSE ) || ( xDiskFileLoggingUsed != pdFALSE ) )\r
+               {\r
+                       /* Create the buffer. */\r
+                       xLogStreamBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xLogStreamBuffer ) - sizeof( xLogStreamBuffer->ucArray ) + dlLOGGING_STREAM_BUFFER_SIZE + 1 );\r
+                       configASSERT( xLogStreamBuffer );\r
+                       memset( xLogStreamBuffer, '\0', sizeof( *xLogStreamBuffer ) - sizeof( xLogStreamBuffer->ucArray ) );\r
+                       xLogStreamBuffer->LENGTH = dlLOGGING_STREAM_BUFFER_SIZE + 1;\r
+\r
+                       /* Create the Windows event. */\r
+                       pvLoggingThreadEvent = CreateEvent( NULL, FALSE, TRUE, "StdoutLoggingEvent" );\r
+\r
+                       /* Create the thread itself. */\r
+                       Win32Thread = CreateThread(\r
+                               NULL,   /* Pointer to thread security attributes. */\r
+                               0,              /* Initial thread stack size, in bytes. */\r
+                               prvWin32LoggingThread,  /* Pointer to thread function. */\r
+                               NULL,   /* Argument for new thread. */\r
+                               0,              /* Creation flags. */\r
+                               NULL );\r
+\r
+                       /* Use the cores that are not used by the FreeRTOS tasks. */\r
+                       SetThreadAffinityMask( Win32Thread, ~0x01u );\r
+                       SetThreadPriorityBoost( Win32Thread, TRUE );\r
+                       SetThreadPriority( Win32Thread, THREAD_PRIORITY_IDLE );\r
+               }\r
+       }\r
+       #else\r
+       {\r
+               /* FreeRTOSIPConfig is set such that no print messages will be output.\r
+               Avoid compiler warnings about unused parameters. */\r
+               ( void ) xLogToStdout;\r
+               ( void ) xLogToFile;\r
+               ( void ) xLogToUDP;\r
+               ( void ) usRemotePort;\r
+               ( void ) ulRemoteIPAddress;\r
+       }\r
+       #endif /* ( ipconfigHAS_DEBUG_PRINTF == 1 ) || ( ipconfigHAS_PRINTF == 1 )  */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCreatePrintSocket( void *pvParameter1, uint32_t ulParameter2 )\r
+{\r
+static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 0 );\r
+Socket_t xSocket;\r
+\r
+       /* The function prototype is that of a deferred function, but the parameters\r
+       are not actually used. */\r
+       ( void ) pvParameter1;\r
+       ( void ) ulParameter2;\r
+\r
+       xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
+\r
+       if( xSocket != FREERTOS_INVALID_SOCKET )\r
+       {\r
+               /* FreeRTOS+TCP decides which port to bind to. */\r
+               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) );\r
+               FreeRTOS_bind( xSocket, NULL, 0 );\r
+\r
+               /* Now the socket is bound it can be assigned to the print socket. */\r
+               xPrintSocket = xSocket;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vLoggingPrintf( const char *pcFormat, ... )\r
+{\r
+char cPrintString[ dlMAX_PRINT_STRING_LENGTH ];\r
+char cOutputString[ dlMAX_PRINT_STRING_LENGTH ];\r
+char *pcSource, *pcTarget, *pcBegin;\r
+size_t xLength, xLength2, rc;\r
+static BaseType_t xMessageNumber = 0;\r
+va_list args;\r
+uint32_t ulIPAddress;\r
+const char *pcTaskName;\r
+const char *pcNoTask = "None";\r
+int iOriginalPriority;\r
+HANDLE xCurrentTask;\r
+\r
+\r
+       if( ( xStdoutLoggingUsed != pdFALSE ) || ( xDiskFileLoggingUsed != pdFALSE ) || ( xUDPLoggingUsed != pdFALSE ) )\r
+       {\r
+               /* There are a variable number of parameters. */\r
+               va_start( args, pcFormat );\r
+\r
+               /* Additional info to place at the start of the log. */\r
+               if( xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED )\r
+               {\r
+                       pcTaskName = pcTaskGetName( NULL );\r
+               }\r
+               else\r
+               {\r
+                       pcTaskName = pcNoTask;\r
+               }\r
+\r
+               if( strcmp( pcFormat, "\n" ) != 0 )\r
+               {\r
+                       xLength = snprintf( cPrintString, dlMAX_PRINT_STRING_LENGTH, "%lu %lu [%s] ",\r
+                               xMessageNumber++,\r
+                               ( unsigned long ) xTaskGetTickCount(),\r
+                               pcTaskName );\r
+               }\r
+               else\r
+               {\r
+                       xLength = 0;\r
+                       memset( cPrintString, 0x00, dlMAX_PRINT_STRING_LENGTH );\r
+               }\r
+\r
+               xLength2 = vsnprintf( cPrintString + xLength, dlMAX_PRINT_STRING_LENGTH - xLength, pcFormat, args );\r
+\r
+               if( xLength2 <  0 )\r
+               {\r
+                       /* Clean up. */\r
+                       xLength2 = sizeof( cPrintString ) - 1 - xLength;\r
+                       cPrintString[ sizeof( cPrintString ) - 1 ] = '\0';\r
+               }\r
+\r
+               xLength += xLength2;\r
+               va_end( args );\r
+\r
+               /* For ease of viewing, copy the string into another buffer, converting\r
+               IP addresses to dot notation on the way. */\r
+               pcSource = cPrintString;\r
+               pcTarget = cOutputString;\r
+\r
+               while( ( *pcSource ) != '\0' )\r
+               {\r
+                       *pcTarget = *pcSource;\r
+                       pcTarget++;\r
+                       pcSource++;\r
+\r
+                       /* Look forward for an IP address denoted by 'ip'. */\r
+                       if( ( isxdigit( pcSource[ 0 ] ) != pdFALSE ) && ( pcSource[ 1 ] == 'i' ) && ( pcSource[ 2 ] == 'p' ) )\r
+                       {\r
+                               *pcTarget = *pcSource;\r
+                               pcTarget++;\r
+                               *pcTarget = '\0';\r
+                               pcBegin = pcTarget - 8;\r
+\r
+                               while( ( pcTarget > pcBegin ) && ( isxdigit( pcTarget[ -1 ] ) != pdFALSE ) )\r
+                               {\r
+                                       pcTarget--;\r
+                               }\r
+\r
+                               sscanf( pcTarget, "%8X", &ulIPAddress );\r
+                               rc = sprintf( pcTarget, "%lu.%lu.%lu.%lu",\r
+                                       ( unsigned long ) ( ulIPAddress >> 24UL ),\r
+                                       ( unsigned long ) ( (ulIPAddress >> 16UL) & 0xffUL ),\r
+                                       ( unsigned long ) ( (ulIPAddress >> 8UL) & 0xffUL ),\r
+                                       ( unsigned long ) ( ulIPAddress & 0xffUL ) );\r
+                               pcTarget += rc;\r
+                               pcSource += 3; /* skip "<n>ip" */\r
+                       }\r
+               }\r
+\r
+               /* How far through the buffer was written? */\r
+               xLength = ( BaseType_t ) ( pcTarget - cOutputString );\r
+\r
+               /* If the message is to be logged to a UDP port then it can be sent directly\r
+               because it only uses FreeRTOS function (not Win32 functions). */\r
+               if( xUDPLoggingUsed != pdFALSE )\r
+               {\r
+                       if( ( xPrintSocket == FREERTOS_INVALID_SOCKET ) && ( FreeRTOS_IsNetworkUp() != pdFALSE ) )\r
+                       {\r
+                               /* Create and bind the socket to which print messages are sent.  The\r
+                               xTimerPendFunctionCall() function is used even though this is\r
+                               not an interrupt because this function is called from the IP task\r
+                               and the IP task cannot itself wait for a socket to bind.  The\r
+                               parameters to prvCreatePrintSocket() are not required so set to\r
+                               NULL or 0. */\r
+                               xTimerPendFunctionCall( prvCreatePrintSocket, NULL, 0, dlDONT_BLOCK );\r
+                       }\r
+\r
+                       if( xPrintSocket != FREERTOS_INVALID_SOCKET )\r
+                       {\r
+                               FreeRTOS_sendto( xPrintSocket, cOutputString, xLength, 0, &xPrintUDPAddress, sizeof( xPrintUDPAddress ) );\r
+\r
+                               /* Just because the UDP data logger I'm using is dumb. */\r
+                               FreeRTOS_sendto( xPrintSocket, "\r", sizeof( char ), 0, &xPrintUDPAddress, sizeof( xPrintUDPAddress ) );\r
+                       }\r
+               }\r
+\r
+               /* If logging is also to go to either stdout or a disk file then it cannot\r
+               be output here - so instead write the message to the stream buffer and wake\r
+               the Win32 thread which will read it from the stream buffer and perform the\r
+               actual output. */\r
+               if( ( xStdoutLoggingUsed != pdFALSE ) || ( xDiskFileLoggingUsed != pdFALSE ) )\r
+               {\r
+                       configASSERT( xLogStreamBuffer );\r
+\r
+                       /* How much space is in the buffer? */\r
+                       xLength2 = uxStreamBufferGetSpace( xLogStreamBuffer );\r
+\r
+                       /* There must be enough space to write both the string and the length of\r
+                       the string. */\r
+                       if( xLength2 >= ( xLength + sizeof( xLength ) ) )\r
+                       {\r
+                               /* First write in the length of the data, then write in the data\r
+                               itself.  Raising the thread priority is used as a critical section\r
+                               as there are potentially multiple writers.  The stream buffer is\r
+                               only thread safe when there is a single writer (likewise for\r
+                               reading from the buffer). */\r
+                               xCurrentTask = GetCurrentThread();\r
+                               iOriginalPriority = GetThreadPriority( xCurrentTask );\r
+                               SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );\r
+                               uxStreamBufferAdd( xLogStreamBuffer, 0, ( const uint8_t * ) &( xLength ), sizeof( xLength ) );\r
+                               uxStreamBufferAdd( xLogStreamBuffer, 0, ( const uint8_t * ) cOutputString, xLength );\r
+                               SetThreadPriority( GetCurrentThread(), iOriginalPriority );\r
+                       }\r
+\r
+                       /* xDirectPrint is initialised to pdTRUE, and while it remains true the\r
+                       logging output function is called directly.  When the system is running\r
+                       the output function cannot be called directly because it would get\r
+                       called from both FreeRTOS tasks and Win32 threads - so instead wake the\r
+                       Win32 thread responsible for the actual output. */\r
+                       if( xDirectPrint != pdFALSE )\r
+                       {\r
+                               /* While starting up, the thread which calls prvWin32LoggingThread()\r
+                               is not running yet and xDirectPrint will be pdTRUE. */\r
+                               prvLoggingFlushBuffer();\r
+                       }\r
+                       else if( pvLoggingThreadEvent != NULL )\r
+                       {\r
+                               /* While running, wake up prvWin32LoggingThread() to send the\r
+                               logging data. */\r
+                               SetEvent( pvLoggingThreadEvent );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvLoggingFlushBuffer( void )\r
+{\r
+size_t xLength;\r
+char cPrintString[ dlMAX_PRINT_STRING_LENGTH ];\r
+\r
+       /* Is there more than the length value stored in the circular buffer\r
+       used to pass data from the FreeRTOS simulator into this Win32 thread? */\r
+       while( uxStreamBufferGetSize( xLogStreamBuffer ) > sizeof( xLength ) )\r
+       {\r
+               memset( cPrintString, 0x00, dlMAX_PRINT_STRING_LENGTH );\r
+               uxStreamBufferGet( xLogStreamBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );\r
+               uxStreamBufferGet( xLogStreamBuffer, 0, ( uint8_t * ) cPrintString, xLength, pdFALSE );\r
+\r
+               /* Write the message to standard out if requested to do so when\r
+               vLoggingInit() was called, or if the network is not yet up. */\r
+               if( ( xStdoutLoggingUsed != pdFALSE ) || ( FreeRTOS_IsNetworkUp() == pdFALSE ) )\r
+               {\r
+                       /* Write the message to stdout. */\r
+                       printf( "%s", cPrintString ); /*_RB_ Replace with _write(). */\r
+               }\r
+\r
+               /* Write the message to a file if requested to do so when\r
+               vLoggingInit() was called. */\r
+               if( xDiskFileLoggingUsed != pdFALSE )\r
+               {\r
+                       prvLogToFile( cPrintString, xLength );\r
+               }\r
+       }\r
+\r
+       prvFileClose();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static DWORD WINAPI prvWin32LoggingThread( void *pvParameter )\r
+{\r
+const DWORD xMaxWait = 1000;\r
+\r
+       ( void ) pvParameter;\r
+\r
+       /* From now on, prvLoggingFlushBuffer() will only be called from this\r
+       Windows thread */\r
+       xDirectPrint = pdFALSE;\r
+\r
+       for( ;; )\r
+       {\r
+               /* Wait to be told there are message waiting to be logged. */\r
+               WaitForSingleObject( pvLoggingThreadEvent, xMaxWait );\r
+\r
+               /* Write out all waiting messages. */\r
+               prvLoggingFlushBuffer();\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvFileLoggingInit( void )\r
+{\r
+FILE *pxHandle = fopen( pcLogFileName, "a" );\r
+\r
+       if( pxHandle != NULL )\r
+       {\r
+               fseek( pxHandle, SEEK_END, 0ul );\r
+               ulSizeOfLoggingFile = ftell( pxHandle );\r
+               fclose( pxHandle );\r
+       }\r
+       else\r
+       {\r
+               ulSizeOfLoggingFile = 0ul;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvFileClose( void )\r
+{\r
+       if( pxLoggingFileHandle != NULL )\r
+       {\r
+               fclose( pxLoggingFileHandle );\r
+               pxLoggingFileHandle = NULL;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvLogToFile( const char *pcMessage, size_t xLength )\r
+{\r
+       if( pxLoggingFileHandle == NULL )\r
+       {\r
+               pxLoggingFileHandle = fopen( pcLogFileName, "a" );\r
+       }\r
+\r
+       if( pxLoggingFileHandle != NULL )\r
+       {\r
+               fwrite( pcMessage, 1, xLength, pxLoggingFileHandle );\r
+               ulSizeOfLoggingFile += xLength;\r
+\r
+               /* If the file has grown to its maximum permissible size then close and\r
+               rename it - then start with a new file. */\r
+               if( ulSizeOfLoggingFile > ( size_t ) dlLOGGING_FILE_SIZE )\r
+               {\r
+                       prvFileClose();\r
+                       if( _access( pcFullLogFileName, 00 ) == 0 )\r
+                       {\r
+                               remove( pcFullLogFileName );\r
+                       }\r
+                       rename( pcLogFileName, pcFullLogFileName );\r
+                       ulSizeOfLoggingFile = 0;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/demo_logging.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/demo_logging.h
new file mode 100644 (file)
index 0000000..e64ab70
--- /dev/null
@@ -0,0 +1,89 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+#ifndef DEMO_LOGGING_H\r
+#define DEMO_LOGGING_H\r
+\r
+/*\r
+ * Initialise a logging system that can be used from FreeRTOS tasks and Win32\r
+ * threads.  Do not call printf() directly while the scheduler is running.\r
+ *\r
+ * Set xLogToStdout, xLogToFile and xLogToUDP to either pdTRUE or pdFALSE to\r
+ * lot to stdout, a disk file and a UDP port respectively.\r
+ *\r
+ * If xLogToUDP is pdTRUE then ulRemoteIPAddress and usRemotePort must be set\r
+ * to the IP address and port number to which UDP log messages will be sent.\r
+ */\r
+void vLoggingInit(     BaseType_t xLogToStdout,\r
+                                       BaseType_t xLogToFile,\r
+                                       BaseType_t xLogToUDP,\r
+                                       uint32_t ulRemoteIPAddress,\r
+                                       uint16_t usRemotePort );\r
+\r
+#endif /* DEMO_LOGGING_H */\r
+\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/main.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/main.c
new file mode 100644 (file)
index 0000000..c008f37
--- /dev/null
@@ -0,0 +1,380 @@
+/*\r
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    All rights reserved\r
+\r
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\r
+    the terms of the GNU General Public License (version 2) as published by the\r
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+    ***************************************************************************\r
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
+    >>!   obliged to provide the source code for proprietary components     !<<\r
+    >>!   outside of the FreeRTOS kernel.                                   !<<\r
+    ***************************************************************************\r
+\r
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
+    link: http://www.freertos.org/a00114.html\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS provides completely free yet professionally developed,    *\r
+     *    robust, strictly quality controlled, supported, and cross          *\r
+     *    platform software that is more than just the market leader, it     *\r
+     *    is the industry's de facto standard.                               *\r
+     *                                                                       *\r
+     *    Help yourself get started quickly while simultaneously helping     *\r
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
+     *    tutorial book, reference manual, or both:                          *\r
+     *    http://www.FreeRTOS.org/Documentation                              *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
+    the FAQ page "My application does not run, what could be wrong?".  Have you\r
+    defined configASSERT()?\r
+\r
+    http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+    embedded software for free we request you assist our global community by\r
+    participating in the support forum.\r
+\r
+    http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+    be as productive as possible as early as possible.  Now you can receive\r
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+    Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
+    licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+    engineered and independently SIL3 certified version for use in safety and\r
+    mission critical applications that require provable dependability.\r
+\r
+    1 tab == 4 spaces!\r
+*/\r
+\r
+/*\r
+ * This project is a cut down version of the project described on the following\r
+ * link.  Only the simple UDP client and server and the TCP echo clients are\r
+ * included in the build:\r
+ * http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdio.h>\r
+#include <time.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include <FreeRTOS.h>\r
+#include "task.h"\r
+\r
+/* Demo application includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "SimpleUDPClientAndServer.h"\r
+#include "TCPEchoClient_SingleTasks.h"\r
+#include "demo_logging.h"\r
+\r
+/* Simple UDP client and server task parameters. */\r
+#define mainSIMPLE_UDP_CLIENT_SERVER_TASK_PRIORITY             ( tskIDLE_PRIORITY )\r
+#define mainSIMPLE_UDP_CLIENT_SERVER_PORT                              ( 5005UL )\r
+\r
+/* Echo client task parameters - used for both TCP and UDP echo clients. */\r
+#define mainECHO_CLIENT_TASK_STACK_SIZE                                ( configMINIMAL_STACK_SIZE * 2 )        /* Not used in the Windows port. */\r
+#define mainECHO_CLIENT_TASK_PRIORITY                                  ( tskIDLE_PRIORITY + 1 )\r
+\r
+/* Define a name that will be used for LLMNR and NBNS searches. */\r
+#define mainHOST_NAME                          "RTOSDemo"\r
+#define mainDEVICE_NICK_NAME           "windows_demo"\r
+\r
+/* Set the following constants to 1 or 0 to define which tasks to include and\r
+exclude:\r
+\r
+mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS:  When set to 1 two UDP client tasks\r
+and two UDP server tasks are created.  The clients talk to the servers.  One set\r
+of tasks use the standard sockets interface, and the other the zero copy sockets\r
+interface.  These tasks are self checking and will trigger a configASSERT() if\r
+they detect a difference in the data that is received from that which was sent.\r
+As these tasks use UDP, and can therefore loose packets, they will cause\r
+configASSERT() to be called when they are run in a less than perfect networking\r
+environment.\r
+\r
+mainCREATE_TCP_ECHO_TASKS_SINGLE:  When set to 1 a set of tasks are created that\r
+send TCP echo requests to the standard echo port (port 7), then wait for and\r
+verify the echo reply, from within the same task (Tx and Rx are performed in the\r
+same RTOS task).  The IP address of the echo server must be configured using the\r
+configECHO_SERVER_ADDR0 to configECHO_SERVER_ADDR3 constants in\r
+FreeRTOSConfig.h.\r
+*/\r
+#define mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS      1\r
+#define mainCREATE_TCP_ECHO_TASKS_SINGLE                       1\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Just seeds the simple pseudo random number generator.\r
+ */\r
+static void prvSRand( UBaseType_t ulSeed );\r
+\r
+/*\r
+ * Miscellaneous initialisation including preparing the logging and seeding the\r
+ * random number generator.\r
+ */\r
+static void prvMiscInitialisation( void );\r
+\r
+/* The default IP and MAC address used by the demo.  The address configuration\r
+defined here will be used if ipconfigUSE_DHCP is 0, or if ipconfigUSE_DHCP is\r
+1 but a DHCP server could not be contacted.  See the online documentation for\r
+more information. */\r
+static const uint8_t ucIPAddress[ 4 ] = { configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 };\r
+static const uint8_t ucNetMask[ 4 ] = { configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 };\r
+static const uint8_t ucGatewayAddress[ 4 ] = { configGATEWAY_ADDR0, configGATEWAY_ADDR1, configGATEWAY_ADDR2, configGATEWAY_ADDR3 };\r
+static const uint8_t ucDNSServerAddress[ 4 ] = { configDNS_SERVER_ADDR0, configDNS_SERVER_ADDR1, configDNS_SERVER_ADDR2, configDNS_SERVER_ADDR3 };\r
+\r
+/* Set the following constant to pdTRUE to log using the method indicated by the\r
+name of the constant, or pdFALSE to not log using the method indicated by the\r
+name of the constant.  Options include to standard out (xLogToStdout), to a disk\r
+file (xLogToFile), and to a UDP port (xLogToUDP).  If xLogToUDP is set to pdTRUE\r
+then UDP messages are sent to the IP address configured as the echo server\r
+address (see the configECHO_SERVER_ADDR0 definitions in FreeRTOSConfig.h) and\r
+the port number set by configPRINT_PORT in FreeRTOSConfig.h. */\r
+const BaseType_t xLogToStdout = pdTRUE, xLogToFile = pdFALSE, xLogToUDP = pdFALSE;\r
+\r
+/* Default MAC address configuration.  The demo creates a virtual network\r
+connection that uses this MAC address by accessing the raw Ethernet data\r
+to and from a real network connection on the host PC.  See the\r
+configNETWORK_INTERFACE_TO_USE definition for information on how to configure\r
+the real network connection to use. */\r
+const uint8_t ucMACAddress[ 6 ] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 };\r
+\r
+/* Use by the pseudo random number generator. */\r
+static UBaseType_t ulNextRand;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+int main( void )\r
+{\r
+const uint32_t ulLongTime_ms = pdMS_TO_TICKS( 1000UL );\r
+\r
+       /*\r
+        * Instructions for using this project are provided on:\r
+        * http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html\r
+        */\r
+\r
+       /* Miscellaneous initialisation including preparing the logging and seeding\r
+       the random number generator. */\r
+       prvMiscInitialisation();\r
+\r
+       /* Initialise the network interface.\r
+\r
+       ***NOTE*** Tasks that use the network are created in the network event hook\r
+       when the network is connected and ready for use (see the definition of\r
+       vApplicationIPNetworkEventHook() below).  The address values passed in here\r
+       are used if ipconfigUSE_DHCP is set to 0, or if ipconfigUSE_DHCP is set to 1\r
+       but a DHCP server cannot be     contacted. */\r
+       FreeRTOS_debug_printf( ( "FreeRTOS_IPInit\n" ) );\r
+       FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress );\r
+\r
+       /* Start the RTOS scheduler. */\r
+       FreeRTOS_debug_printf( ("vTaskStartScheduler\n") );\r
+       vTaskStartScheduler();\r
+\r
+       /* If all is well, the scheduler will now be running, and the following\r
+       line will never be reached.  If the following line does execute, then\r
+       there was insufficient FreeRTOS heap memory available for the idle and/or\r
+       timer tasks     to be created.  See the memory management section on the\r
+       FreeRTOS web site for more details (this is standard text that is not not\r
+       really applicable to the Win32 simulator port). */\r
+       for( ;; )\r
+       {\r
+               Sleep( ulLongTime_ms );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationIdleHook( void )\r
+{\r
+const uint32_t ulMSToSleep = 1;\r
+\r
+       /* This is just a trivial example of an idle hook.  It is called on each\r
+       cycle of the idle task if configUSE_IDLE_HOOK is set to 1 in\r
+       FreeRTOSConfig.h.  It must *NOT* attempt to block.  In this case the\r
+       idle task just sleeps to lower the CPU usage. */\r
+       Sleep( ulMSToSleep );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vAssertCalled( const char *pcFile, uint32_t ulLine )\r
+{\r
+const uint32_t ulLongSleep = 1000UL;\r
+volatile uint32_t ulBlockVariable = 0UL;\r
+volatile char *pcFileName = ( volatile char *  ) pcFile;\r
+volatile uint32_t ulLineNumber = ulLine;\r
+\r
+       ( void ) pcFileName;\r
+       ( void ) ulLineNumber;\r
+\r
+       FreeRTOS_debug_printf( ( "vAssertCalled( %s, %ld\n", pcFile, ulLine ) );\r
+\r
+       /* Setting ulBlockVariable to a non-zero value in the debugger will allow\r
+       this function to be exited. */\r
+       taskDISABLE_INTERRUPTS();\r
+       {\r
+               while( ulBlockVariable == 0UL )\r
+               {\r
+                       Sleep( ulLongSleep );\r
+               }\r
+       }\r
+       taskENABLE_INTERRUPTS();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Called by FreeRTOS+TCP when the network connects or disconnects.  Disconnect\r
+events are only received if implemented in the MAC driver. */\r
+void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )\r
+{\r
+uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress;\r
+char cBuffer[ 16 ];\r
+static BaseType_t xTasksAlreadyCreated = pdFALSE;\r
+\r
+       /* If the network has just come up...*/\r
+       if( eNetworkEvent == eNetworkUp )\r
+       {\r
+               /* Create the tasks that use the IP stack if they have not already been\r
+               created. */\r
+               if( xTasksAlreadyCreated == pdFALSE )\r
+               {\r
+                       /* See the comments above the definitions of these pre-processor\r
+                       macros at the top of this file for a description of the individual\r
+                       demo tasks. */\r
+                       #if( mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS == 1 )\r
+                       {\r
+                               vStartSimpleUDPClientServerTasks( configMINIMAL_STACK_SIZE, mainSIMPLE_UDP_CLIENT_SERVER_PORT, mainSIMPLE_UDP_CLIENT_SERVER_TASK_PRIORITY );\r
+                       }\r
+                       #endif /* mainCREATE_SIMPLE_UDP_CLIENT_SERVER_TASKS */\r
+\r
+                       #if( mainCREATE_TCP_ECHO_TASKS_SINGLE == 1 )\r
+                       {\r
+                               vStartTCPEchoClientTasks_SingleTasks( mainECHO_CLIENT_TASK_STACK_SIZE, mainECHO_CLIENT_TASK_PRIORITY );\r
+                       }\r
+                       #endif /* mainCREATE_TCP_ECHO_TASKS_SINGLE */\r
+\r
+                       xTasksAlreadyCreated = pdTRUE;\r
+               }\r
+\r
+               /* Print out the network configuration, which may have come from a DHCP\r
+               server. */\r
+               FreeRTOS_GetAddressConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSServerAddress );\r
+               FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );\r
+               FreeRTOS_printf( ( "\r\n\r\nIP Address: %s\r\n", cBuffer ) );\r
+\r
+               FreeRTOS_inet_ntoa( ulNetMask, cBuffer );\r
+               FreeRTOS_printf( ( "Subnet Mask: %s\r\n", cBuffer ) );\r
+\r
+               FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer );\r
+               FreeRTOS_printf( ( "Gateway Address: %s\r\n", cBuffer ) );\r
+\r
+               FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer );\r
+               FreeRTOS_printf( ( "DNS Server Address: %s\r\n\r\n\r\n", cBuffer ) );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationMallocFailedHook( void )\r
+{\r
+       /* Called if a call to pvPortMalloc() fails because there is insufficient\r
+       free memory available in the FreeRTOS heap.  pvPortMalloc() is called\r
+       internally by FreeRTOS API functions that create tasks, queues, software\r
+       timers, and semaphores.  The size of the FreeRTOS heap is set by the\r
+       configTOTAL_HEAP_SIZE configuration constant in FreeRTOSConfig.h. */\r
+       vAssertCalled( __FILE__, __LINE__ );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+UBaseType_t uxRand( void )\r
+{\r
+const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;\r
+\r
+       /* Utility function to generate a pseudo random number. */\r
+\r
+       ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;\r
+       return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSRand( UBaseType_t ulSeed )\r
+{\r
+       /* Utility function to seed the pseudo random number generator. */\r
+    ulNextRand = ulSeed;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMiscInitialisation( void )\r
+{\r
+time_t xTimeNow;\r
+uint32_t ulLoggingIPAddress;\r
+\r
+       ulLoggingIPAddress = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, configECHO_SERVER_ADDR1, configECHO_SERVER_ADDR2, configECHO_SERVER_ADDR3 );\r
+       vLoggingInit( xLogToStdout, xLogToFile, xLogToUDP, ulLoggingIPAddress, configPRINT_PORT );\r
+\r
+       /* Seed the random number generator. */\r
+       time( &xTimeNow );\r
+       FreeRTOS_debug_printf( ( "Seed for randomiser: %lu\n", xTimeNow ) );\r
+       prvSRand( ( uint32_t ) xTimeNow );\r
+       FreeRTOS_debug_printf( ( "Random numbers: %08X %08X %08X %08X\n", ipconfigRAND32(), ipconfigRAND32(), ipconfigRAND32(), ipconfigRAND32() ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) || ( ipconfigDHCP_REGISTER_HOSTNAME == 1 )\r
+\r
+       const char *pcApplicationHostnameHook( void )\r
+       {\r
+               /* Assign the name "FreeRTOS" to this network node.  This function will\r
+               be called during the DHCP: the machine will be registered with an IP\r
+               address plus this name. */\r
+               return mainHOST_NAME;\r
+       }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 )\r
+\r
+       BaseType_t xApplicationDNSQueryHook( const char *pcName )\r
+       {\r
+       BaseType_t xReturn;\r
+\r
+               /* Determine if a name lookup is for this node.  Two names are given\r
+               to this node: that returned by pcApplicationHostnameHook() and that set\r
+               by mainDEVICE_NICK_NAME. */\r
+               if( _stricmp( pcName, pcApplicationHostnameHook() ) == 0 )\r
+               {\r
+                       xReturn = pdPASS;\r
+               }\r
+               else if( _stricmp( pcName, mainDEVICE_NICK_NAME ) == 0 )\r
+               {\r
+                       xReturn = pdPASS;\r
+               }\r
+               else\r
+               {\r
+                       xReturn = pdFAIL;\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/printf-stdarg.c b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/printf-stdarg.c
new file mode 100644 (file)
index 0000000..5505535
--- /dev/null
@@ -0,0 +1,667 @@
+/*\r
+       Copyright 2001, 2002 Georges Menie (www.menie.org)\r
+       stdarg version contributed by Christian Ettinger\r
+\r
+       This program is free software; you can redistribute it and/or modify\r
+       it under the terms of the GNU Lesser General Public License as published by\r
+       the Free Software Foundation; either version 2 of the License, or\r
+       (at your option) any later version.\r
+\r
+       Changes for the FreeRTOS ports:\r
+\r
+       - The dot in "%-8.8s"\r
+       - The specifiers 'l' (long) and 'L' (long long)\r
+       - The specifier 'u' for unsigned\r
+       - Dot notation for IP addresses:\r
+         sprintf("IP = %xip\n", 0xC0A80164);\r
+      will produce "IP = 192.168.1.100\n"\r
+*/\r
+\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "FreeRTOS.h"\r
+\r
+#define PAD_RIGHT 1\r
+#define PAD_ZERO 2\r
+\r
+/*\r
+ * Return 1 for readable, 2 for writeable, 3 for both.\r
+ * Function must be provided by the application.\r
+ */\r
+extern BaseType_t xApplicationMemoryPermissions( uint32_t aAddress );\r
+\r
+extern void vOutputChar( const char cChar, const TickType_t xTicksToWait  );\r
+static const TickType_t xTicksToWait = pdMS_TO_TICKS( 20 );\r
+\r
+struct xPrintFlags\r
+{\r
+       int base;\r
+       int width;\r
+       int printLimit;\r
+       unsigned\r
+               pad : 8,\r
+               letBase : 8,\r
+               isSigned : 1,\r
+               isNumber : 1,\r
+               long32 : 1,\r
+               long64 : 1;\r
+};\r
+\r
+struct SStringBuf\r
+{\r
+       char *str;\r
+       const char *orgStr;\r
+       const char *nulPos;\r
+       int curLen;\r
+       struct xPrintFlags flags;\r
+};\r
+\r
+static void strbuf_init( struct SStringBuf *apStr, char *apBuf, const char *apMaxStr )\r
+{\r
+       apStr->str = apBuf;\r
+       apStr->orgStr = apBuf;\r
+       apStr->nulPos = apMaxStr-1;\r
+       apStr->curLen = 0;\r
+\r
+       memset( &apStr->flags, '\0', sizeof( apStr->flags ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t strbuf_printchar( struct SStringBuf *apStr, int c )\r
+{\r
+       if( apStr->str == NULL )\r
+       {\r
+               vOutputChar( ( char ) c, xTicksToWait );\r
+               apStr->curLen++;\r
+               return pdTRUE;\r
+       }\r
+       if( apStr->str < apStr->nulPos )\r
+       {\r
+               *( apStr->str++ ) = c;\r
+               apStr->curLen++;\r
+               return pdTRUE;\r
+       }\r
+       if( apStr->str == apStr->nulPos )\r
+       {\r
+               *( apStr->str++ ) = '\0';\r
+       }\r
+       return pdFALSE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE BaseType_t strbuf_printchar_inline( struct SStringBuf *apStr, int c )\r
+{\r
+       if( apStr->str == NULL )\r
+       {\r
+               vOutputChar( ( char ) c, xTicksToWait );\r
+               if( c == 0 )\r
+               {\r
+                       return pdFALSE;\r
+               }\r
+               apStr->curLen++;\r
+               return pdTRUE;\r
+       }\r
+       if( apStr->str < apStr->nulPos )\r
+       {\r
+               *(apStr->str++) = c;\r
+               if( c == 0 )\r
+               {\r
+                       return pdFALSE;\r
+               }\r
+               apStr->curLen++;\r
+               return pdTRUE;\r
+       }\r
+       if( apStr->str == apStr->nulPos )\r
+       {\r
+               *( apStr->str++ ) = '\0';\r
+       }\r
+       return pdFALSE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE int i2hex( int aCh )\r
+{\r
+int iResult;\r
+\r
+       if( aCh < 10 )\r
+       {\r
+               iResult = '0' + aCh;\r
+       }\r
+       else\r
+       {\r
+               iResult = 'A' + aCh - 10;\r
+       }\r
+\r
+       return iResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prints(struct SStringBuf *apBuf, const char *apString )\r
+{\r
+       register int padchar = ' ';\r
+       int i,len;\r
+\r
+       if( xApplicationMemoryPermissions( ( uint32_t )apString ) == 0 )\r
+       {\r
+               /* The user has probably made a mistake with the parameter\r
+               for '%s', the memory is not readbale. */\r
+               apString = "INV_MEM";\r
+       }\r
+\r
+       if( apBuf->flags.width > 0 )\r
+       {\r
+               register int len = 0;\r
+               register const char *ptr;\r
+               for( ptr = apString; *ptr; ++ptr )\r
+               {\r
+                       ++len;\r
+               }\r
+\r
+               if( len >= apBuf->flags.width )\r
+               {\r
+                       apBuf->flags.width = 0;\r
+               }\r
+               else\r
+               {\r
+                       apBuf->flags.width -= len;\r
+               }\r
+\r
+               if( apBuf->flags.pad & PAD_ZERO )\r
+               {\r
+                       padchar = '0';\r
+               }\r
+       }\r
+       if( ( apBuf->flags.pad & PAD_RIGHT ) == 0 )\r
+       {\r
+               for( ; apBuf->flags.width > 0; --apBuf->flags.width )\r
+               {\r
+                       if( strbuf_printchar( apBuf, padchar ) == 0 )\r
+                       {\r
+                               return pdFALSE;\r
+                       }\r
+               }\r
+       }\r
+       if( ( apBuf->flags.isNumber == pdTRUE ) && ( apBuf->flags.pad == pdTRUE ) )\r
+       {\r
+               /* The string to print represents an integer number.\r
+                * In this case, printLimit is the min number of digits to print\r
+                * If the length of the number to print is less than the min nb of i\r
+                * digits to display, we add 0 before printing the number\r
+                */\r
+               len = strlen( apString );\r
+\r
+               if( len < apBuf->flags.printLimit )\r
+               {\r
+                       i = apBuf->flags.printLimit - len;\r
+                       for( ; i; i-- )\r
+                       {\r
+                               if( strbuf_printchar( apBuf, '0' )  == 0 )\r
+                               {\r
+                                       return pdFALSE;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       /* The string to print is not the result of a number conversion to ascii.\r
+        * For a string, printLimit is the max number of characters to display\r
+        */\r
+       for( ; apBuf->flags.printLimit && *apString ; ++apString, --apBuf->flags.printLimit )\r
+       {\r
+               if( !strbuf_printchar( apBuf, *apString ) )\r
+               {\r
+                       return pdFALSE;\r
+               }\r
+       }\r
+\r
+       for( ; apBuf->flags.width > 0; --apBuf->flags.width )\r
+       {\r
+               if( !strbuf_printchar( apBuf, padchar ) )\r
+               {\r
+                       return pdFALSE;\r
+               }\r
+       }\r
+\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* the following should be enough for 32 bit int */\r
+#define PRINT_BUF_LEN 12       /* to print 4294967296 */\r
+\r
+#if    SPRINTF_LONG_LONG\r
+#warning 64-bit libraries will be included as well\r
+static BaseType_t printll( struct SStringBuf *apBuf, long long i )\r
+{\r
+       char print_buf[ 2 * PRINT_BUF_LEN ];\r
+       register char *s;\r
+       register int t, neg = 0;\r
+       register unsigned long long u = i;\r
+       lldiv_t lldiv_result;\r
+\r
+/* typedef struct\r
+ * {\r
+ *     long long int quot; // quotient\r
+ *     long long int rem;  // remainder\r
+ * } lldiv_t;\r
+ */\r
+\r
+       apBuf->flags.isNumber = pdTRUE; /* Parameter for prints */\r
+       if( i == 0LL )\r
+       {\r
+               print_buf[ 0 ] = '0';\r
+               print_buf[ 1 ] = '\0';\r
+               return prints( apBuf, print_buf );\r
+       }\r
+\r
+       if( ( apBuf->flags.isSigned == pdTRUE ) && ( apBuf->flags.base == 10 ) && ( i < 0LL ) )\r
+       {\r
+               neg = 1;\r
+               u = -i;\r
+       }\r
+\r
+       s = print_buf + sizeof( print_buf ) - 1;\r
+\r
+       *s = '\0';\r
+       /* 18446744073709551616 */\r
+       while( u != 0 )\r
+       {\r
+               lldiv_result = lldiv( u, ( unsigned long long ) apBuf->flags.base );\r
+               t = lldiv_result.rem;\r
+               if( t >= 10 )\r
+               {\r
+                       t += apBuf->flags.letBase - '0' - 10;\r
+               }\r
+               *( --s ) = t + '0';\r
+               u = lldiv_result.quot;\r
+       }\r
+\r
+       if( neg != 0 )\r
+       {\r
+               if( ( apBuf->flags.width != 0 ) && ( apBuf->flags.pad & PAD_ZERO ) )\r
+               {\r
+                       if( !strbuf_printchar( apBuf, '-' ) )\r
+                       {\r
+                               return pdFALSE;\r
+                       }\r
+                       --apBuf->flags.width;\r
+               }\r
+               else\r
+               {\r
+                       *( --s ) = '-';\r
+               }\r
+       }\r
+\r
+       return prints( apBuf, s );\r
+}\r
+#endif /* SPRINTF_LONG_LONG */\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t printi( struct SStringBuf *apBuf, int i )\r
+{\r
+       char print_buf[ PRINT_BUF_LEN ];\r
+       register char *s;\r
+       register int t, neg = 0;\r
+       register unsigned int u = i;\r
+       register unsigned base = apBuf->flags.base;\r
+\r
+       apBuf->flags.isNumber = pdTRUE; /* Parameter for prints */\r
+\r
+       if( i == 0 )\r
+       {\r
+               print_buf[ 0 ] = '0';\r
+               print_buf[ 1 ] = '\0';\r
+               return prints( apBuf, print_buf );\r
+       }\r
+\r
+       if( ( apBuf->flags.isSigned == pdTRUE ) && ( base == 10 ) && ( i < 0 ) )\r
+       {\r
+               neg = 1;\r
+               u = -i;\r
+       }\r
+\r
+       s = print_buf + sizeof( print_buf ) - 1;\r
+\r
+       *s = '\0';\r
+       switch( base )\r
+       {\r
+       case 16:\r
+               while( u != 0 )\r
+               {\r
+                       t = u & 0xF;\r
+                       if( t >= 10 )\r
+                       {\r
+                               t += apBuf->flags.letBase - '0' - 10;\r
+                       }\r
+                       *( --s ) = t + '0';\r
+                       u >>= 4;\r
+               }\r
+               break;\r
+\r
+       case 8:\r
+       case 10:\r
+               /* GCC compiles very efficient */\r
+               while( u )\r
+               {\r
+                       t = u % base;\r
+                       *( --s ) = t + '0';\r
+                       u /= base;\r
+               }\r
+               break;\r
+/*\r
+       // The generic case, not yet in use\r
+       default:\r
+               while( u )\r
+               {\r
+                       t = u % base;\r
+                       if( t >= 10)\r
+                       {\r
+                               t += apBuf->flags.letBase - '0' - 10;\r
+                       }\r
+                       *( --s ) = t + '0';\r
+                       u /= base;\r
+               }\r
+               break;\r
+*/\r
+       }\r
+\r
+       if( neg != 0 )\r
+       {\r
+               if( apBuf->flags.width && (apBuf->flags.pad & PAD_ZERO ) )\r
+               {\r
+                       if( strbuf_printchar( apBuf, '-' ) == 0 )\r
+                       {\r
+                               return pdFALSE;\r
+                       }\r
+                       --apBuf->flags.width;\r
+               }\r
+               else\r
+               {\r
+                       *( --s ) = '-';\r
+               }\r
+       }\r
+\r
+       return prints( apBuf, s );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t printIp(struct SStringBuf *apBuf, unsigned i )\r
+{\r
+       char print_buf[16];\r
+\r
+       sprintf( print_buf, "%u.%u.%u.%u",\r
+               i >> 24,\r
+               ( i >> 16 ) & 0xff,\r
+               ( i >> 8 ) & 0xff,\r
+               i & 0xff );\r
+       apBuf->flags.isNumber = pdTRUE; /* Parameter for prints */\r
+       prints( apBuf, print_buf );\r
+\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void tiny_print( struct SStringBuf *apBuf, const char *format, va_list args )\r
+{\r
+       char scr[2];\r
+\r
+       for( ; ; )\r
+       {\r
+               int ch = *( format++ );\r
+\r
+               if( ch != '%' )\r
+               {\r
+                       do\r
+                       {\r
+                               /* Put the most like flow in a small loop */\r
+                               if( strbuf_printchar_inline( apBuf, ch ) == 0 )\r
+                               {\r
+                                       return;\r
+                               }\r
+                               ch = *( format++ );\r
+                       } while( ch != '%' );\r
+               }\r
+               ch = *( format++ );\r
+               /* Now ch has character after '%', format pointing to next */\r
+\r
+               if( ch == '\0' )\r
+               {\r
+                       break;\r
+               }\r
+               if( ch == '%' )\r
+               {\r
+                       if( strbuf_printchar( apBuf, ch ) == 0 )\r
+                       {\r
+                               return;\r
+                       }\r
+                       continue;\r
+               }\r
+               memset( &apBuf->flags, '\0', sizeof( apBuf->flags ) );\r
+\r
+               if( ch == '-' )\r
+               {\r
+                       ch = *( format++ );\r
+                       apBuf->flags.pad = PAD_RIGHT;\r
+               }\r
+               while( ch == '0' )\r
+               {\r
+                       ch = *( format++ );\r
+                       apBuf->flags.pad |= PAD_ZERO;\r
+               }\r
+               if( ch == '*' )\r
+               {\r
+                       ch = *( format++ );\r
+                       apBuf->flags.width = va_arg( args, int );\r
+               }\r
+               else\r
+               {\r
+                       while( ch >= '0' && ch <= '9' )\r
+                       {\r
+                               apBuf->flags.width *= 10;\r
+                               apBuf->flags.width += ch - '0';\r
+                               ch = *( format++ );\r
+                       }\r
+               }\r
+               if( ch == '.' )\r
+               {\r
+                       ch = *( format++ );\r
+                       if( ch == '*' )\r
+                       {\r
+                               apBuf->flags.printLimit = va_arg( args, int );\r
+                               ch = *( format++ );\r
+                       }\r
+                       else\r
+                       {\r
+                               while( ch >= '0' && ch <= '9' )\r
+                               {\r
+                                       apBuf->flags.printLimit *= 10;\r
+                                       apBuf->flags.printLimit += ch - '0';\r
+                                       ch = *( format++ );\r
+                               }\r
+                       }\r
+               }\r
+               if( apBuf->flags.printLimit == 0 )\r
+               {\r
+                       apBuf->flags.printLimit--;  /* -1: make it unlimited */\r
+               }\r
+               if( ch == 's' )\r
+               {\r
+                       register char *s = ( char * )va_arg( args, int );\r
+                       if( prints( apBuf, s ? s : "(null)" ) == 0 )\r
+                       {\r
+                               break;\r
+                       }\r
+                       continue;\r
+               }\r
+               if( ch == 'c' )\r
+               {\r
+                       /* char are converted to int then pushed on the stack */\r
+                       scr[0] = ( char ) va_arg( args, int );\r
+\r
+                       if( strbuf_printchar( apBuf, scr[0] )  == 0 )\r
+                       {\r
+                               return;\r
+                       }\r
+\r
+                       continue;\r
+               }\r
+               if( ch == 'l' )\r
+               {\r
+                       ch = *( format++ );\r
+                       apBuf->flags.long32 = 1;\r
+                       /* Makes not difference as u32 == long */\r
+               }\r
+               if( ch == 'L' )\r
+               {\r
+                       ch = *( format++ );\r
+                       apBuf->flags.long64 = 1;\r
+                       /* Does make a difference */\r
+               }\r
+               apBuf->flags.base = 10;\r
+               apBuf->flags.letBase = 'a';\r
+\r
+               if( ch == 'd' || ch == 'u' )\r
+               {\r
+                       apBuf->flags.isSigned = ( ch == 'd' );\r
+#if    SPRINTF_LONG_LONG\r
+                       if( apBuf->flags.long64 != pdFALSE )\r
+                       {\r
+                               if( printll( apBuf, va_arg( args, long long ) ) == 0 )\r
+                               {\r
+                                       break;\r
+                               }\r
+                       } else\r
+#endif /* SPRINTF_LONG_LONG */\r
+                       if( printi( apBuf, va_arg( args, int ) ) == 0 )\r
+                       {\r
+                               break;\r
+                       }\r
+                       continue;\r
+               }\r
+\r
+               apBuf->flags.base = 16;         /* From here all hexadecimal */\r
+\r
+               if( ch == 'x' && format[0] == 'i' && format[1] == 'p' )\r
+               {\r
+                       format += 2;    /* eat the "xi" of "xip" */\r
+                       /* Will use base 10 again */\r
+                       if( printIp( apBuf, va_arg( args, int ) ) == 0 )\r
+                       {\r
+                               break;\r
+                       }\r
+                       continue;\r
+               }\r
+               if( ch == 'x' || ch == 'X' || ch == 'p' || ch == 'o' )\r
+               {\r
+                       if( ch == 'X' )\r
+                       {\r
+                               apBuf->flags.letBase = 'A';\r
+                       }\r
+                       else if( ch == 'o' )\r
+                       {\r
+                               apBuf->flags.base = 8;\r
+                       }\r
+#if    SPRINTF_LONG_LONG\r
+                       if( apBuf->flags.long64 != pdFALSE )\r
+                       {\r
+                               if( printll( apBuf, va_arg( args, long long ) ) == 0 )\r
+                               {\r
+                                       break;\r
+                               }\r
+                       } else\r
+#endif /* SPRINTF_LONG_LONG */\r
+                       if( printi( apBuf, va_arg( args, int ) ) == 0 )\r
+                       {\r
+                               break;\r
+                       }\r
+                       continue;\r
+               }\r
+       }\r
+       strbuf_printchar( apBuf, '\0' );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+int vsnprintf( char *apBuf, size_t aMaxLen, const char *apFmt, va_list args )\r
+{\r
+       struct SStringBuf strBuf;\r
+       strbuf_init( &strBuf, apBuf, ( const char* )apBuf + aMaxLen );\r
+       tiny_print( &strBuf, apFmt, args );\r
+\r
+       return strBuf.curLen;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+int snprintf( char *apBuf, size_t aMaxLen, const char *apFmt, ... )\r
+{\r
+       va_list args;\r
+\r
+       va_start( args,  apFmt );\r
+       struct SStringBuf strBuf;\r
+       strbuf_init( &strBuf, apBuf, ( const char* )apBuf + aMaxLen );\r
+       tiny_print( &strBuf, apFmt, args );\r
+       va_end( args );\r
+\r
+       return strBuf.curLen;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+int sprintf( char *apBuf, const char *apFmt, ... )\r
+{\r
+       va_list args;\r
+\r
+       va_start( args,  apFmt );\r
+       struct SStringBuf strBuf;\r
+       strbuf_init( &strBuf, apBuf, ( const char * )apBuf + 1024 );\r
+       tiny_print( &strBuf, apFmt, args );\r
+       va_end( args );\r
+\r
+       return strBuf.curLen;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+int vsprintf( char *apBuf, const char *apFmt, va_list args )\r
+{\r
+       struct SStringBuf strBuf;\r
+       strbuf_init( &strBuf, apBuf, ( const char* ) apBuf + 1024 );\r
+       tiny_print( &strBuf, apFmt, args );\r
+\r
+       return strBuf.curLen;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+const char *mkSize (unsigned long long aSize, char *apBuf, int aLen)\r
+{\r
+static char retString[33];\r
+size_t gb, mb, kb, sb;\r
+\r
+       if (apBuf == NULL) {\r
+               apBuf = retString;\r
+               aLen = sizeof( retString );\r
+       }\r
+       gb = aSize / (1024*1024*1024);\r
+       aSize -= gb * (1024*1024*1024);\r
+       mb = aSize / (1024*1024);\r
+       aSize -= mb * (1024*1024);\r
+       kb = aSize / (1024);\r
+       aSize -= kb * (1024);\r
+       sb = aSize;\r
+       if( gb )\r
+       {\r
+               snprintf (apBuf, aLen, "%u.%02u GB", ( unsigned ) gb, ( unsigned ) ( ( 100 * mb ) / 1024ul ) );\r
+       }\r
+       else if( mb )\r
+       {\r
+               snprintf (apBuf, aLen, "%u.%02u MB", ( unsigned ) mb, ( unsigned ) ( ( 100 * kb) / 1024ul ) );\r
+       }\r
+       else if( kb != 0ul )\r
+       {\r
+               snprintf (apBuf, aLen, "%u.%02u KB", ( unsigned ) kb, ( unsigned ) ( ( 100 * sb) / 1024ul ) );\r
+       }\r
+       else\r
+       {\r
+               snprintf (apBuf, aLen, "%u bytes", ( unsigned ) sb);\r
+       }\r
+       return apBuf;\r
+}\r
index ed0774e309b5901c3525e5a2a4a01005b4ab51ce..b97ce71fcf1e39f8784b1d7d766727e5a33e20b7 100644 (file)
@@ -5,14 +5,14 @@
                        <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.crt.advproject.config.exe.debug.56486929" moduleId="org.eclipse.cdt.core.settings" name="Debug">\r
                                <externalSettings/>\r
                                <extensions>\r
+                                       <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>\r
+                                       <extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>\r
                                        <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
                                        <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>\r
                                        <extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
                                        <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
                                        <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
                                        <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>\r
-                                       <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>\r
-                                       <extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>\r
                                </extensions>\r
                        </storageModule>\r
                        <storageModule moduleId="cdtBuildSystem" version="4.0.0">\r
@@ -79,6 +79,7 @@
                                                                <option id="gnu.c.link.option.nodeflibs.2072403274" name="Do not use default libraries (-nodefaultlibs)" superClass="gnu.c.link.option.nodeflibs" value="false" valueType="boolean"/>\r
                                                                <option id="com.crt.advproject.link.gcc.multicore.slave.1911982348" name="Multicore slave" superClass="com.crt.advproject.link.gcc.multicore.slave"/>\r
                                                                <option id="com.crt.advproject.link.gcc.multicore.master.userobjs.502901386" superClass="com.crt.advproject.link.gcc.multicore.master.userobjs" valueType="userObjs"/>\r
+                                                               <option id="com.crt.advproject.link.memory.heapAndStack.1733504656" superClass="com.crt.advproject.link.memory.heapAndStack" value="&amp;Heap:Default;Post Data;Default&amp;Stack:Default;End;Default" valueType="string"/>\r
                                                                <inputType id="cdt.managedbuild.tool.gnu.c.linker.input.1085761099" superClass="cdt.managedbuild.tool.gnu.c.linker.input">\r
                                                                        <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>\r
                                                                        <additionalInput kind="additionalinput" paths="$(LIBS)"/>\r
                                                        </tool>\r
                                                </toolChain>\r
                                        </folderInfo>\r
-                                       <folderInfo id="com.crt.advproject.config.exe.debug.56486929.1781697322" name="/" resourcePath="ThirdParty/CMSISv2p10_LPC18xx_DriverLib">\r
-                                               <toolChain id="com.crt.advproject.toolchain.exe.debug.222538953" name="Code Red MCU Tools" superClass="com.crt.advproject.toolchain.exe.debug" unusedChildren="">\r
-                                                       <targetPlatform binaryParser="org.eclipse.cdt.core.ELF;org.eclipse.cdt.core.GNU_ELF" id="com.crt.advproject.platform.exe.debug" name="ARM-based MCU (Debug)" superClass="com.crt.advproject.platform.exe.debug"/>\r
-                                                       <tool id="com.crt.advproject.cpp.exe.debug.906161578" name="MCU C++ Compiler" superClass="com.crt.advproject.cpp.exe.debug.359174792"/>\r
-                                                       <tool id="com.crt.advproject.gcc.exe.debug.1015468334" name="MCU C Compiler" superClass="com.crt.advproject.gcc.exe.debug.517029683">\r
-                                                               <option id="com.crt.advproject.gcc.exe.debug.option.optimization.level.2021633161" name="Optimization Level" superClass="com.crt.advproject.gcc.exe.debug.option.optimization.level" value="gnu.c.optimization.level.size" valueType="enumerated"/>\r
-                                                               <inputType id="com.crt.advproject.compiler.input.1878730423" superClass="com.crt.advproject.compiler.input"/>\r
-                                                       </tool>\r
-                                                       <tool id="com.crt.advproject.gas.exe.debug.253843695" name="MCU Assembler" superClass="com.crt.advproject.gas.exe.debug.281614531">\r
-                                                               <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1935362347" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>\r
-                                                               <inputType id="com.crt.advproject.assembler.input.190369423" name="Additional Assembly Source Files" superClass="com.crt.advproject.assembler.input"/>\r
-                                                       </tool>\r
-                                                       <tool id="com.crt.advproject.link.cpp.exe.debug.1715304950" name="MCU C++ Linker" superClass="com.crt.advproject.link.cpp.exe.debug.1490011469"/>\r
-                                                       <tool id="com.crt.advproject.link.exe.debug.536813209" name="MCU Linker" superClass="com.crt.advproject.link.exe.debug.1212311005"/>\r
-                                               </toolChain>\r
-                                       </folderInfo>\r
+                                       <fileInfo id="com.crt.advproject.config.exe.debug.56486929.src/cr_startup_lpc18xx.cpp" name="cr_startup_lpc18xx.cpp" rcbsApplicability="disable" resourcePath="src/cr_startup_lpc18xx.cpp" toolsToInvoke=""/>\r
                                        <folderInfo id="com.crt.advproject.config.exe.debug.56486929.2106668528" name="/" resourcePath="ThirdParty/USB_CDC">\r
                                                <toolChain id="com.crt.advproject.toolchain.exe.debug.1865989435" name="Code Red MCU Tools" superClass="com.crt.advproject.toolchain.exe.debug" unusedChildren="">\r
                                                        <targetPlatform binaryParser="org.eclipse.cdt.core.ELF;org.eclipse.cdt.core.GNU_ELF" id="com.crt.advproject.platform.exe.debug" name="ARM-based MCU (Debug)" superClass="com.crt.advproject.platform.exe.debug"/>\r
                                                        <tool id="com.crt.advproject.link.exe.debug.1734116997" name="MCU Linker" superClass="com.crt.advproject.link.exe.debug.1212311005"/>\r
                                                </toolChain>\r
                                        </folderInfo>\r
-                                       <fileInfo id="com.crt.advproject.config.exe.debug.56486929.src/cr_startup_lpc18xx.cpp" name="cr_startup_lpc18xx.cpp" rcbsApplicability="disable" resourcePath="src/cr_startup_lpc18xx.cpp" toolsToInvoke=""/>\r
+                                       <folderInfo id="com.crt.advproject.config.exe.debug.56486929.1781697322" name="/" resourcePath="ThirdParty/CMSISv2p10_LPC18xx_DriverLib">\r
+                                               <toolChain id="com.crt.advproject.toolchain.exe.debug.222538953" name="Code Red MCU Tools" superClass="com.crt.advproject.toolchain.exe.debug" unusedChildren="">\r
+                                                       <targetPlatform binaryParser="org.eclipse.cdt.core.ELF;org.eclipse.cdt.core.GNU_ELF" id="com.crt.advproject.platform.exe.debug" name="ARM-based MCU (Debug)" superClass="com.crt.advproject.platform.exe.debug"/>\r
+                                                       <tool id="com.crt.advproject.cpp.exe.debug.906161578" name="MCU C++ Compiler" superClass="com.crt.advproject.cpp.exe.debug.359174792"/>\r
+                                                       <tool id="com.crt.advproject.gcc.exe.debug.1015468334" name="MCU C Compiler" superClass="com.crt.advproject.gcc.exe.debug.517029683">\r
+                                                               <option id="com.crt.advproject.gcc.exe.debug.option.optimization.level.2021633161" name="Optimization Level" superClass="com.crt.advproject.gcc.exe.debug.option.optimization.level" value="gnu.c.optimization.level.size" valueType="enumerated"/>\r
+                                                               <inputType id="com.crt.advproject.compiler.input.1878730423" superClass="com.crt.advproject.compiler.input"/>\r
+                                                       </tool>\r
+                                                       <tool id="com.crt.advproject.gas.exe.debug.253843695" name="MCU Assembler" superClass="com.crt.advproject.gas.exe.debug.281614531">\r
+                                                               <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1935362347" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>\r
+                                                               <inputType id="com.crt.advproject.assembler.input.190369423" name="Additional Assembly Source Files" superClass="com.crt.advproject.assembler.input"/>\r
+                                                       </tool>\r
+                                                       <tool id="com.crt.advproject.link.cpp.exe.debug.1715304950" name="MCU C++ Linker" superClass="com.crt.advproject.link.cpp.exe.debug.1490011469"/>\r
+                                                       <tool id="com.crt.advproject.link.exe.debug.536813209" name="MCU Linker" superClass="com.crt.advproject.link.exe.debug.1212311005"/>\r
+                                               </toolChain>\r
+                                       </folderInfo>\r
                                        <sourceEntries>\r
                                                <entry excluding="ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_wwdt.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_utils.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_uart.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_timer.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_ssp.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_sct.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_rtc.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_rit.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_qei.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_pwr.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_nvic.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_mcpwm.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_libcfg_default.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_lcd.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_i2s.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_i2c.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_gpdma.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_evrt.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_emc.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_dac.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_can.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_atimer.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/lpc18xx_adc.c|ThirdParty/CMSISv2p10_LPC18xx_DriverLib/src/debug_frmwrk.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>\r
                                        </sourceEntries>\r
        <storageModule moduleId="com.crt.config">\r
                <projectStorage>&lt;?xml version="1.0" encoding="UTF-8"?&gt;&#13;\r
 &lt;TargetConfig&gt;&#13;\r
-&lt;Properties property_0="" property_2="LPC1850A_4350A_SPIFI.cfx" property_3="NXP" property_4="LPC1830" property_count="5" version="70200"/&gt;&#13;\r
+&lt;Properties property_2="LPC1850A_4350A_SPIFI.cfx" property_3="NXP" property_4="LPC1830" property_count="5" version="70200"/&gt;&#13;\r
 &lt;infoList vendor="NXP"&gt;&lt;info chip="LPC1830" match_id="0x0" name="LPC1830" resetscript="LPC18LPC43ExternalFLASHBootResetscript.scp" stub="crt_emu_lpc18_43_nxp"&gt;&lt;chip&gt;&lt;name&gt;LPC1830&lt;/name&gt;&#13;\r
 &lt;family&gt;LPC18xx&lt;/family&gt;&#13;\r
 &lt;vendor&gt;NXP (formerly Philips)&lt;/vendor&gt;&#13;\r
                        <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.crt.advproject.GCCManagedMakePerProjectProfile"/>\r
                </scannerConfigBuildInfo>\r
        </storageModule>\r
+       <storageModule moduleId="com.crt.advproject"/>\r
+       <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>\r
 </cproject>\r
index 0ff8644191e3eab06eec71793aa373cf8aa20303..e4f1e6f0f58b2878df3062f3c4d7a57a104bd12e 100644 (file)
@@ -254,7 +254,8 @@ void vRegisterCLICommands( void )
 \r
 static BaseType_t prvTaskStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
 {\r
-const char *const pcHeader = "Task          State  Priority  Stack     #\r\n************************************************\r\n";\r
+const char *const pcHeader = "  State\tPriority\tStack\t#\r\n************************************************\r\n";\r
+BaseType_t xSpacePadding;\r
 \r
        /* Remove compile time warnings about unused parameters, and check the\r
        write buffer is not NULL.  NOTE - for simplicity, this example assumes the\r
@@ -264,6 +265,22 @@ const char *const pcHeader = "Task          State  Priority  Stack #\r\n********
        configASSERT( pcWriteBuffer );\r
 \r
        /* Generate a table of task stats. */\r
+       strcpy( pcWriteBuffer, "Task" );\r
+       pcWriteBuffer += strlen( pcWriteBuffer );\r
+\r
+       /* Pad the string "task" with however many bytes necessary to make it the\r
+       length of a task name.  Minus three for the null terminator and half the \r
+       number of characters in "Task" so the column lines up with the centre of \r
+       the heading. */\r
+       for( xSpacePadding = strlen( "Task" ); xSpacePadding < ( configMAX_TASK_NAME_LEN - 3 ); xSpacePadding++ )\r
+       {\r
+               /* Add a space to align columns after the task's name. */\r
+               *pcWriteBuffer = ' ';\r
+               pcWriteBuffer++;\r
+\r
+               /* Ensure always terminated. */\r
+               *pcWriteBuffer = 0x00;\r
+       }\r
        strcpy( pcWriteBuffer, pcHeader );\r
        vTaskList( pcWriteBuffer + strlen( pcHeader ) );\r
 \r
@@ -275,7 +292,8 @@ const char *const pcHeader = "Task          State  Priority  Stack  #\r\n********
 \r
 static BaseType_t prvRunTimeStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
 {\r
-const char * const pcHeader = "Task            Abs Time      % Time\r\n****************************************\r\n";\r
+const char * const pcHeader = "  Abs Time      % Time\r\n****************************************\r\n";\r
+BaseType_t xSpacePadding;\r
 \r
        /* Remove compile time warnings about unused parameters, and check the\r
        write buffer is not NULL.  NOTE - for simplicity, this example assumes the\r
@@ -285,6 +303,23 @@ const char * const pcHeader = "Task            Abs Time      % Time\r\n*********
        configASSERT( pcWriteBuffer );\r
 \r
        /* Generate a table of task stats. */\r
+       strcpy( pcWriteBuffer, "Task" );\r
+       pcWriteBuffer += strlen( pcWriteBuffer );\r
+\r
+       /* Pad the string "task" with however many bytes necessary to make it the\r
+       length of a task name.  Minus three for the null terminator and half the \r
+       number of characters in "Task" so the column lines up with the centre of \r
+       the heading. */\r
+       for( xSpacePadding = strlen( "Task" ); xSpacePadding < ( configMAX_TASK_NAME_LEN - 3 ); xSpacePadding++ )\r
+       {\r
+               /* Add a space to align columns after the task's name. */\r
+               *pcWriteBuffer = ' ';\r
+               pcWriteBuffer++;\r
+\r
+               /* Ensure always terminated. */\r
+               *pcWriteBuffer = 0x00;\r
+       }\r
+\r
        strcpy( pcWriteBuffer, pcHeader );\r
        vTaskGetRunTimeStats( pcWriteBuffer + strlen( pcHeader ) );\r
 \r
index d40c9b2694f34df8dd6d9c5b4539822da935fa41..a805f5e7764731175358a2e22b90d046281131e3 100644 (file)
@@ -189,7 +189,7 @@ standard names. */
 \r
 /* Set to 1 to include "trace start" and "trace stop" CLI commands.  These\r
 commands start and stop the FreeRTOS+Trace recording. */\r
-#define configINCLUDE_TRACE_RELATED_CLI_COMMANDS 1\r
+#define configINCLUDE_TRACE_RELATED_CLI_COMMANDS 0\r
 \r
 /* Dimensions a buffer that can be used by the FreeRTOS+CLI command\r
 interpreter.  See the FreeRTOS+CLI documentation for more information:\r
@@ -277,10 +277,8 @@ ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */
 #define configNET_MASK2                255\r
 #define configNET_MASK3                0\r
 \r
-#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1\r
-       /* Only include the trace macro definitions required by FreeRTOS+Trace if\r
-       the trace start and trace stop CLI commands are included. */\r
-       #include "trcKernelPort.h"\r
-#endif\r
+/* Only include the trace macro definitions required by FreeRTOS+Trace if\r
+the trace start and trace stop CLI commands are included. */\r
+#include "trcRecorder.h"\r
 \r
 #endif /* FREERTOS_CONFIG_H */\r
index 6ff5961a6bc45859946a29eadd2ec23e90f3accb..f09345f97017b18aa0fa635026a103cd57c5e81e 100644 (file)
-/*******************************************************************************\r
- * Tracealyzer v2.7.0 Recorder Library\r
+/*******************************************************************************\r
+ * Trace Recorder Library for Tracealyzer v3.1.2\r
  * Percepio AB, www.percepio.com\r
  *\r
  * trcConfig.h\r
  *\r
- * Configuration parameters for the trace recorder library. Before using the\r
- * trace recorder library, please check that the default settings are\r
- * appropriate for your system, and if necessary adjust these. Most likely, you\r
- * will need to adjust the NTask, NISR, NQueue, NMutex and NSemaphore values to\r
- * reflect the number of such objects in your system. These may be\r
- * over-approximated, although larger values values implies more RAM usage.\r
+ * Main configuration parameters for the trace recorder library.\r
+ * More settings can be found in trcStreamingConfig.h and trcSnapshotConfig.h.\r
+ *\r
+ * Read more at http://percepio.com/2016/10/05/rtos-tracing/\r
  *\r
  * Terms of Use\r
- * This software is copyright Percepio AB. The recorder library is free for\r
- * use together with Percepio products. You may distribute the recorder library\r
- * in its original form, including modifications in trcHardwarePort.c/.h\r
- * given that these modification are clearly marked as your own modifications\r
- * and documented in the initial comment section of these source files.\r
- * This software is the intellectual property of Percepio AB and may not be\r
- * sold or in other ways commercially redistributed without explicit written\r
- * permission by Percepio AB.\r
+ * This file is part of the trace recorder library (RECORDER), which is the\r
+ * intellectual property of Percepio AB (PERCEPIO) and provided under a\r
+ * license as follows.\r
+ * The RECORDER may be used free of charge for the purpose of recording data\r
+ * intended for analysis in PERCEPIO products. It may not be used or modified\r
+ * for other purposes without explicit permission from PERCEPIO.\r
+ * You may distribute the RECORDER in its original source code form, assuming\r
+ * this text (terms of use, disclaimer, copyright notice) is unchanged. You are\r
+ * allowed to distribute the RECORDER with minor modifications intended for\r
+ * configuration or porting of the RECORDER, e.g., to allow using it on a\r
+ * specific processor, processor family or with a specific communication\r
+ * interface. Any such modifications should be documented directly below\r
+ * this comment block.\r
  *\r
  * Disclaimer\r
- * The trace tool and recorder library is being delivered to you AS IS and\r
- * Percepio AB makes no warranty as to its use or performance. Percepio AB does\r
- * not and cannot warrant the performance or results you may obtain by using the\r
- * software or documentation. Percepio AB make no warranties, express or\r
- * implied, as to noninfringement of third party rights, merchantability, or\r
- * fitness for any particular purpose. In no event will Percepio AB, its\r
- * technology partners, or distributors be liable to you for any consequential,\r
- * incidental or special damages, including any lost profits or lost savings,\r
- * even if a representative of Percepio AB has been advised of the possibility\r
- * of such damages, or for any claim by any third party. Some jurisdictions do\r
- * not allow the exclusion or limitation of incidental, consequential or special\r
- * damages, or the exclusion of implied warranties or limitations on how long an\r
- * implied warranty may last, so the above limitations may not apply to you.\r
+ * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty\r
+ * as to its use or performance. PERCEPIO does not and cannot warrant the\r
+ * performance or results you may obtain by using the RECORDER or documentation.\r
+ * PERCEPIO make no warranties, express or implied, as to noninfringement of\r
+ * third party rights, merchantability, or fitness for any particular purpose.\r
+ * In no event will PERCEPIO, its technology partners, or distributors be liable\r
+ * to you for any consequential, incidental or special damages, including any\r
+ * lost profits or lost savings, even if a representative of PERCEPIO has been\r
+ * advised of the possibility of such damages, or for any claim by any third\r
+ * party. Some jurisdictions do not allow the exclusion or limitation of\r
+ * incidental, consequential or special damages, or the exclusion of implied\r
+ * warranties or limitations on how long an implied warranty may last, so the\r
+ * above limitations may not apply to you.\r
  *\r
  * Tabs are used for indent in this file (1 tab = 4 spaces)\r
  *\r
- * Copyright Percepio AB, 2014.\r
+ * Copyright Percepio AB, 2016.\r
  * www.percepio.com\r
  ******************************************************************************/\r
 \r
-#ifndef TRCCONFIG_H\r
-#define TRCCONFIG_H\r
-\r
-/******************************************************************************\r
- * SELECTED_PORT\r
- *\r
- * Macro that specifies what hardware port that should be used.\r
- * Available ports are:\r
- *\r
- * Port Name                                                   Code     Official       OS supported\r
- * PORT_APPLICATION_DEFINED                            -2              -                       -\r
- * PORT_NOT_SET                                                        -1              -                       -\r
- * PORT_HWIndependent                                  0               Yes                     Any\r
- * PORT_Win32                                                  1               Yes                     FreeRTOS on Win32\r
- * PORT_Atmel_AT91SAM7                                 2               No                      Any\r
- * PORT_Atmel_UC3A0                                            3               No                      Any\r
- * PORT_ARM_CortexM                                            4               Yes                     Any\r
- * PORT_Renesas_RX600                                  5               Yes                     Any\r
- * PORT_Microchip_dsPIC_AND_PIC24              6               Yes                     Any\r
- * PORT_TEXAS_INSTRUMENTS_TMS570               7               No                      Any\r
- * PORT_TEXAS_INSTRUMENTS_MSP430               8               No                      Any\r
- * PORT_MICROCHIP_PIC32MX                              9               Yes                     Any\r
- * PORT_XILINX_PPC405                                  10              No                      FreeRTOS\r
- * PORT_XILINX_PPC440                                  11              No                      FreeRTOS\r
- * PORT_XILINX_MICROBLAZE                              12              No                      Any\r
- * PORT_NXP_LPC210X                                            13              No                      Any\r
- * PORT_MICROCHIP_PIC32MZ                              14              Yes                     Any\r
- * PORT_ARM_CORTEX_A9                                  15              No                      Any\r
- *****************************************************************************/\r
-\r
-#ifndef WIN32\r
-       // Set the port setting here!\r
-       #define SELECTED_PORT PORT_ARM_CortexM\r
+#ifndef TRC_CONFIG_H\r
+#define TRC_CONFIG_H\r
 \r
-       #if (SELECTED_PORT == PORT_NOT_SET)\r
-               #error "You need to define SELECTED_PORT here!"\r
-       #endif\r
-#else\r
-       // For Win32 demo projects this is set automatically\r
-       #define SELECTED_PORT PORT_Win32\r
+#ifdef __cplusplus\r
+extern "C" {\r
 #endif\r
 \r
-/******************************************************************************\r
- * FREERTOS_VERSION\r
- *\r
- * Specify what version of FreeRTOS that is used. This is necessary compensate\r
- * for renamed symbols in the FreeRTOS kernel (does not build if incorrect).\r
- *\r
- * FREERTOS_VERSION_7_3_OR_7_4 (= 1)           If using FreeRTOS v7.3.0 - v7.4.2\r
- * FREERTOS_VERSION_7_5_OR_7_6 (= 2)           If using FreeRTOS v7.5.0 - v7.6.0\r
- * FREERTOS_VERSION_8_0_OR_LATER (= 3)         If using FreeRTOS v8.0.0 or later\r
- *****************************************************************************/\r
-#define FREERTOS_VERSION       FREERTOS_VERSION_8_0_OR_LATER\r
+#include "trcPortDefines.h"\r
 \r
 /******************************************************************************\r
- * TRACE_RECORDER_STORE_MODE\r
+ * Include of processor header file\r
  *\r
- * Macro which should be defined as one of:\r
- * - TRACE_STORE_MODE_RING_BUFFER\r
- * - TRACE_STORE_MODE_STOP_WHEN_FULL\r
- * Default is TRACE_STORE_MODE_RING_BUFFER.\r
- *\r
- * With TRACE_RECORDER_STORE_MODE set to TRACE_STORE_MODE_RING_BUFFER, the\r
- * events are stored in a ring buffer, i.e., where the oldest events are\r
- * overwritten when the buffer becomes full. This allows you to get the last\r
- * events leading up to an interesting state, e.g., an error, without having\r
- * to store the whole run since startup.\r
- *\r
- * When TRACE_RECORDER_STORE_MODE is TRACE_STORE_MODE_STOP_WHEN_FULL, the\r
- * recording is stopped when the buffer becomes full. This is useful for\r
- * recording events following a specific state, e.g., the startup sequence.\r
+ * Here you may need to include the header file for your processor. This is\r
+ * required at least for the ARM Cortex-M port, that uses the ARM CMSIS API.\r
+ * Try that in case of build problems. Otherwise, remove the #error line below.\r
  *****************************************************************************/\r
-#define TRACE_RECORDER_STORE_MODE TRACE_STORE_MODE_RING_BUFFER\r
+//#error "Trace Recorder: Please include your processor's header file here and remove this line."\r
+#include "lpc18xx.h"\r
 \r
 /*******************************************************************************\r
- * TRACE_SCHEDULING_ONLY\r
+ * Configuration Macro: TRC_CFG_HARDWARE_PORT\r
  *\r
- * Macro which should be defined as an integer value.\r
+ * Specify what hardware port to use (i.e., the "timestamping driver").\r
  *\r
- * If this setting is enabled (= 1), only scheduling events are recorded.\r
- * If disabled (= 0), all events are recorded.\r
+ * All ARM Cortex-M MCUs are supported by "TRC_HARDWARE_PORT_ARM_Cortex_M".\r
+ * This port uses the DWT cycle counter for Cortex-M3/M4/M7 devices, which is\r
+ * available on most such devices. In case your device don't have DWT support,\r
+ * you will get an error message opening the trace. In that case, you may\r
+ * force the recorder to use SysTick timestamping instead, using this define:\r
  *\r
- * Users of FreeRTOS+Trace Free Edition only displays scheduling events, so this\r
- * option can be used to avoid storing unsupported events.\r
+ * #define TRC_CFG_ARM_CM_USE_SYSTICK\r
  *\r
- * Default value is 0 (store all enabled events).\r
+ * For ARM Cortex-M0/M0+ devices, SysTick mode is used automatically.\r
  *\r
+ * See trcHardwarePort.h for available ports and information on how to\r
+ * define your own port, if not already present.\r
  ******************************************************************************/\r
-#define TRACE_SCHEDULING_ONLY 0\r
+#define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_ARM_Cortex_M\r
 \r
 /*******************************************************************************\r
- * EVENT_BUFFER_SIZE\r
+ * Configuration Macro: TRC_CFG_RECORDER_MODE\r
  *\r
- * Macro which should be defined as an integer value.\r
+ * Specify what recording mode to use. Snapshot means that the data is saved in\r
+ * an internal RAM buffer, for later upload. Streaming means that the data is\r
+ * transferred continuously to the host PC.\r
  *\r
- * This defines the capacity of the event buffer, i.e., the number of records\r
- * it may store. Most events use one record (4 byte), although some events\r
- * require multiple 4-byte records. You should adjust this to the amount of RAM\r
- * available in the target system.\r
+ * For more information, see http://percepio.com/2016/10/05/rtos-tracing/\r
+ * and the Tracealyzer User Manual.\r
  *\r
- * Default value is 1000, which means that 4000 bytes is allocated for the\r
- * event buffer.\r
+ * Values:\r
+ * TRC_RECORDER_MODE_SNAPSHOT\r
+ * TRC_RECORDER_MODE_STREAMING\r
  ******************************************************************************/\r
-#define EVENT_BUFFER_SIZE 1000\r
+#define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_SNAPSHOT\r
 \r
 /*******************************************************************************\r
- * NTask, NISR, NQueue, NSemaphore, NMutex\r
- *\r
- * A group of macros which should be defined as integer values, zero or larger.\r
+ * Configuration Macro: TRC_CFG_RECORDER_BUFFER_ALLOCATION\r
  *\r
- * These define the capacity of the Object Property Table, i.e., the maximum\r
- * number of objects active at any given point, within each object class (e.g.,\r
- * task, queue, semaphore, ...).\r
+ * Specifies how the recorder buffer is allocated (also in case of streaming, in\r
+ * port using the recorder's internal temporary buffer)\r
  *\r
- * If tasks or other other objects are deleted in your system, this\r
- * setting does not limit the total amount of objects created, only the number\r
- * of objects that have been successfully created but not yet deleted.\r
+ * Values:\r
+ * TRC_RECORDER_BUFFER_ALLOCATION_STATIC  - Static allocation (internal)\r
+ * TRC_RECORDER_BUFFER_ALLOCATION_DYNAMIC - Malloc in vTraceEnable\r
+ * TRC_RECORDER_BUFFER_ALLOCATION_CUSTOM  - Use vTraceSetRecorderDataBuffer\r
  *\r
- * Using too small values will cause vTraceError to be called, which stores an\r
- * error message in the trace that is shown when opening the trace file.\r
- *\r
- * It can be wise to start with large values for these constants,\r
- * unless you are very confident on these numbers. Then do a recording and\r
- * check the actual usage by selecting View menu -> Trace Details ->\r
- * Resource Usage -> Object Table.\r
+ * Static and dynamic mode does the allocation for you, either in compile time\r
+ * (static) or in runtime (malloc).\r
+ * The custom mode allows you to control how and where the allocation is made,\r
+ * for details see TRC_ALLOC_CUSTOM_BUFFER and vTraceSetRecorderDataBuffer().\r
  ******************************************************************************/\r
-#define NTask                  15\r
-#define NISR                   4\r
-#define NQueue                 10\r
-#define NSemaphore             10\r
-#define NMutex                 5\r
-#define NTimer                 10\r
-#define NEventGroup            1\r
+#define TRC_CFG_RECORDER_BUFFER_ALLOCATION TRC_RECORDER_BUFFER_ALLOCATION_STATIC\r
 \r
 /******************************************************************************\r
- * INCLUDE_MEMMANG_EVENTS\r
- *\r
- * Macro which should be defined as either zero (0) or one (1).\r
+ * TRC_CFG_FREERTOS_VERSION\r
  *\r
- * This controls if malloc and free calls should be traced. Set this to zero to\r
- * exclude malloc/free calls, or one (1) to include such events in the trace.\r
+ * Specify what version of FreeRTOS that is used (don't change unless using the\r
+ * trace recorder library with an older version of FreeRTOS).\r
  *\r
- * Default value is 1.\r
+ * TRC_FREERTOS_VERSION_7_3_OR_7_4                             If using FreeRTOS v7.3.0 - v7.4.2\r
+ * TRC_FREERTOS_VERSION_7_5_OR_7_6                             If using FreeRTOS v7.5.0 - v7.6.0\r
+ * TRC_FREERTOS_VERSION_8_X                                            If using FreeRTOS v8.X.X\r
+ * TRC_FREERTOS_VERSION_9_X                                            If using FreeRTOS v9.X.X\r
  *****************************************************************************/\r
-#define INCLUDE_MEMMANG_EVENTS 1\r
+#define TRC_CFG_FREERTOS_VERSION       TRC_FREERTOS_VERSION_9_X\r
 \r
 /******************************************************************************\r
- * INCLUDE_USER_EVENTS\r
+ * TRC_CFG_MAX_ISR_NESTING\r
  *\r
- * Macro which should be defined as either zero (0) or one (1).\r
+ * Defines how many levels of interrupt nesting the recorder can handle, in\r
+ * case multiple ISRs are traced and ISR nesting is possible. If this\r
+ * is exceeded, the particular ISR will not be traced and the recorder then\r
+ * logs an error message. This setting is used to allocate an internal stack\r
+ * for keeping track of the previous execution context (4 byte per entry).\r
  *\r
- * If this is zero (0) the code for creating User Events is excluded to\r
- * reduce code size. User Events are application-generated events, like\r
- * "printf" but for the trace log instead of console output. User Events are\r
- * much faster than a printf and can therefore be used in timing critical code.\r
- * See vTraceUserEvent() and vTracePrintF() in trcUser.h\r
+ * This value must be a non-zero positive constant, at least 1.\r
  *\r
- * Default value is 1.\r
- *\r
- * Note that User Events are only displayed in Professional Edition.\r
+ * Default value: 8\r
  *****************************************************************************/\r
-#define INCLUDE_USER_EVENTS 0\r
+#define TRC_CFG_MAX_ISR_NESTING 8\r
 \r
-/*****************************************************************************\r
- * INCLUDE_ISR_TRACING\r
- *\r
- * Macro which should be defined as either zero (0) or one (1).\r
- *\r
- * If this is zero (0), the code for recording Interrupt Service Routines is\r
- * excluded to reduce code size.\r
- *\r
- * Default value is 1.\r
- *\r
- * Note, if the kernel has no central interrupt dispatcher, recording ISRs\r
- * require that you insert calls to vTraceStoreISRBegin and vTraceStoreISREnd\r
- * in your interrupt handlers.\r
- *****************************************************************************/\r
-#define INCLUDE_ISR_TRACING 1\r
-\r
-/*****************************************************************************\r
- * INCLUDE_READY_EVENTS\r
- *\r
- * Macro which should be defined as either zero (0) or one (1).\r
- *\r
- * If one (1), events are recorded when tasks enter scheduling state "ready".\r
- * This uses a lot of space in the event buffer, so excluding "ready events"\r
- * will allow for longer traces. Including ready events however allows for\r
- * showing the initial pending time before tasks enter the execution state, and\r
- * for presenting accurate response times.\r
- *\r
- * Default value is 1.\r
- *****************************************************************************/\r
-#define INCLUDE_READY_EVENTS 1\r
-\r
-/*****************************************************************************\r
- * INCLUDE_NEW_TIME_EVENTS\r
- *\r
- * Macro which should be defined as either zero (0) or one (1).\r
- *\r
- * If this is zero (1), events will be generated whenever the OS clock is\r
- * increased.\r
- *\r
- * Default value is 0.\r
- *****************************************************************************/\r
-#define INCLUDE_NEW_TIME_EVENTS 0\r
-\r
-/******************************************************************************\r
- * INCLUDE_FLOAT_SUPPORT\r
- *\r
- * Macro which should be defined as either zero (0) or one (1).\r
- *\r
- * If this is zero (0), all references to floating point values are removed,\r
- * in case floating point values are not supported by the platform used.\r
- * Floating point values are only used in vTracePrintF and its subroutines, to\r
- * store float (%f) or double (%lf) arguments.\r
- *\r
- * vTracePrintF can be used with integer and string arguments in either case.\r
- *\r
- * Default value is 1.\r
- *****************************************************************************/\r
-#define INCLUDE_FLOAT_SUPPORT 0\r
-\r
-/******************************************************************************\r
- * INCLUDE_OBJECT_DELETE\r
- *\r
- * Macro which should be defined as either zero (0) or one (1).\r
- *\r
- * This must be enabled (1) if tasks, queues or other\r
- * traced kernel objects are deleted at runtime. If no deletes are made, this\r
- * can be set to 0 in order to exclude the delete-handling code.\r
- *\r
- * Default value is 1.\r
- *****************************************************************************/\r
-#define INCLUDE_OBJECT_DELETE 1\r
-\r
-/*******************************************************************************\r
- * SYMBOL_TABLE_SIZE\r
- *\r
- * Macro which should be defined as an integer value.\r
- *\r
- * This defines the capacity of the symbol table, in bytes. This symbol table\r
- * stores User Events labels and names of deleted tasks, queues, or other kernel\r
- * objects. If you don't use User Events or delete any kernel\r
- * objects you set this to a very low value. The minimum recommended value is 4.\r
- * A size of zero (0) is not allowed since a zero-sized array may result in a\r
- * 32-bit pointer, i.e., using 4 bytes rather than 0.\r
- *\r
- * Default value is 800.\r
- ******************************************************************************/\r
-#define SYMBOL_TABLE_SIZE 5000\r
-\r
-#if (SYMBOL_TABLE_SIZE == 0)\r
-#error "SYMBOL_TABLE_SIZE may not be zero!"\r
+/* Specific configuration, depending on Streaming/Snapshot mode */\r
+#if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_SNAPSHOT)\r
+#include "trcSnapshotConfig.h"\r
+#elif (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)\r
+#include "trcStreamingConfig.h"\r
 #endif\r
 \r
-/******************************************************************************\r
- * NameLenTask, NameLenQueue, ...\r
- *\r
- * Macros that specify the maximum lengths (number of characters) for names of\r
- * kernel objects, such as tasks and queues. If longer names are used, they will\r
- * be truncated when stored in the recorder.\r
- *****************************************************************************/\r
-#define NameLenTask                    15\r
-#define NameLenISR                     15\r
-#define NameLenQueue           15\r
-#define NameLenSemaphore       15\r
-#define NameLenMutex           15\r
-#define NameLenTimer           15\r
-#define NameLenEventGroup      15\r
-\r
-/******************************************************************************\r
- * TRACE_DATA_ALLOCATION\r
- *\r
- * This defines how to allocate the recorder data structure, i.e., using a\r
- * static declaration or using a dynamic allocation in runtime (malloc).\r
- *\r
- * Should be one of these two options:\r
- * - TRACE_DATA_ALLOCATION_STATIC (default)\r
- * - TRACE_DATA_ALLOCATION_DYNAMIC\r
- *\r
- * Using static allocation has the benefits of compile-time errors if the buffer\r
- * is too large (too large constants in trcConfig.h) and no need to call the\r
- * initialization routine (xTraceInitTraceData).\r
- *\r
- * Using dynamic allocation may give more flexibility in some cases.\r
- *****************************************************************************/\r
-#define TRACE_DATA_ALLOCATION TRACE_DATA_ALLOCATION_STATIC\r
-\r
-\r
-\r
-/******************************************************************************\r
- *** ADVANCED SETTINGS ********************************************************\r
- ******************************************************************************\r
- * The remaining settings are not necessary to modify but allows for optimizing\r
- * the recorder setup for your specific needs, e.g., to exclude events that you\r
- * are not interested in, in order to get longer traces.\r
- *****************************************************************************/\r
-\r
-/******************************************************************************\r
-* HEAP_SIZE_BELOW_16M\r
-*\r
-* An integer constant that can be used to reduce the buffer usage of memory\r
-* allocation events (malloc/free). This value should be 1 if the heap size is\r
-* below 16 MB (2^24 byte), and you can live with reported addresses showing the\r
-* lower 24 bits only. If 0, you get the full 32-bit addresses.\r
-*\r
-* Default value is 0.\r
-******************************************************************************/\r
-#define HEAP_SIZE_BELOW_16M 0\r
-\r
-/******************************************************************************\r
- * USE_LINKER_PRAGMA\r
- *\r
- * Macro which should be defined as an integer value, default is 0.\r
- *\r
- * If this is 1, the header file "recorderdata_linker_pragma.h" is included just\r
- * before the declaration of RecorderData (in trcBase.c), i.e., the trace data\r
- * structure. This allows the user to specify a pragma with linker options.\r
- *\r
- * Example (for IAR Embedded Workbench and NXP LPC17xx):\r
- * #pragma location="AHB_RAM_MEMORY"\r
- *\r
- * This example instructs the IAR linker to place RecorderData in another RAM\r
- * bank, the AHB RAM. This can also be used for other compilers with a similar\r
- * pragmas for linker options.\r
- *\r
- * Note that this only applies if using static allocation, see below.\r
- ******************************************************************************/\r
-#define USE_LINKER_PRAGMA 0\r
-\r
-/******************************************************************************\r
- * USE_IMPLICIT_IFE_RULES\r
- *\r
- * Macro which should be defined as either zero (0) or one (1).\r
- * Default is 1.\r
- *\r
- * Tracealyzer groups the events into actor instances, based on context-switches\r
- * and a definition of "Instance Finish Events", or IFEs. These are kernel calls\r
- * considered to be the last event in a task instance. Some kernel calls are\r
- * considered IFEs by default (e.g., delay functions), but it is also possible\r
- * to specify this individually for each task (see vTraceTaskInstanceFinish).\r
- *\r
- * If USE_IMPLICIT_IFE_RULES is one (1), the default IFEs will be enabled, which\r
- * gives a "typical" grouping of events into instances. You can combine this\r
- * with calls to vTraceTaskInstanceFinish for specific tasks.\r
- *\r
- * If USE_IMPLICIT_IFE_RULES is zero (0), the implicit IFEs are disabled and all\r
- * events withing each task is then shown as a single instance, unless  you call\r
- * vTraceTaskInstanceFinish() at suitable locations to mark the IFEs.\r
- *****************************************************************************/\r
-#define USE_IMPLICIT_IFE_RULES 1\r
-\r
-/******************************************************************************\r
- * USE_16BIT_OBJECT_HANDLES\r
- *\r
- * Macro which should be defined as either zero (0) or one (1).\r
- *\r
- * If set to 0 (zero), the recorder uses 8-bit handles to identify kernel\r
- * objects such as tasks and queues. This limits the supported number of\r
- * concurrently active objects to 255 of each type (object class).\r
- *\r
- * If set to 1 (one), the recorder uses 16-bit handles to identify kernel\r
- * objects such as tasks and queues. This limits the supported number of\r
- * concurrent objects to 65535 of each type (object class). However, since the\r
- * object property table is limited to 64 KB, the practical limit is about\r
- * 3000 objects in total.\r
- *\r
- * Default is 0.\r
- *\r
- * NOTE: An object with handle above 255 will use an extra 4-byte record in\r
- * the event buffer whenever referenced. Moreover, some internal tables in the\r
- * recorder gets larger when using 16-bit handles. The additional RAM usage is\r
- * 5-10 byte plus 1 byte per kernel object i.e., task, queue, mutex, etc.\r
- *****************************************************************************/\r
-#define USE_16BIT_OBJECT_HANDLES 0\r
-\r
-/******************************************************************************\r
- * USE_TRACE_ASSERT\r
- *\r
- * Macro which should be defined as either zero (0) or one (1).\r
- * Default is 1.\r
- *\r
- * If this is one (1), the TRACE_ASSERT macro will verify that a condition is\r
- * true. If the condition is false, vTraceError() will be called.\r
- * This is used on several places in the recorder code for sanity checks on\r
- * parameters. Can be switched off to reduce CPU usage of the tracing.\r
- *****************************************************************************/\r
-#define USE_TRACE_ASSERT 1\r
-\r
-/*******************************************************************************\r
- * USE_SEPARATE_USER_EVENT_BUFFER\r
- *\r
- * Macro which should be defined as an integer value.\r
- * Default is zero (0).\r
- *\r
- * This enables and disables the use of the separate user event buffer. Using\r
- * this separate buffer has the benefit of not overwriting the user events with\r
- * kernel events (usually generated at a much higher rate), i.e., when using\r
- * ring-buffer mode.\r
- *\r
- * Note: When using the separate user event buffer, you may get an artificial\r
- * task instance named "Unknown actor". This is added as a placeholder when the\r
- * user event history is longer than the task scheduling history.\r
- ******************************************************************************/\r
-#define USE_SEPARATE_USER_EVENT_BUFFER 0\r
-\r
-/*******************************************************************************\r
- * USER_EVENT_BUFFER_SIZE\r
- *\r
- * Macro which should be defined as an integer value.\r
- *\r
- * This defines the capacity of the user event buffer, in number of slots.\r
- * A single user event can use between 1 and X slots, depending on the data.\r
- *\r
- * Only in use if USE_SEPARATE_USER_EVENT_BUFFER is set to 1.\r
- ******************************************************************************/\r
-#define USER_EVENT_BUFFER_SIZE 10\r
-\r
-/*******************************************************************************\r
- * USER_EVENT_CHANNELS\r
- *\r
- * Macro which should be defined as an integer value.\r
- *\r
- * This defines the number of allowed user event channels.\r
- *\r
- * Only in use if USE_SEPARATE_USER_EVENT_BUFFER is set to 1.\r
- ******************************************************************************/\r
-#define CHANNEL_FORMAT_PAIRS 32\r
-\r
+#ifdef __cplusplus\r
+}\r
 #endif\r
 \r
+#endif /* _TRC_CONFIG_H */\r
diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC/trcSnapshotConfig.h b/FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_LPC1830_GCC/trcSnapshotConfig.h
new file mode 100644 (file)
index 0000000..e84a40b
--- /dev/null
@@ -0,0 +1,472 @@
+/*******************************************************************************\r
+ * Trace Recorder Library for Tracealyzer v3.1.2\r
+ * Percepio AB, www.percepio.com\r
+ *\r
+ * trcSnapshotConfig.h\r
+ *\r
+ * Configuration parameters for trace recorder library in snapshot mode.\r
+ * Read more at http://percepio.com/2016/10/05/rtos-tracing/\r
+ *\r
+ * Terms of Use\r
+ * This file is part of the trace recorder library (RECORDER), which is the\r
+ * intellectual property of Percepio AB (PERCEPIO) and provided under a\r
+ * license as follows.\r
+ * The RECORDER may be used free of charge for the purpose of recording data\r
+ * intended for analysis in PERCEPIO products. It may not be used or modified\r
+ * for other purposes without explicit permission from PERCEPIO.\r
+ * You may distribute the RECORDER in its original source code form, assuming\r
+ * this text (terms of use, disclaimer, copyright notice) is unchanged. You are\r
+ * allowed to distribute the RECORDER with minor modifications intended for\r
+ * configuration or porting of the RECORDER, e.g., to allow using it on a\r
+ * specific processor, processor family or with a specific communication\r
+ * interface. Any such modifications should be documented directly below\r
+ * this comment block.\r
+ *\r
+ * Disclaimer\r
+ * The RECORDER is being delivered to you AS IS and PERCEPIO makes no warranty\r
+ * as to its use or performance. PERCEPIO does not and cannot warrant the\r
+ * performance or results you may obtain by using the RECORDER or documentation.\r
+ * PERCEPIO make no warranties, express or implied, as to noninfringement of\r
+ * third party rights, merchantability, or fitness for any particular purpose.\r
+ * In no event will PERCEPIO, its technology partners, or distributors be liable\r
+ * to you for any consequential, incidental or special damages, including any\r
+ * lost profits or lost savings, even if a representative of PERCEPIO has been\r
+ * advised of the possibility of such damages, or for any claim by any third\r
+ * party. Some jurisdictions do not allow the exclusion or limitation of\r
+ * incidental, consequential or special damages, or the exclusion of implied\r
+ * warranties or limitations on how long an implied warranty may last, so the\r
+ * above limitations may not apply to you.\r
+ *\r
+ * Tabs are used for indent in this file (1 tab = 4 spaces)\r
+ *\r
+ * Copyright Percepio AB, 2017.\r
+ * www.percepio.com\r
+ ******************************************************************************/\r
+\r
+#ifndef TRC_SNAPSHOT_CONFIG_H\r
+#define TRC_SNAPSHOT_CONFIG_H\r
+\r
+#define TRC_SNAPSHOT_MODE_RING_BUFFER          (0x01)\r
+#define TRC_SNAPSHOT_MODE_STOP_WHEN_FULL       (0x02)\r
+\r
+/******************************************************************************\r
+ * TRC_CFG_SNAPSHOT_MODE\r
+ *\r
+ * Macro which should be defined as one of:\r
+ * - TRC_SNAPSHOT_MODE_RING_BUFFER\r
+ * - TRC_SNAPSHOT_MODE_STOP_WHEN_FULL\r
+ * Default is TRC_SNAPSHOT_MODE_RING_BUFFER.\r
+ *\r
+ * With TRC_CFG_SNAPSHOT_MODE set to TRC_SNAPSHOT_MODE_RING_BUFFER, the\r
+ * events are stored in a ring buffer, i.e., where the oldest events are\r
+ * overwritten when the buffer becomes full. This allows you to get the last\r
+ * events leading up to an interesting state, e.g., an error, without having\r
+ * to store the whole run since startup.\r
+ *\r
+ * When TRC_CFG_SNAPSHOT_MODE is TRC_SNAPSHOT_MODE_STOP_WHEN_FULL, the\r
+ * recording is stopped when the buffer becomes full. This is useful for\r
+ * recording events following a specific state, e.g., the startup sequence.\r
+ *****************************************************************************/\r
+#define TRC_CFG_SNAPSHOT_MODE TRC_SNAPSHOT_MODE_RING_BUFFER\r
+\r
+/*******************************************************************************\r
+ * TRC_CFG_SCHEDULING_ONLY\r
+ *\r
+ * Macro which should be defined as an integer value.\r
+ *\r
+ * If this setting is enabled (= 1), only scheduling events are recorded.\r
+ * If disabled (= 0), all events are recorded.\r
+ *\r
+ * For users of Tracealyzer Free Edition, that only displays scheduling events, this\r
+ * option can be used to avoid storing other events.\r
+ *\r
+ * Default value is 0 (store all enabled events).\r
+ *\r
+ ******************************************************************************/\r
+#define TRC_CFG_SCHEDULING_ONLY 0\r
+\r
+/*******************************************************************************\r
+ * TRC_CFG_EVENT_BUFFER_SIZE\r
+ *\r
+ * Macro which should be defined as an integer value.\r
+ *\r
+ * This defines the capacity of the event buffer, i.e., the number of records\r
+ * it may store. Most events use one record (4 byte), although some events\r
+ * require multiple 4-byte records. You should adjust this to the amount of RAM\r
+ * available in the target system.\r
+ *\r
+ * Default value is 1000, which means that 4000 bytes is allocated for the\r
+ * event buffer.\r
+ ******************************************************************************/\r
+#define TRC_CFG_EVENT_BUFFER_SIZE 1000\r
+\r
+/*******************************************************************************\r
+ * TRC_CFG_NTASK, TRC_CFG_NISR, TRC_CFG_NQUEUE, TRC_CFG_NSEMAPHORE...\r
+ *\r
+ * A group of macros which should be defined as integer values, zero or larger.\r
+ *\r
+ * These define the capacity of the Object Property Table, i.e., the maximum\r
+ * number of objects active at any given point, within each object class (e.g.,\r
+ * task, queue, semaphore, ...).\r
+ *\r
+ * If tasks or other objects are deleted in your system, this\r
+ * setting does not limit the total amount of objects created, only the number\r
+ * of objects that have been successfully created but not yet deleted.\r
+ *\r
+ * Using too small values will cause vTraceError to be called, which stores an\r
+ * error message in the trace that is shown when opening the trace file. The\r
+ * error message can also be retrieved using xTraceGetLastError.\r
+ *\r
+ * It can be wise to start with large values for these constants,\r
+ * unless you are very confident on these numbers. Then do a recording and\r
+ * check the actual usage by selecting View menu -> Trace Details ->\r
+ * Resource Usage -> Object Table.\r
+ ******************************************************************************/\r
+#define TRC_CFG_NTASK                  15\r
+#define TRC_CFG_NISR                   4\r
+#define TRC_CFG_NQUEUE                 10\r
+#define TRC_CFG_NSEMAPHORE             10\r
+#define TRC_CFG_NMUTEX                 5\r
+#define TRC_CFG_NTIMER                 10\r
+#define TRC_CFG_NEVENTGROUP            1\r
+\r
+/******************************************************************************\r
+ * TRC_CFG_INCLUDE_MEMMANG_EVENTS\r
+ *\r
+ * Macro which should be defined as either zero (0) or one (1).\r
+ *\r
+ * This controls if malloc and free calls should be traced. Set this to zero (0)\r
+ * to exclude malloc/free calls, or one (1) to include such events in the trace.\r
+ *\r
+ * Default value is 1.\r
+ *****************************************************************************/\r
+#define TRC_CFG_INCLUDE_MEMMANG_EVENTS 1\r
+\r
+/******************************************************************************\r
+ * TRC_CFG_INCLUDE_USER_EVENTS\r
+ *\r
+ * Macro which should be defined as either zero (0) or one (1).\r
+ *\r
+ * If this is zero (0) the code for creating User Events is excluded to\r
+ * reduce code size. User Events are application-generated events, like\r
+ * "printf" but for the trace log and the formatting is done offline, by the\r
+ * Tracealyzer visualization tool. User Events are much faster than a printf\r
+ * and can therefore be used in timing critical code.\r
+ *\r
+ * Default value is 1.\r
+ *****************************************************************************/\r
+#define TRC_CFG_INCLUDE_USER_EVENTS 0\r
+\r
+/*****************************************************************************\r
+ * TRC_CFG_INCLUDE_ISR_TRACING\r
+ *\r
+ * Macro which should be defined as either zero (0) or one (1).\r
+ *\r
+ * If this is zero (0), the code for recording Interrupt Service Routines is\r
+ * excluded, in order to reduce code size.\r
+ *\r
+ * Default value is 1.\r
+ *\r
+ * Note: tracing ISRs requires that you insert calls to vTraceStoreISRBegin\r
+ * and vTraceStoreISREnd in your interrupt handlers.\r
+ *****************************************************************************/\r
+#define TRC_CFG_INCLUDE_ISR_TRACING 1\r
+\r
+/*****************************************************************************\r
+ * TRC_CFG_INCLUDE_READY_EVENTS\r
+ *\r
+ * Macro which should be defined as either zero (0) or one (1).\r
+ *\r
+ * If one (1), events are recorded when tasks enter scheduling state "ready".\r
+ * This allows Tracealyzer to show the initial pending time before tasks enter\r
+ * the execution state, and present accurate response times.\r
+ * If zero (0), "ready events" are not created, which allows for recording\r
+ * longer traces in the same amount of RAM.\r
+ *\r
+ * Default value is 1.\r
+ *****************************************************************************/\r
+#define TRC_CFG_INCLUDE_READY_EVENTS 1\r
+\r
+/*****************************************************************************\r
+ * TRC_CFG_INCLUDE_OSTICK_EVENTS\r
+ *\r
+ * Macro which should be defined as either zero (0) or one (1).\r
+ *\r
+ * If this is one (1), events will be generated whenever the OS clock is\r
+ * increased. If zero (0), OS tick events are not generated, which allows for\r
+ * recording longer traces in the same amount of RAM.\r
+ *\r
+ * Default value is 0.\r
+ *****************************************************************************/\r
+#define TRC_CFG_INCLUDE_OSTICK_EVENTS 1\r
+\r
+/******************************************************************************\r
+ * TRC_CFG_INCLUDE_FLOAT_SUPPORT\r
+ *\r
+ * Macro which should be defined as either zero (0) or one (1).\r
+ *\r
+ * If this is zero (0), the support for logging floating point values in\r
+ * vTracePrintF is stripped out, in case floating point values are not used or\r
+ * supported by the platform used.\r
+ *\r
+ * Floating point values are only used in vTracePrintF and its subroutines, to\r
+ * allow for storing float (%f) or double (%lf) arguments.\r
+ *\r
+ * vTracePrintF can be used with integer and string arguments in either case.\r
+ *\r
+ * Default value is 0.\r
+ *****************************************************************************/\r
+#define TRC_CFG_INCLUDE_FLOAT_SUPPORT 0\r
+\r
+/******************************************************************************\r
+ * TRC_CFG_INCLUDE_OBJECT_DELETE\r
+ *\r
+ * Macro which should be defined as either zero (0) or one (1).\r
+ *\r
+ * This must be enabled (1) if tasks, queues or other\r
+ * traced kernel objects are deleted at runtime. If no deletes are made, this\r
+ * can be set to 0 in order to exclude the delete-handling code.\r
+ *\r
+ * Default value is 1.\r
+ *****************************************************************************/\r
+#define TRC_CFG_INCLUDE_OBJECT_DELETE 1\r
+\r
+/*******************************************************************************\r
+ * TRC_CFG_SYMBOL_TABLE_SIZE\r
+ *\r
+ * Macro which should be defined as an integer value.\r
+ *\r
+ * This defines the capacity of the symbol table, in bytes. This symbol table\r
+ * stores User Events labels and names of deleted tasks, queues, or other kernel\r
+ * objects. If you don't use User Events or delete any kernel\r
+ * objects you set this to a very low value. The minimum recommended value is 4.\r
+ * A size of zero (0) is not allowed since a zero-sized array may result in a\r
+ * 32-bit pointer, i.e., using 4 bytes rather than 0.\r
+ *\r
+ * Default value is 800.\r
+ ******************************************************************************/\r
+#define TRC_CFG_SYMBOL_TABLE_SIZE 5000\r
+\r
+#if (TRC_CFG_SYMBOL_TABLE_SIZE == 0)\r
+#error "TRC_CFG_SYMBOL_TABLE_SIZE may not be zero!"\r
+#endif\r
+\r
+/******************************************************************************\r
+ * TRC_CFG_NAME_LEN_TASK, TRC_CFG_NAME_LEN_QUEUE, ...\r
+ *\r
+ * Macros that specify the maximum lengths (number of characters) for names of\r
+ * kernel objects, such as tasks and queues. If longer names are used, they will\r
+ * be truncated when stored in the recorder.\r
+ *****************************************************************************/\r
+#define TRC_CFG_NAME_LEN_TASK                  15\r
+#define TRC_CFG_NAME_LEN_ISR                   15\r
+#define TRC_CFG_NAME_LEN_QUEUE                 15\r
+#define TRC_CFG_NAME_LEN_SEMAPHORE             15\r
+#define TRC_CFG_NAME_LEN_MUTEX                 15\r
+#define TRC_CFG_NAME_LEN_TIMER                 15\r
+#define TRC_CFG_NAME_LEN_EVENTGROUP    15\r
+\r
+/******************************************************************************\r
+ *** ADVANCED SETTINGS ********************************************************\r
+ ******************************************************************************\r
+ * The remaining settings are not necessary to modify but allows for optimizing\r
+ * the recorder setup for your specific needs, e.g., to exclude events that you\r
+ * are not interested in, in order to get longer traces.\r
+ *****************************************************************************/\r
+\r
+/******************************************************************************\r
+* TRC_CFG_HEAP_SIZE_BELOW_16M\r
+*\r
+* An integer constant that can be used to reduce the buffer usage of memory\r
+* allocation events (malloc/free). This value should be 1 if the heap size is\r
+* below 16 MB (2^24 byte), and you can live with reported addresses showing the\r
+* lower 24 bits only. If 0, you get the full 32-bit addresses.\r
+*\r
+* Default value is 0.\r
+******************************************************************************/\r
+#define TRC_CFG_HEAP_SIZE_BELOW_16M 0\r
+\r
+/******************************************************************************\r
+ * TRC_CFG_USE_IMPLICIT_IFE_RULES\r
+ *\r
+ * Macro which should be defined as either zero (0) or one (1).\r
+ * Default is 1.\r
+ *\r
+ * Tracealyzer groups the events into "instances" based on Instance Finish\r
+ * Events (IFEs), produced either by default rules or calls to the recorder\r
+ * functions vTraceInstanceFinishedNow and vTraceInstanceFinishedNext.\r
+ *\r
+ * If TRC_CFG_USE_IMPLICIT_IFE_RULES is one (1), the default IFE rules is\r
+ * used, resulting in a "typical" grouping of events into instances.\r
+ * If these rules don't give appropriate instances in your case, you can\r
+ * override the default rules using vTraceInstanceFinishedNow/Next for one\r
+ * or several tasks. The default IFE rules are then disabled for those tasks.\r
+ *\r
+ * If TRC_CFG_USE_IMPLICIT_IFE_RULES is zero (0), the implicit IFE rules are\r
+ * disabled globally. You must then call vTraceInstanceFinishedNow or\r
+ * vTraceInstanceFinishedNext to manually group the events into instances,\r
+ * otherwise the tasks will appear a single long instance.\r
+ *\r
+ * The default IFE rules count the following events as "instance finished":\r
+ * - Task delay, delay until\r
+ * - Task suspend\r
+ * - Blocking on "input" operations, i.e., when the task is waiting for the\r
+ *   next a message/signal/event. But only if this event is blocking.\r
+ *\r
+ * For details, see trcSnapshotKernelPort.h and look for references to the\r
+ * macro trcKERNEL_HOOKS_SET_TASK_INSTANCE_FINISHED.\r
+ *****************************************************************************/\r
+#define TRC_CFG_USE_IMPLICIT_IFE_RULES 1\r
+\r
+/******************************************************************************\r
+ * TRC_CFG_USE_16BIT_OBJECT_HANDLES\r
+ *\r
+ * Macro which should be defined as either zero (0) or one (1).\r
+ *\r
+ * If set to 0 (zero), the recorder uses 8-bit handles to identify kernel\r
+ * objects such as tasks and queues. This limits the supported number of\r
+ * concurrently active objects to 255 of each type (tasks, queues, mutexes,\r
+ * etc.) Note: 255, not 256, since handle 0 is reserved.\r
+ *\r
+ * If set to 1 (one), the recorder uses 16-bit handles to identify kernel\r
+ * objects such as tasks and queues. This limits the supported number of\r
+ * concurrent objects to 65535 of each type (object class). However, since the\r
+ * object property table is limited to 64 KB, the practical limit is about\r
+ * 3000 objects in total.\r
+ *\r
+ * Default is 0 (8-bit handles)\r
+ *\r
+ * NOTE: An object with handle above 255 will use an extra 4-byte record in\r
+ * the event buffer whenever the object is referenced. Moreover, some internal\r
+ * tables in the recorder gets slightly larger when using 16-bit handles.\r
+ *****************************************************************************/\r
+#define TRC_CFG_USE_16BIT_OBJECT_HANDLES 0\r
+\r
+/******************************************************************************\r
+ * TRC_CFG_USE_TRACE_ASSERT\r
+ *\r
+ * Macro which should be defined as either zero (0) or one (1).\r
+ * Default is 1.\r
+ *\r
+ * If this is one (1), the TRACE_ASSERT macro (used at various locations in the\r
+ * trace recorder) will verify that a relevant condition is true.\r
+ * If the condition is false, prvTraceError() will be called, which stops the\r
+ * recording and stores an error message that is displayed when opening the\r
+ * trace in Tracealyzer.\r
+ *\r
+ * This is used on several places in the recorder code for sanity checks on\r
+ * parameters. Can be switched off to reduce the footprint of the tracing, but\r
+ * we recommend to have it enabled initially.\r
+ *****************************************************************************/\r
+#define TRC_CFG_USE_TRACE_ASSERT 1\r
+\r
+/*******************************************************************************\r
+ * TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER\r
+ *\r
+ * Macro which should be defined as an integer value.\r
+ *\r
+ * Set TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER to 1 to enable the\r
+ * separate user event buffer (UB).\r
+ * In this mode, user events are stored separately from other events,\r
+ * e.g., RTOS events. Thereby you can get a much longer history of\r
+ * user events as they don't need to share the buffer space with more\r
+ * frequent events.\r
+ *\r
+ * The UB is typically used with the snapshot ring-buffer mode, so the\r
+ * recording can continue when the main buffer gets full. And since the\r
+ * main buffer then overwrites the earliest events, Tracealyzer displays\r
+ * "Unknown Actor" instead of task scheduling for periods with UB data only.\r
+ *\r
+ * In UB mode, user events are structured as UB channels, which contains\r
+ * a channel name and a default format string. Register a UB channel using\r
+ * xTraceRegisterUBChannel.\r
+ *\r
+ * Events and data arguments are written using vTraceUBEvent and\r
+ * vTraceUBData. They are designed to provide efficient logging of\r
+ * repeating events, using the same format string within each channel.\r
+ *\r
+ * Examples:\r
+ *\r
+ *  traceString chn1 = xTraceRegisterString("Channel 1");\r
+ *  traceString fmt1 = xTraceRegisterString("Event!");\r
+ *  traceUBChannel UBCh1 = xTraceRegisterUBChannel(chn1, fmt1);\r
+ *\r
+ *  traceString chn2 = xTraceRegisterString("Channel 2");\r
+ *  traceString fmt2 = xTraceRegisterString("X: %d, Y: %d");\r
+ *     traceUBChannel UBCh2 = xTraceRegisterUBChannel(chn2, fmt2);\r
+ *\r
+ *  // Result in "[Channel 1] Event!"\r
+ *     vTraceUBEvent(UBCh1);\r
+ *\r
+ *  // Result in "[Channel 2] X: 23, Y: 19"\r
+ *     vTraceUBData(UBCh2, 23, 19);\r
+ *\r
+ * You can also use the other user event functions, like vTracePrintF.\r
+ * as they are then rerouted to the UB instead of the main event buffer.\r
+ * vTracePrintF then looks up the correct UB channel based on the\r
+ * provided channel name and format string, or creates a new UB channel\r
+ * if no match is found. The format string should therefore not contain\r
+ * "random" messages but mainly format specifiers. Random strings should\r
+ * be stored using %s and with the string as an argument.\r
+ *\r
+ *  // Creates a new UB channel ("Channel 2", "%Z: %d")\r
+ *  vTracePrintF(chn2, "%Z: %d", value1);\r
+ *\r
+ *  // Finds the existing UB channel\r
+ *  vTracePrintF(chn2, "%Z: %d", value2);\r
+\r
+ ******************************************************************************/\r
+#define TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER 0\r
+\r
+/*******************************************************************************\r
+ * TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE\r
+ *\r
+ * Macro which should be defined as an integer value.\r
+ *\r
+ * This defines the capacity of the user event buffer (UB), in number of slots.\r
+ * A single user event can use multiple slots, depending on the arguments.\r
+ *\r
+ * Only applicable if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is 1.\r
+ ******************************************************************************/\r
+#define TRC_CFG_SEPARATE_USER_EVENT_BUFFER_SIZE 10\r
+\r
+/*******************************************************************************\r
+ * TRC_CFG_UB_CHANNELS\r
+ *\r
+ * Macro which should be defined as an integer value.\r
+ *\r
+ * This defines the number of User Event Buffer Channels (UB channels).\r
+ * These are used to structure the events when using the separate user\r
+ * event buffer, and contains both a User Event Channel (the name) and\r
+ * a default format string for the channel.\r
+ *\r
+ * Only applicable if TRC_CFG_USE_SEPARATE_USER_EVENT_BUFFER is 1.\r
+ ******************************************************************************/\r
+#define TRC_CFG_UB_CHANNELS 32\r
+\r
+/*******************************************************************************\r
+ * TRC_CFG_ISR_TAILCHAINING_THRESHOLD\r
+ *\r
+ * Macro which should be defined as an integer value.\r
+ *\r
+ * If tracing multiple ISRs, this setting allows for accurate display of the\r
+ * context-switching also in cases when the ISRs execute in direct sequence.\r
+ *\r
+ * vTraceStoreISREnd normally assumes that the ISR returns to the previous\r
+ * context, i.e., a task or a preempted ISR. But if another traced ISR\r
+ * executes in direct sequence, Tracealyzer may incorrectly display a minimal\r
+ * fragment of the previous context in between the ISRs.\r
+ *\r
+ * By using TRC_CFG_ISR_TAILCHAINING_THRESHOLD you can avoid this. This is\r
+ * however a threshold value that must be measured for your specific setup.\r
+ * See http://percepio.com/2014/03/21/isr_tailchaining_threshold/\r
+ *\r
+ * The default setting is 0, meaning "disabled" and that you may get an\r
+ * extra fragments of the previous context in between tail-chained ISRs.\r
+ *\r
+ * Note: This setting has separate definitions in trcSnapshotConfig.h and\r
+ * trcStreamingConfig.h, since it is affected by the recorder mode.\r
+ ******************************************************************************/\r
+#define TRC_CFG_ISR_TAILCHAINING_THRESHOLD 0\r
+\r
+#endif /*TRC_SNAPSHOT_CONFIG_H*/\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_ARP.c
new file mode 100644 (file)
index 0000000..5f2ff25
--- /dev/null
@@ -0,0 +1,682 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "FreeRTOS_ARP.h"\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_DHCP.h"\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       #include "FreeRTOS_DNS.h"\r
+#endif /* ipconfigUSE_LLMNR */\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+\r
+/* When the age of an entry in the ARP table reaches this value (it counts down\r
+to zero, so this is an old entry) an ARP request will be sent to see if the\r
+entry is still valid and can therefore be refreshed. */\r
+#define arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST          ( 3 )\r
+\r
+/* The time between gratuitous ARPs. */\r
+#ifndef arpGRATUITOUS_ARP_PERIOD\r
+       #define arpGRATUITOUS_ARP_PERIOD                                        ( pdMS_TO_TICKS( 20000 ) )\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Lookup an MAC address in the ARP cache from the IP address.\r
+ */\r
+static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, MACAddress_t * const pxMACAddress );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The ARP cache. */\r
+static ARPCacheRow_t xARPCache[ ipconfigARP_CACHE_ENTRIES ];\r
+\r
+/* The time at which the last gratuitous ARP was sent.  Gratuitous ARPs are used\r
+to ensure ARP tables are up to date and to detect IP address conflicts. */\r
+static TickType_t xLastGratuitousARPTime = ( TickType_t ) 0;\r
+\r
+/*\r
+ * IP-clash detection is currently only used internally. When DHCP doesn't respond, the\r
+ * driver can try out a random LinkLayer IP address (169.254.x.x).  It will send out a\r
+ * gratuitos ARP message and, after a period of time, check the variables here below:\r
+ */\r
+#if( ipconfigARP_USE_CLASH_DETECTION != 0 )\r
+       /* Becomes non-zero if another device responded to a gratuitos ARP message. */\r
+       BaseType_t xARPHadIPClash;\r
+       /* MAC-address of the other device containing the same IP-address. */\r
+       MACAddress_t xARPClashMacAddress;\r
+#endif /* ipconfigARP_USE_CLASH_DETECTION */\r
+\r
+/* Part of the Ethernet and ARP headers are always constant when sending an IPv4\r
+ARP packet.  This array defines the constant parts, allowing this part of the\r
+packet to be filled in using a simple memcpy() instead of individual writes. */\r
+static const uint8_t xDefaultPartARPPacketHeader[] =\r
+{\r
+       0xff, 0xff, 0xff, 0xff, 0xff, 0xff,     /* Ethernet destination address. */\r
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     /* Ethernet source address. */\r
+       0x08, 0x06,                                                     /* Ethernet frame type (ipARP_FRAME_TYPE). */\r
+       0x00, 0x01,                                                     /* usHardwareType (ipARP_HARDWARE_TYPE_ETHERNET). */\r
+       0x08, 0x00,                                                             /* usProtocolType. */\r
+       ipMAC_ADDRESS_LENGTH_BYTES,                     /* ucHardwareAddressLength. */\r
+       ipIP_ADDRESS_LENGTH_BYTES,                              /* ucProtocolAddressLength. */\r
+       0x00, 0x01,                                                     /* usOperation (ipARP_REQUEST). */\r
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     /* xSenderHardwareAddress. */\r
+       0x00, 0x00, 0x00, 0x00,                                 /* ulSenderProtocolAddress. */\r
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00              /* xTargetHardwareAddress. */\r
+};\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )\r
+{\r
+eFrameProcessingResult_t eReturn = eReleaseBuffer;\r
+ARPHeader_t *pxARPHeader;\r
+uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;\r
+\r
+       pxARPHeader = &( pxARPFrame->xARPHeader );\r
+\r
+       /* The field ulSenderProtocolAddress is badly aligned, copy byte-by-byte. */\r
+       memcpy( ( void *)&( ulSenderProtocolAddress ), ( void * )pxARPHeader->ucSenderProtocolAddress, sizeof( ulSenderProtocolAddress ) );\r
+       /* The field ulTargetProtocolAddress is well-aligned, a 32-bits copy. */\r
+       ulTargetProtocolAddress = pxARPHeader->ulTargetProtocolAddress;\r
+\r
+       traceARP_PACKET_RECEIVED();\r
+\r
+       /* Don't do anything if the local IP address is zero because\r
+       that means a DHCP request has not completed. */\r
+       if( *ipLOCAL_IP_ADDRESS_POINTER != 0UL )\r
+       {\r
+               switch( pxARPHeader->usOperation )\r
+               {\r
+                       case ipARP_REQUEST      :\r
+                               /* The packet contained an ARP request.  Was it for the IP\r
+                               address of the node running this code? */\r
+                               if( ulTargetProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER )\r
+                               {\r
+                                       iptraceSENDING_ARP_REPLY( ulSenderProtocolAddress );\r
+\r
+                                       /* The request is for the address of this node.  Add the\r
+                                       entry into the ARP cache, or refresh the entry if it\r
+                                       already exists. */\r
+                                       vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress );\r
+\r
+                                       /* Generate a reply payload in the same buffer. */\r
+                                       pxARPHeader->usOperation = ( uint16_t ) ipARP_REPLY;\r
+                                       if( ulTargetProtocolAddress == ulSenderProtocolAddress )\r
+                                       {\r
+                                               /* A double IP address is detected! */\r
+                                               /* Give the sources MAC address the value of the broadcast address, will be swapped later */\r
+                                               memcpy( pxARPFrame->xEthernetHeader.xSourceAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( xBroadcastMACAddress ) );\r
+                                               memset( pxARPHeader->xTargetHardwareAddress.ucBytes, '\0', sizeof( MACAddress_t ) );\r
+                                               pxARPHeader->ulTargetProtocolAddress = 0UL;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               memcpy( pxARPHeader->xTargetHardwareAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( MACAddress_t ) );\r
+                                               pxARPHeader->ulTargetProtocolAddress = ulSenderProtocolAddress;\r
+                                       }\r
+                                       memcpy( pxARPHeader->xSenderHardwareAddress.ucBytes, ( void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );\r
+                                       memcpy( ( void* )pxARPHeader->ucSenderProtocolAddress, ( void* )ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPHeader->ucSenderProtocolAddress ) );\r
+\r
+                                       eReturn = eReturnEthernetFrame;\r
+                               }\r
+                               break;\r
+\r
+                       case ipARP_REPLY :\r
+                               iptracePROCESSING_RECEIVED_ARP_REPLY( ulTargetProtocolAddress );\r
+                               vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress );\r
+                               /* Process received ARP frame to see if there is a clash. */\r
+                               #if( ipconfigARP_USE_CLASH_DETECTION != 0 )\r
+                               {\r
+                                       if( ulSenderProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER )\r
+                                       {\r
+                                               xARPHadIPClash = pdTRUE;\r
+                                               memcpy( xARPClashMacAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( xARPClashMacAddress.ucBytes ) );\r
+                                       }\r
+                               }\r
+                               #endif /* ipconfigARP_USE_CLASH_DETECTION */\r
+                               break;\r
+\r
+                       default :\r
+                               /* Invalid. */\r
+                               break;\r
+               }\r
+       }\r
+\r
+       return eReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_ARP_REMOVE_ENTRY != 0 )\r
+\r
+       uint32_t ulARPRemoveCacheEntryByMac( const MACAddress_t * pxMACAddress )\r
+       {\r
+       BaseType_t x;\r
+       uint32_t lResult = 0;\r
+\r
+               /* For each entry in the ARP cache table. */\r
+               for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )\r
+               {\r
+                       if( ( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) )\r
+                       {\r
+                               lResult = xARPCache[ x ].ulIPAddress;\r
+                               memset( &xARPCache[ x ], '\0', sizeof( xARPCache[ x ] ) );\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               return lResult;\r
+       }\r
+\r
+#endif /* ipconfigUSE_ARP_REMOVE_ENTRY != 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress, const uint32_t ulIPAddress )\r
+{\r
+BaseType_t x, xIpEntry = -1, xMacEntry = -1, xUseEntry = 0;\r
+uint8_t ucMinAgeFound = 0U;\r
+\r
+       #if( ipconfigARP_STORES_REMOTE_ADDRESSES == 0 )\r
+               /* Only process the IP address if it is on the local network.\r
+               Unless: when '*ipLOCAL_IP_ADDRESS_POINTER' equals zero, the IP-address\r
+               and netmask are still unknown. */\r
+               if( ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ) ||\r
+                       ( *ipLOCAL_IP_ADDRESS_POINTER == 0ul ) )\r
+       #else\r
+               /* If ipconfigARP_STORES_REMOTE_ADDRESSES is non-zero, IP addresses with\r
+               a different netmask will also be stored.  After when replying to a UDP\r
+               message from a different netmask, the IP address can be looped up and a\r
+               reply sent.  This option is useful for systems with multiple gateways,\r
+               the reply will surely arrive.  If ipconfigARP_STORES_REMOTE_ADDRESSES is\r
+               zero the the gateway address is the only option. */\r
+               if( pdTRUE )\r
+       #endif\r
+       {\r
+               /* Start with the maximum possible number. */\r
+               ucMinAgeFound--;\r
+\r
+               /* For each entry in the ARP cache table. */\r
+               for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )\r
+               {\r
+                       /* Does this line in the cache table hold an entry for the IP\r
+                       address being queried? */\r
+                       if( xARPCache[ x ].ulIPAddress == ulIPAddress )\r
+                       {\r
+                               if( pxMACAddress == NULL )\r
+                               {\r
+                                       /* In case the parameter pxMACAddress is NULL, an entry will be reserved to\r
+                                       indicate that there is an outstanding ARP request, This entry will have\r
+                                       "ucValid == pdFALSE". */\r
+                                       xIpEntry = x;\r
+                                       break;\r
+                               }\r
+\r
+                               /* See if the MAC-address also matches. */\r
+                               if( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 )\r
+                               {\r
+                                       /* This function will be called for each received packet\r
+                                       As this is by far the most common path the coding standard\r
+                                       is relaxed in this case and a return is permitted as an\r
+                                       optimisation. */\r
+                                       xARPCache[ x ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;\r
+                                       xARPCache[ x ].ucValid = ( uint8_t ) pdTRUE;\r
+                                       return;\r
+                               }\r
+\r
+                               /* Found an entry containing ulIPAddress, but the MAC address\r
+                               doesn't match.  Might be an entry with ucValid=pdFALSE, waiting\r
+                               for an ARP reply.  Still want to see if there is match with the\r
+                               given MAC address.ucBytes.  If found, either of the two entries\r
+                               must be cleared. */\r
+                               xIpEntry = x;\r
+                       }\r
+                       else if( ( pxMACAddress != NULL ) && ( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) )\r
+                       {\r
+                               /* Found an entry with the given MAC-address, but the IP-address\r
+                               is different.  Continue looping to find a possible match with\r
+                               ulIPAddress. */\r
+       #if( ipconfigARP_STORES_REMOTE_ADDRESSES != 0 )\r
+                               /* If ARP stores the MAC address of IP addresses outside the\r
+                               network, than the MAC address of the gateway should not be\r
+                               overwritten. */\r
+                               BaseType_t bIsLocal[ 2 ];\r
+                               bIsLocal[ 0 ] = ( ( xARPCache[ x ].ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) );\r
+                               bIsLocal[ 1 ] = ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) );\r
+                               if( bIsLocal[ 0 ] == bIsLocal[ 1 ] )\r
+                               {\r
+                                       xMacEntry = x;\r
+                               }\r
+       #else\r
+                               xMacEntry = x;\r
+       #endif\r
+                       }\r
+                       /* _HT_\r
+                       Shouldn't we test for xARPCache[ x ].ucValid == pdFALSE here ? */\r
+                       else if( xARPCache[ x ].ucAge < ucMinAgeFound )\r
+                       {\r
+                               /* As the table is traversed, remember the table row that\r
+                               contains the oldest entry (the lowest age count, as ages are\r
+                               decremented to zero) so the row can be re-used if this function\r
+                               needs to add an entry that does not already exist. */\r
+                               ucMinAgeFound = xARPCache[ x ].ucAge;\r
+                               xUseEntry = x;\r
+                       }\r
+               }\r
+\r
+               if( xMacEntry >= 0 )\r
+               {\r
+                       xUseEntry = xMacEntry;\r
+\r
+                       if( xIpEntry >= 0 )\r
+                       {\r
+                               /* Both the MAC address as well as the IP address were found in\r
+                               different locations: clear the entry which matches the\r
+                               IP-address */\r
+                               memset( &xARPCache[ xIpEntry ], '\0', sizeof( xARPCache[ xIpEntry ] ) );\r
+                       }\r
+               }\r
+               else if( xIpEntry >= 0 )\r
+               {\r
+                       /* An entry containing the IP-address was found, but it had a different MAC address */\r
+                       xUseEntry = xIpEntry;\r
+               }\r
+\r
+               /* If the entry was not found, we use the oldest entry and set the IPaddress */\r
+               xARPCache[ xUseEntry ].ulIPAddress = ulIPAddress;\r
+\r
+               if( pxMACAddress != NULL )\r
+               {\r
+                       memcpy( xARPCache[ xUseEntry ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) );\r
+\r
+                       iptraceARP_TABLE_ENTRY_CREATED( ulIPAddress, (*pxMACAddress) );\r
+                       /* And this entry does not need immediate attention */\r
+                       xARPCache[ xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;\r
+                       xARPCache[ xUseEntry ].ucValid = ( uint8_t ) pdTRUE;\r
+               }\r
+               else if( xIpEntry < 0 )\r
+               {\r
+                       xARPCache[ xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_RETRANSMISSIONS;\r
+                       xARPCache[ xUseEntry ].ucValid = ( uint8_t ) pdFALSE;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_ARP_REVERSED_LOOKUP == 1 )\r
+       eARPLookupResult_t eARPGetCacheEntryByMac( MACAddress_t * const pxMACAddress, uint32_t *pulIPAddress )\r
+       {\r
+       BaseType_t x;\r
+       eARPLookupResult_t eReturn = eARPCacheMiss;\r
+\r
+               /* Loop through each entry in the ARP cache. */\r
+               for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )\r
+               {\r
+                       /* Does this row in the ARP cache table hold an entry for the MAC\r
+                       address being searched? */\r
+                       if( memcmp( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )\r
+                       {\r
+                               *pulIPAddress = xARPCache[ x ].ulIPAddress;\r
+                               eReturn = eARPCacheHit;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               return eReturn;\r
+       }\r
+#endif /* ipconfigUSE_ARP_REVERSED_LOOKUP */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+eARPLookupResult_t eARPGetCacheEntry( uint32_t *pulIPAddress, MACAddress_t * const pxMACAddress )\r
+{\r
+eARPLookupResult_t eReturn;\r
+uint32_t ulAddressToLookup;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       if( *pulIPAddress == ipLLMNR_IP_ADDR )  /* Is in network byte order. */\r
+       {\r
+               /* The LLMNR IP-address has a fixed virtual MAC address. */\r
+               memcpy( pxMACAddress->ucBytes, xLLMNR_MacAdress.ucBytes, sizeof( MACAddress_t ) );\r
+               eReturn = eARPCacheHit;\r
+       }\r
+       else\r
+#endif\r
+       if( ( *pulIPAddress == ipBROADCAST_IP_ADDRESS ) ||      /* Is it the general broadcast address 255.255.255.255? */\r
+               ( *pulIPAddress == xNetworkAddressing.ulBroadcastAddress ) )/* Or a local broadcast address, eg 192.168.1.255? */\r
+       {\r
+               /* This is a broadcast so uses the broadcast MAC address. */\r
+               memcpy( pxMACAddress->ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) );\r
+               eReturn = eARPCacheHit;\r
+       }\r
+       else if( *ipLOCAL_IP_ADDRESS_POINTER == 0UL )\r
+       {\r
+               /* The IP address has not yet been assigned, so there is nothing that\r
+               can be done. */\r
+               eReturn = eCantSendPacket;\r
+       }\r
+       else\r
+       {\r
+               eReturn = eARPCacheMiss;\r
+\r
+               if( ( *pulIPAddress & xNetworkAddressing.ulNetMask ) != ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) )\r
+               {\r
+#if( ipconfigARP_STORES_REMOTE_ADDRESSES == 1 )\r
+                       eReturn = prvCacheLookup( *pulIPAddress, pxMACAddress );\r
+\r
+                       if( eReturn == eARPCacheHit )\r
+                       {\r
+                               /* The stack is configured to store 'remote IP addresses', i.e. addresses\r
+                               belonging to a different the netmask.  prvCacheLookup() returned a hit, so\r
+                               the MAC address is known */\r
+                       }\r
+                       else\r
+#endif\r
+                       {\r
+                               /* The IP address is off the local network, so look up the\r
+                               hardware address of the router, if any. */\r
+                               if( xNetworkAddressing.ulGatewayAddress != ( uint32_t )0u )\r
+                               {\r
+                                       ulAddressToLookup = xNetworkAddressing.ulGatewayAddress;\r
+                               }\r
+                               else\r
+                               {\r
+                                       ulAddressToLookup = *pulIPAddress;\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* The IP address is on the local network, so lookup the requested\r
+                       IP address directly. */\r
+                       ulAddressToLookup = *pulIPAddress;\r
+               }\r
+\r
+               if( eReturn == eARPCacheMiss )\r
+               {\r
+                       if( ulAddressToLookup == 0UL )\r
+                       {\r
+                               /* The address is not on the local network, and there is not a\r
+                               router. */\r
+                               eReturn = eCantSendPacket;\r
+                       }\r
+                       else\r
+                       {\r
+                               eReturn = prvCacheLookup( ulAddressToLookup, pxMACAddress );\r
+\r
+                               if( eReturn == eARPCacheMiss )\r
+                               {\r
+                                       /* It might be that the ARP has to go to the gateway. */\r
+                                       *pulIPAddress = ulAddressToLookup;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       return eReturn;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, MACAddress_t * const pxMACAddress )\r
+{\r
+BaseType_t x;\r
+eARPLookupResult_t eReturn = eARPCacheMiss;\r
+\r
+       /* Loop through each entry in the ARP cache. */\r
+       for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )\r
+       {\r
+               /* Does this row in the ARP cache table hold an entry for the IP address\r
+               being queried? */\r
+               if( xARPCache[ x ].ulIPAddress == ulAddressToLookup )\r
+               {\r
+                       /* A matching valid entry was found. */\r
+                       if( xARPCache[ x ].ucValid == ( uint8_t ) pdFALSE )\r
+                       {\r
+                               /* This entry is waiting an ARP reply, so is not valid. */\r
+                               eReturn = eCantSendPacket;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* A valid entry was found. */\r
+                               memcpy( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) );\r
+                               eReturn = eARPCacheHit;\r
+                       }\r
+                       break;\r
+               }\r
+       }\r
+\r
+       return eReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vARPAgeCache( void )\r
+{\r
+BaseType_t x;\r
+TickType_t xTimeNow;\r
+\r
+       /* Loop through each entry in the ARP cache. */\r
+       for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )\r
+       {\r
+               /* If the entry is valid (its age is greater than zero). */\r
+               if( xARPCache[ x ].ucAge > 0U )\r
+               {\r
+                       /* Decrement the age value of the entry in this ARP cache table row.\r
+                       When the age reaches zero it is no longer considered valid. */\r
+                       ( xARPCache[ x ].ucAge )--;\r
+\r
+                       /* If the entry is not yet valid, then it is waiting an ARP\r
+                       reply, and the ARP request should be retransmitted. */\r
+                       if( xARPCache[ x ].ucValid == ( uint8_t ) pdFALSE )\r
+                       {\r
+                               FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress );\r
+                       }\r
+                       else if( xARPCache[ x ].ucAge <= ( uint8_t ) arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST )\r
+                       {\r
+                               /* This entry will get removed soon.  See if the MAC address is\r
+                               still valid to prevent this happening. */\r
+                               iptraceARP_TABLE_ENTRY_WILL_EXPIRE( xARPCache[ x ].ulIPAddress );\r
+                               FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* The age has just ticked down, with nothing to do. */\r
+                       }\r
+\r
+                       if( xARPCache[ x ].ucAge == 0u )\r
+                       {\r
+                               /* The entry is no longer valid.  Wipe it out. */\r
+                               iptraceARP_TABLE_ENTRY_EXPIRED( xARPCache[ x ].ulIPAddress );\r
+                               xARPCache[ x ].ulIPAddress = 0UL;\r
+                       }\r
+               }\r
+       }\r
+\r
+       xTimeNow = xTaskGetTickCount ();\r
+\r
+       if( ( xLastGratuitousARPTime == ( TickType_t ) 0 ) || ( ( xTimeNow - xLastGratuitousARPTime ) > ( TickType_t ) arpGRATUITOUS_ARP_PERIOD ) )\r
+       {\r
+               FreeRTOS_OutputARPRequest( *ipLOCAL_IP_ADDRESS_POINTER );\r
+               xLastGratuitousARPTime = xTimeNow;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vARPSendGratuitous( void )\r
+{\r
+       /* Setting xLastGratuitousARPTime to 0 will force a gratuitous ARP the next\r
+       time vARPAgeCache() is called. */\r
+       xLastGratuitousARPTime = ( TickType_t ) 0;\r
+\r
+       /* Let the IP-task call vARPAgeCache(). */\r
+       xSendEventToIPTask( eARPTimerEvent );\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress )\r
+{\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+\r
+       /* This is called from the context of the IP event task, so a block time\r
+       must not be used. */\r
+       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( ARPPacket_t ), ( TickType_t ) 0 );\r
+\r
+       if( pxNetworkBuffer != NULL )\r
+       {\r
+               pxNetworkBuffer->ulIPAddress = ulIPAddress;\r
+               vARPGenerateRequestPacket( pxNetworkBuffer );\r
+\r
+               #if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
+               {\r
+                       if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
+                       {\r
+                       BaseType_t xIndex;\r
+\r
+                               for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )\r
+                               {\r
+                                       pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;\r
+                               }\r
+                               pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;\r
+                       }\r
+               }\r
+               #endif\r
+\r
+               xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );\r
+       }\r
+}\r
+\r
+void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+ARPPacket_t *pxARPPacket;\r
+\r
+       pxARPPacket = ( ARPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;\r
+\r
+       /* memcpy the const part of the header information into the correct\r
+       location in the packet.  This copies:\r
+               xEthernetHeader.ulDestinationAddress\r
+               xEthernetHeader.usFrameType;\r
+               xARPHeader.usHardwareType;\r
+               xARPHeader.usProtocolType;\r
+               xARPHeader.ucHardwareAddressLength;\r
+               xARPHeader.ucProtocolAddressLength;\r
+               xARPHeader.usOperation;\r
+               xARPHeader.xTargetHardwareAddress;\r
+       */\r
+       memcpy( ( void * ) &( pxARPPacket->xEthernetHeader ), ( void * ) xDefaultPartARPPacketHeader, sizeof( xDefaultPartARPPacketHeader ) );\r
+       memcpy( ( void * ) pxARPPacket->xEthernetHeader.xSourceAddress.ucBytes , ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );\r
+       memcpy( ( void * ) pxARPPacket->xARPHeader.xSenderHardwareAddress.ucBytes, ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );\r
+\r
+       memcpy( ( void* )pxARPPacket->xARPHeader.ucSenderProtocolAddress, ( void* )ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPPacket->xARPHeader.ucSenderProtocolAddress ) );\r
+       pxARPPacket->xARPHeader.ulTargetProtocolAddress = pxNetworkBuffer->ulIPAddress;\r
+\r
+       pxNetworkBuffer->xDataLength = sizeof( ARPPacket_t );\r
+\r
+       iptraceCREATING_ARP_REQUEST( pxNetworkBuffer->ulIPAddress );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FreeRTOS_ClearARP( void )\r
+{\r
+       memset( xARPCache, '\0', sizeof( xARPCache ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+\r
+       void FreeRTOS_PrintARPCache( void )\r
+       {\r
+       BaseType_t x, xCount = 0;\r
+\r
+               /* Loop through each entry in the ARP cache. */\r
+               for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )\r
+               {\r
+                       if( ( xARPCache[ x ].ulIPAddress != 0ul ) && ( xARPCache[ x ].ucAge > 0U ) )\r
+                       {\r
+                               /* See if the MAC-address also matches, and we're all happy */\r
+                               FreeRTOS_printf( ( "Arp %2ld: %3u - %16lxip : %02x:%02x:%02x : %02x:%02x:%02x\n",\r
+                                       x,\r
+                                       xARPCache[ x ].ucAge,\r
+                                       xARPCache[ x ].ulIPAddress,\r
+                                       xARPCache[ x ].xMACAddress.ucBytes[0],\r
+                                       xARPCache[ x ].xMACAddress.ucBytes[1],\r
+                                       xARPCache[ x ].xMACAddress.ucBytes[2],\r
+                                       xARPCache[ x ].xMACAddress.ucBytes[3],\r
+                                       xARPCache[ x ].xMACAddress.ucBytes[4],\r
+                                       xARPCache[ x ].xMACAddress.ucBytes[5] ) );\r
+                               xCount++;\r
+                       }\r
+               }\r
+\r
+               FreeRTOS_printf( ( "Arp has %ld entries\n", xCount ) );\r
+       }\r
+\r
+#endif /* ( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 ) */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DHCP.c
new file mode 100644 (file)
index 0000000..2e3377a
--- /dev/null
@@ -0,0 +1,1015 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_TCP_IP.h"\r
+#include "FreeRTOS_DHCP.h"\r
+#include "FreeRTOS_ARP.h"\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* Exclude the entire file if DHCP is not enabled. */\r
+#if( ipconfigUSE_DHCP != 0 )\r
+\r
+#if ( ipconfigUSE_DHCP != 0 ) && ( ipconfigNETWORK_MTU < 586u )\r
+       /* DHCP must be able to receive an options field of 312 bytes, the fixed\r
+       part of the DHCP packet is 240 bytes, and the IP/UDP headers take 28 bytes. */\r
+       #error ipconfigNETWORK_MTU needs to be at least 586 to use DHCP\r
+#endif\r
+\r
+/* Parameter widths in the DHCP packet. */\r
+#define dhcpCLIENT_HARDWARE_ADDRESS_LENGTH             16\r
+#define dhcpSERVER_HOST_NAME_LENGTH                            64\r
+#define dhcpBOOT_FILE_NAME_LENGTH                              128\r
+\r
+/* Timer parameters */\r
+#ifndef dhcpINITIAL_DHCP_TX_PERIOD\r
+       #define dhcpINITIAL_TIMER_PERIOD                        ( pdMS_TO_TICKS( 250 ) )\r
+       #define dhcpINITIAL_DHCP_TX_PERIOD                      ( pdMS_TO_TICKS( 5000 ) )\r
+#endif\r
+\r
+/* Codes of interest found in the DHCP options field. */\r
+#define dhcpIPv4_ZERO_PAD_OPTION_CODE                  ( 0u )\r
+#define dhcpIPv4_SUBNET_MASK_OPTION_CODE               ( 1u )\r
+#define dhcpIPv4_GATEWAY_OPTION_CODE                   ( 3u )\r
+#define dhcpIPv4_DNS_SERVER_OPTIONS_CODE               ( 6u )\r
+#define dhcpIPv4_DNS_HOSTNAME_OPTIONS_CODE             ( 12u )\r
+#define dhcpIPv4_REQUEST_IP_ADDRESS_OPTION_CODE        ( 50u )\r
+#define dhcpIPv4_LEASE_TIME_OPTION_CODE                        ( 51u )\r
+#define dhcpIPv4_MESSAGE_TYPE_OPTION_CODE              ( 53u )\r
+#define dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE ( 54u )\r
+#define dhcpIPv4_PARAMETER_REQUEST_OPTION_CODE ( 55u )\r
+#define dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE ( 61u )\r
+\r
+/* The four DHCP message types of interest. */\r
+#define dhcpMESSAGE_TYPE_DISCOVER                              ( 1 )\r
+#define dhcpMESSAGE_TYPE_OFFER                                 ( 2 )\r
+#define dhcpMESSAGE_TYPE_REQUEST                               ( 3 )\r
+#define dhcpMESSAGE_TYPE_ACK                                   ( 5 )\r
+#define dhcpMESSAGE_TYPE_NACK                                  ( 6 )\r
+\r
+/* Offsets into the transmitted DHCP options fields at which various parameters\r
+are located. */\r
+#define dhcpCLIENT_IDENTIFIER_OFFSET                   ( 5 )\r
+#define dhcpREQUESTED_IP_ADDRESS_OFFSET                        ( 13 )\r
+#define dhcpDHCP_SERVER_IP_ADDRESS_OFFSET              ( 19 )\r
+\r
+/* Values used in the DHCP packets. */\r
+#define dhcpREQUEST_OPCODE                                             ( 1 )\r
+#define dhcpREPLY_OPCODE                                               ( 2 )\r
+#define dhcpADDRESS_TYPE_ETHERNET                              ( 1 )\r
+#define dhcpETHERNET_ADDRESS_LENGTH                            ( 6 )\r
+\r
+/* If a lease time is not received, use the default of two days. */\r
+/* 48 hours in ticks.  Can not use pdMS_TO_TICKS() as integer overflow can occur. */\r
+#define dhcpDEFAULT_LEASE_TIME                                 ( ( 48UL * 60UL * 60UL ) * configTICK_RATE_HZ )\r
+\r
+/* Don't allow the lease time to be too short. */\r
+#define dhcpMINIMUM_LEASE_TIME                                 ( pdMS_TO_TICKS( 60000UL ) )    /* 60 seconds in ticks. */\r
+\r
+/* Marks the end of the variable length options field in the DHCP packet. */\r
+#define dhcpOPTION_END_BYTE 0xffu\r
+\r
+/* Offset into a DHCP message at which the first byte of the options is\r
+located. */\r
+#define dhcpFIRST_OPTION_BYTE_OFFSET                   ( 0xf0 )\r
+\r
+/* When walking the variable length options field, the following value is used\r
+to ensure the walk has not gone past the end of the valid options.  2 bytes is\r
+made up of the length byte, and minimum one byte value. */\r
+#define dhcpMAX_OPTION_LENGTH_OF_INTEREST              ( 2L )\r
+\r
+/* Standard DHCP port numbers and magic cookie value.\r
+DHCPv4 uses UDP port number  68 for clients and port number  67 for servers.\r
+*/\r
+#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )\r
+       #define dhcpCLIENT_PORT 0x4400u\r
+       #define dhcpSERVER_PORT 0x4300u\r
+       #define dhcpCOOKIE              0x63538263ul\r
+       #define dhcpBROADCAST   0x0080u\r
+#else\r
+       #define dhcpCLIENT_PORT 0x0044u\r
+       #define dhcpSERVER_PORT 0x0043u\r
+       #define dhcpCOOKIE              0x63825363ul\r
+       #define dhcpBROADCAST   0x8000u\r
+#endif /* ipconfigBYTE_ORDER */\r
+\r
+#include "pack_struct_start.h"\r
+struct xDHCPMessage\r
+{\r
+       uint8_t ucOpcode;\r
+       uint8_t ucAddressType;\r
+       uint8_t ucAddressLength;\r
+       uint8_t ucHops;\r
+       uint32_t ulTransactionID;\r
+       uint16_t usElapsedTime;\r
+       uint16_t usFlags;\r
+       uint32_t ulClientIPAddress_ciaddr;\r
+       uint32_t ulYourIPAddress_yiaddr;\r
+       uint32_t ulServerIPAddress_siaddr;\r
+       uint32_t ulRelayAgentIPAddress_giaddr;\r
+       uint8_t ucClientHardwareAddress[ dhcpCLIENT_HARDWARE_ADDRESS_LENGTH ];\r
+       uint8_t ucServerHostName[ dhcpSERVER_HOST_NAME_LENGTH ];\r
+       uint8_t ucBootFileName[ dhcpBOOT_FILE_NAME_LENGTH ];\r
+       uint32_t ulDHCPCookie;\r
+       uint8_t ucFirstOptionByte;\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xDHCPMessage DHCPMessage_t;\r
+\r
+/* DHCP state machine states. */\r
+typedef enum\r
+{\r
+       eWaitingSendFirstDiscover = 0,  /* Initial state.  Send a discover the first time it is called, and reset all timers. */\r
+       eWaitingOffer,                                  /* Either resend the discover, or, if the offer is forthcoming, send a request. */\r
+       eWaitingAcknowledge,                    /* Either resend the request. */\r
+       #if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )\r
+               eGetLinkLayerAddress,           /* When DHCP didn't respond, try to obtain a LinkLayer address 168.254.x.x. */\r
+       #endif\r
+       eLeasedAddress,                                 /* Resend the request at the appropriate time to renew the lease. */\r
+       eNotUsingLeasedAddress                  /* DHCP failed, and a default IP address is being used. */\r
+} eDHCPState_t;\r
+\r
+/* Hold information in between steps in the DHCP state machine. */\r
+struct xDHCP_DATA\r
+{\r
+       uint32_t ulTransactionId;\r
+       uint32_t ulOfferedIPAddress;\r
+       uint32_t ulDHCPServerAddress;\r
+       uint32_t ulLeaseTime;\r
+       /* Hold information on the current timer state. */\r
+       TickType_t xDHCPTxTime;\r
+       TickType_t xDHCPTxPeriod;\r
+       /* Try both without and with the broadcast flag */\r
+       BaseType_t xUseBroadcast;\r
+       /* Maintains the DHCP state machine state. */\r
+       eDHCPState_t eDHCPState;\r
+       /* The UDP socket used for all incoming and outgoing DHCP traffic. */\r
+       Socket_t xDHCPSocket;\r
+};\r
+\r
+typedef struct xDHCP_DATA DHCPData_t;\r
+\r
+#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )\r
+       /* Define the Link Layer IP address: 169.254.x.x */\r
+       #define LINK_LAYER_ADDRESS_0    169\r
+       #define LINK_LAYER_ADDRESS_1    254\r
+\r
+       /* Define the netmask used: 255.255.0.0 */\r
+       #define LINK_LAYER_NETMASK_0    255\r
+       #define LINK_LAYER_NETMASK_1    255\r
+       #define LINK_LAYER_NETMASK_2    0\r
+       #define LINK_LAYER_NETMASK_3    0\r
+#endif\r
+\r
+\r
+/*\r
+ * Generate a DHCP discover message and send it on the DHCP socket.\r
+ */\r
+static void prvSendDHCPDiscover( void );\r
+\r
+/*\r
+ * Interpret message received on the DHCP socket.\r
+ */\r
+static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType );\r
+\r
+/*\r
+ * Generate a DHCP request packet, and send it on the DHCP socket.\r
+ */\r
+static void prvSendDHCPRequest( void );\r
+\r
+/*\r
+ * Prepare to start a DHCP transaction.  This initialises some state variables\r
+ * and creates the DHCP socket if necessary.\r
+ */\r
+static void prvInitialiseDHCP( void );\r
+\r
+/*\r
+ * Creates the part of outgoing DHCP messages that are common to all outgoing\r
+ * DHCP messages.\r
+ */\r
+static uint8_t *prvCreatePartDHCPMessage( struct freertos_sockaddr *pxAddress, BaseType_t xOpcode, const uint8_t * const pucOptionsArray, size_t *pxOptionsArraySize );\r
+\r
+/*\r
+ * Create the DHCP socket, if it has not been created already.\r
+ */\r
+static void prvCreateDHCPSocket( void );\r
+\r
+/*\r
+ * After DHCP has failed to answer, prepare everything to start searching\r
+ * for (trying-out) LinkLayer IP-addresses, using the random method: Send\r
+ * a gratuitous ARP request and wait if another device responds to it.\r
+ */\r
+#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )\r
+       static void prvPrepareLinkLayerIPLookUp( void );\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The next DHCP transaction Id to be used. */\r
+static DHCPData_t xDHCPData;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xIsDHCPSocket( Socket_t xSocket )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( xDHCPData.xDHCPSocket == xSocket )\r
+       {\r
+               xReturn = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdFALSE;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vDHCPProcess( BaseType_t xReset )\r
+{\r
+BaseType_t xGivingUp = pdFALSE;\r
+#if( ipconfigUSE_DHCP_HOOK != 0 )\r
+       eDHCPCallbackAnswer_t eAnswer;\r
+#endif /* ipconfigUSE_DHCP_HOOK */\r
+\r
+       /* Is DHCP starting over? */\r
+       if( xReset != pdFALSE )\r
+       {\r
+               xDHCPData.eDHCPState = eWaitingSendFirstDiscover;\r
+       }\r
+\r
+       switch( xDHCPData.eDHCPState )\r
+       {\r
+               case eWaitingSendFirstDiscover :\r
+                       /* Ask the user if a DHCP discovery is required. */\r
+               #if( ipconfigUSE_DHCP_HOOK != 0 )\r
+                       eAnswer = xApplicationDHCPHook( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress );\r
+                       if( eAnswer == eDHCPContinue )\r
+               #endif  /* ipconfigUSE_DHCP_HOOK */\r
+                       {\r
+                               /* Initial state.  Create the DHCP socket, timer, etc. if they\r
+                               have not already been created. */\r
+                               prvInitialiseDHCP();\r
+\r
+                               /* See if prvInitialiseDHCP() has creates a socket. */\r
+                               if( xDHCPData.xDHCPSocket == NULL )\r
+                               {\r
+                                       xGivingUp = pdTRUE;\r
+                                       break;\r
+                               }\r
+\r
+                               *ipLOCAL_IP_ADDRESS_POINTER = 0UL;\r
+\r
+                               /* Send the first discover request. */\r
+                               if( xDHCPData.xDHCPSocket != NULL )\r
+                               {\r
+                                       xDHCPData.xDHCPTxTime = xTaskGetTickCount();\r
+                                       prvSendDHCPDiscover( );\r
+                                       xDHCPData.eDHCPState = eWaitingOffer;\r
+                               }\r
+                       }\r
+               #if( ipconfigUSE_DHCP_HOOK != 0 )\r
+                       else\r
+                       {\r
+                               if( eAnswer == eDHCPUseDefaults )\r
+                               {\r
+                                       memcpy( &xNetworkAddressing, &xDefaultAddressing, sizeof( xNetworkAddressing ) );\r
+                               }\r
+\r
+                               /* The user indicates that the DHCP process does not continue. */\r
+                               xGivingUp = pdTRUE;\r
+                       }\r
+               #endif  /* ipconfigUSE_DHCP_HOOK */\r
+                       break;\r
+\r
+               case eWaitingOffer :\r
+\r
+                       xGivingUp = pdFALSE;\r
+\r
+                       /* Look for offers coming in. */\r
+                       if( prvProcessDHCPReplies( dhcpMESSAGE_TYPE_OFFER ) == pdPASS )\r
+                       {\r
+                       #if( ipconfigUSE_DHCP_HOOK != 0 )\r
+                               /* Ask the user if a DHCP request is required. */\r
+                               eAnswer = xApplicationDHCPHook( eDHCPPhasePreRequest, xDHCPData.ulOfferedIPAddress );\r
+\r
+                               if( eAnswer == eDHCPContinue )\r
+                       #endif  /* ipconfigUSE_DHCP_HOOK */\r
+                               {\r
+                                       /* An offer has been made, the user wants to continue,\r
+                                       generate the request. */\r
+                                       xDHCPData.xDHCPTxTime = xTaskGetTickCount();\r
+                                       xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;\r
+                                       prvSendDHCPRequest( );\r
+                                       xDHCPData.eDHCPState = eWaitingAcknowledge;\r
+                                       break;\r
+                               }\r
+\r
+                       #if( ipconfigUSE_DHCP_HOOK != 0 )\r
+                               if( eAnswer == eDHCPUseDefaults )\r
+                               {\r
+                                       memcpy( &xNetworkAddressing, &xDefaultAddressing, sizeof( xNetworkAddressing ) );\r
+                               }\r
+\r
+                               /* The user indicates that the DHCP process does not continue. */\r
+                               xGivingUp = pdTRUE;\r
+                       #endif  /* ipconfigUSE_DHCP_HOOK */\r
+                       }\r
+                       else if( ( xTaskGetTickCount() - xDHCPData.xDHCPTxTime ) > xDHCPData.xDHCPTxPeriod )\r
+                       {\r
+                               /* It is time to send another Discover.  Increase the time\r
+                               period, and if it has not got to the point of giving up - send\r
+                               another discovery. */\r
+                               xDHCPData.xDHCPTxPeriod <<= 1;\r
+\r
+                               if( xDHCPData.xDHCPTxPeriod <= ipconfigMAXIMUM_DISCOVER_TX_PERIOD )\r
+                               {\r
+                                       xDHCPData.ulTransactionId++;\r
+                                       xDHCPData.xDHCPTxTime = xTaskGetTickCount();\r
+                                       xDHCPData.xUseBroadcast = !xDHCPData.xUseBroadcast;\r
+                                       prvSendDHCPDiscover( );\r
+                                       FreeRTOS_debug_printf( ( "vDHCPProcess: timeout %lu ticks\n", xDHCPData.xDHCPTxPeriod ) );\r
+                               }\r
+                               else\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "vDHCPProcess: giving up %lu > %lu ticks\n", xDHCPData.xDHCPTxPeriod, ipconfigMAXIMUM_DISCOVER_TX_PERIOD ) );\r
+\r
+                                       #if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )\r
+                                       {\r
+                                               /* Only use a fake Ack if the default IP address == 0x00\r
+                                               and the link local addressing is used.  Start searching\r
+                                               a free LinkLayer IP-address.  Next state will be\r
+                                               'eGetLinkLayerAddress'. */\r
+                                               prvPrepareLinkLayerIPLookUp();\r
+\r
+                                               /* Setting an IP address manually so set to not using\r
+                                               leased address mode. */\r
+                                               xDHCPData.eDHCPState = eGetLinkLayerAddress;\r
+                                       }\r
+                                       #else\r
+                                       {\r
+                                               xGivingUp = pdTRUE;\r
+                                       }\r
+                                       #endif /* ipconfigDHCP_FALL_BACK_AUTO_IP */\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case eWaitingAcknowledge :\r
+\r
+                       /* Look for acks coming in. */\r
+                       if( prvProcessDHCPReplies( dhcpMESSAGE_TYPE_ACK ) == pdPASS )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "vDHCPProcess: acked %lxip\n", FreeRTOS_ntohl( xDHCPData.ulOfferedIPAddress ) ) );\r
+\r
+                               /* DHCP completed.  The IP address can now be used, and the\r
+                               timer set to the lease timeout time. */\r
+                               *ipLOCAL_IP_ADDRESS_POINTER = xDHCPData.ulOfferedIPAddress;\r
+\r
+                               /* Setting the 'local' broadcast address, something like\r
+                               '192.168.1.255'. */\r
+                               xNetworkAddressing.ulBroadcastAddress = ( xDHCPData.ulOfferedIPAddress & xNetworkAddressing.ulNetMask ) |  ~xNetworkAddressing.ulNetMask;\r
+                               xDHCPData.eDHCPState = eLeasedAddress;\r
+\r
+                               iptraceDHCP_SUCCEDEED( xDHCPData.ulOfferedIPAddress );\r
+\r
+                               /* DHCP failed, the default configured IP-address will be used\r
+                               Now call vIPNetworkUpCalls() to send the network-up event and\r
+                               start the ARP timer. */\r
+                               vIPNetworkUpCalls( );\r
+\r
+                               /* Close socket to ensure packets don't queue on it. */\r
+                               vSocketClose( xDHCPData.xDHCPSocket );\r
+                               xDHCPData.xDHCPSocket = NULL;\r
+\r
+                               if( xDHCPData.ulLeaseTime == 0UL )\r
+                               {\r
+                                       xDHCPData.ulLeaseTime = dhcpDEFAULT_LEASE_TIME;\r
+                               }\r
+                               else if( xDHCPData.ulLeaseTime < dhcpMINIMUM_LEASE_TIME )\r
+                               {\r
+                                       xDHCPData.ulLeaseTime = dhcpMINIMUM_LEASE_TIME;\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* The lease time is already valid. */\r
+                               }\r
+\r
+                               /* Check for clashes. */\r
+                               vARPSendGratuitous();\r
+                               vIPReloadDHCPTimer( xDHCPData.ulLeaseTime );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Is it time to send another Discover? */\r
+                               if( ( xTaskGetTickCount() - xDHCPData.xDHCPTxTime ) > xDHCPData.xDHCPTxPeriod )\r
+                               {\r
+                                       /* Increase the time period, and if it has not got to the\r
+                                       point of giving up - send another request. */\r
+                                       xDHCPData.xDHCPTxPeriod <<= 1;\r
+\r
+                                       if( xDHCPData.xDHCPTxPeriod <= ipconfigMAXIMUM_DISCOVER_TX_PERIOD )\r
+                                       {\r
+                                               xDHCPData.xDHCPTxTime = xTaskGetTickCount();\r
+                                               prvSendDHCPRequest( );\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               /* Give up, start again. */\r
+                                               xDHCPData.eDHCPState = eWaitingSendFirstDiscover;\r
+                                       }\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+       #if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )\r
+               case eGetLinkLayerAddress:\r
+                       if( ( xTaskGetTickCount() - xDHCPData.xDHCPTxTime ) > xDHCPData.xDHCPTxPeriod )\r
+                       {\r
+                               if( xARPHadIPClash == pdFALSE )\r
+                               {\r
+                                       /* ARP OK. proceed. */\r
+                                       iptraceDHCP_SUCCEDEED( xDHCPData.ulOfferedIPAddress );\r
+\r
+                                       /* Auto-IP succeeded, the default configured IP-address will\r
+                                       be used.  Now call vIPNetworkUpCalls() to send the\r
+                                       network-up event and start the ARP timer. */\r
+                                       vIPNetworkUpCalls( );\r
+                                       xDHCPData.eDHCPState = eNotUsingLeasedAddress;\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* ARP clashed - try another IP address. */\r
+                                       prvPrepareLinkLayerIPLookUp();\r
+\r
+                                       /* Setting an IP address manually so set to not using leased\r
+                                       address mode. */\r
+                                       xDHCPData.eDHCPState = eGetLinkLayerAddress;\r
+                               }\r
+                       }\r
+                       break;\r
+       #endif  /* ipconfigDHCP_FALL_BACK_AUTO_IP */\r
+\r
+               case eLeasedAddress :\r
+\r
+                       /* Resend the request at the appropriate time to renew the lease. */\r
+                       prvCreateDHCPSocket();\r
+\r
+                       if( xDHCPData.xDHCPSocket != NULL )\r
+                       {\r
+                               xDHCPData.xDHCPTxTime = xTaskGetTickCount();\r
+                               xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;\r
+                               prvSendDHCPRequest( );\r
+                               xDHCPData.eDHCPState = eWaitingAcknowledge;\r
+\r
+                               /* From now on, we should be called more often */\r
+                               vIPReloadDHCPTimer( dhcpINITIAL_TIMER_PERIOD );\r
+                       }\r
+                       break;\r
+\r
+               case eNotUsingLeasedAddress:\r
+\r
+                       vIPSetDHCPTimerEnableState( pdFALSE );\r
+                       break;\r
+\r
+               default:\r
+                       break;\r
+       }\r
+\r
+       if( xGivingUp != pdFALSE )\r
+       {\r
+               /* xGivingUp became true either because of a time-out, or because\r
+               xApplicationDHCPHook() returned another value than 'eDHCPContinue',\r
+               meaning that the conversion is cancelled from here. */\r
+\r
+               /* Revert to static IP address. */\r
+               taskENTER_CRITICAL();\r
+               {\r
+                       *ipLOCAL_IP_ADDRESS_POINTER = xNetworkAddressing.ulDefaultIPAddress;\r
+                       iptraceDHCP_REQUESTS_FAILED_USING_DEFAULT_IP_ADDRESS( xNetworkAddressing.ulDefaultIPAddress );\r
+               }\r
+               taskEXIT_CRITICAL();\r
+\r
+               xDHCPData.eDHCPState = eNotUsingLeasedAddress;\r
+               vIPSetDHCPTimerEnableState( pdFALSE );\r
+\r
+               /* DHCP failed, the default configured IP-address will be used.  Now\r
+               call vIPNetworkUpCalls() to send the network-up event and start the ARP\r
+               timer. */\r
+               vIPNetworkUpCalls( );\r
+\r
+               /* Test if socket was indeed created. */\r
+               if( xDHCPData.xDHCPSocket != NULL )\r
+               {\r
+                       /* Close socket to ensure packets don't queue on it. */\r
+                       vSocketClose( xDHCPData.xDHCPSocket );\r
+                       xDHCPData.xDHCPSocket = NULL;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCreateDHCPSocket( void )\r
+{\r
+struct freertos_sockaddr xAddress;\r
+BaseType_t xReturn;\r
+TickType_t xTimeoutTime = ( TickType_t ) 0;\r
+\r
+       /* Create the socket, if it has not already been created. */\r
+       if( xDHCPData.xDHCPSocket == NULL )\r
+       {\r
+               xDHCPData.xDHCPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
+               if( xDHCPData.xDHCPSocket != FREERTOS_INVALID_SOCKET )\r
+               {\r
+\r
+                       /* Ensure the Rx and Tx timeouts are zero as the DHCP executes in the\r
+                       context of the IP task. */\r
+                       FreeRTOS_setsockopt( xDHCPData.xDHCPSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xTimeoutTime, sizeof( TickType_t ) );\r
+                       FreeRTOS_setsockopt( xDHCPData.xDHCPSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xTimeoutTime, sizeof( TickType_t ) );\r
+\r
+                       /* Bind to the standard DHCP client port. */\r
+                       xAddress.sin_port = ( uint16_t ) dhcpCLIENT_PORT;\r
+                       xReturn = vSocketBind( xDHCPData.xDHCPSocket, &xAddress, sizeof( xAddress ), pdFALSE );\r
+                       if( xReturn != 0 )\r
+                       {\r
+                               /* Binding failed, close the socket again. */\r
+                               vSocketClose( xDHCPData.xDHCPSocket );\r
+                               xDHCPData.xDHCPSocket = NULL;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* Change to NULL for easier testing. */\r
+                       xDHCPData.xDHCPSocket = NULL;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInitialiseDHCP( void )\r
+{\r
+       /* Initialise the parameters that will be set by the DHCP process. */\r
+       if( xDHCPData.ulTransactionId == 0ul )\r
+       {\r
+               xDHCPData.ulTransactionId = ipconfigRAND32();\r
+       }\r
+       else\r
+       {\r
+               xDHCPData.ulTransactionId++;\r
+       }\r
+\r
+       xDHCPData.xUseBroadcast = 0;\r
+       xDHCPData.ulOfferedIPAddress = 0UL;\r
+       xDHCPData.ulDHCPServerAddress = 0UL;\r
+       xDHCPData.xDHCPTxPeriod = dhcpINITIAL_DHCP_TX_PERIOD;\r
+\r
+       /* Create the DHCP socket if it has not already been created. */\r
+       prvCreateDHCPSocket();\r
+       FreeRTOS_debug_printf( ( "prvInitialiseDHCP: start after %lu ticks\n", dhcpINITIAL_TIMER_PERIOD ) );\r
+       vIPReloadDHCPTimer( dhcpINITIAL_TIMER_PERIOD );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvProcessDHCPReplies( BaseType_t xExpectedMessageType )\r
+{\r
+uint8_t *pucUDPPayload, *pucLastByte;\r
+struct freertos_sockaddr xClient;\r
+uint32_t xClientLength = sizeof( xClient );\r
+int32_t lBytes;\r
+DHCPMessage_t *pxDHCPMessage;\r
+uint8_t *pucByte, ucOptionCode, ucLength;\r
+uint32_t ulProcessed, ulParameter;\r
+BaseType_t xReturn = pdFALSE;\r
+const uint32_t ulMandatoryOptions = 2ul; /* DHCP server address, and the correct DHCP message type must be present in the options. */\r
+\r
+       lBytes = FreeRTOS_recvfrom( xDHCPData.xDHCPSocket, ( void * ) &pucUDPPayload, 0ul, FREERTOS_ZERO_COPY, &xClient, &xClientLength );\r
+\r
+       if( lBytes > 0 )\r
+       {\r
+               /* Map a DHCP structure onto the received data. */\r
+               pxDHCPMessage = ( DHCPMessage_t * ) ( pucUDPPayload );\r
+\r
+               /* Sanity check. */\r
+               if( ( pxDHCPMessage->ulDHCPCookie == ( uint32_t ) dhcpCOOKIE ) &&\r
+                       ( pxDHCPMessage->ucOpcode == ( uint8_t ) dhcpREPLY_OPCODE ) &&\r
+                       ( pxDHCPMessage->ulTransactionID == FreeRTOS_htonl( xDHCPData.ulTransactionId ) ) )\r
+               {\r
+                       if( memcmp( ( void * ) &( pxDHCPMessage->ucClientHardwareAddress ), ( void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ) == 0 )\r
+                       {\r
+                               /* None of the essential options have been processed yet. */\r
+                               ulProcessed = 0ul;\r
+\r
+                               /* Walk through the options until the dhcpOPTION_END_BYTE byte\r
+                               is found, taking care not to walk off the end of the options. */\r
+                               pucByte = &( pxDHCPMessage->ucFirstOptionByte );\r
+                               pucLastByte = &( pucUDPPayload[ lBytes - dhcpMAX_OPTION_LENGTH_OF_INTEREST ] );\r
+\r
+                               while( pucByte < pucLastByte )\r
+                               {\r
+                                       ucOptionCode = pucByte[ 0 ];\r
+                                       if( ucOptionCode == ( uint8_t ) dhcpOPTION_END_BYTE )\r
+                                       {\r
+                                               /* Ready, the last byte has been seen. */\r
+                                               break;\r
+                                       }\r
+                                       if( ucOptionCode == ( uint8_t ) dhcpIPv4_ZERO_PAD_OPTION_CODE )\r
+                                       {\r
+                                               /* The value zero is used as a pad byte,\r
+                                               it is not followed by a length byte. */\r
+                                               pucByte += 1;\r
+                                               continue;\r
+                                       }\r
+                                       ucLength = pucByte[ 1 ];\r
+                                       pucByte += 2;\r
+\r
+                                       /* In most cases, a 4-byte network-endian parameter follows,\r
+                                       just get it once here and use later */\r
+                                       memcpy( ( void * ) &( ulParameter ), ( void * ) pucByte, ( size_t ) sizeof( ulParameter ) );\r
+\r
+                                       switch( ucOptionCode )\r
+                                       {\r
+                                               case dhcpIPv4_MESSAGE_TYPE_OPTION_CODE  :\r
+\r
+                                                       if( *pucByte == ( uint8_t ) xExpectedMessageType )\r
+                                                       {\r
+                                                               /* The message type is the message type the\r
+                                                               state machine is expecting. */\r
+                                                               ulProcessed++;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               if( *pucByte == ( uint8_t ) dhcpMESSAGE_TYPE_NACK )\r
+                                                               {\r
+                                                                       if( xExpectedMessageType == ( BaseType_t ) dhcpMESSAGE_TYPE_ACK )\r
+                                                                       {\r
+                                                                               /* Start again. */\r
+                                                                               xDHCPData.eDHCPState = eWaitingSendFirstDiscover;\r
+                                                                       }\r
+                                                               }\r
+                                                               /* Stop processing further options. */\r
+                                                               ucLength = 0;\r
+                                                       }\r
+                                                       break;\r
+\r
+                                               case dhcpIPv4_SUBNET_MASK_OPTION_CODE :\r
+\r
+                                                       if( ucLength == sizeof( uint32_t ) )\r
+                                                       {\r
+                                                               xNetworkAddressing.ulNetMask = ulParameter;\r
+                                                       }\r
+                                                       break;\r
+\r
+                                               case dhcpIPv4_GATEWAY_OPTION_CODE :\r
+                                                       /* The DHCP server may send more than 1 gateway addresses. */\r
+                                                       if( ucLength >= sizeof( uint32_t ) )\r
+                                                       {\r
+                                                               /* ulProcessed is not incremented in this case\r
+                                                               because the gateway is not essential. */\r
+                                                               xNetworkAddressing.ulGatewayAddress = ulParameter;\r
+                                                       }\r
+                                                       break;\r
+\r
+                                               case dhcpIPv4_DNS_SERVER_OPTIONS_CODE :\r
+\r
+                                                       /* ulProcessed is not incremented in this case\r
+                                                       because the DNS server is not essential.  Only the\r
+                                                       first DNS server address is taken. */\r
+                                                       xNetworkAddressing.ulDNSServerAddress = ulParameter;\r
+                                                       break;\r
+\r
+                                               case dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE :\r
+\r
+                                                       if( ucLength == sizeof( uint32_t ) )\r
+                                                       {\r
+                                                               if( xExpectedMessageType == ( BaseType_t ) dhcpMESSAGE_TYPE_OFFER )\r
+                                                               {\r
+                                                                       /* Offers state the replying server. */\r
+                                                                       ulProcessed++;\r
+                                                                       xDHCPData.ulDHCPServerAddress = ulParameter;\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+                                                                       /* The ack must come from the expected server. */\r
+                                                                       if( xDHCPData.ulDHCPServerAddress == ulParameter )\r
+                                                                       {\r
+                                                                               ulProcessed++;\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
+                                                       break;\r
+\r
+                                               case dhcpIPv4_LEASE_TIME_OPTION_CODE :\r
+\r
+                                                       if( ucLength == sizeof( xDHCPData.ulLeaseTime ) )\r
+                                                       {\r
+                                                               /* ulProcessed is not incremented in this case\r
+                                                               because the lease time is not essential. */\r
+                                                               /* The DHCP parameter is in seconds, convert\r
+                                                               to host-endian format. */\r
+                                                               xDHCPData.ulLeaseTime = FreeRTOS_ntohl( ulParameter );\r
+\r
+                                                               /* Divide the lease time by two to ensure a\r
+                                                               renew request is sent before the lease actually\r
+                                                               expires. */\r
+                                                               xDHCPData.ulLeaseTime >>= 1UL;\r
+\r
+                                                               /* Multiply with configTICK_RATE_HZ to get clock\r
+                                                               ticks. */\r
+                                                               xDHCPData.ulLeaseTime = configTICK_RATE_HZ * xDHCPData.ulLeaseTime;\r
+                                                       }\r
+                                                       break;\r
+\r
+                                               default :\r
+\r
+                                                       /* Not interested in this field. */\r
+\r
+                                                       break;\r
+                                       }\r
+\r
+                                       /* Jump over the data to find the next option code. */\r
+                                       if( ucLength == 0u )\r
+                                       {\r
+                                               break;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               pucByte += ucLength;\r
+                                       }\r
+                               }\r
+\r
+                               /* Were all the mandatory options received? */\r
+                               if( ulProcessed >= ulMandatoryOptions )\r
+                               {\r
+                                       /* HT:endian: used to be network order */\r
+                                       xDHCPData.ulOfferedIPAddress = pxDHCPMessage->ulYourIPAddress_yiaddr;\r
+                                       FreeRTOS_printf( ( "vDHCPProcess: offer %lxip\n", FreeRTOS_ntohl( xDHCPData.ulOfferedIPAddress ) ) );\r
+                                       xReturn = pdPASS;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayload );\r
+       } /* if( lBytes > 0 ) */\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint8_t *prvCreatePartDHCPMessage( struct freertos_sockaddr *pxAddress, BaseType_t xOpcode, const uint8_t * const pucOptionsArray, size_t *pxOptionsArraySize )\r
+{\r
+DHCPMessage_t *pxDHCPMessage;\r
+size_t xRequiredBufferSize = sizeof( DHCPMessage_t ) + *pxOptionsArraySize;\r
+uint8_t *pucUDPPayloadBuffer;\r
+\r
+#if( ipconfigDHCP_REGISTER_HOSTNAME == 1 )\r
+       const char *pucHostName = pcApplicationHostnameHook ();\r
+       size_t xNameLength = strlen( pucHostName );\r
+       uint8_t *pucPtr;\r
+\r
+       xRequiredBufferSize += ( 2 + xNameLength );\r
+#endif\r
+\r
+       /* Get a buffer.  This uses a maximum delay, but the delay will be capped\r
+       to ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS so the return value still needs to\r
+       be test. */\r
+       do\r
+       {\r
+       } while( ( pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xRequiredBufferSize, portMAX_DELAY ) ) == NULL );\r
+\r
+       pxDHCPMessage = ( DHCPMessage_t * ) pucUDPPayloadBuffer;\r
+\r
+       /* Most fields need to be zero. */\r
+       memset( ( void * ) pxDHCPMessage, 0x00, sizeof( DHCPMessage_t ) );\r
+\r
+       /* Create the message. */\r
+       pxDHCPMessage->ucOpcode = ( uint8_t ) xOpcode;\r
+       pxDHCPMessage->ucAddressType = ( uint8_t ) dhcpADDRESS_TYPE_ETHERNET;\r
+       pxDHCPMessage->ucAddressLength = ( uint8_t ) dhcpETHERNET_ADDRESS_LENGTH;\r
+\r
+       /* ulTransactionID doesn't really need a htonl() translation, but when DHCP\r
+       times out, it is nicer to see an increasing number in this ID field */\r
+       pxDHCPMessage->ulTransactionID = FreeRTOS_htonl( xDHCPData.ulTransactionId );\r
+       pxDHCPMessage->ulDHCPCookie = ( uint32_t ) dhcpCOOKIE;\r
+       if( xDHCPData.xUseBroadcast != pdFALSE )\r
+       {\r
+               pxDHCPMessage->usFlags = ( uint16_t ) dhcpBROADCAST;\r
+       }\r
+       else\r
+       {\r
+               pxDHCPMessage->usFlags = 0u;\r
+       }\r
+\r
+       memcpy( ( void * ) &( pxDHCPMessage->ucClientHardwareAddress[ 0 ] ), ( void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );\r
+\r
+       /* Copy in the const part of the options options. */\r
+       memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET ] ), ( void * ) pucOptionsArray, *pxOptionsArraySize );\r
+\r
+       #if( ipconfigDHCP_REGISTER_HOSTNAME == 1 )\r
+       {\r
+               /* With this option, the hostname can be registered as well which makes\r
+               it easier to lookup a device in a router's list of DHCP clients. */\r
+\r
+               /* Point to where the OPTION_END was stored to add data. */\r
+               pucPtr = &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + ( *pxOptionsArraySize - 1 ) ] );\r
+               pucPtr[ 0 ] = dhcpIPv4_DNS_HOSTNAME_OPTIONS_CODE;\r
+               pucPtr[ 1 ] = ( uint8_t ) xNameLength;\r
+               memcpy( ( void *) ( pucPtr + 2 ), pucHostName, xNameLength );\r
+               pucPtr[ 2 + xNameLength ] = dhcpOPTION_END_BYTE;\r
+               *pxOptionsArraySize += ( 2 + xNameLength );\r
+       }\r
+       #endif\r
+\r
+       /* Map in the client identifier. */\r
+       memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpCLIENT_IDENTIFIER_OFFSET ] ),\r
+               ( void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );\r
+\r
+       /* Set the addressing. */\r
+       pxAddress->sin_addr = ipBROADCAST_IP_ADDRESS;\r
+       pxAddress->sin_port = ( uint16_t ) dhcpSERVER_PORT;\r
+\r
+       return pucUDPPayloadBuffer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSendDHCPRequest( void )\r
+{\r
+uint8_t *pucUDPPayloadBuffer;\r
+struct freertos_sockaddr xAddress;\r
+static const uint8_t ucDHCPRequestOptions[] =\r
+{\r
+       /* Do not change the ordering without also changing\r
+       dhcpCLIENT_IDENTIFIER_OFFSET, dhcpREQUESTED_IP_ADDRESS_OFFSET and\r
+       dhcpDHCP_SERVER_IP_ADDRESS_OFFSET. */\r
+       dhcpIPv4_MESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_REQUEST,         /* Message type option. */\r
+       dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE, 6, 0, 0, 0, 0, 0, 0,                    /* Client identifier. */\r
+       dhcpIPv4_REQUEST_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0,                         /* The IP address being requested. */\r
+       dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE, 4, 0, 0, 0, 0,                          /* The IP address of the DHCP server. */\r
+       dhcpOPTION_END_BYTE\r
+};\r
+size_t xOptionsLength = sizeof( ucDHCPRequestOptions );\r
+\r
+       pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress, ( uint8_t ) dhcpREQUEST_OPCODE, ucDHCPRequestOptions, &xOptionsLength );\r
+\r
+       /* Copy in the IP address being requested. */\r
+       memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpREQUESTED_IP_ADDRESS_OFFSET ] ),\r
+               ( void * ) &( xDHCPData.ulOfferedIPAddress ), sizeof( xDHCPData.ulOfferedIPAddress ) );\r
+\r
+       /* Copy in the address of the DHCP server being used. */\r
+       memcpy( ( void * ) &( pucUDPPayloadBuffer[ dhcpFIRST_OPTION_BYTE_OFFSET + dhcpDHCP_SERVER_IP_ADDRESS_OFFSET ] ),\r
+               ( void * ) &( xDHCPData.ulDHCPServerAddress ), sizeof( xDHCPData.ulDHCPServerAddress ) );\r
+\r
+       FreeRTOS_debug_printf( ( "vDHCPProcess: reply %lxip\n", FreeRTOS_ntohl( xDHCPData.ulOfferedIPAddress ) ) );\r
+       iptraceSENDING_DHCP_REQUEST();\r
+\r
+       if( FreeRTOS_sendto( xDHCPData.xDHCPSocket, pucUDPPayloadBuffer, ( sizeof( DHCPMessage_t ) + xOptionsLength ), FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) == 0 )\r
+       {\r
+               /* The packet was not successfully queued for sending and must be\r
+               returned to the stack. */\r
+               FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSendDHCPDiscover( void )\r
+{\r
+uint8_t *pucUDPPayloadBuffer;\r
+struct freertos_sockaddr xAddress;\r
+static const uint8_t ucDHCPDiscoverOptions[] =\r
+{\r
+       /* Do not change the ordering without also changing dhcpCLIENT_IDENTIFIER_OFFSET. */\r
+       dhcpIPv4_MESSAGE_TYPE_OPTION_CODE, 1, dhcpMESSAGE_TYPE_DISCOVER,                                        /* Message type option. */\r
+       dhcpIPv4_CLIENT_IDENTIFIER_OPTION_CODE, 6, 0, 0, 0, 0, 0, 0,                                            /* Client identifier. */\r
+       dhcpIPv4_PARAMETER_REQUEST_OPTION_CODE, 3, dhcpIPv4_SUBNET_MASK_OPTION_CODE, dhcpIPv4_GATEWAY_OPTION_CODE, dhcpIPv4_DNS_SERVER_OPTIONS_CODE,    /* Parameter request option. */\r
+       dhcpOPTION_END_BYTE\r
+};\r
+size_t xOptionsLength = sizeof( ucDHCPDiscoverOptions );\r
+\r
+       pucUDPPayloadBuffer = prvCreatePartDHCPMessage( &xAddress, ( uint8_t ) dhcpREQUEST_OPCODE, ucDHCPDiscoverOptions, &xOptionsLength );\r
+\r
+       FreeRTOS_debug_printf( ( "vDHCPProcess: discover\n" ) );\r
+       iptraceSENDING_DHCP_DISCOVER();\r
+\r
+       if( FreeRTOS_sendto( xDHCPData.xDHCPSocket, pucUDPPayloadBuffer, ( sizeof( DHCPMessage_t ) + xOptionsLength ), FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) == 0 )\r
+       {\r
+               /* The packet was not successfully queued for sending and must be\r
+               returned to the stack. */\r
+               FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )\r
+\r
+       static void prvPrepareLinkLayerIPLookUp( void )\r
+       {\r
+       uint8_t ucLinkLayerIPAddress[ 2 ];\r
+\r
+               /* After DHCP has failed to answer, prepare everything to start\r
+               trying-out LinkLayer IP-addresses, using the random method. */\r
+               xDHCPData.xDHCPTxTime = xTaskGetTickCount();\r
+\r
+               ucLinkLayerIPAddress[ 0 ] = ( uint8_t )1 + ( uint8_t )( ipconfigRAND32() % 0xFDu );             /* get value 1..254 for IP-address 3rd byte of IP address to try. */\r
+               ucLinkLayerIPAddress[ 1 ] = ( uint8_t )1 + ( uint8_t )( ipconfigRAND32() % 0xFDu );             /* get value 1..254 for IP-address 4th byte of IP address to try. */\r
+\r
+               xNetworkAddressing.ulGatewayAddress = FreeRTOS_htonl( 0xA9FE0203 );\r
+\r
+               /* prepare xDHCPData with data to test. */\r
+               xDHCPData.ulOfferedIPAddress =\r
+                       FreeRTOS_inet_addr_quick( LINK_LAYER_ADDRESS_0, LINK_LAYER_ADDRESS_1, ucLinkLayerIPAddress[ 0 ], ucLinkLayerIPAddress[ 1 ] );\r
+\r
+               xDHCPData.ulLeaseTime = dhcpDEFAULT_LEASE_TIME;  /*  don't care about lease time. just put anything. */\r
+\r
+               xNetworkAddressing.ulNetMask =\r
+                       FreeRTOS_inet_addr_quick( LINK_LAYER_NETMASK_0, LINK_LAYER_NETMASK_1, LINK_LAYER_NETMASK_2, LINK_LAYER_NETMASK_3 );\r
+\r
+               /* DHCP completed.  The IP address can now be used, and the\r
+               timer set to the lease timeout time. */\r
+               *ipLOCAL_IP_ADDRESS_POINTER = xDHCPData.ulOfferedIPAddress;\r
+\r
+               /* Setting the 'local' broadcast address, something like 192.168.1.255' */\r
+               xNetworkAddressing.ulBroadcastAddress = ( xDHCPData.ulOfferedIPAddress & xNetworkAddressing.ulNetMask ) |  ~xNetworkAddressing.ulNetMask;\r
+\r
+               /* Close socket to ensure packets don't queue on it. not needed anymore as DHCP failed. but still need timer for ARP testing. */\r
+               vSocketClose( xDHCPData.xDHCPSocket );\r
+               xDHCPData.xDHCPSocket = NULL;\r
+               xDHCPData.xDHCPTxPeriod = pdMS_TO_TICKS( 3000ul + ( ipconfigRAND32() & 0x3fful ) ); /*  do ARP test every (3 + 0-1024mS) seconds. */\r
+\r
+               xARPHadIPClash = pdFALSE;          /* reset flag that shows if have ARP clash. */\r
+               vARPSendGratuitous();\r
+       }\r
+\r
+#endif /* ipconfigDHCP_FALL_BACK_AUTO_IP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#endif /* ipconfigUSE_DHCP != 0 */\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_DNS.c
new file mode 100644 (file)
index 0000000..34fffab
--- /dev/null
@@ -0,0 +1,1228 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "list.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_DNS.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+#include "IPTraceMacroDefaults.h"\r
+\r
+/* Exclude the entire file if DNS is not enabled. */\r
+#if( ipconfigUSE_DNS != 0 )\r
+\r
+#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )\r
+       #define dnsDNS_PORT                                             0x3500u\r
+       #define dnsONE_QUESTION                                 0x0100u\r
+       #define dnsOUTGOING_FLAGS                               0x0001u /* Standard query. */\r
+       #define dnsRX_FLAGS_MASK                                0x0f80u /* The bits of interest in the flags field of incoming DNS messages. */\r
+       #define dnsEXPECTED_RX_FLAGS                    0x0080u /* Should be a response, without any errors. */\r
+#else\r
+       #define dnsDNS_PORT                                             0x0035u\r
+       #define dnsONE_QUESTION                                 0x0001u\r
+       #define dnsOUTGOING_FLAGS                               0x0100u /* Standard query. */\r
+       #define dnsRX_FLAGS_MASK                                0x800fu /* The bits of interest in the flags field of incoming DNS messages. */\r
+       #define dnsEXPECTED_RX_FLAGS                    0x8000u /* Should be a response, without any errors. */\r
+\r
+#endif /* ipconfigBYTE_ORDER */\r
+\r
+/* The maximum number of times a DNS request should be sent out if a response\r
+is not received, before giving up. */\r
+#ifndef ipconfigDNS_REQUEST_ATTEMPTS\r
+       #define ipconfigDNS_REQUEST_ATTEMPTS            5\r
+#endif\r
+\r
+/* If the top two bits in the first character of a name field are set then the\r
+name field is an offset to the string, rather than the string itself. */\r
+#define dnsNAME_IS_OFFSET                                      ( ( uint8_t ) 0xc0 )\r
+\r
+/* NBNS flags. */\r
+#define dnsNBNS_FLAGS_RESPONSE                         0x8000u\r
+#define dnsNBNS_FLAGS_OPCODE_MASK                      0x7800u\r
+#define dnsNBNS_FLAGS_OPCODE_QUERY                     0x0000u\r
+#define dnsNBNS_FLAGS_OPCODE_REGISTRATION      0x2800u\r
+\r
+/* Host types. */\r
+#define dnsTYPE_A_HOST                                         0x0001u\r
+#define dnsCLASS_IN                                                    0x0001u\r
+\r
+/* LLMNR constants. */\r
+#define dnsLLMNR_TTL_VALUE                                     300000u\r
+#define dnsLLMNR_FLAGS_IS_REPONSE                      0x8000u\r
+\r
+/* NBNS constants. */\r
+#define dnsNBNS_TTL_VALUE                                      3600u /* 1 hour valid */\r
+#define dnsNBNS_TYPE_NET_BIOS                          0x0020u\r
+#define dnsNBNS_CLASS_IN                                       0x0001u\r
+#define dnsNBNS_NAME_FLAGS                                     0x6000u\r
+#define dnsNBNS_ENCODED_NAME_LENGTH                    32\r
+\r
+/* If the queried NBNS name matches with the device's name,\r
+the query will be responded to with these flags: */\r
+#define dnsNBNS_QUERY_RESPONSE_FLAGS           0x8500u\r
+\r
+/*\r
+ * Create a socket and bind it to the standard DNS port number.  Return the\r
+ * the created socket - or NULL if the socket could not be created or bound.\r
+ */\r
+static Socket_t prvCreateDNSSocket( void );\r
+\r
+/*\r
+ * Create the DNS message in the zero copy buffer passed in the first parameter.\r
+ */\r
+static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer, const char *pcHostName, TickType_t xIdentifier );\r
+\r
+/*\r
+ * Simple routine that jumps over the NAME field of a resource record.\r
+ */\r
+static uint8_t *prvSkipNameField( uint8_t *pucByte );\r
+\r
+/*\r
+ * Process a response packet from a DNS server.\r
+ */\r
+static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer, TickType_t xIdentifier );\r
+\r
+/*\r
+ * Prepare and send a message to a DNS server.  'xReadTimeOut_ms' will be passed as\r
+ * zero, in case the user has supplied a call-back function.\r
+ */\r
+static uint32_t prvGetHostByName( const char *pcHostName, TickType_t xIdentifier, TickType_t xReadTimeOut_ms );\r
+\r
+/*\r
+ * The NBNS and the LLMNR protocol share this reply function.\r
+ */\r
+#if( ( ipconfigUSE_NBNS == 1 ) || ( ipconfigUSE_LLMNR == 1 ) )\r
+       static void prvReplyDNSMessage( NetworkBufferDescriptor_t *pxNetworkBuffer, BaseType_t lNetLength );\r
+#endif\r
+\r
+#if( ipconfigUSE_NBNS == 1 )\r
+       static portINLINE void prvTreatNBNS( uint8_t *pucUDPPayloadBuffer, uint32_t ulIPAddress );\r
+#endif /* ipconfigUSE_NBNS */\r
+\r
+#if( ipconfigUSE_DNS_CACHE == 1 )\r
+       static uint8_t *prvReadNameField( uint8_t *pucByte, char *pcName, BaseType_t xLen );\r
+       static void prvProcessDNSCache( const char *pcName, uint32_t *pulIP, BaseType_t xLookUp );\r
+\r
+       typedef struct xDNS_CACHE_TABLE_ROW\r
+       {\r
+               uint32_t ulIPAddress;           /* The IP address of an ARP cache entry. */\r
+               char pcName[ipconfigDNS_CACHE_NAME_LENGTH];  /* The name of the host */\r
+               uint8_t ucAge;                          /* A value that is periodically decremented but can also be refreshed by active communication.  The ARP cache entry is removed if the value reaches zero. */\r
+       } DNSCacheRow_t;\r
+\r
+       static DNSCacheRow_t xDNSCache[ ipconfigDNS_CACHE_ENTRIES ];\r
+#endif /* ipconfigUSE_DNS_CACHE == 1 */\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       const MACAddress_t xLLMNR_MacAdress = { { 0x01, 0x00, 0x5e, 0x00, 0x00, 0xfc } };\r
+#endif /* ipconfigUSE_LLMNR == 1 */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#include "pack_struct_start.h"\r
+struct xDNSMessage\r
+{\r
+       uint16_t usIdentifier;\r
+       uint16_t usFlags;\r
+       uint16_t usQuestions;\r
+       uint16_t usAnswers;\r
+       uint16_t usAuthorityRRs;\r
+       uint16_t usAdditionalRRs;\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xDNSMessage DNSMessage_t;\r
+\r
+/* A DNS query consists of a header, as described in 'struct xDNSMessage'\r
+It is followed by 1 or more queries, each one consisting of a name and a tail,\r
+with two fields: type and class\r
+*/\r
+#include "pack_struct_start.h"\r
+struct xDNSTail\r
+{\r
+       uint16_t usType;\r
+       uint16_t usClass;\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xDNSTail DNSTail_t;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+\r
+       #include "pack_struct_start.h"\r
+       struct xLLMNRAnswer\r
+       {\r
+               uint8_t ucNameCode;\r
+               uint8_t ucNameOffset;   /* The name is not repeated in the answer, only the offset is given with "0xc0 <offs>" */\r
+               uint16_t usType;\r
+               uint16_t usClass;\r
+               uint32_t ulTTL;\r
+               uint16_t usDataLength;\r
+               uint32_t ulIPAddress;\r
+       }\r
+       #include "pack_struct_end.h"\r
+       typedef struct xLLMNRAnswer LLMNRAnswer_t;\r
+\r
+#endif /* ipconfigUSE_LLMNR == 1 */\r
+\r
+#if( ipconfigUSE_NBNS == 1 )\r
+\r
+       #include "pack_struct_start.h"\r
+       struct xNBNSRequest\r
+       {\r
+               uint16_t usRequestId;\r
+               uint16_t usFlags;\r
+               uint16_t ulRequestCount;\r
+               uint16_t usAnswerRSS;\r
+               uint16_t usAuthRSS;\r
+               uint16_t usAdditionalRSS;\r
+               uint8_t ucNameSpace;\r
+               uint8_t ucName[ dnsNBNS_ENCODED_NAME_LENGTH ];\r
+               uint8_t ucNameZero;\r
+               uint16_t usType;\r
+               uint16_t usClass;\r
+       }\r
+       #include "pack_struct_end.h"\r
+       typedef struct xNBNSRequest NBNSRequest_t;\r
+\r
+       #include "pack_struct_start.h"\r
+       struct xNBNSAnswer\r
+       {\r
+               uint16_t usType;\r
+               uint16_t usClass;\r
+               uint32_t ulTTL;\r
+               uint16_t usDataLength;\r
+               uint16_t usNbFlags;             /* NetBIOS flags 0x6000 : IP-address, big-endian */\r
+               uint32_t ulIPAddress;\r
+       }\r
+       #include "pack_struct_end.h"\r
+       typedef struct xNBNSAnswer NBNSAnswer_t;\r
+\r
+#endif /* ipconfigUSE_NBNS == 1 */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_DNS_CACHE == 1 )\r
+       uint32_t FreeRTOS_dnslookup( const char *pcHostName )\r
+       {\r
+       uint32_t ulIPAddress = 0UL;\r
+               prvProcessDNSCache( pcHostName, &ulIPAddress, pdTRUE );\r
+               return ulIPAddress;\r
+       }\r
+#endif /* ipconfigUSE_DNS_CACHE == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigDNS_USE_CALLBACKS != 0 )\r
+\r
+       typedef struct xDNS_Callback {\r
+               TickType_t xRemaningTime;               /* Timeout in ms */\r
+               FOnDNSEvent pCallbackFunction;  /* Function to be called when the address has been found or when a timeout has beeen reached */\r
+               TimeOut_t xTimeoutState;\r
+               void *pvSearchID;\r
+               struct xLIST_ITEM xListItem;\r
+               char pcName[ 1 ];\r
+       } DNSCallback_t;\r
+\r
+       static List_t xCallbackList;\r
+\r
+       /* Define FreeRTOS_gethostbyname() as a normal blocking call. */\r
+       uint32_t FreeRTOS_gethostbyname( const char *pcHostName )\r
+       {\r
+               return FreeRTOS_gethostbyname_a( pcHostName, ( FOnDNSEvent ) NULL, ( void* )NULL, 0 );\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+       /* Initialise the list of call-back structures. */\r
+       void vDNSInitialise( void );\r
+       void vDNSInitialise( void )\r
+       {\r
+               vListInitialise( &xCallbackList );\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+       /* Iterate through the list of call-back structures and remove\r
+       old entries which have reached a timeout.\r
+       As soon as the list hase become empty, the DNS timer will be stopped\r
+       In case pvSearchID is supplied, the user wants to cancel a DNS request\r
+       */\r
+       void vDNSCheckCallBack( void *pvSearchID );\r
+       void vDNSCheckCallBack( void *pvSearchID )\r
+       {\r
+       const ListItem_t *pxIterator;\r
+       const MiniListItem_t* xEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xCallbackList );\r
+\r
+               vTaskSuspendAll();\r
+               {\r
+                       for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( xEnd );\r
+                                pxIterator != ( const ListItem_t * ) xEnd;\r
+                                 )\r
+                       {\r
+                               DNSCallback_t *pxCallback = ( DNSCallback_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
+                               /* Move to the next item because we might remove this item */\r
+                               pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator );\r
+                               if( ( pvSearchID != NULL ) && ( pvSearchID == pxCallback->pvSearchID ) )\r
+                               {\r
+                                       uxListRemove( &pxCallback->xListItem );\r
+                                       vPortFree( pxCallback );\r
+                               }\r
+                               else if( xTaskCheckForTimeOut( &pxCallback->xTimeoutState, &pxCallback->xRemaningTime ) != pdFALSE )\r
+                               {\r
+                                       pxCallback->pCallbackFunction( pxCallback->pcName, pxCallback->pvSearchID, 0 );\r
+                                       uxListRemove( &pxCallback->xListItem );\r
+                                       vPortFree( ( void * ) pxCallback );\r
+                               }\r
+                       }\r
+               }\r
+               xTaskResumeAll();\r
+\r
+               if( listLIST_IS_EMPTY( &xCallbackList ) )\r
+               {\r
+                       vIPSetDnsTimerEnableState( pdFALSE );\r
+               }\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+       void FreeRTOS_gethostbyname_cancel( void *pvSearchID )\r
+       {\r
+               /* _HT_ Should better become a new API call to have the IP-task remove the callback */\r
+               vDNSCheckCallBack( pvSearchID );\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+       /* FreeRTOS_gethostbyname_a() was called along with callback parameters.\r
+       Store them in a list for later reference. */\r
+       static void vDNSSetCallBack( const char *pcHostName, void *pvSearchID, FOnDNSEvent pCallbackFunction, TickType_t xTimeout, TickType_t xIdentifier );\r
+       static void vDNSSetCallBack( const char *pcHostName, void *pvSearchID, FOnDNSEvent pCallbackFunction, TickType_t xTimeout, TickType_t xIdentifier )\r
+       {\r
+               size_t lLength = strlen( pcHostName );\r
+               DNSCallback_t *pxCallback = ( DNSCallback_t * )pvPortMalloc( sizeof( *pxCallback ) + lLength );\r
+\r
+               /* Translate from ms to number of clock ticks. */\r
+               xTimeout /= portTICK_PERIOD_MS;\r
+               if( pxCallback != NULL )\r
+               {\r
+                       if( listLIST_IS_EMPTY( &xCallbackList ) )\r
+                       {\r
+                               /* This is the first one, start the DNS timer to check for timeouts */\r
+                               vIPReloadDNSTimer( FreeRTOS_min_uint32( 1000U, xTimeout ) );\r
+                       }\r
+                       strcpy( pxCallback->pcName, pcHostName );\r
+                       pxCallback->pCallbackFunction = pCallbackFunction;\r
+                       pxCallback->pvSearchID = pvSearchID;\r
+                       pxCallback->xRemaningTime = xTimeout;\r
+                       vTaskSetTimeOutState( &pxCallback->xTimeoutState );\r
+                       listSET_LIST_ITEM_OWNER( &( pxCallback->xListItem ), ( void* ) pxCallback );\r
+                       listSET_LIST_ITEM_VALUE( &( pxCallback->xListItem ), xIdentifier );\r
+                       vTaskSuspendAll();\r
+                       {\r
+                               vListInsertEnd( &xCallbackList, &pxCallback->xListItem );\r
+                       }\r
+                       xTaskResumeAll();\r
+               }\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+       /* A DNS reply was received, see if there is any matching entry and\r
+       call the handler. */\r
+       static void vDNSDoCallback( TickType_t xIdentifier, const char *pcName, uint32_t ulIPAddress );\r
+       static void vDNSDoCallback( TickType_t xIdentifier, const char *pcName, uint32_t ulIPAddress )\r
+       {\r
+               const ListItem_t *pxIterator;\r
+               const MiniListItem_t* xEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xCallbackList );\r
+\r
+               vTaskSuspendAll();\r
+               {\r
+                       for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( xEnd );\r
+                                pxIterator != ( const ListItem_t * ) xEnd;\r
+                                pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
+                       {\r
+                               if( listGET_LIST_ITEM_VALUE( pxIterator ) == xIdentifier )\r
+                               {\r
+                                       DNSCallback_t *pxCallback = ( DNSCallback_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
+                                       pxCallback->pCallbackFunction( pcName, pxCallback->pvSearchID, ulIPAddress );\r
+                                       uxListRemove( &pxCallback->xListItem );\r
+                                       vPortFree( pxCallback );\r
+                                       if( listLIST_IS_EMPTY( &xCallbackList ) )\r
+                                       {\r
+                                               vIPSetDnsTimerEnableState( pdFALSE );\r
+                                       }\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+               xTaskResumeAll();\r
+       }\r
+\r
+#endif /* ipconfigDNS_USE_CALLBACKS != 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigDNS_USE_CALLBACKS == 0 )\r
+uint32_t FreeRTOS_gethostbyname( const char *pcHostName )\r
+#else\r
+uint32_t FreeRTOS_gethostbyname_a( const char *pcHostName, FOnDNSEvent pCallback, void *pvSearchID, TickType_t xTimeout )\r
+#endif\r
+{\r
+uint32_t ulIPAddress = 0UL;\r
+static uint16_t usIdentifier = 0u;\r
+TickType_t xReadTimeOut_ms = 1200U;\r
+/* Generate a unique identifier for this query. Keep it in a local variable\r
+ as gethostbyname() may be called from different threads */\r
+TickType_t xIdentifier = ( TickType_t )usIdentifier++;\r
+\r
+       /* If a DNS cache is used then check the cache before issuing another DNS\r
+       request. */\r
+       #if( ipconfigUSE_DNS_CACHE == 1 )\r
+       {\r
+               ulIPAddress = FreeRTOS_dnslookup( pcHostName );\r
+               if( ulIPAddress != 0 )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "FreeRTOS_gethostbyname: found '%s' in cache: %lxip\n", pcHostName, ulIPAddress ) );\r
+               }\r
+               else\r
+               {\r
+                       /* prvGetHostByName will be called to start a DNS lookup. */\r
+               }\r
+       }\r
+       #endif /* ipconfigUSE_DNS_CACHE == 1 */\r
+\r
+       #if( ipconfigDNS_USE_CALLBACKS != 0 )\r
+       {\r
+               if( pCallback != NULL )\r
+               {\r
+                       if( ulIPAddress == 0UL )\r
+                       {\r
+                               /* The user has provided a callback function, so do not block on recvfrom() */\r
+                               xReadTimeOut_ms  = 0;\r
+                               vDNSSetCallBack( pcHostName, pvSearchID, pCallback, xTimeout, ( TickType_t ) xIdentifier );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* The IP address is known, do the call-back now. */\r
+                               pCallback( pcHostName, pvSearchID, ulIPAddress );\r
+                       }\r
+               }\r
+       }\r
+       #endif\r
+\r
+       if( ulIPAddress == 0UL)\r
+       {\r
+               ulIPAddress = prvGetHostByName( pcHostName, xIdentifier, xReadTimeOut_ms );\r
+       }\r
+\r
+       return ulIPAddress;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvGetHostByName( const char *pcHostName, TickType_t xIdentifier, TickType_t xReadTimeOut_ms )\r
+{\r
+struct freertos_sockaddr xAddress;\r
+Socket_t xDNSSocket;\r
+uint32_t ulIPAddress = 0UL;\r
+uint8_t *pucUDPPayloadBuffer;\r
+static uint32_t ulAddressLength;\r
+BaseType_t xAttempt;\r
+int32_t lBytes;\r
+size_t xPayloadLength, xExpectedPayloadLength;\r
+TickType_t xWriteTimeOut_ms = 100U;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       BaseType_t bHasDot = pdFALSE;\r
+#endif /* ipconfigUSE_LLMNR == 1 */\r
+\r
+       /* If LLMNR is being used then determine if the host name includes a '.' -\r
+       if not then LLMNR can be used as the lookup method. */\r
+       #if( ipconfigUSE_LLMNR == 1 )\r
+       {\r
+               const char *pucPtr;\r
+               for( pucPtr = pcHostName; *pucPtr; pucPtr++ )\r
+               {\r
+                       if( *pucPtr == '.' )\r
+                       {\r
+                               bHasDot = pdTRUE;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       #endif /* ipconfigUSE_LLMNR == 1 */\r
+\r
+       /* Two is added at the end for the count of characters in the first\r
+       subdomain part and the string end byte. */\r
+       xExpectedPayloadLength = sizeof( DNSMessage_t ) + strlen( pcHostName ) + sizeof( uint16_t ) + sizeof( uint16_t ) + 2u;\r
+\r
+       xDNSSocket = prvCreateDNSSocket();\r
+\r
+       if( xDNSSocket != NULL )\r
+       {\r
+               FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xWriteTimeOut_ms, sizeof( TickType_t ) );\r
+               FreeRTOS_setsockopt( xDNSSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xReadTimeOut_ms,  sizeof( TickType_t ) );\r
+\r
+               for( xAttempt = 0; xAttempt < ipconfigDNS_REQUEST_ATTEMPTS; xAttempt++ )\r
+               {\r
+                       /* Get a buffer.  This uses a maximum delay, but the delay will be\r
+                       capped to ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS so the return value\r
+                       still needs to be tested. */\r
+                       pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xExpectedPayloadLength, portMAX_DELAY );\r
+\r
+                       if( pucUDPPayloadBuffer != NULL )\r
+                       {\r
+                               /* Create the message in the obtained buffer. */\r
+                               xPayloadLength = prvCreateDNSMessage( pucUDPPayloadBuffer, pcHostName, xIdentifier );\r
+\r
+                               iptraceSENDING_DNS_REQUEST();\r
+\r
+                               /* Obtain the DNS server address. */\r
+                               FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulIPAddress );\r
+\r
+                               /* Send the DNS message. */\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+                               if( bHasDot == pdFALSE )\r
+                               {\r
+                                       /* Use LLMNR addressing. */\r
+                                       ( ( DNSMessage_t * ) pucUDPPayloadBuffer) -> usFlags = 0;\r
+                                       xAddress.sin_addr = ipLLMNR_IP_ADDR;    /* Is in network byte order. */\r
+                                       xAddress.sin_port = FreeRTOS_ntohs( ipLLMNR_PORT );\r
+                               }\r
+                               else\r
+#endif\r
+                               {\r
+                                       /* Use DNS server. */\r
+                                       xAddress.sin_addr = ulIPAddress;\r
+                                       xAddress.sin_port = dnsDNS_PORT;\r
+                               }\r
+\r
+                               ulIPAddress = 0UL;\r
+\r
+                               if( FreeRTOS_sendto( xDNSSocket, pucUDPPayloadBuffer, xPayloadLength, FREERTOS_ZERO_COPY, &xAddress, sizeof( xAddress ) ) != 0 )\r
+                               {\r
+                                       /* Wait for the reply. */\r
+                                       lBytes = FreeRTOS_recvfrom( xDNSSocket, &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xAddress, &ulAddressLength );\r
+\r
+                                       if( lBytes > 0 )\r
+                                       {\r
+                                               /* The reply was received.  Process it. */\r
+                                               ulIPAddress = prvParseDNSReply( pucUDPPayloadBuffer, xIdentifier );\r
+\r
+                                               /* Finished with the buffer.  The zero copy interface\r
+                                               is being used, so the buffer must be freed by the\r
+                                               task. */\r
+                                               FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );\r
+\r
+                                               if( ulIPAddress != 0UL )\r
+                                               {\r
+                                                       /* All done. */\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* The message was not sent so the stack will not be\r
+                                       releasing the zero copy - it must be released here. */\r
+                                       FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );\r
+                               }\r
+                       }\r
+               }\r
+\r
+               /* Finished with the socket. */\r
+               FreeRTOS_closesocket( xDNSSocket );\r
+       }\r
+\r
+       return ulIPAddress;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static size_t prvCreateDNSMessage( uint8_t *pucUDPPayloadBuffer, const char *pcHostName, TickType_t xIdentifier )\r
+{\r
+DNSMessage_t *pxDNSMessageHeader;\r
+uint8_t *pucStart, *pucByte;\r
+DNSTail_t *pxTail;\r
+static const DNSMessage_t xDefaultPartDNSHeader =\r
+{\r
+       0,                                      /* The identifier will be overwritten. */\r
+       dnsOUTGOING_FLAGS,      /* Flags set for standard query. */\r
+       dnsONE_QUESTION,        /* One question is being asked. */\r
+       0,                                      /* No replies are included. */\r
+       0,                                      /* No authorities. */\r
+       0                                       /* No additional authorities. */\r
+};\r
+\r
+       /* Copy in the const part of the header. */\r
+       memcpy( ( void * ) pucUDPPayloadBuffer, ( void * ) &xDefaultPartDNSHeader, sizeof( xDefaultPartDNSHeader ) );\r
+\r
+       /* Write in a unique identifier. */\r
+       pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer;\r
+       pxDNSMessageHeader->usIdentifier = ( uint16_t ) xIdentifier;\r
+\r
+       /* Create the resource record at the end of the header.  First\r
+       find the end of the header. */\r
+       pucStart = pucUDPPayloadBuffer + sizeof( xDefaultPartDNSHeader );\r
+\r
+       /* Leave a gap for the first length bytes. */\r
+       pucByte = pucStart + 1;\r
+\r
+       /* Copy in the host name. */\r
+       strcpy( ( char * ) pucByte, pcHostName );\r
+\r
+       /* Mark the end of the string. */\r
+       pucByte += strlen( pcHostName );\r
+       *pucByte = 0x00u;\r
+\r
+       /* Walk the string to replace the '.' characters with byte counts.\r
+       pucStart holds the address of the byte count.  Walking the string\r
+       starts after the byte count position. */\r
+       pucByte = pucStart;\r
+\r
+       do\r
+       {\r
+               pucByte++;\r
+\r
+               while( ( *pucByte != 0x00 ) && ( *pucByte != '.' ) )\r
+               {\r
+                       pucByte++;\r
+               }\r
+\r
+               /* Fill in the byte count, then move the pucStart pointer up to\r
+               the found byte position. */\r
+               *pucStart = ( uint8_t ) ( ( uint32_t ) pucByte - ( uint32_t ) pucStart );\r
+               ( *pucStart )--;\r
+\r
+               pucStart = pucByte;\r
+\r
+       } while( *pucByte != 0x00 );\r
+\r
+       /* Finish off the record. */\r
+\r
+       pxTail = (DNSTail_t *)( pucByte + 1 );\r
+\r
+       vSetField16( pxTail, DNSTail_t, usType, dnsTYPE_A_HOST );       /* Type A: host */\r
+       vSetField16( pxTail, DNSTail_t, usClass, dnsCLASS_IN ); /* 1: Class IN */\r
+\r
+       /* Return the total size of the generated message, which is the space from\r
+       the last written byte to the beginning of the buffer. */\r
+       return ( ( uint32_t ) pucByte - ( uint32_t ) pucUDPPayloadBuffer + 1 ) + sizeof( *pxTail );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_DNS_CACHE == 1 )\r
+\r
+       static uint8_t *prvReadNameField( uint8_t *pucByte, char *pcName, BaseType_t xLen )\r
+       {\r
+       BaseType_t xNameLen = 0;\r
+               /* Determine if the name is the fully coded name, or an offset to the name\r
+               elsewhere in the message. */\r
+               if( ( *pucByte & dnsNAME_IS_OFFSET ) == dnsNAME_IS_OFFSET )\r
+               {\r
+                       /* Jump over the two byte offset. */\r
+                       pucByte += sizeof( uint16_t );\r
+\r
+               }\r
+               else\r
+               {\r
+                       /* pucByte points to the full name.  Walk over the string. */\r
+                       while( *pucByte != 0x00 )\r
+                       {\r
+                               BaseType_t xCount;\r
+                               if( xNameLen && xNameLen < xLen - 1 )\r
+                                       pcName[xNameLen++] = '.';\r
+                               for( xCount = *(pucByte++); xCount--; pucByte++ )\r
+                               {\r
+                                       if( xNameLen < xLen - 1 )\r
+                                               pcName[xNameLen++] = *( ( char * ) pucByte );\r
+                               }\r
+                       }\r
+\r
+                       pucByte++;\r
+               }\r
+\r
+               return pucByte;\r
+       }\r
+#endif /* ipconfigUSE_DNS_CACHE == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint8_t *prvSkipNameField( uint8_t *pucByte )\r
+{\r
+       /* Determine if the name is the fully coded name, or an offset to the name\r
+       elsewhere in the message. */\r
+       if( ( *pucByte & dnsNAME_IS_OFFSET ) == dnsNAME_IS_OFFSET )\r
+       {\r
+               /* Jump over the two byte offset. */\r
+               pucByte += sizeof( uint16_t );\r
+\r
+       }\r
+       else\r
+       {\r
+               /* pucByte points to the full name.  Walk over the string. */\r
+               while( *pucByte != 0x00 )\r
+               {\r
+                       /* The number of bytes to jump for each name section is stored in the byte\r
+                       before the name section. */\r
+                       pucByte += ( *pucByte + 1 );\r
+               }\r
+\r
+               pucByte++;\r
+       }\r
+\r
+       return pucByte;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer )\r
+{\r
+uint8_t *pucUDPPayloadBuffer = pxNetworkBuffer->pucEthernetBuffer + sizeof( UDPPacket_t );\r
+DNSMessage_t *pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer;\r
+\r
+       prvParseDNSReply( pucUDPPayloadBuffer, ( uint32_t ) pxDNSMessageHeader->usIdentifier );\r
+\r
+       /* The packet was not consumed. */\r
+       return pdFAIL;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_NBNS == 1 )\r
+\r
+       uint32_t ulNBNSHandlePacket (NetworkBufferDescriptor_t *pxNetworkBuffer )\r
+       {\r
+       UDPPacket_t *pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;\r
+       uint8_t *pucUDPPayloadBuffer = pxNetworkBuffer->pucEthernetBuffer + sizeof( *pxUDPPacket );\r
+\r
+               prvTreatNBNS( pucUDPPayloadBuffer, pxUDPPacket->xIPHeader.ulSourceIPAddress );\r
+\r
+               /* The packet was not consumed. */\r
+               return pdFAIL;\r
+       }\r
+\r
+#endif /* ipconfigUSE_NBNS */\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer, TickType_t xIdentifier )\r
+{\r
+DNSMessage_t *pxDNSMessageHeader;\r
+uint32_t ulIPAddress = 0UL;\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       char *pcRequestedName = NULL;\r
+#endif\r
+uint8_t *pucByte;\r
+uint16_t x, usDataLength, usQuestions;\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       uint16_t usType = 0, usClass = 0;\r
+#endif\r
+#if( ipconfigUSE_DNS_CACHE == 1 )\r
+       char pcName[128] = ""; /*_RB_ What is the significance of 128?  Probably too big to go on the stack for a small MCU but don't know how else it could be made re-entrant.  Might be necessary. */\r
+#endif\r
+\r
+       pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer;\r
+\r
+       if( pxDNSMessageHeader->usIdentifier == ( uint16_t ) xIdentifier )\r
+       {\r
+               /* Start at the first byte after the header. */\r
+               pucByte = pucUDPPayloadBuffer + sizeof( DNSMessage_t );\r
+\r
+               /* Skip any question records. */\r
+               usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions );\r
+               for( x = 0; x < usQuestions; x++ )\r
+               {\r
+                       #if( ipconfigUSE_LLMNR == 1 )\r
+                       {\r
+                               if( x == 0 )\r
+                               {\r
+                                       pcRequestedName = ( char * ) pucByte;\r
+                               }\r
+                       }\r
+                       #endif\r
+\r
+#if( ipconfigUSE_DNS_CACHE == 1 )\r
+                       if( x == 0 )\r
+                       {\r
+                               pucByte = prvReadNameField( pucByte, pcName, sizeof( pcName ) );\r
+                       }\r
+                       else\r
+#endif /* ipconfigUSE_DNS_CACHE */\r
+                       {\r
+                               /* Skip the variable length pcName field. */\r
+                               pucByte = prvSkipNameField( pucByte );\r
+                       }\r
+\r
+                       #if( ipconfigUSE_LLMNR == 1 )\r
+                       {\r
+                               /* usChar2u16 returns value in host endianness. */\r
+                               usType = usChar2u16( pucByte );\r
+                               usClass = usChar2u16( pucByte + 2 );\r
+                       }\r
+                       #endif /* ipconfigUSE_LLMNR */\r
+\r
+                       /* Skip the type and class fields. */\r
+                       pucByte += sizeof( uint32_t );\r
+               }\r
+\r
+               /* Search through the answers records. */\r
+               pxDNSMessageHeader->usAnswers = FreeRTOS_ntohs( pxDNSMessageHeader->usAnswers );\r
+\r
+               if( ( pxDNSMessageHeader->usFlags & dnsRX_FLAGS_MASK ) == dnsEXPECTED_RX_FLAGS )\r
+               {\r
+                       for( x = 0; x < pxDNSMessageHeader->usAnswers; x++ )\r
+                       {\r
+                               pucByte = prvSkipNameField( pucByte );\r
+\r
+                               /* Is the type field that of an A record? */\r
+                               if( usChar2u16( pucByte ) == dnsTYPE_A_HOST )\r
+                               {\r
+                                       /* This is the required record.  Skip the type, class, and\r
+                                       time to live fields, plus the first byte of the data\r
+                                       length. */\r
+                                       pucByte += ( sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( uint8_t ) );\r
+\r
+                                       /* Sanity check the data length. */\r
+                                       if( ( size_t ) *pucByte == sizeof( uint32_t ) )\r
+                                       {\r
+                                               /* Skip the second byte of the length. */\r
+                                               pucByte++;\r
+\r
+                                               /* Copy the IP address out of the record. */\r
+                                               memcpy( ( void * ) &ulIPAddress, ( void * ) pucByte, sizeof( uint32_t ) );\r
+\r
+                                               #if( ipconfigUSE_DNS_CACHE == 1 )\r
+                                               {\r
+                                                       prvProcessDNSCache( pcName, &ulIPAddress, pdFALSE );\r
+                                               }\r
+                                               #endif /* ipconfigUSE_DNS_CACHE */\r
+                                               #if( ipconfigDNS_USE_CALLBACKS != 0 )\r
+                                               {\r
+                                                       /* See if any asynchronous call was made to FreeRTOS_gethostbyname_a() */\r
+                                                       vDNSDoCallback( ( TickType_t ) pxDNSMessageHeader->usIdentifier, pcName, ulIPAddress );\r
+                                               }\r
+                                               #endif  /* ipconfigDNS_USE_CALLBACKS != 0 */\r
+                                       }\r
+\r
+                                       break;\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Skip the type, class and time to live fields. */\r
+                                       pucByte += ( sizeof( uint32_t ) + sizeof( uint32_t ) );\r
+\r
+                                       /* Determine the length of the data in the field. */\r
+                                       memcpy( ( void * ) &usDataLength, ( void * ) pucByte, sizeof( uint16_t ) );\r
+                                       usDataLength = FreeRTOS_ntohs( usDataLength );\r
+\r
+                                       /* Jump over the data length bytes, and the data itself. */\r
+                                       pucByte += usDataLength + sizeof( uint16_t );\r
+                               }\r
+                       }\r
+               }\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+               else if( ( usQuestions != ( uint16_t )0u ) && ( usType == ( uint16_t )dnsTYPE_A_HOST ) && ( usClass == ( uint16_t )dnsCLASS_IN ) )\r
+               {\r
+                       /* If this is not a reply to our DNS request, it might an LLMNR\r
+                       request. */\r
+                       if( xApplicationDNSQueryHook ( ( pcRequestedName + 1 ) ) )\r
+                       {\r
+                       int16_t usLength;\r
+                       NetworkBufferDescriptor_t *pxNewBuffer = NULL;\r
+                       NetworkBufferDescriptor_t *pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer );\r
+                       LLMNRAnswer_t *pxAnswer;\r
+\r
+                               if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) )\r
+                               {\r
+                               BaseType_t xDataLength = pxNetworkBuffer->xDataLength + sizeof( UDPHeader_t ) +\r
+                                       sizeof( EthernetHeader_t ) + sizeof( IPHeader_t );\r
+\r
+                                       /* The field xDataLength was set to the length of the UDP payload.\r
+                                       The answer (reply) will be longer than the request, so the packet\r
+                                       must be duplicaed into a bigger buffer */\r
+                                       pxNetworkBuffer->xDataLength = xDataLength;\r
+                                       pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, xDataLength + 16 );\r
+                                       if( pxNewBuffer != NULL )\r
+                                       {\r
+                                       BaseType_t xOffset1, xOffset2;\r
+\r
+                                               xOffset1 = ( BaseType_t ) ( pucByte - pucUDPPayloadBuffer );\r
+                                               xOffset2 = ( BaseType_t ) ( ( ( uint8_t * ) pcRequestedName ) - pucUDPPayloadBuffer );\r
+\r
+                                               pxNetworkBuffer = pxNewBuffer;\r
+                                               pucUDPPayloadBuffer = pxNetworkBuffer->pucEthernetBuffer + ipUDP_PAYLOAD_OFFSET_IPv4;\r
+\r
+                                               pucByte = pucUDPPayloadBuffer + xOffset1;\r
+                                               pcRequestedName = ( char * ) ( pucUDPPayloadBuffer + xOffset2 );\r
+                                               pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer;\r
+\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               /* Just to indicate that the message may not be answered. */\r
+                                               pxNetworkBuffer = NULL;\r
+                                       }\r
+                               }\r
+                               if( pxNetworkBuffer != NULL )\r
+                               {\r
+                                       pxAnswer = (LLMNRAnswer_t *)pucByte;\r
+\r
+                                       /* Leave 'usIdentifier' and 'usQuestions' untouched. */\r
+                                       vSetField16( pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_REPONSE );    /* Set the response flag */\r
+                                       vSetField16( pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 );  /* Provide a single answer */\r
+                                       vSetField16( pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 );     /* No authority */\r
+                                       vSetField16( pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 );    /* No additional info */\r
+\r
+                                       pxAnswer->ucNameCode = dnsNAME_IS_OFFSET;\r
+                                       pxAnswer->ucNameOffset = ( uint8_t )( pcRequestedName - ( char * ) pucUDPPayloadBuffer );\r
+\r
+                                       vSetField16( pxAnswer, LLMNRAnswer_t, usType, dnsTYPE_A_HOST ); /* Type A: host */\r
+                                       vSetField16( pxAnswer, LLMNRAnswer_t, usClass, dnsCLASS_IN );   /* 1: Class IN */\r
+                                       vSetField32( pxAnswer, LLMNRAnswer_t, ulTTL, dnsLLMNR_TTL_VALUE );\r
+                                       vSetField16( pxAnswer, LLMNRAnswer_t, usDataLength, 4 );\r
+                                       vSetField32( pxAnswer, LLMNRAnswer_t, ulIPAddress, FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) );\r
+\r
+                                       usLength = ( int16_t ) ( sizeof( *pxAnswer ) + ( size_t ) ( pucByte - pucUDPPayloadBuffer ) );\r
+\r
+                                       prvReplyDNSMessage( pxNetworkBuffer, usLength );\r
+\r
+                                       if( pxNewBuffer != NULL )\r
+                                       {\r
+                                               vReleaseNetworkBufferAndDescriptor( pxNewBuffer );\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+#endif /* ipconfigUSE_LLMNR == 1 */\r
+       }\r
+\r
+       return ulIPAddress;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_NBNS == 1 )\r
+\r
+       static void prvTreatNBNS( uint8_t *pucUDPPayloadBuffer, uint32_t ulIPAddress )\r
+       {\r
+               uint16_t usFlags, usType, usClass;\r
+               uint8_t *pucSource, *pucTarget;\r
+               uint8_t ucByte;\r
+               uint8_t ucNBNSName[ 17 ];\r
+\r
+               usFlags = usChar2u16( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usFlags ) );\r
+\r
+               if( ( usFlags & dnsNBNS_FLAGS_OPCODE_MASK ) == dnsNBNS_FLAGS_OPCODE_QUERY )\r
+               {\r
+                       usType  = usChar2u16( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usType ) );\r
+                       usClass = usChar2u16( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usClass ) );\r
+\r
+                       /* Not used for now */\r
+                       ( void )usClass;\r
+                       /* For NBNS a name is 16 bytes long, written with capitals only.\r
+                       Make sure that the copy is terminated with a zero. */\r
+                       pucTarget = ucNBNSName + sizeof(ucNBNSName ) - 2;\r
+                       pucTarget[ 1 ] = '\0';\r
+\r
+                       /* Start with decoding the last 2 bytes. */\r
+                       pucSource = pucUDPPayloadBuffer + ( offsetof( NBNSRequest_t, ucName ) + ( dnsNBNS_ENCODED_NAME_LENGTH - 2 ) );\r
+\r
+                       for( ;; )\r
+                       {\r
+                               ucByte = ( uint8_t ) ( ( ( pucSource[ 0 ] - 0x41 ) << 4 ) | ( pucSource[ 1 ] - 0x41 ) );\r
+\r
+                               /* Make sure there are no trailing spaces in the name. */\r
+                               if( ( ucByte == ' ' ) && ( pucTarget[ 1 ] == '\0' ) )\r
+                               {\r
+                                       ucByte = '\0';\r
+                               }\r
+\r
+                               *pucTarget = ucByte;\r
+\r
+                               if( pucTarget == ucNBNSName )\r
+                               {\r
+                                       break;\r
+                               }\r
+\r
+                               pucTarget -= 1;\r
+                               pucSource -= 2;\r
+                       }\r
+\r
+                       #if( ipconfigUSE_DNS_CACHE == 1 )\r
+                       {\r
+                               if( ( usFlags & dnsNBNS_FLAGS_RESPONSE ) != 0 )\r
+                               {\r
+                                       /* If this is a response from another device,\r
+                                       add the name to the DNS cache */\r
+                                       prvProcessDNSCache( ( char * ) ucNBNSName, &ulIPAddress, pdFALSE );\r
+                               }\r
+                       }\r
+                       #else\r
+                       {\r
+                               /* Avoid compiler warnings. */\r
+                               ( void ) ulIPAddress;\r
+                       }\r
+                       #endif /* ipconfigUSE_DNS_CACHE */\r
+\r
+                       if( ( ( usFlags & dnsNBNS_FLAGS_RESPONSE ) == 0 ) &&\r
+                               ( usType == dnsNBNS_TYPE_NET_BIOS ) &&\r
+                               ( xApplicationDNSQueryHook( ( const char * ) ucNBNSName ) != pdFALSE ) )\r
+                       {\r
+                       uint16_t usLength;\r
+                       DNSMessage_t *pxMessage;\r
+                       NBNSAnswer_t *pxAnswer;\r
+\r
+                               /* Someone is looking for a device with ucNBNSName,\r
+                               prepare a positive reply. */\r
+                               NetworkBufferDescriptor_t *pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer );\r
+\r
+                               if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) )\r
+                               {\r
+                               NetworkBufferDescriptor_t *pxNewBuffer;\r
+                               BaseType_t xDataLength = pxNetworkBuffer->xDataLength + sizeof( UDPHeader_t ) +\r
+\r
+                                       sizeof( EthernetHeader_t ) + sizeof( IPHeader_t );\r
+\r
+                                       /* The field xDataLength was set to the length of the UDP payload.\r
+                                       The answer (reply) will be longer than the request, so the packet\r
+                                       must be duplicated into a bigger buffer */\r
+                                       pxNetworkBuffer->xDataLength = xDataLength;\r
+                                       pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, xDataLength + 16 );\r
+                                       if( pxNewBuffer != NULL )\r
+                                       {\r
+                                               pucUDPPayloadBuffer = pxNewBuffer->pucEthernetBuffer + sizeof( UDPPacket_t );\r
+                                               pxNetworkBuffer = pxNewBuffer;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               /* Just prevent that a reply will be sent */\r
+                                               pxNetworkBuffer = NULL;\r
+                                       }\r
+                               }\r
+\r
+                               /* Should not occur: pucUDPPayloadBuffer is part of a xNetworkBufferDescriptor */\r
+                               if( pxNetworkBuffer != NULL )\r
+                               {\r
+                                       pxMessage = (DNSMessage_t *)pucUDPPayloadBuffer;\r
+\r
+                                       /* As the fields in the structures are not word-aligned, we have to\r
+                                       copy the values byte-by-byte using macro's vSetField16() and vSetField32() */\r
+                                       vSetField16( pxMessage, DNSMessage_t, usFlags, dnsNBNS_QUERY_RESPONSE_FLAGS ); /* 0x8500 */\r
+                                       vSetField16( pxMessage, DNSMessage_t, usQuestions, 0 );\r
+                                       vSetField16( pxMessage, DNSMessage_t, usAnswers, 1 );\r
+                                       vSetField16( pxMessage, DNSMessage_t, usAuthorityRRs, 0 );\r
+                                       vSetField16( pxMessage, DNSMessage_t, usAdditionalRRs, 0 );\r
+\r
+                                       pxAnswer = (NBNSAnswer_t *)( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usType ) );\r
+\r
+                                       vSetField16( pxAnswer, NBNSAnswer_t, usType, usType );  /* Type */\r
+                                       vSetField16( pxAnswer, NBNSAnswer_t, usClass, dnsNBNS_CLASS_IN );       /* Class */\r
+                                       vSetField32( pxAnswer, NBNSAnswer_t, ulTTL, dnsNBNS_TTL_VALUE );\r
+                                       vSetField16( pxAnswer, NBNSAnswer_t, usDataLength, 6 ); /* 6 bytes including the length field */\r
+                                       vSetField16( pxAnswer, NBNSAnswer_t, usNbFlags, dnsNBNS_NAME_FLAGS );\r
+                                       vSetField32( pxAnswer, NBNSAnswer_t, ulIPAddress, FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) );\r
+\r
+                                       usLength = ( uint16_t ) ( offsetof( NBNSRequest_t, usType ) + sizeof( NBNSAnswer_t ) );\r
+\r
+                                       prvReplyDNSMessage( pxNetworkBuffer, usLength );\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+#endif /* ipconfigUSE_NBNS */\r
+/*-----------------------------------------------------------*/\r
+\r
+static Socket_t prvCreateDNSSocket( void )\r
+{\r
+static Socket_t xSocket = NULL;\r
+struct freertos_sockaddr xAddress;\r
+BaseType_t xReturn;\r
+TickType_t xTimeoutTime = pdMS_TO_TICKS( 200 );\r
+\r
+       /* This must be the first time this function has been called.  Create\r
+       the socket. */\r
+       xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
+\r
+       /* Auto bind the port. */\r
+       xAddress.sin_port = 0u;\r
+       xReturn = FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );\r
+\r
+       /* Check the bind was successful, and clean up if not. */\r
+       if( xReturn != 0 )\r
+       {\r
+               FreeRTOS_closesocket( xSocket );\r
+               xSocket = NULL;\r
+       }\r
+       else\r
+       {\r
+               /* Set the send and receive timeouts. */\r
+               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xTimeoutTime, sizeof( TickType_t ) );\r
+               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xTimeoutTime, sizeof( TickType_t ) );\r
+       }\r
+\r
+       return xSocket;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ( ipconfigUSE_NBNS == 1 ) || ( ipconfigUSE_LLMNR == 1 ) )\r
+\r
+       static void prvReplyDNSMessage( NetworkBufferDescriptor_t *pxNetworkBuffer, BaseType_t lNetLength )\r
+       {\r
+       UDPPacket_t *pxUDPPacket;\r
+       IPHeader_t *pxIPHeader;\r
+       UDPHeader_t *pxUDPHeader;\r
+\r
+               pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;\r
+               pxIPHeader = &pxUDPPacket->xIPHeader;\r
+               pxUDPHeader = &pxUDPPacket->xUDPHeader;\r
+               /* HT: started using defines like 'ipSIZE_OF_xxx' */\r
+               pxIPHeader->usLength               = FreeRTOS_htons( lNetLength + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_UDP_HEADER );\r
+               /* HT:endian: should not be translated, copying from packet to packet */\r
+               pxIPHeader->ulDestinationIPAddress = pxIPHeader->ulSourceIPAddress;\r
+               pxIPHeader->ulSourceIPAddress      = *ipLOCAL_IP_ADDRESS_POINTER;\r
+               pxIPHeader->ucTimeToLive           = ipconfigUDP_TIME_TO_LIVE;\r
+               pxIPHeader->usIdentification       = FreeRTOS_htons( usPacketIdentifier );\r
+               usPacketIdentifier++;\r
+               pxUDPHeader->usLength              = FreeRTOS_htons( lNetLength + ipSIZE_OF_UDP_HEADER );\r
+               vFlip_16( pxUDPPacket->xUDPHeader.usSourcePort, pxUDPPacket->xUDPHeader.usDestinationPort );\r
+\r
+               #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )\r
+               {\r
+                       /* calculate the IP header checksum */\r
+                       pxIPHeader->usHeaderChecksum       = 0x00;\r
+                       pxIPHeader->usHeaderChecksum       = usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );\r
+                       pxIPHeader->usHeaderChecksum       = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );\r
+\r
+                       /* calculate the UDP checksum for outgoing package */\r
+                       usGenerateProtocolChecksum( ( uint8_t* ) pxUDPPacket, pdTRUE );\r
+               }\r
+               #endif\r
+\r
+               /* Important: tell NIC driver how many bytes must be sent */\r
+               pxNetworkBuffer->xDataLength = ( size_t ) ( lNetLength + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_UDP_HEADER + ipSIZE_OF_ETH_HEADER );\r
+\r
+               /* This function will fill in the eth addresses and send the packet */\r
+               vReturnEthernetFrame( pxNetworkBuffer, pdFALSE );\r
+       }\r
+\r
+#endif /* ipconfigUSE_NBNS == 1 || ipconfigUSE_LLMNR == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_DNS_CACHE == 1 )\r
+\r
+       static void prvProcessDNSCache( const char *pcName, uint32_t *pulIP, BaseType_t xLookUp )\r
+       {\r
+       BaseType_t x;\r
+       BaseType_t xFound = pdFALSE;\r
+       static BaseType_t xFreeEntry = 0;\r
+\r
+               /* For each entry in the DNS cache table. */\r
+               for( x = 0; x < ipconfigDNS_CACHE_ENTRIES; x++ )\r
+               {\r
+                       if( xDNSCache[ x ].pcName[ 0 ] == 0 )\r
+                       {\r
+                               break;\r
+                       }\r
+\r
+                       if( strncmp( xDNSCache[ x ].pcName, pcName, sizeof( xDNSCache[ x ].pcName ) ) == 0 )\r
+                       {\r
+                               /* Is this function called for a lookup or to add/update an IP address? */\r
+                               if( xLookUp != pdFALSE )\r
+                               {\r
+                                       *pulIP = xDNSCache[ x ].ulIPAddress;\r
+                               }\r
+                               else\r
+                               {\r
+                                       xDNSCache[ x ].ulIPAddress = *pulIP;\r
+                               }\r
+\r
+                               xFound = pdTRUE;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if( xFound == pdFALSE )\r
+               {\r
+                       if( xLookUp != pdFALSE )\r
+                       {\r
+                               *pulIP = 0;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Called to add or update an item */\r
+                               strncpy( xDNSCache[ xFreeEntry ].pcName, pcName, sizeof( xDNSCache[ xFreeEntry ].pcName ) );\r
+                               xDNSCache[ xFreeEntry ].ulIPAddress = *pulIP;\r
+\r
+                               xFreeEntry++;\r
+                               if( xFreeEntry == ipconfigDNS_CACHE_ENTRIES )\r
+                               {\r
+                                       xFreeEntry = 0;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if( ( xLookUp == 0 ) || ( *pulIP != 0 ) )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "prvProcessDNSCache: %s: '%s' @ %lxip\n", xLookUp ? "look-up" : "add", pcName, FreeRTOS_ntohl( *pulIP ) ) );\r
+               }\r
+       }\r
+\r
+#endif /* ipconfigUSE_DNS_CACHE */\r
+\r
+#endif /* ipconfigUSE_DNS != 0 */\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_IP.c
new file mode 100644 (file)
index 0000000..6b7ec5f
--- /dev/null
@@ -0,0 +1,2205 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "FreeRTOS_ARP.h"\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_TCP_IP.h"\r
+#include "FreeRTOS_DHCP.h"\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "FreeRTOS_DNS.h"\r
+\r
+\r
+/* Used to ensure the structure packing is having the desired effect.  The\r
+'volatile' is used to prevent compiler warnings about comparing a constant with\r
+a constant. */\r
+#define ipEXPECTED_EthernetHeader_t_SIZE       ( ( size_t ) 14 )\r
+#define ipEXPECTED_ARPHeader_t_SIZE                    ( ( size_t ) 28 )\r
+#define ipEXPECTED_IPHeader_t_SIZE                     ( ( size_t ) 20 )\r
+#define ipEXPECTED_IGMPHeader__SIZE                    ( ( size_t ) 8 )\r
+#define ipEXPECTED_ICMPHeader_t_SIZE           ( ( size_t ) 8 )\r
+#define ipEXPECTED_UDPHeader_t_SIZE                    ( ( size_t ) 8 )\r
+#define ipEXPECTED_TCPHeader_t_SIZE                    ( ( size_t ) 20 )\r
+\r
+\r
+/* ICMP protocol definitions. */\r
+#define ipICMP_ECHO_REQUEST                            ( ( uint8_t ) 8 )\r
+#define ipICMP_ECHO_REPLY                              ( ( uint8_t ) 0 )\r
+\r
+\r
+/* Time delay between repeated attempts to initialise the network hardware. */\r
+#define ipINITIALISATION_RETRY_DELAY   ( pdMS_TO_TICKS( 3000 ) )\r
+\r
+/* Defines how often the ARP timer callback function is executed.  The time is\r
+shorted in the Windows simulator as simulated time is not real time. */\r
+#ifndef        ipARP_TIMER_PERIOD_MS\r
+       #ifdef _WINDOWS_\r
+               #define ipARP_TIMER_PERIOD_MS   ( 500 ) /* For windows simulator builds. */\r
+       #else\r
+               #define ipARP_TIMER_PERIOD_MS   ( 10000 )\r
+       #endif\r
+#endif\r
+\r
+#ifndef iptraceIP_TASK_STARTING\r
+       #define iptraceIP_TASK_STARTING()       do {} while( 0 )\r
+#endif\r
+\r
+#if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )\r
+       /* When initialising the TCP timer,\r
+       give it an initial time-out of 1 second. */\r
+       #define ipTCP_TIMER_PERIOD_MS   ( 1000 )\r
+#endif\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+driver will filter incoming packets and only pass the stack those packets it\r
+considers need processing.  In this case ipCONSIDER_FRAME_FOR_PROCESSING() can\r
+be #defined away.  If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 0\r
+then the Ethernet driver will pass all received packets to the stack, and the\r
+stack must do the filtering itself.  In this case ipCONSIDER_FRAME_FOR_PROCESSING\r
+needs to call eConsiderFrameForProcessing. */\r
+#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#else\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#endif\r
+\r
+/* The character used to fill ICMP echo requests, and therefore also the\r
+character expected to fill ICMP echo replies. */\r
+#define ipECHO_DATA_FILL_BYTE                                          'x'\r
+\r
+#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )\r
+       /* The bits in the two byte IP header field that make up the fragment offset value. */\r
+       #define ipFRAGMENT_OFFSET_BIT_MASK                              ( ( uint16_t ) 0xff0f )\r
+#else\r
+       /* The bits in the two byte IP header field that make up the fragment offset value. */\r
+       #define ipFRAGMENT_OFFSET_BIT_MASK                              ( ( uint16_t ) 0x0fff )\r
+#endif /* ipconfigBYTE_ORDER */\r
+\r
+/* The maximum time the IP task is allowed to remain in the Blocked state if no\r
+events are posted to the network event queue. */\r
+#ifndef        ipconfigMAX_IP_TASK_SLEEP_TIME\r
+       #define ipconfigMAX_IP_TASK_SLEEP_TIME ( pdMS_TO_TICKS( 10000UL ) )\r
+#endif\r
+\r
+/* When a new TCP connection is established, the value of\r
+'ulNextInitialSequenceNumber' will be used as the initial sequence number.  It\r
+is very important that at start-up, 'ulNextInitialSequenceNumber' contains a\r
+random value.  Also its value must be increased continuously in time, to prevent\r
+a third party guessing the next sequence number and take-over a TCP connection.\r
+It is advised to increment it by 1 ever 4us, which makes about 256 times\r
+per ms: */\r
+#define ipINITIAL_SEQUENCE_NUMBER_FACTOR       256UL\r
+\r
+/* Returned as the (invalid) checksum when the protocol being checked is not\r
+handled.  The value is chosen simply to be easy to spot when debugging. */\r
+#define ipUNHANDLED_PROTOCOL           0x4321u\r
+\r
+/* Returned to indicate a valid checksum when the checksum does not need to be\r
+calculated. */\r
+#define ipCORRECT_CRC                          0xffffu\r
+\r
+/* Returned as the (invalid) checksum when the length of the data being checked\r
+had an invalid length. */\r
+#define ipINVALID_LENGTH                       0x1234u\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+typedef struct xIP_TIMER\r
+{\r
+       uint32_t\r
+               bActive : 1,    /* This timer is running and must be processed. */\r
+               bExpired : 1;   /* Timer has expired and a task must be processed. */\r
+       TimeOut_t xTimeOut;\r
+       TickType_t ulRemainingTime;\r
+       TickType_t ulReloadTime;\r
+} IPTimer_t;\r
+\r
+/* Used in checksum calculation. */\r
+typedef union _xUnion32\r
+{\r
+       uint32_t u32;\r
+       uint16_t u16[ 2 ];\r
+       uint8_t u8[ 4 ];\r
+} xUnion32;\r
+\r
+/* Used in checksum calculation. */\r
+typedef union _xUnionPtr\r
+{\r
+       uint32_t *u32ptr;\r
+       uint16_t *u16ptr;\r
+       uint8_t *u8ptr;\r
+} xUnionPtr;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * The main TCP/IP stack processing task.  This task receives commands/events\r
+ * from the network hardware drivers and tasks that are using sockets.  It also\r
+ * maintains a set of protocol timers.\r
+ */\r
+static void prvIPTask( void *pvParameters );\r
+\r
+/*\r
+ * Called when new data is available from the network interface.\r
+ */\r
+static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer );\r
+\r
+/*\r
+ * Process incoming IP packets.\r
+ */\r
+static eFrameProcessingResult_t prvProcessIPPacket( const IPPacket_t * const pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer );\r
+\r
+#if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )\r
+       /*\r
+        * Process incoming ICMP packets.\r
+        */\r
+       static eFrameProcessingResult_t prvProcessICMPPacket( ICMPPacket_t * const pxICMPPacket );\r
+#endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */\r
+\r
+/*\r
+ * Turns around an incoming ping request to convert it into a ping reply.\r
+ */\r
+#if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 )\r
+       static eFrameProcessingResult_t prvProcessICMPEchoRequest( ICMPPacket_t * const pxICMPPacket );\r
+#endif /* ipconfigREPLY_TO_INCOMING_PINGS */\r
+\r
+/*\r
+ * Processes incoming ping replies.  The application callback function\r
+ * vApplicationPingReplyHook() is called with the results.\r
+ */\r
+#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )\r
+       static void prvProcessICMPEchoReply( ICMPPacket_t * const pxICMPPacket );\r
+#endif /* ipconfigSUPPORT_OUTGOING_PINGS */\r
+\r
+/*\r
+ * Called to create a network connection when the stack is first started, or\r
+ * when the network connection is lost.\r
+ */\r
+static void prvProcessNetworkDownEvent( void );\r
+\r
+/*\r
+ * Checks the ARP, DHCP and TCP timers to see if any periodic or timeout\r
+ * processing is required.\r
+ */\r
+static void prvCheckNetworkTimers( void );\r
+\r
+/*\r
+ * Determine how long the IP task can sleep for, which depends on when the next\r
+ * periodic or timeout processing must be performed.\r
+ */\r
+static TickType_t prvCalculateSleepTime( void );\r
+\r
+/*\r
+ * The network card driver has received a packet.  In the case that it is part\r
+ * of a linked packet chain, walk through it to handle every message.\r
+ */\r
+static void prvHandleEthernetPacket( NetworkBufferDescriptor_t *pxBuffer );\r
+\r
+/*\r
+ * Utility functions for the light weight IP timers.\r
+ */\r
+static void prvIPTimerStart( IPTimer_t *pxTimer, TickType_t xTime );\r
+static BaseType_t prvIPTimerCheck( IPTimer_t *pxTimer );\r
+static void prvIPTimerReload( IPTimer_t *pxTimer, TickType_t xTime );\r
+\r
+static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPPacket,\r
+       NetworkBufferDescriptor_t * const pxNetworkBuffer, UBaseType_t uxHeaderLength );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The queue used to pass events into the IP-task for processing. */\r
+QueueHandle_t xNetworkEventQueue = NULL;\r
+\r
+/*_RB_ Requires comment. */\r
+uint16_t usPacketIdentifier = 0U;\r
+\r
+/* For convenience, a MAC address of all 0xffs is defined const for quick\r
+reference. */\r
+const MACAddress_t xBroadcastMACAddress = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };\r
+\r
+/* Structure that stores the netmask, gateway address and DNS server addresses. */\r
+NetworkAddressingParameters_t xNetworkAddressing = { 0, 0, 0, 0, 0 };\r
+\r
+/* Default values for the above struct in case DHCP\r
+does not lead to a confirmed request. */\r
+NetworkAddressingParameters_t xDefaultAddressing = { 0, 0, 0, 0, 0 };\r
+\r
+/* Used to ensure network down events cannot be missed when they cannot be\r
+posted to the network event queue because the network event queue is already\r
+full. */\r
+static BaseType_t xNetworkDownEventPending = pdFALSE;\r
+\r
+/* Stores the handle of the task that handles the stack.  The handle is used\r
+(indirectly) by some utility function to determine if the utility function is\r
+being called by a task (in which case it is ok to block) or by the IP task\r
+itself (in which case it is not ok to block). */\r
+static TaskHandle_t xIPTaskHandle = NULL;\r
+\r
+#if( ipconfigUSE_TCP != 0 )\r
+       /* Set to a non-zero value if one or more TCP message have been processed\r
+       within the last round. */\r
+       static BaseType_t xProcessedTCPMessage;\r
+#endif\r
+\r
+/* Simple set to pdTRUE or pdFALSE depending on whether the network is up or\r
+down (connected, not connected) respectively. */\r
+static BaseType_t xNetworkUp = pdFALSE;\r
+\r
+/*\r
+A timer for each of the following processes, all of which need attention on a\r
+regular basis:\r
+       1. ARP, to check its table entries\r
+       2. DPHC, to send requests and to renew a reservation\r
+       3. TCP, to check for timeouts, resends\r
+       4. DNS, to check for timeouts when looking-up a domain.\r
+ */\r
+static IPTimer_t xARPTimer;\r
+#if( ipconfigUSE_DHCP != 0 )\r
+       static IPTimer_t xDHCPTimer;\r
+#endif\r
+#if( ipconfigUSE_TCP != 0 )\r
+       static IPTimer_t xTCPTimer;\r
+#endif\r
+#if( ipconfigDNS_USE_CALLBACKS != 0 )\r
+       static IPTimer_t xDNSTimer;\r
+#endif\r
+\r
+/* Set to pdTRUE when the IP task is ready to start processing packets. */\r
+static BaseType_t xIPTaskInitialised = pdFALSE;\r
+\r
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+       /* Keep track of the lowest amount of space in 'xNetworkEventQueue'. */\r
+       static UBaseType_t uxQueueMinimumSpace = ipconfigEVENT_QUEUE_LENGTH;\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvIPTask( void *pvParameters )\r
+{\r
+IPStackEvent_t xReceivedEvent;\r
+TickType_t xNextIPSleep;\r
+FreeRTOS_Socket_t *pxSocket;\r
+struct freertos_sockaddr xAddress;\r
+\r
+       /* Just to prevent compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       /* A possibility to set some additional task properties. */\r
+       iptraceIP_TASK_STARTING();\r
+\r
+       /* Generate a dummy message to say that the network connection has gone\r
+       down.  This will cause this task to initialise the network interface.  After\r
+       this it is the responsibility of the network interface hardware driver to\r
+       send this message if a previously connected network is disconnected. */\r
+       FreeRTOS_NetworkDown();\r
+\r
+       #if( ipconfigUSE_TCP == 1 )\r
+       {\r
+               /* Initialise the TCP timer. */\r
+               prvIPTimerReload( &xTCPTimer, pdMS_TO_TICKS( ipTCP_TIMER_PERIOD_MS ) );\r
+       }\r
+       #endif\r
+\r
+       /* Initialisation is complete and events can now be processed. */\r
+       xIPTaskInitialised = pdTRUE;\r
+\r
+       FreeRTOS_debug_printf( ( "prvIPTask started\n" ) );\r
+\r
+       /* Loop, processing IP events. */\r
+       for( ;; )\r
+       {\r
+               ipconfigWATCHDOG_TIMER();\r
+\r
+               /* Check the ARP, DHCP and TCP timers to see if there is any periodic\r
+               or timeout processing to perform. */\r
+               prvCheckNetworkTimers();\r
+\r
+               /* Calculate the acceptable maximum sleep time. */\r
+               xNextIPSleep = prvCalculateSleepTime();\r
+\r
+               /* Wait until there is something to do.  The event is initialised to "no\r
+               event" in case the following call exits due to a time out rather than a\r
+               message being received. */\r
+               xReceivedEvent.eEventType = eNoEvent;\r
+               xQueueReceive( xNetworkEventQueue, ( void * ) &xReceivedEvent, xNextIPSleep );\r
+\r
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+               {\r
+                       if( xReceivedEvent.eEventType != eNoEvent )\r
+                       {\r
+                       UBaseType_t uxCount;\r
+\r
+                               uxCount = uxQueueSpacesAvailable( xNetworkEventQueue );\r
+                               if( uxQueueMinimumSpace > uxCount )\r
+                               {\r
+                                       uxQueueMinimumSpace = uxCount;\r
+                               }\r
+                       }\r
+               }\r
+               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+               iptraceNETWORK_EVENT_RECEIVED( xReceivedEvent.eEventType );\r
+\r
+               switch( xReceivedEvent.eEventType )\r
+               {\r
+                       case eNetworkDownEvent :\r
+                               /* Attempt to establish a connection. */\r
+                               xNetworkUp = pdFALSE;\r
+                               prvProcessNetworkDownEvent();\r
+                               break;\r
+\r
+                       case eNetworkRxEvent:\r
+                               /* The network hardware driver has received a new packet.  A\r
+                               pointer to the received buffer is located in the pvData member\r
+                               of the received event structure. */\r
+                               prvHandleEthernetPacket( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ) );\r
+                               break;\r
+\r
+                       case eARPTimerEvent :\r
+                               /* The ARP timer has expired, process the ARP cache. */\r
+                               vARPAgeCache();\r
+                               break;\r
+\r
+                       case eSocketBindEvent:\r
+                               /* FreeRTOS_bind (a user API) wants the IP-task to bind a socket\r
+                               to a port. The port number is communicated in the socket field\r
+                               usLocalPort. vSocketBind() will actually bind the socket and the\r
+                               API will unblock as soon as the eSOCKET_BOUND event is\r
+                               triggered. */\r
+                               pxSocket = ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData );\r
+                               xAddress.sin_addr = 0u; /* For the moment. */\r
+                               xAddress.sin_port = FreeRTOS_ntohs( pxSocket->usLocalPort );\r
+                               pxSocket->usLocalPort = 0u;\r
+                               vSocketBind( pxSocket, &xAddress, sizeof( xAddress ), pdFALSE );\r
+\r
+                               /* Before 'eSocketBindEvent' was sent it was tested that\r
+                               ( xEventGroup != NULL ) so it can be used now to wake up the\r
+                               user. */\r
+                               pxSocket->xEventBits |= eSOCKET_BOUND;\r
+                               vSocketWakeUpUser( pxSocket );\r
+                               break;\r
+\r
+                       case eSocketCloseEvent :\r
+                               /* The user API FreeRTOS_closesocket() has sent a message to the\r
+                               IP-task to actually close a socket. This is handled in\r
+                               vSocketClose().  As the socket gets closed, there is no way to\r
+                               report back to the API, so the API won't wait for the result */\r
+                               vSocketClose( ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData ) );\r
+                               break;\r
+\r
+                       case eStackTxEvent :\r
+                               /* The network stack has generated a packet to send.  A\r
+                               pointer to the generated buffer is located in the pvData\r
+                               member of the received event structure. */\r
+                               vProcessGeneratedUDPPacket( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ) );\r
+                               break;\r
+\r
+                       case eDHCPEvent:\r
+                               /* The DHCP state machine needs processing. */\r
+                               #if( ipconfigUSE_DHCP == 1 )\r
+                               {\r
+                                       vDHCPProcess( pdFALSE );\r
+                               }\r
+                               #endif /* ipconfigUSE_DHCP */\r
+                               break;\r
+\r
+                       case eSocketSelectEvent :\r
+                               /* FreeRTOS_select() has got unblocked by a socket event,\r
+                               vSocketSelect() will check which sockets actually have an event\r
+                               and update the socket field xSocketBits. */\r
+                               #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+                               {\r
+                                       vSocketSelect( ( SocketSelect_t * ) ( xReceivedEvent.pvData ) );\r
+                               }\r
+                               #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
+                               break;\r
+\r
+                       case eSocketSignalEvent :\r
+                               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
+                               {\r
+                                       /* Some task wants to signal the user of this socket in\r
+                                       order to interrupt a call to recv() or a call to select(). */\r
+                                       FreeRTOS_SignalSocket( ( Socket_t ) xReceivedEvent.pvData );\r
+                               }\r
+                               #endif /* ipconfigSUPPORT_SIGNALS */\r
+                               break;\r
+\r
+                       case eTCPTimerEvent :\r
+                               #if( ipconfigUSE_TCP == 1 )\r
+                               {\r
+                                       /* Simply mark the TCP timer as expired so it gets processed\r
+                                       the next time prvCheckNetworkTimers() is called. */\r
+                                       xTCPTimer.bExpired = pdTRUE_UNSIGNED;\r
+                               }\r
+                               #endif /* ipconfigUSE_TCP */\r
+                               break;\r
+\r
+                       case eTCPAcceptEvent:\r
+                               /* The API FreeRTOS_accept() was called, the IP-task will now\r
+                               check if the listening socket (communicated in pvData) actually\r
+                               received a new connection. */\r
+                               #if( ipconfigUSE_TCP == 1 )\r
+                               {\r
+                                       pxSocket = ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData );\r
+\r
+                                       if( xTCPCheckNewClient( pxSocket ) != pdFALSE )\r
+                                       {\r
+                                               pxSocket->xEventBits |= eSOCKET_ACCEPT;\r
+                                               vSocketWakeUpUser( pxSocket );\r
+                                       }\r
+                               }\r
+                               #endif /* ipconfigUSE_TCP */\r
+                               break;\r
+\r
+                       case eTCPNetStat:\r
+                               /* FreeRTOS_netstat() was called to have the IP-task print an\r
+                               overview of all sockets and their connections */\r
+                               #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_PRINTF == 1 ) )\r
+                               {\r
+                                       vTCPNetStat();\r
+                               }\r
+                               #endif /* ipconfigUSE_TCP */\r
+                               break;\r
+\r
+                       default :\r
+                               /* Should not get here. */\r
+                               break;\r
+               }\r
+\r
+               if( xNetworkDownEventPending != pdFALSE )\r
+               {\r
+                       /* A network down event could not be posted to the network event\r
+                       queue because the queue was full.  Try posting again. */\r
+                       FreeRTOS_NetworkDown();\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xIsCallingFromIPTask( void )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( xTaskGetCurrentTaskHandle() == xIPTaskHandle )\r
+       {\r
+               xReturn = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdFALSE;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvHandleEthernetPacket( NetworkBufferDescriptor_t *pxBuffer )\r
+{\r
+       #if( ipconfigUSE_LINKED_RX_MESSAGES == 0 )\r
+       {\r
+               /* When ipconfigUSE_LINKED_RX_MESSAGES is not set to 0 then only one\r
+               buffer will be sent at a time.  This is the default way for +TCP to pass\r
+               messages from the MAC to the TCP/IP stack. */\r
+               prvProcessEthernetPacket( pxBuffer );\r
+       }\r
+       #else /* ipconfigUSE_LINKED_RX_MESSAGES */\r
+       {\r
+       NetworkBufferDescriptor_t *pxNextBuffer;\r
+\r
+               /* An optimisation that is useful when there is high network traffic.\r
+               Instead of passing received packets into the IP task one at a time the\r
+               network interface can chain received packets together and pass them into\r
+               the IP task in one go.  The packets are chained using the pxNextBuffer\r
+               member.  The loop below walks through the chain processing each packet\r
+               in the chain in turn. */\r
+               do\r
+               {\r
+                       /* Store a pointer to the buffer after pxBuffer for use later on. */\r
+                       pxNextBuffer = pxBuffer->pxNextBuffer;\r
+\r
+                       /* Make it NULL to avoid using it later on. */\r
+                       pxBuffer->pxNextBuffer = NULL;\r
+\r
+                       prvProcessEthernetPacket( pxBuffer );\r
+                       pxBuffer = pxNextBuffer;\r
+\r
+               /* While there is another packet in the chain. */\r
+               } while( pxBuffer != NULL );\r
+       }\r
+       #endif /* ipconfigUSE_LINKED_RX_MESSAGES */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static TickType_t prvCalculateSleepTime( void )\r
+{\r
+TickType_t xMaximumSleepTime;\r
+\r
+       /* Start with the maximum sleep time, then check this against the remaining\r
+       time in any other timers that are active. */\r
+       xMaximumSleepTime = ipconfigMAX_IP_TASK_SLEEP_TIME;\r
+\r
+       if( xARPTimer.bActive != pdFALSE_UNSIGNED )\r
+       {\r
+               if( xARPTimer.ulRemainingTime < xMaximumSleepTime )\r
+               {\r
+                       xMaximumSleepTime = xARPTimer.ulReloadTime;\r
+               }\r
+       }\r
+\r
+       #if( ipconfigUSE_DHCP == 1 )\r
+       {\r
+               if( xDHCPTimer.bActive != pdFALSE_UNSIGNED )\r
+               {\r
+                       if( xDHCPTimer.ulRemainingTime < xMaximumSleepTime )\r
+                       {\r
+                               xMaximumSleepTime = xDHCPTimer.ulRemainingTime;\r
+                       }\r
+               }\r
+       }\r
+       #endif /* ipconfigUSE_DHCP */\r
+\r
+       #if( ipconfigUSE_TCP == 1 )\r
+       {\r
+               if( xTCPTimer.ulRemainingTime < xMaximumSleepTime )\r
+               {\r
+                       xMaximumSleepTime = xTCPTimer.ulRemainingTime;\r
+               }\r
+       }\r
+       #endif\r
+\r
+       #if( ipconfigDNS_USE_CALLBACKS != 0 )\r
+       {\r
+               if( xDNSTimer.bActive != pdFALSE )\r
+               {\r
+                       if( xDNSTimer.ulRemainingTime < xMaximumSleepTime )\r
+                       {\r
+                               xMaximumSleepTime = xDNSTimer.ulRemainingTime;\r
+                       }\r
+               }\r
+       }\r
+       #endif\r
+\r
+       return xMaximumSleepTime;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCheckNetworkTimers( void )\r
+{\r
+       /* Is it time for ARP processing? */\r
+       if( prvIPTimerCheck( &xARPTimer ) != pdFALSE )\r
+       {\r
+               xSendEventToIPTask( eARPTimerEvent );\r
+       }\r
+\r
+       #if( ipconfigUSE_DHCP == 1 )\r
+       {\r
+               /* Is it time for DHCP processing? */\r
+               if( prvIPTimerCheck( &xDHCPTimer ) != pdFALSE )\r
+               {\r
+                       xSendEventToIPTask( eDHCPEvent );\r
+               }\r
+       }\r
+       #endif /* ipconfigUSE_DHCP */\r
+\r
+       #if( ipconfigDNS_USE_CALLBACKS != 0 )\r
+       {\r
+       extern void vDNSCheckCallBack( void *pvSearchID );\r
+\r
+               /* Is it time for DNS processing? */\r
+               if( prvIPTimerCheck( &xDNSTimer ) != pdFALSE )\r
+               {\r
+                       vDNSCheckCallBack( NULL );\r
+               }\r
+       }\r
+       #endif /* ipconfigDNS_USE_CALLBACKS */\r
+\r
+       #if( ipconfigUSE_TCP == 1 )\r
+       {\r
+       BaseType_t xWillSleep;\r
+       /* xStart keeps a copy of the last time this function was active,\r
+       and during every call it will be updated with xTaskGetTickCount()\r
+       '0' means: not yet initialised (although later '0' might be returned\r
+       by xTaskGetTickCount(), which is no problem). */\r
+       static TickType_t xStart = ( TickType_t ) 0;\r
+       TickType_t xTimeNow, xNextTime;\r
+       BaseType_t xCheckTCPSockets;\r
+       extern uint32_t ulNextInitialSequenceNumber;\r
+\r
+               if( uxQueueMessagesWaiting( xNetworkEventQueue ) == 0u )\r
+               {\r
+                       xWillSleep = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       xWillSleep = pdFALSE;\r
+               }\r
+\r
+               xTimeNow = xTaskGetTickCount();\r
+\r
+               if( xStart != ( TickType_t ) 0 )\r
+               {\r
+                       /* It is advised to increment the Initial Sequence Number every 4\r
+                       microseconds which makes 250 times per ms.  This will make it harder\r
+                       for a third party to 'guess' our sequence number and 'take over'\r
+                       a TCP connection */\r
+                       ulNextInitialSequenceNumber += ipINITIAL_SEQUENCE_NUMBER_FACTOR * ( ( xTimeNow - xStart ) * portTICK_PERIOD_MS );\r
+               }\r
+\r
+               xStart = xTimeNow;\r
+\r
+               /* Sockets need to be checked if the TCP timer has expired. */\r
+               xCheckTCPSockets = prvIPTimerCheck( &xTCPTimer );\r
+\r
+               /* Sockets will also be checked if there are TCP messages but the\r
+               message queue is empty (indicated by xWillSleep being true). */\r
+               if( ( xProcessedTCPMessage != pdFALSE ) && ( xWillSleep != pdFALSE ) )\r
+               {\r
+                       xCheckTCPSockets = pdTRUE;\r
+               }\r
+\r
+               if( xCheckTCPSockets != pdFALSE )\r
+               {\r
+                       /* Attend to the sockets, returning the period after which the\r
+                       check must be repeated. */\r
+                       xNextTime = xTCPTimerCheck( xWillSleep );\r
+                       prvIPTimerStart( &xTCPTimer, xNextTime );\r
+                       xProcessedTCPMessage = 0;\r
+               }\r
+       }\r
+       #endif /* ipconfigUSE_TCP == 1 */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvIPTimerStart( IPTimer_t *pxTimer, TickType_t xTime )\r
+{\r
+       vTaskSetTimeOutState( &pxTimer->xTimeOut );\r
+       pxTimer->ulRemainingTime = xTime;\r
+\r
+       if( xTime == ( TickType_t ) 0 )\r
+       {\r
+               pxTimer->bExpired = pdTRUE_UNSIGNED;\r
+       }\r
+       else\r
+       {\r
+               pxTimer->bExpired = pdFALSE_UNSIGNED;\r
+       }\r
+\r
+       pxTimer->bActive = pdTRUE_UNSIGNED;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvIPTimerReload( IPTimer_t *pxTimer, TickType_t xTime )\r
+{\r
+       pxTimer->ulReloadTime = xTime;\r
+       prvIPTimerStart( pxTimer, xTime );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvIPTimerCheck( IPTimer_t *pxTimer )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( pxTimer->bActive == pdFALSE_UNSIGNED )\r
+       {\r
+               /* The timer is not enabled. */\r
+               xReturn = pdFALSE;\r
+       }\r
+       else\r
+       {\r
+               /* The timer might have set the bExpired flag already, if not, check the\r
+               value of xTimeOut against ulRemainingTime. */\r
+               if( ( pxTimer->bExpired != pdFALSE_UNSIGNED ) ||\r
+                       ( xTaskCheckForTimeOut( &( pxTimer->xTimeOut ), &( pxTimer->ulRemainingTime ) ) != pdFALSE ) )\r
+               {\r
+                       prvIPTimerStart( pxTimer, pxTimer->ulReloadTime );\r
+                       xReturn = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       xReturn = pdFALSE;\r
+               }\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FreeRTOS_NetworkDown( void )\r
+{\r
+static const IPStackEvent_t xNetworkDownEvent = { eNetworkDownEvent, NULL };\r
+const TickType_t xDontBlock = ( TickType_t ) 0;\r
+\r
+       /* Simply send the network task the appropriate event. */\r
+       if( xSendEventStructToIPTask( &xNetworkDownEvent, xDontBlock ) != pdPASS )\r
+       {\r
+               /* Could not send the message, so it is still pending. */\r
+               xNetworkDownEventPending = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               /* Message was sent so it is not pending. */\r
+               xNetworkDownEventPending = pdFALSE;\r
+       }\r
+\r
+       iptraceNETWORK_DOWN();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t FreeRTOS_NetworkDownFromISR( void )\r
+{\r
+static const IPStackEvent_t xNetworkDownEvent = { eNetworkDownEvent, NULL };\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       /* Simply send the network task the appropriate event. */\r
+       if( xQueueSendToBackFromISR( xNetworkEventQueue, &xNetworkDownEvent, &xHigherPriorityTaskWoken ) != pdPASS )\r
+       {\r
+               xNetworkDownEventPending = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xNetworkDownEventPending = pdFALSE;\r
+       }\r
+\r
+       iptraceNETWORK_DOWN();\r
+\r
+       return xHigherPriorityTaskWoken;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void *FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )\r
+{\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+void *pvReturn;\r
+\r
+       /* Cap the block time.  The reason for this is explained where\r
+       ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined (assuming an official\r
+       FreeRTOSIPConfig.h header file is being used). */\r
+       if( xBlockTimeTicks > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )\r
+       {\r
+               xBlockTimeTicks = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;\r
+       }\r
+\r
+       /* Obtain a network buffer with the required amount of storage. */\r
+       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( UDPPacket_t ) + xRequestedSizeBytes, xBlockTimeTicks );\r
+\r
+       if( pxNetworkBuffer != NULL )\r
+       {\r
+               /* Leave space for the UPD header. */\r
+               pvReturn = ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );\r
+       }\r
+       else\r
+       {\r
+               pvReturn = NULL;\r
+       }\r
+\r
+       return ( void * ) pvReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer,\r
+       BaseType_t xNewLength )\r
+{\r
+NetworkBufferDescriptor_t * pxNewBuffer;\r
+\r
+       /* This function is only used when 'ipconfigZERO_COPY_TX_DRIVER' is set to 1.\r
+       The transmit routine wants to have ownership of the network buffer\r
+       descriptor, because it will pass the buffer straight to DMA. */\r
+       pxNewBuffer = pxGetNetworkBufferWithDescriptor( ( size_t ) xNewLength, ( TickType_t ) 0 );\r
+\r
+       if( pxNewBuffer != NULL )\r
+       {\r
+               pxNewBuffer->ulIPAddress = pxNetworkBuffer->ulIPAddress;\r
+               pxNewBuffer->usPort = pxNetworkBuffer->usPort;\r
+               pxNewBuffer->usBoundPort = pxNetworkBuffer->usBoundPort;\r
+               memcpy( pxNewBuffer->pucEthernetBuffer, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );\r
+       }\r
+\r
+       return pxNewBuffer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 ) || ( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+\r
+       NetworkBufferDescriptor_t *pxPacketBuffer_to_NetworkBuffer( const void *pvBuffer )\r
+       {\r
+       uint8_t *pucBuffer;\r
+       NetworkBufferDescriptor_t *pxResult;\r
+\r
+               if( pvBuffer == NULL )\r
+               {\r
+                       pxResult = NULL;\r
+               }\r
+               else\r
+               {\r
+                       /* Obtain the network buffer from the zero copy pointer. */\r
+                       pucBuffer = ( uint8_t * ) pvBuffer;\r
+\r
+                       /* The input here is a pointer to a payload buffer.  Subtract the\r
+                       size of the header in the network buffer, usually 8 + 2 bytes. */\r
+                       pucBuffer -= ipBUFFER_PADDING;\r
+\r
+                       /* Here a pointer was placed to the network descriptor.  As a\r
+                       pointer is dereferenced, make sure it is well aligned. */\r
+                       if( ( ( ( uint32_t ) pucBuffer ) & ( sizeof( pucBuffer ) - ( size_t ) 1 ) ) == ( uint32_t ) 0 )\r
+                       {\r
+                               pxResult = * ( ( NetworkBufferDescriptor_t ** ) pucBuffer );\r
+                       }\r
+                       else\r
+                       {\r
+                               pxResult = NULL;\r
+                       }\r
+               }\r
+\r
+               return pxResult;\r
+       }\r
+\r
+#endif /* ipconfigZERO_COPY_TX_DRIVER != 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( void *pvBuffer )\r
+{\r
+uint8_t *pucBuffer;\r
+NetworkBufferDescriptor_t *pxResult;\r
+\r
+       if( pvBuffer == NULL )\r
+       {\r
+               pxResult = NULL;\r
+       }\r
+       else\r
+       {\r
+               /* Obtain the network buffer from the zero copy pointer. */\r
+               pucBuffer = ( uint8_t * ) pvBuffer;\r
+\r
+               /* The input here is a pointer to a payload buffer.  Subtract\r
+               the total size of a UDP/IP header plus the size of the header in\r
+               the network buffer, usually 8 + 2 bytes. */\r
+               pucBuffer -= ( sizeof( UDPPacket_t ) + ipBUFFER_PADDING );\r
+\r
+               /* Here a pointer was placed to the network descriptor,\r
+               As a pointer is dereferenced, make sure it is well aligned */\r
+               if( ( ( ( uint32_t ) pucBuffer ) & ( sizeof( pucBuffer ) - 1 ) ) == 0 )\r
+               {\r
+                       /* The following statement may trigger a:\r
+                       warning: cast increases required alignment of target type [-Wcast-align].\r
+                       It has been confirmed though that the alignment is suitable. */\r
+                       pxResult = * ( ( NetworkBufferDescriptor_t ** ) pucBuffer );\r
+               }\r
+               else\r
+               {\r
+                       pxResult = NULL;\r
+               }\r
+       }\r
+\r
+       return pxResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer )\r
+{\r
+       vReleaseNetworkBufferAndDescriptor( pxUDPPayloadBuffer_to_NetworkBuffer( pvBuffer ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*_RB_ Should we add an error or assert if the task priorities are set such that the servers won't function as expected? */\r
+/*_HT_ There was a bug in FreeRTOS_TCP_IP.c that only occurred when the applications' priority was too high.\r
+ As that bug has been repaired, there is not an urgent reason to warn.\r
+ It is better though to use the advised priority scheme. */\r
+BaseType_t FreeRTOS_IPInit( const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES ], const uint8_t ucNetMask[ ipIP_ADDRESS_LENGTH_BYTES ], const uint8_t ucGatewayAddress[ ipIP_ADDRESS_LENGTH_BYTES ], const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ], const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] )\r
+{\r
+BaseType_t xReturn = pdFALSE;\r
+\r
+       /* This function should only be called once. */\r
+       configASSERT( xIPIsNetworkTaskReady() == pdFALSE );\r
+       configASSERT( xNetworkEventQueue == NULL );\r
+       configASSERT( xIPTaskHandle == NULL );\r
+\r
+       /* Check structure packing is correct. */\r
+       configASSERT( sizeof( EthernetHeader_t ) == ipEXPECTED_EthernetHeader_t_SIZE );\r
+       configASSERT( sizeof( ARPHeader_t ) == ipEXPECTED_ARPHeader_t_SIZE );\r
+       configASSERT( sizeof( IPHeader_t ) == ipEXPECTED_IPHeader_t_SIZE );\r
+       configASSERT( sizeof( ICMPHeader_t ) == ipEXPECTED_ICMPHeader_t_SIZE );\r
+       configASSERT( sizeof( UDPHeader_t ) == ipEXPECTED_UDPHeader_t_SIZE );\r
+\r
+       /* Attempt to create the queue used to communicate with the IP task. */\r
+       xNetworkEventQueue = xQueueCreate( ( UBaseType_t ) ipconfigEVENT_QUEUE_LENGTH, ( UBaseType_t ) sizeof( IPStackEvent_t ) );\r
+       configASSERT( xNetworkEventQueue );\r
+\r
+       if( xNetworkEventQueue != NULL )\r
+       {\r
+               #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
+               {\r
+                       /* A queue registry is normally used to assist a kernel aware\r
+                       debugger.  If one is in use then it will be helpful for the debugger\r
+                       to show information about the network event queue. */\r
+                       vQueueAddToRegistry( xNetworkEventQueue, "NetEvnt" );\r
+               }\r
+               #endif /* configQUEUE_REGISTRY_SIZE */\r
+\r
+               if( xNetworkBuffersInitialise() == pdPASS )\r
+               {\r
+                       /* Store the local IP and MAC address. */\r
+                       xNetworkAddressing.ulDefaultIPAddress = FreeRTOS_inet_addr_quick( ucIPAddress[ 0 ], ucIPAddress[ 1 ], ucIPAddress[ 2 ], ucIPAddress[ 3 ] );\r
+                       xNetworkAddressing.ulNetMask = FreeRTOS_inet_addr_quick( ucNetMask[ 0 ], ucNetMask[ 1 ], ucNetMask[ 2 ], ucNetMask[ 3 ] );\r
+                       xNetworkAddressing.ulGatewayAddress = FreeRTOS_inet_addr_quick( ucGatewayAddress[ 0 ], ucGatewayAddress[ 1 ], ucGatewayAddress[ 2 ], ucGatewayAddress[ 3 ] );\r
+                       xNetworkAddressing.ulDNSServerAddress = FreeRTOS_inet_addr_quick( ucDNSServerAddress[ 0 ], ucDNSServerAddress[ 1 ], ucDNSServerAddress[ 2 ], ucDNSServerAddress[ 3 ] );\r
+                       xNetworkAddressing.ulBroadcastAddress = ( xNetworkAddressing.ulDefaultIPAddress & xNetworkAddressing.ulNetMask ) |  ~xNetworkAddressing.ulNetMask;\r
+\r
+                       memcpy( &xDefaultAddressing, &xNetworkAddressing, sizeof( xDefaultAddressing ) );\r
+\r
+                       #if ipconfigUSE_DHCP == 1\r
+                       {\r
+                               /* The IP address is not set until DHCP completes. */\r
+                               *ipLOCAL_IP_ADDRESS_POINTER = 0x00UL;\r
+                       }\r
+                       #else\r
+                       {\r
+                               /* The IP address is set from the value passed in. */\r
+                               *ipLOCAL_IP_ADDRESS_POINTER = xNetworkAddressing.ulDefaultIPAddress;\r
+\r
+                               /* Added to prevent ARP flood to gateway.  Ensure the\r
+                               gateway is on the same subnet as the IP address. */\r
+                               configASSERT( ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) == ( xNetworkAddressing.ulGatewayAddress & xNetworkAddressing.ulNetMask ) );\r
+                       }\r
+                       #endif /* ipconfigUSE_DHCP == 1 */\r
+\r
+                       /* The MAC address is stored in the start of the default packet\r
+                       header fragment, which is used when sending UDP packets. */\r
+                       memcpy( ( void * ) ipLOCAL_MAC_ADDRESS, ( void * ) ucMACAddress, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );\r
+\r
+                       /* Prepare the sockets interface. */\r
+                       vNetworkSocketsInit();\r
+\r
+                       /* Create the task that processes Ethernet and stack events. */\r
+                       xReturn = xTaskCreate( prvIPTask, "IP-task", ( uint16_t ) ipconfigIP_TASK_STACK_SIZE_WORDS, NULL, ( UBaseType_t ) ipconfigIP_TASK_PRIORITY, &xIPTaskHandle );\r
+               }\r
+               else\r
+               {\r
+                       FreeRTOS_debug_printf( ( "FreeRTOS_IPInit: xNetworkBuffersInitialise() failed\n") );\r
+\r
+                       /* Clean up. */\r
+                       vQueueDelete( xNetworkEventQueue );\r
+                       xNetworkEventQueue = NULL;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               FreeRTOS_debug_printf( ( "FreeRTOS_IPInit: Network event queue could not be created\n") );\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetMask, uint32_t *pulGatewayAddress, uint32_t *pulDNSServerAddress )\r
+{\r
+       /* Return the address configuration to the caller. */\r
+\r
+       if( pulIPAddress != NULL )\r
+       {\r
+               *pulIPAddress = *ipLOCAL_IP_ADDRESS_POINTER;\r
+       }\r
+\r
+       if( pulNetMask != NULL )\r
+       {\r
+               *pulNetMask = xNetworkAddressing.ulNetMask;\r
+       }\r
+\r
+       if( pulGatewayAddress != NULL )\r
+       {\r
+               *pulGatewayAddress = xNetworkAddressing.ulGatewayAddress;\r
+       }\r
+\r
+       if( pulDNSServerAddress != NULL )\r
+       {\r
+               *pulDNSServerAddress = xNetworkAddressing.ulDNSServerAddress;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint32_t *pulNetMask, const uint32_t *pulGatewayAddress, const uint32_t *pulDNSServerAddress )\r
+{\r
+       /* Update the address configuration. */\r
+\r
+       if( pulIPAddress != NULL )\r
+       {\r
+               *ipLOCAL_IP_ADDRESS_POINTER = *pulIPAddress;\r
+       }\r
+\r
+       if( pulNetMask != NULL )\r
+       {\r
+               xNetworkAddressing.ulNetMask = *pulNetMask;\r
+       }\r
+\r
+       if( pulGatewayAddress != NULL )\r
+       {\r
+               xNetworkAddressing.ulGatewayAddress = *pulGatewayAddress;\r
+       }\r
+\r
+       if( pulDNSServerAddress != NULL )\r
+       {\r
+               xNetworkAddressing.ulDNSServerAddress = *pulDNSServerAddress;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )\r
+\r
+       BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t xNumberOfBytesToSend, TickType_t xBlockTimeTicks )\r
+       {\r
+       NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+       ICMPHeader_t *pxICMPHeader;\r
+       BaseType_t xReturn = pdFAIL;\r
+       static uint16_t usSequenceNumber = 0;\r
+       uint8_t *pucChar;\r
+       IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };\r
+\r
+               if( (xNumberOfBytesToSend >= 1 ) && ( xNumberOfBytesToSend < ( ( ipconfigNETWORK_MTU - sizeof( IPHeader_t ) ) - sizeof( ICMPHeader_t ) ) ) && ( uxGetNumberOfFreeNetworkBuffers() >= 3 ) )\r
+               {\r
+                       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xNumberOfBytesToSend + sizeof( ICMPPacket_t ), xBlockTimeTicks );\r
+\r
+                       if( pxNetworkBuffer != NULL )\r
+                       {\r
+                               pxICMPHeader = ( ICMPHeader_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipIP_PAYLOAD_OFFSET ] );\r
+                               usSequenceNumber++;\r
+\r
+                               /* Fill in the basic header information. */\r
+                               pxICMPHeader->ucTypeOfMessage = ipICMP_ECHO_REQUEST;\r
+                               pxICMPHeader->ucTypeOfService = 0;\r
+                               pxICMPHeader->usIdentifier = usSequenceNumber;\r
+                               pxICMPHeader->usSequenceNumber = usSequenceNumber;\r
+\r
+                               /* Find the start of the data. */\r
+                               pucChar = ( uint8_t * ) pxICMPHeader;\r
+                               pucChar += sizeof( ICMPHeader_t );\r
+\r
+                               /* Just memset the data to a fixed value. */\r
+                               memset( ( void * ) pucChar, ( int ) ipECHO_DATA_FILL_BYTE, xNumberOfBytesToSend );\r
+\r
+                               /* The message is complete, IP and checksum's are handled by\r
+                               vProcessGeneratedUDPPacket */\r
+                               pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = FREERTOS_SO_UDPCKSUM_OUT;\r
+                               pxNetworkBuffer->ulIPAddress = ulIPAddress;\r
+                               pxNetworkBuffer->usPort = ipPACKET_CONTAINS_ICMP_DATA;\r
+                               pxNetworkBuffer->xDataLength = xNumberOfBytesToSend + sizeof( ICMPHeader_t );\r
+\r
+                               /* Send to the stack. */\r
+                               xStackTxEvent.pvData = pxNetworkBuffer;\r
+\r
+                               if( xSendEventStructToIPTask( &xStackTxEvent, xBlockTimeTicks) != pdPASS )\r
+                               {\r
+                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                                       iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );\r
+                               }\r
+                               else\r
+                               {\r
+                                       xReturn = usSequenceNumber;\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* The requested number of bytes will not fit in the available space\r
+                       in the network buffer. */\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_OUTGOING_PINGS == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xSendEventToIPTask( eIPEvent_t eEvent )\r
+{\r
+IPStackEvent_t xEventMessage;\r
+const TickType_t xDontBlock = ( TickType_t ) 0;\r
+\r
+       xEventMessage.eEventType = eEvent;\r
+       xEventMessage.pvData = ( void* )NULL;\r
+\r
+       return xSendEventStructToIPTask( &xEventMessage, xDontBlock );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t xTimeout )\r
+{\r
+BaseType_t xReturn, xSendMessage;\r
+\r
+       if( ( xIPIsNetworkTaskReady() == pdFALSE ) && ( pxEvent->eEventType != eNetworkDownEvent ) )\r
+       {\r
+               /* Only allow eNetworkDownEvent events if the IP task is not ready\r
+               yet.  Not going to attempt to send the message so the send failed. */\r
+               xReturn = pdFAIL;\r
+       }\r
+       else\r
+       {\r
+               xSendMessage = pdTRUE;\r
+\r
+               #if( ipconfigUSE_TCP == 1 )\r
+               {\r
+                       if( pxEvent->eEventType == eTCPTimerEvent )\r
+                       {\r
+                               /* TCP timer events are sent to wake the timer task when\r
+                               xTCPTimer has expired, but there is no point sending them if the\r
+                               IP task is already awake processing other message. */\r
+                               xTCPTimer.bExpired = pdTRUE_UNSIGNED;\r
+\r
+                               if( uxQueueMessagesWaiting( xNetworkEventQueue ) != 0u )\r
+                               {\r
+                                       /* Not actually going to send the message but this is not a\r
+                                       failure as the message didn't need to be sent. */\r
+                                       xSendMessage = pdFALSE;\r
+                               }\r
+                       }\r
+               }\r
+               #endif /* ipconfigUSE_TCP */\r
+\r
+               if( xSendMessage != pdFALSE )\r
+               {\r
+                       /* The IP task cannot block itself while waiting for itself to\r
+                       respond. */\r
+                       if( ( xIsCallingFromIPTask() == pdTRUE ) && ( xTimeout > ( TickType_t ) 0 ) )\r
+                       {\r
+                               xTimeout = ( TickType_t ) 0;\r
+                       }\r
+\r
+                       xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, xTimeout );\r
+\r
+                       if( xReturn == pdFAIL )\r
+                       {\r
+                               /* A message should have been sent to the IP task, but wasn't. */\r
+                               FreeRTOS_debug_printf( ( "xSendEventStructToIPTask: CAN NOT ADD %d\n", pxEvent->eEventType ) );\r
+                               iptraceSTACK_TX_EVENT_LOST( pxEvent->eEventType );\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* It was not necessary to send the message to process the event so\r
+                       even though the message was not sent the call was successful. */\r
+                       xReturn = pdPASS;\r
+               }\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucEthernetBuffer )\r
+{\r
+eFrameProcessingResult_t eReturn;\r
+const EthernetHeader_t *pxEthernetHeader;\r
+\r
+       pxEthernetHeader = ( const EthernetHeader_t * ) pucEthernetBuffer;\r
+\r
+       if( memcmp( ( void * ) ipLOCAL_MAC_ADDRESS, ( void * ) &( pxEthernetHeader->xDestinationAddress ), sizeof( MACAddress_t ) ) == 0 )\r
+       {\r
+               /* The packet was directed to this node directly - process it. */\r
+               eReturn = eProcessBuffer;\r
+       }\r
+       else if( memcmp( ( void * ) xBroadcastMACAddress.ucBytes, ( void * ) pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )\r
+       {\r
+               /* The packet was a broadcast - process it. */\r
+               eReturn = eProcessBuffer;\r
+       }\r
+       else\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       if( memcmp( ( void * ) xLLMNR_MacAdress.ucBytes, ( void * ) pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )\r
+       {\r
+               /* The packet is a request for LLMNR - process it. */\r
+               eReturn = eProcessBuffer;\r
+       }\r
+       else\r
+#endif /* ipconfigUSE_LLMNR */\r
+       {\r
+               /* The packet was not a broadcast, or for this node, just release\r
+               the buffer without taking any other action. */\r
+               eReturn = eReleaseBuffer;\r
+       }\r
+\r
+       #if( ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES == 1 )\r
+       {\r
+       uint16_t usFrameType;\r
+\r
+               if( eReturn == eProcessBuffer )\r
+               {\r
+                       usFrameType = pxEthernetHeader->usFrameType;\r
+                       usFrameType = FreeRTOS_ntohs( usFrameType );\r
+\r
+                       if( usFrameType <= 0x600U )\r
+                       {\r
+                               /* Not an Ethernet II frame. */\r
+                               eReturn = eReleaseBuffer;\r
+                       }\r
+               }\r
+       }\r
+       #endif /* ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES == 1  */\r
+\r
+       return eReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvProcessNetworkDownEvent( void )\r
+{\r
+       /* Stop the ARP timer while there is no network. */\r
+       xARPTimer.bActive = pdFALSE_UNSIGNED;\r
+\r
+       #if ipconfigUSE_NETWORK_EVENT_HOOK == 1\r
+       {\r
+               static BaseType_t xCallEventHook = pdFALSE;\r
+\r
+               /* The first network down event is generated by the IP stack itself to\r
+               initialise the network hardware, so do not call the network down event\r
+               the first time through. */\r
+               if( xCallEventHook == pdTRUE )\r
+               {\r
+                       vApplicationIPNetworkEventHook( eNetworkDown );\r
+               }\r
+               xCallEventHook = pdTRUE;\r
+       }\r
+       #endif\r
+\r
+       /* The network has been disconnected (or is being initialised for the first\r
+       time).  Perform whatever hardware processing is necessary to bring it up\r
+       again, or wait for it to be available again.  This is hardware dependent. */\r
+       if( xNetworkInterfaceInitialise() != pdPASS )\r
+       {\r
+               /* Ideally the network interface initialisation function will only\r
+               return when the network is available.  In case this is not the case,\r
+               wait a while before retrying the initialisation. */\r
+               vTaskDelay( ipINITIALISATION_RETRY_DELAY );\r
+               FreeRTOS_NetworkDown();\r
+       }\r
+       else\r
+       {\r
+               /* Set remaining time to 0 so it will become active immediately. */\r
+               #if ipconfigUSE_DHCP == 1\r
+               {\r
+                       /* The network is not up until DHCP has completed. */\r
+                       vDHCPProcess( pdTRUE );\r
+                       xSendEventToIPTask( eDHCPEvent );\r
+               }\r
+               #else\r
+               {\r
+                       /* Perform any necessary 'network up' processing. */\r
+                       vIPNetworkUpCalls();\r
+               }\r
+               #endif\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vIPNetworkUpCalls( void )\r
+{\r
+       xNetworkUp = pdTRUE;\r
+\r
+       #if( ipconfigUSE_NETWORK_EVENT_HOOK == 1 )\r
+       {\r
+               vApplicationIPNetworkEventHook( eNetworkUp );\r
+       }\r
+       #endif /* ipconfigUSE_NETWORK_EVENT_HOOK */\r
+\r
+       #if( ipconfigDNS_USE_CALLBACKS != 0 )\r
+       {\r
+               /* The following function is declared in FreeRTOS_DNS.c and 'private' to\r
+               this library */\r
+               extern void vDNSInitialise( void );\r
+               vDNSInitialise();\r
+       }\r
+       #endif /* ipconfigDNS_USE_CALLBACKS != 0 */\r
+\r
+       /* Set remaining time to 0 so it will become active immediately. */\r
+       prvIPTimerReload( &xARPTimer, pdMS_TO_TICKS( ipARP_TIMER_PERIOD_MS ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+EthernetHeader_t *pxEthernetHeader;\r
+volatile eFrameProcessingResult_t eReturned; /* Volatile to prevent complier warnings when ipCONSIDER_FRAME_FOR_PROCESSING just sets it to eProcessBuffer. */\r
+\r
+       configASSERT( pxNetworkBuffer );\r
+\r
+       /* Interpret the Ethernet frame. */\r
+       eReturned = ipCONSIDER_FRAME_FOR_PROCESSING( pxNetworkBuffer->pucEthernetBuffer );\r
+       pxEthernetHeader = ( EthernetHeader_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+\r
+       if( eReturned == eProcessBuffer )\r
+       {\r
+               /* Interpret the received Ethernet packet. */\r
+               switch( pxEthernetHeader->usFrameType )\r
+               {\r
+                       case ipARP_FRAME_TYPE :\r
+                               /* The Ethernet frame contains an ARP packet. */\r
+                               eReturned = eARPProcessPacket( ( ARPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer );\r
+                               break;\r
+\r
+                       case ipIPv4_FRAME_TYPE :\r
+                               /* The Ethernet frame contains an IP packet. */\r
+                               eReturned = prvProcessIPPacket( ( IPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer );\r
+                               break;\r
+\r
+                       default :\r
+                               /* No other packet types are handled.  Nothing to do. */\r
+                               eReturned = eReleaseBuffer;\r
+                               break;\r
+               }\r
+       }\r
+\r
+       /* Perform any actions that resulted from processing the Ethernet frame. */\r
+       switch( eReturned )\r
+       {\r
+               case eReturnEthernetFrame :\r
+                       /* The Ethernet frame will have been updated (maybe it was\r
+                       an ARP request or a PING request?) and should be sent back to\r
+                       its source. */\r
+                       vReturnEthernetFrame( pxNetworkBuffer, pdTRUE );\r
+                       /* parameter pdTRUE: the buffer must be released once\r
+                       the frame has been transmitted */\r
+                       break;\r
+\r
+               case eFrameConsumed :\r
+                       /* The frame is in use somewhere, don't release the buffer\r
+                       yet. */\r
+                       break;\r
+\r
+               default :\r
+                       /* The frame is not being used anywhere, and the\r
+                       NetworkBufferDescriptor_t structure containing the frame should\r
+                       just be released back to the list of free buffers. */\r
+                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                       break;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPPacket,\r
+       NetworkBufferDescriptor_t * const pxNetworkBuffer, UBaseType_t uxHeaderLength )\r
+{\r
+eFrameProcessingResult_t eReturn = eProcessBuffer;\r
+\r
+#if( ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) )\r
+       const IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );\r
+#else\r
+       /* or else, the parameter won't be used and the function will be optimised\r
+       away */\r
+       ( void ) pxIPPacket;\r
+#endif\r
+\r
+       #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 )\r
+       {\r
+               /* In systems with a very small amount of RAM, it might be advantageous\r
+               to have incoming messages checked earlier, by the network card driver.\r
+               This method may decrease the usage of sparse network buffers. */\r
+               uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;\r
+\r
+                       /* Ensure that the incoming packet is not fragmented (fragmentation\r
+                       was only supported for outgoing packets, and is not currently\r
+                       not supported at all). */\r
+                       if( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U )\r
+                       {\r
+                               /* Can not handle, fragmented packet. */\r
+                               eReturn = eReleaseBuffer;\r
+                       }\r
+                       /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes\r
+                        * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */\r
+                       else if( ( pxIPHeader->ucVersionHeaderLength < 0x45u ) || ( pxIPHeader->ucVersionHeaderLength > 0x4Fu ) )\r
+                       {\r
+                               /* Can not handle, unknown or invalid header version. */\r
+                               eReturn = eReleaseBuffer;\r
+                       }\r
+                               /* Is the packet for this IP address? */\r
+                       else if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&\r
+                               /* Is it the global broadcast address 255.255.255.255 ? */\r
+                               ( ulDestinationIPAddress != ipBROADCAST_IP_ADDRESS ) &&\r
+                               /* Is it a specific broadcast address 192.168.1.255 ? */\r
+                               ( ulDestinationIPAddress != xNetworkAddressing.ulBroadcastAddress ) &&\r
+                       #if( ipconfigUSE_LLMNR == 1 )\r
+                               /* Is it the LLMNR multicast address? */\r
+                               ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&\r
+                       #endif\r
+                               /* Or (during DHCP negotiation) we have no IP-address yet? */\r
+                               ( *ipLOCAL_IP_ADDRESS_POINTER != 0UL ) )\r
+                       {\r
+                               /* Packet is not for this node, release it */\r
+                               eReturn = eReleaseBuffer;\r
+                       }\r
+       }\r
+       #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
+\r
+       #if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 )\r
+       {\r
+               /* Some drivers of NIC's with checksum-offloading will enable the above\r
+               define, so that the checksum won't be checked again here */\r
+               if (eReturn == eProcessBuffer )\r
+               {\r
+                       /* Is the IP header checksum correct? */\r
+                       if( ( pxIPHeader->ucProtocol != ( uint8_t ) ipPROTOCOL_ICMP ) &&\r
+                               ( usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength ) != ipCORRECT_CRC ) )\r
+                       {\r
+                               /* Check sum in IP-header not correct. */\r
+                               eReturn = eReleaseBuffer;\r
+                       }\r
+                       /* Is the upper-layer checksum (TCP/UDP/ICMP) correct? */\r
+                       else if( usGenerateProtocolChecksum( ( uint8_t * )( pxNetworkBuffer->pucEthernetBuffer ), pdFALSE ) != ipCORRECT_CRC )\r
+                       {\r
+                               /* Protocol checksum not accepted. */\r
+                               eReturn = eReleaseBuffer;\r
+                       }\r
+               }\r
+       }\r
+       #else\r
+       {\r
+               /* to avoid warning unused parameters */\r
+               ( void ) pxNetworkBuffer;\r
+               ( void ) uxHeaderLength;\r
+       }\r
+       #endif /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 */\r
+\r
+       return eReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static eFrameProcessingResult_t prvProcessIPPacket( const IPPacket_t * const pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+eFrameProcessingResult_t eReturn;\r
+const IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );\r
+UBaseType_t uxHeaderLength = ( UBaseType_t ) ( ( pxIPHeader->ucVersionHeaderLength & 0x0Fu ) << 2 );\r
+uint8_t ucProtocol;\r
+\r
+       ucProtocol = pxIPPacket->xIPHeader.ucProtocol;\r
+       /* Check if the IP headers are acceptable and if it has our destination. */\r
+       eReturn = prvAllowIPPacket( pxIPPacket, pxNetworkBuffer, uxHeaderLength );\r
+\r
+       if( eReturn == eProcessBuffer )\r
+       {\r
+               if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )\r
+               {\r
+                       /* All structs of headers expect a IP header size of 20 bytes\r
+                        * IP header options were included, we'll ignore them and cut them out\r
+                        * Note: IP options are mostly use in Multi-cast protocols */\r
+                       const size_t optlen = ( ( size_t ) uxHeaderLength ) - ipSIZE_OF_IPv4_HEADER;\r
+                       /* From: the previous start of UDP/ICMP/TCP data */\r
+                       uint8_t *pucSource = ( ( uint8_t * ) pxIPHeader ) + uxHeaderLength;\r
+                       /* To: the usual start of UDP/ICMP/TCP data at offset 20 from IP header */\r
+                       uint8_t *pucTarget = ( ( uint8_t * ) pxIPHeader ) + ipSIZE_OF_IPv4_HEADER;\r
+                       /* How many: total length minus the options and the lower headers */\r
+                       const size_t  xMoveLen = pxNetworkBuffer->xDataLength - optlen - ipSIZE_OF_IPv4_HEADER - ipSIZE_OF_ETH_HEADER;\r
+\r
+                       memmove( pucTarget, pucSource, xMoveLen );\r
+                       pxNetworkBuffer->xDataLength -= optlen;\r
+               }\r
+               /* Add the IP and MAC addresses to the ARP table if they are not\r
+               already there - otherwise refresh the age of the existing\r
+               entry. */\r
+               if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP )\r
+               {\r
+                       /* Refresh the ARP cache with the IP/MAC-address of the received packet\r
+                        * For UDP packets, this will be done later in xProcessReceivedUDPPacket()\r
+                        * as soon as know that the message will be handled by someone\r
+                        * This will prevent that the ARP cache will get overwritten\r
+                        * with the IP-address of useless broadcast packets\r
+                        */\r
+                       vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress );\r
+               }\r
+               switch( ucProtocol )\r
+               {\r
+                       case ipPROTOCOL_ICMP :\r
+                               /* The IP packet contained an ICMP frame.  Don't bother\r
+                               checking the ICMP checksum, as if it is wrong then the\r
+                               wrong data will also be returned, and the source of the\r
+                               ping will know something went wrong because it will not\r
+                               be able to validate what it receives. */\r
+                               #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )\r
+                               {\r
+                                       ICMPPacket_t *pxICMPPacket = ( ICMPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+                                       if( pxIPHeader->ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )\r
+                                       {\r
+                                               eReturn = prvProcessICMPPacket( pxICMPPacket );\r
+                                       }\r
+                               }\r
+                               #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */\r
+                               break;\r
+\r
+                       case ipPROTOCOL_UDP :\r
+                               {\r
+                                       /* The IP packet contained a UDP frame. */\r
+                                       UDPPacket_t *pxUDPPacket = ( UDPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+\r
+                                       /* Note the header values required prior to the\r
+                                       checksum generation as the checksum pseudo header\r
+                                       may clobber some of these values. */\r
+                                       pxNetworkBuffer->xDataLength = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) - sizeof( UDPHeader_t );\r
+                                       /* HT:endian: fields in pxNetworkBuffer (usPort, ulIPAddress) were network order */\r
+                                       pxNetworkBuffer->usPort = pxUDPPacket->xUDPHeader.usSourcePort;\r
+                                       pxNetworkBuffer->ulIPAddress = pxUDPPacket->xIPHeader.ulSourceIPAddress;\r
+\r
+                                       /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM:\r
+                                        * In some cases, the upper-layer checksum has been calculated\r
+                                        * by the NIC driver */\r
+                                       /* Pass the packet payload to the UDP sockets implementation. */\r
+                                       /* HT:endian: xProcessReceivedUDPPacket wanted network order */\r
+                                       if( xProcessReceivedUDPPacket( pxNetworkBuffer, pxUDPPacket->xUDPHeader.usDestinationPort ) == pdPASS )\r
+                                       {\r
+                                               eReturn = eFrameConsumed;\r
+                                       }\r
+                               }\r
+                               break;\r
+\r
+#if ipconfigUSE_TCP == 1\r
+                       case ipPROTOCOL_TCP :\r
+                               {\r
+\r
+                                       if( xProcessReceivedTCPPacket( pxNetworkBuffer ) == pdPASS )\r
+                                       {\r
+                                               eReturn = eFrameConsumed;\r
+                                       }\r
+\r
+                                       /* Setting this variable will cause xTCPTimerCheck()\r
+                                       to be called just before the IP-task blocks. */\r
+                                       xProcessedTCPMessage++;\r
+                               }\r
+                               break;\r
+#endif\r
+                       default :\r
+                               /* Not a supported frame type. */\r
+                               break;\r
+               }\r
+       }\r
+\r
+       return eReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )\r
+\r
+       static void prvProcessICMPEchoReply( ICMPPacket_t * const pxICMPPacket )\r
+       {\r
+       ePingReplyStatus_t eStatus = eSuccess;\r
+       uint16_t usDataLength, usCount;\r
+       uint8_t *pucByte;\r
+\r
+               /* Find the total length of the IP packet. */\r
+               usDataLength = pxICMPPacket->xIPHeader.usLength;\r
+               usDataLength = FreeRTOS_ntohs( usDataLength );\r
+\r
+               /* Remove the length of the IP headers to obtain the length of the ICMP\r
+               message itself. */\r
+               usDataLength = ( uint16_t ) ( ( ( uint32_t ) usDataLength ) - ipSIZE_OF_IPv4_HEADER );\r
+\r
+               /* Remove the length of the ICMP header, to obtain the length of\r
+               data contained in the ping. */\r
+               usDataLength = ( uint16_t ) ( ( ( uint32_t ) usDataLength ) - ipSIZE_OF_ICMP_HEADER );\r
+\r
+               /* Checksum has already been checked before in prvProcessIPPacket */\r
+\r
+               /* Find the first byte of the data within the ICMP packet. */\r
+               pucByte = ( uint8_t * ) pxICMPPacket;\r
+               pucByte += sizeof( ICMPPacket_t );\r
+\r
+               /* Check each byte. */\r
+               for( usCount = 0; usCount < usDataLength; usCount++ )\r
+               {\r
+                       if( *pucByte != ipECHO_DATA_FILL_BYTE )\r
+                       {\r
+                               eStatus = eInvalidData;\r
+                               break;\r
+                       }\r
+\r
+                       pucByte++;\r
+               }\r
+\r
+               /* Call back into the application to pass it the result. */\r
+               vApplicationPingReplyHook( eStatus, pxICMPPacket->xICMPHeader.usIdentifier );\r
+       }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 )\r
+\r
+       static eFrameProcessingResult_t prvProcessICMPEchoRequest( ICMPPacket_t * const pxICMPPacket )\r
+       {\r
+       ICMPHeader_t *pxICMPHeader;\r
+       IPHeader_t *pxIPHeader;\r
+       uint16_t usRequest;\r
+\r
+               pxICMPHeader = &( pxICMPPacket->xICMPHeader );\r
+               pxIPHeader = &( pxICMPPacket->xIPHeader );\r
+\r
+               /* HT:endian: changed back */\r
+               iptraceSENDING_PING_REPLY( pxIPHeader->ulSourceIPAddress );\r
+\r
+               /* The checksum can be checked here - but a ping reply should be\r
+               returned even if the checksum is incorrect so the other end can\r
+               tell that the ping was received - even if the ping reply contains\r
+               invalid data. */\r
+               pxICMPHeader->ucTypeOfMessage = ( uint8_t ) ipICMP_ECHO_REPLY;\r
+               pxIPHeader->ulDestinationIPAddress = pxIPHeader->ulSourceIPAddress;\r
+               pxIPHeader->ulSourceIPAddress = *ipLOCAL_IP_ADDRESS_POINTER;\r
+\r
+               /* Update the checksum because the ucTypeOfMessage member in the header\r
+               has been changed to ipICMP_ECHO_REPLY.  This is faster than calling\r
+               usGenerateChecksum(). */\r
+\r
+               /* due to compiler warning "integer operation result is out of range" */\r
+\r
+               usRequest = ( uint16_t ) ( ( uint16_t )ipICMP_ECHO_REQUEST << 8 );\r
+\r
+               if( pxICMPHeader->usChecksum >= FreeRTOS_htons( 0xFFFFu - usRequest ) )\r
+               {\r
+                       pxICMPHeader->usChecksum = ( uint16_t )\r
+                               ( ( ( uint32_t ) pxICMPHeader->usChecksum ) +\r
+                                       FreeRTOS_htons( usRequest + 1UL ) );\r
+               }\r
+               else\r
+               {\r
+                       pxICMPHeader->usChecksum = ( uint16_t )\r
+                               ( ( ( uint32_t ) pxICMPHeader->usChecksum ) +\r
+                                       FreeRTOS_htons( usRequest ) );\r
+               }\r
+               return eReturnEthernetFrame;\r
+       }\r
+\r
+#endif /* ipconfigREPLY_TO_INCOMING_PINGS == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )\r
+\r
+       static eFrameProcessingResult_t prvProcessICMPPacket( ICMPPacket_t * const pxICMPPacket )\r
+       {\r
+       eFrameProcessingResult_t eReturn = eReleaseBuffer;\r
+\r
+               iptraceICMP_PACKET_RECEIVED();\r
+               switch( pxICMPPacket->xICMPHeader.ucTypeOfMessage )\r
+               {\r
+                       case ipICMP_ECHO_REQUEST        :\r
+                               #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 )\r
+                               {\r
+                                       eReturn = prvProcessICMPEchoRequest( pxICMPPacket );\r
+                               }\r
+                               #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) */\r
+                               break;\r
+\r
+                       case ipICMP_ECHO_REPLY          :\r
+                               #if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )\r
+                               {\r
+                                       prvProcessICMPEchoReply( pxICMPPacket );\r
+                               }\r
+                               #endif /* ipconfigSUPPORT_OUTGOING_PINGS */\r
+                               break;\r
+\r
+                       default :\r
+                               break;\r
+               }\r
+\r
+               return eReturn;\r
+       }\r
+\r
+#endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */\r
+/*-----------------------------------------------------------*/\r
+\r
+uint16_t usGenerateProtocolChecksum( const uint8_t * const pucEthernetBuffer, BaseType_t xOutgoingPacket )\r
+{\r
+uint32_t ulLength;\r
+uint16_t usChecksum, *pusChecksum;\r
+const IPPacket_t * pxIPPacket;\r
+UBaseType_t uxIPHeaderLength;\r
+ProtocolPacket_t *pxProtPack;\r
+uint8_t ucProtocol;\r
+#if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+       const char *pcType;\r
+#endif\r
+\r
+       pxIPPacket = ( const IPPacket_t * ) pucEthernetBuffer;\r
+       uxIPHeaderLength = ( UBaseType_t ) ( 4u * ( pxIPPacket->xIPHeader.ucVersionHeaderLength & 0x0Fu ) ); /*_RB_ Why 4? */\r
+       pxProtPack = ( ProtocolPacket_t * ) ( pucEthernetBuffer + ( uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ) );\r
+       ucProtocol = pxIPPacket->xIPHeader.ucProtocol;\r
+\r
+       if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )\r
+       {\r
+               pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );\r
+               #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+               {\r
+                       pcType = "UDP";\r
+               }\r
+               #endif  /* ipconfigHAS_DEBUG_PRINTF != 0 */\r
+       }\r
+       else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )\r
+       {\r
+               pusChecksum = ( uint16_t * ) ( &( pxProtPack->xTCPPacket.xTCPHeader.usChecksum ) );\r
+               #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+               {\r
+                       pcType = "TCP";\r
+               }\r
+               #endif  /* ipconfigHAS_DEBUG_PRINTF != 0 */\r
+       }\r
+       else if( ( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) ||\r
+                       ( ucProtocol == ( uint8_t ) ipPROTOCOL_IGMP ) )\r
+       {\r
+               pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) );\r
+\r
+               #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+               {\r
+                       if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )\r
+                       {\r
+                               pcType = "ICMP";\r
+                       }\r
+                       else\r
+                       {\r
+                               pcType = "IGMP";\r
+                       }\r
+               }\r
+               #endif  /* ipconfigHAS_DEBUG_PRINTF != 0 */\r
+       }\r
+       else\r
+       {\r
+               /* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */\r
+               return ipUNHANDLED_PROTOCOL;\r
+       }\r
+\r
+       if( xOutgoingPacket != pdFALSE )\r
+       {\r
+               /* This is an outgoing packet. Before calculating the checksum, set it\r
+               to zero. */\r
+               *( pusChecksum ) = 0u;\r
+       }\r
+       else if( ( *pusChecksum == 0u ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )\r
+       {\r
+               /* Sender hasn't set the checksum, no use to calculate it. */\r
+               return ipCORRECT_CRC;\r
+       }\r
+\r
+       ulLength = ( uint32_t )\r
+               ( FreeRTOS_ntohs( pxIPPacket->xIPHeader.usLength ) - ( ( uint16_t ) uxIPHeaderLength ) ); /* normally minus 20 */\r
+\r
+       if( ( ulLength < sizeof( pxProtPack->xUDPPacket.xUDPHeader ) ) ||\r
+               ( ulLength > ( uint32_t )( ipconfigNETWORK_MTU - uxIPHeaderLength ) ) )\r
+       {\r
+               #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: len invalid: %lu\n", pcType, ulLength ) );\r
+               }\r
+               #endif  /* ipconfigHAS_DEBUG_PRINTF != 0 */\r
+\r
+               /* Again, in a 16-bit return value there is no space to indicate an\r
+               error.  For incoming packets, 0x1234 will cause dropping of the packet.\r
+               For outgoing packets, there is a serious problem with the\r
+               format/length */\r
+               return ipINVALID_LENGTH;\r
+       }\r
+       if( ucProtocol <= ( uint8_t ) ipPROTOCOL_IGMP )\r
+       {\r
+               /* ICMP/IGMP do not have a pseudo header for CRC-calculation. */\r
+               usChecksum = ( uint16_t )\r
+                       ( ~usGenerateChecksum( 0UL,\r
+                               ( uint8_t * ) &( pxProtPack->xTCPPacket.xTCPHeader ), ( size_t ) ulLength ) );\r
+       }\r
+       else\r
+       {\r
+               /* For UDP and TCP, sum the pseudo header, i.e. IP protocol + length\r
+               fields */\r
+               usChecksum = ( uint16_t ) ( ulLength + ( ( uint16_t ) ucProtocol ) );\r
+\r
+               /* And then continue at the IPv4 source and destination addresses. */\r
+               usChecksum = ( uint16_t )\r
+                       ( ~usGenerateChecksum( ( uint32_t ) usChecksum, ( uint8_t * )&( pxIPPacket->xIPHeader.ulSourceIPAddress ),\r
+                               ( size_t )( 2u * sizeof( pxIPPacket->xIPHeader.ulSourceIPAddress ) + ulLength ) ) );\r
+\r
+               /* Sum TCP header and data. */\r
+       }\r
+\r
+       if( xOutgoingPacket == pdFALSE )\r
+       {\r
+               /* This is in incoming packet. If the CRC is correct, it should be zero. */\r
+               if( usChecksum == 0u )\r
+               {\r
+                       usChecksum = ( uint16_t )ipCORRECT_CRC;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if( ( usChecksum == 0u ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )\r
+               {\r
+                       /* In case of UDP, a calculated checksum of 0x0000 is transmitted\r
+                       as 0xffff. A value of zero would mean that the checksum is not used. */\r
+                       #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+                       {\r
+                               if( xOutgoingPacket != pdFALSE )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) );\r
+                               }\r
+                       }\r
+                       #endif  /* ipconfigHAS_DEBUG_PRINTF != 0 */\r
+\r
+                       usChecksum = ( uint16_t )0xffffu;\r
+               }\r
+       }\r
+       usChecksum = FreeRTOS_htons( usChecksum );\r
+\r
+       if( xOutgoingPacket != pdFALSE )\r
+       {\r
+               *( pusChecksum ) = usChecksum;\r
+       }\r
+       #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+       else if( ( xOutgoingPacket == pdFALSE ) && ( usChecksum != ipCORRECT_CRC ) )\r
+       {\r
+               FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: ID %04X: from %lxip to %lxip bad crc: %04X\n",\r
+                       pcType,\r
+                       FreeRTOS_ntohs( pxIPPacket->xIPHeader.usIdentification ),\r
+                       FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ),\r
+                       FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulDestinationIPAddress ),\r
+                       FreeRTOS_ntohs( *pusChecksum ) ) );\r
+       }\r
+       #endif  /* ipconfigHAS_DEBUG_PRINTF != 0 */\r
+\r
+       return usChecksum;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+uint16_t usGenerateChecksum( uint32_t ulSum, const uint8_t * pucNextData, size_t uxDataLengthBytes )\r
+{\r
+xUnion32 xSum2, xSum, xTerm;\r
+xUnionPtr xSource;             /* Points to first byte */\r
+xUnionPtr xLastSource; /* Points to last byte plus one */\r
+uint32_t ulAlignBits, ulCarry = 0ul;\r
+\r
+       /* Small MCUs often spend up to 30% of the time doing checksum calculations\r
+       This function is optimised for 32-bit CPUs; Each time it will try to fetch\r
+       32-bits, sums it with an accumulator and counts the number of carries. */\r
+\r
+       /* Swap the input (little endian platform only). */\r
+       xSum.u32 = FreeRTOS_ntohs( ulSum );\r
+       xTerm.u32 = 0ul;\r
+\r
+       xSource.u8ptr = ( uint8_t * ) pucNextData;\r
+       ulAlignBits = ( ( ( uint32_t ) pucNextData ) & 0x03u ); /* gives 0, 1, 2, or 3 */\r
+\r
+       /* If byte (8-bit) aligned... */\r
+       if( ( ( ulAlignBits & 1ul ) != 0ul ) && ( uxDataLengthBytes >= ( size_t ) 1 ) )\r
+       {\r
+               xTerm.u8[ 1 ] = *( xSource.u8ptr );\r
+               ( xSource.u8ptr )++;\r
+               uxDataLengthBytes--;\r
+               /* Now xSource is word (16-bit) aligned. */\r
+       }\r
+\r
+       /* If half-word (16-bit) aligned... */\r
+       if( ( ( ulAlignBits == 1u ) || ( ulAlignBits == 2u ) ) && ( uxDataLengthBytes >= 2u ) )\r
+       {\r
+               xSum.u32 += *(xSource.u16ptr);\r
+               ( xSource.u16ptr )++;\r
+               uxDataLengthBytes -= 2u;\r
+               /* Now xSource is word (32-bit) aligned. */\r
+       }\r
+\r
+       /* Word (32-bit) aligned, do the most part. */\r
+       xLastSource.u32ptr = ( xSource.u32ptr + ( uxDataLengthBytes / 4u ) ) - 3u;\r
+\r
+       /* In this loop, four 32-bit additions will be done, in total 16 bytes.\r
+       Indexing with constants (0,1,2,3) gives faster code than using\r
+       post-increments. */\r
+       while( xSource.u32ptr < xLastSource.u32ptr )\r
+       {\r
+               /* Use a secondary Sum2, just to see if the addition produced an\r
+               overflow. */\r
+               xSum2.u32 = xSum.u32 + xSource.u32ptr[ 0 ];\r
+               if( xSum2.u32 < xSum.u32 )\r
+               {\r
+                       ulCarry++;\r
+               }\r
+\r
+               /* Now add the secondary sum to the major sum, and remember if there was\r
+               a carry. */\r
+               xSum.u32 = xSum2.u32 + xSource.u32ptr[ 1 ];\r
+               if( xSum2.u32 > xSum.u32 )\r
+               {\r
+                       ulCarry++;\r
+               }\r
+\r
+               /* And do the same trick once again for indexes 2 and 3 */\r
+               xSum2.u32 = xSum.u32 + xSource.u32ptr[ 2 ];\r
+               if( xSum2.u32 < xSum.u32 )\r
+               {\r
+                       ulCarry++;\r
+               }\r
+\r
+               xSum.u32 = xSum2.u32 + xSource.u32ptr[ 3 ];\r
+\r
+               if( xSum2.u32 > xSum.u32 )\r
+               {\r
+                       ulCarry++;\r
+               }\r
+\r
+               /* And finally advance the pointer 4 * 4 = 16 bytes. */\r
+               xSource.u32ptr += 4;\r
+       }\r
+\r
+       /* Now add all carries. */\r
+       xSum.u32 = ( uint32_t )xSum.u16[ 0 ] + xSum.u16[ 1 ] + ulCarry;\r
+\r
+       uxDataLengthBytes %= 16u;\r
+       xLastSource.u8ptr = ( uint8_t * ) ( xSource.u8ptr + ( uxDataLengthBytes & ~( ( size_t ) 1 ) ) );\r
+\r
+       /* Half-word aligned. */\r
+       while( xSource.u16ptr < xLastSource.u16ptr )\r
+       {\r
+               /* At least one more short. */\r
+               xSum.u32 += xSource.u16ptr[ 0 ];\r
+               xSource.u16ptr++;\r
+       }\r
+\r
+       if( ( uxDataLengthBytes & ( size_t ) 1 ) != 0u )        /* Maybe one more ? */\r
+       {\r
+               xTerm.u8[ 0 ] = xSource.u8ptr[ 0 ];\r
+       }\r
+       xSum.u32 += xTerm.u32;\r
+\r
+       /* Now add all carries again. */\r
+       xSum.u32 = ( uint32_t ) xSum.u16[ 0 ] + xSum.u16[ 1 ];\r
+\r
+       /* The previous summation might have given a 16-bit carry. */\r
+       xSum.u32 = ( uint32_t ) xSum.u16[ 0 ] + xSum.u16[ 1 ];\r
+\r
+       if( ( ulAlignBits & 1u ) != 0u )\r
+       {\r
+               /* Quite unlikely, but pucNextData might be non-aligned, which would\r
+                mean that a checksum is calculated starting at an odd position. */\r
+               xSum.u32 = ( ( xSum.u32 & 0xffu ) << 8 ) | ( ( xSum.u32 & 0xff00u ) >> 8 );\r
+       }\r
+\r
+       /* swap the output (little endian platform only). */\r
+       return FreeRTOS_htons( ( (uint16_t) xSum.u32 ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType_t xReleaseAfterSend )\r
+{\r
+EthernetHeader_t *pxEthernetHeader;\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       NetworkBufferDescriptor_t *pxNewBuffer;\r
+#endif\r
+\r
+       #if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
+       {\r
+               if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
+               {\r
+               BaseType_t xIndex;\r
+\r
+                       FreeRTOS_printf( ( "vReturnEthernetFrame: length %lu\n", ( uint32_t )pxNetworkBuffer->xDataLength ) );\r
+                       for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )\r
+                       {\r
+                               pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;\r
+                       }\r
+                       pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;\r
+               }\r
+       }\r
+       #endif\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+\r
+       if( xReleaseAfterSend == pdFALSE )\r
+       {\r
+               pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, ( BaseType_t ) pxNetworkBuffer->xDataLength );\r
+               xReleaseAfterSend = pdTRUE;\r
+               pxNetworkBuffer = pxNewBuffer;\r
+       }\r
+\r
+       if( pxNetworkBuffer != NULL )\r
+#endif\r
+       {\r
+               pxEthernetHeader = ( EthernetHeader_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+\r
+               /* Swap source and destination MAC addresses. */\r
+               memcpy( ( void * ) &( pxEthernetHeader->xDestinationAddress ), ( void * ) &( pxEthernetHeader->xSourceAddress ), sizeof( pxEthernetHeader->xDestinationAddress ) );\r
+               memcpy( ( void * ) &( pxEthernetHeader->xSourceAddress) , ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );\r
+\r
+               /* Send! */\r
+               xNetworkInterfaceOutput( pxNetworkBuffer, xReleaseAfterSend );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+uint32_t FreeRTOS_GetIPAddress( void )\r
+{\r
+       /* Returns the IP address of the NIC. */\r
+       return *ipLOCAL_IP_ADDRESS_POINTER;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FreeRTOS_SetIPAddress( uint32_t ulIPAddress )\r
+{\r
+       /* Sets the IP address of the NIC. */\r
+       *ipLOCAL_IP_ADDRESS_POINTER = ulIPAddress;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+uint32_t FreeRTOS_GetGatewayAddress( void )\r
+{\r
+       return xNetworkAddressing.ulGatewayAddress;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+uint32_t FreeRTOS_GetDNSServerAddress( void )\r
+{\r
+       return xNetworkAddressing.ulDNSServerAddress;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+uint32_t FreeRTOS_GetNetmask( void )\r
+{\r
+       return xNetworkAddressing.ulNetMask;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+const uint8_t * FreeRTOS_GetMACAddress( void )\r
+{\r
+       return ipLOCAL_MAC_ADDRESS;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FreeRTOS_SetNetmask ( uint32_t ulNetmask )\r
+{\r
+       xNetworkAddressing.ulNetMask = ulNetmask;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FreeRTOS_SetGatewayAddress ( uint32_t ulGatewayAddress )\r
+{\r
+       xNetworkAddressing.ulGatewayAddress = ulGatewayAddress;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_DHCP == 1 )\r
+       void vIPSetDHCPTimerEnableState( BaseType_t xEnableState )\r
+       {\r
+               if( xEnableState != pdFALSE )\r
+               {\r
+                       xDHCPTimer.bActive = pdTRUE_UNSIGNED;\r
+               }\r
+               else\r
+               {\r
+                       xDHCPTimer.bActive = pdFALSE_UNSIGNED;\r
+               }\r
+       }\r
+#endif /* ipconfigUSE_DHCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_DHCP == 1 )\r
+       void vIPReloadDHCPTimer( uint32_t ulLeaseTime )\r
+       {\r
+               prvIPTimerReload( &xDHCPTimer, ulLeaseTime );\r
+       }\r
+#endif /* ipconfigUSE_DHCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigDNS_USE_CALLBACKS == 1 )\r
+       void vIPSetDnsTimerEnableState( BaseType_t xEnableState )\r
+       {\r
+               if( xEnableState != 0 )\r
+               {\r
+                       xDNSTimer.bActive = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       xDNSTimer.bActive = pdFALSE;\r
+               }\r
+       }\r
+#endif /* ipconfigUSE_DHCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigDNS_USE_CALLBACKS != 0 )\r
+       void vIPReloadDNSTimer( uint32_t ulCheckTime )\r
+       {\r
+               prvIPTimerReload( &xDNSTimer, ulCheckTime );\r
+       }\r
+#endif /* ipconfigDNS_USE_CALLBACKS != 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xIPIsNetworkTaskReady( void )\r
+{\r
+       return xIPTaskInitialised;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t FreeRTOS_IsNetworkUp( void )\r
+{\r
+       return xNetworkUp;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+       UBaseType_t uxGetMinimumIPQueueSpace( void )\r
+       {\r
+               return uxQueueMinimumSpace;\r
+       }\r
+#endif\r
+/*-----------------------------------------------------------*/\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Sockets.c
new file mode 100644 (file)
index 0000000..e5fd643
--- /dev/null
@@ -0,0 +1,3644 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "FreeRTOS_DNS.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* The ItemValue of the sockets xBoundSocketListItem member holds the socket's\r
+port number. */\r
+#define socketSET_SOCKET_PORT( pxSocket, usPort ) listSET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ), ( usPort ) )\r
+#define socketGET_SOCKET_PORT( pxSocket ) listGET_LIST_ITEM_VALUE( ( &( ( pxSocket )->xBoundSocketListItem ) ) )\r
+\r
+/* Test if a socket it bound which means it is either included in\r
+xBoundUDPSocketsList or xBoundTCPSocketsList */\r
+#define socketSOCKET_IS_BOUND( pxSocket )      ( listLIST_ITEM_CONTAINER( & ( pxSocket )->xBoundSocketListItem ) != NULL )\r
+\r
+/* If FreeRTOS_sendto() is called on a socket that is not bound to a port\r
+number then, depending on the FreeRTOSIPConfig.h settings, it might be that a\r
+port number is automatically generated for the socket.  Automatically generated\r
+port numbers will be between socketAUTO_PORT_ALLOCATION_START_NUMBER and\r
+0xffff. */\r
+/* _HT_ thinks that the default of 0xc000 is pretty high */\r
+#if !defined( socketAUTO_PORT_ALLOCATION_START_NUMBER )\r
+       #define socketAUTO_PORT_ALLOCATION_START_NUMBER ( ( uint16_t ) 0xc000 )\r
+#endif\r
+\r
+/* When the automatically generated port numbers overflow, the next value used\r
+is not set back to socketAUTO_PORT_ALLOCATION_START_NUMBER because it is likely\r
+that the first few automatically generated ports will still be in use.  Instead\r
+it is reset back to the value defined by this constant. */\r
+#define socketAUTO_PORT_ALLOCATION_RESET_NUMBER ( ( uint16_t ) 0xc100 )\r
+#define socketAUTO_PORT_ALLOCATION_MAX_NUMBER   ( ( uint16_t ) 0xff00 )\r
+\r
+/* The number of octets that make up an IP address. */\r
+#define socketMAX_IP_ADDRESS_OCTETS            4u\r
+\r
+/* A block time of 0 simply means "don't block". */\r
+#define socketDONT_BLOCK                               ( ( TickType_t ) 0 )\r
+\r
+#if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )\r
+       #define ipTCP_TIMER_PERIOD_MS   ( 1000 )\r
+#endif\r
+\r
+/* The next private port number to use when binding a client socket is stored in\r
+the usNextPortToUse[] array - which has either 1 or two indexes depending on\r
+whether TCP is being supported. */\r
+#if( ipconfigUSE_TCP == 1 )\r
+       #define socketPROTOCOL_COUNT            2\r
+#else\r
+       #define socketPROTOCOL_COUNT            1\r
+#endif\r
+\r
+/* Indexes into the usNextPortToUse[] array for UDP and TCP sockets\r
+respectively. */\r
+#define socketNEXT_UDP_PORT_NUMBER_INDEX       0\r
+#define socketNEXT_TCP_PORT_NUMBER_INDEX       1\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Allocate the next port number from the private allocation range.\r
+ * TCP and UDP each have their own series of port numbers\r
+ * ulProtocol is either ipPROTOCOL_UDP or ipPROTOCOL_TCP\r
+ */\r
+static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol );\r
+\r
+/*\r
+ * Return the list item from within pxList that has an item value of\r
+ * xWantedItemValue.  If there is no such list item return NULL.\r
+ */\r
+static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue );\r
+\r
+/*\r
+ * Return pdTRUE only if pxSocket is valid and bound, as far as can be\r
+ * determined.\r
+ */\r
+static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound );\r
+\r
+/*\r
+ * Before creating a socket, check the validity of the parameters used\r
+ * and find the size of the socket space, which is different for UDP and TCP\r
+ */\r
+static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize );\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+       /*\r
+        * Create a txStream or a rxStream, depending on the parameter 'xIsInputStream'\r
+        */\r
+       static StreamBuffer_t *prvTCPCreateStream (FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream );\r
+#endif /* ipconfigUSE_TCP == 1 */\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+       /*\r
+        * Called from FreeRTOS_send(): some checks which will be done before\r
+        * sending a TCP packed.\r
+        */\r
+       static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength );\r
+#endif /* ipconfigUSE_TCP */\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+       /*\r
+        * When a child socket gets closed, make sure to update the child-count of the parent\r
+        */\r
+       static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete );\r
+#endif  /* ipconfigUSE_TCP == 1 */\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+       /*\r
+        * Called from FreeRTOS_connect(): make some checks and if allowed, send a\r
+        * message to the IP-task to start connecting to a remote socket\r
+        */\r
+       static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress );\r
+#endif /* ipconfigUSE_TCP */\r
+\r
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+\r
+       /* Executed by the IP-task, it will check all sockets belonging to a set */\r
+       static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet );\r
+\r
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The list that contains mappings between sockets and port numbers.  Accesses\r
+to this list must be protected by critical sections of one kind or another. */\r
+List_t xBoundUDPSocketsList;\r
+\r
+#if ipconfigUSE_TCP == 1\r
+       List_t xBoundTCPSocketsList;\r
+#endif /* ipconfigUSE_TCP == 1 */\r
+\r
+/* Holds the next private port number to use when binding a client socket for\r
+UDP, and if ipconfigUSE_TCP is set to 1, also TCP.  UDP uses index\r
+socketNEXT_UDP_PORT_NUMBER_INDEX and TCP uses index\r
+socketNEXT_TCP_PORT_NUMBER_INDEX.  The initial value is set to be between\r
+socketAUTO_PORT_ALLOCATION_RESET_NUMBER and socketAUTO_PORT_ALLOCATION_MAX_NUMBER\r
+when the IP stack is initialised.  Note ipconfigRAND32() is used, which must be\r
+seeded prior to the IP task being started. */\r
+static uint16_t usNextPortToUse[ socketPROTOCOL_COUNT ] = { 0 };\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvValidSocket( FreeRTOS_Socket_t *pxSocket, BaseType_t xProtocol, BaseType_t xIsBound )\r
+{\r
+BaseType_t xReturn = pdTRUE;\r
+\r
+       if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )\r
+       {\r
+               xReturn = pdFALSE;\r
+       }\r
+       else if( ( xIsBound != pdFALSE ) && ( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE ) )\r
+       {\r
+               /* The caller expects the socket to be bound, but it isn't. */\r
+               xReturn = pdFALSE;\r
+       }\r
+       else if( pxSocket->ucProtocol != ( uint8_t ) xProtocol )\r
+       {\r
+               /* Socket has a wrong type (UDP != TCP). */\r
+               xReturn = pdFALSE;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vNetworkSocketsInit( void )\r
+{\r
+const uint32_t ulAutoPortRange = socketAUTO_PORT_ALLOCATION_MAX_NUMBER - socketAUTO_PORT_ALLOCATION_RESET_NUMBER;\r
+uint32_t ulRandomPort;\r
+\r
+       vListInitialise( &xBoundUDPSocketsList );\r
+\r
+       /* Determine the first anonymous UDP port number to get assigned.  Give it\r
+       a random value in order to avoid confusion about port numbers being used\r
+       earlier, before rebooting the device.  Start with the first auto port\r
+       number, then add a random offset up to a maximum of the range of numbers. */\r
+       ulRandomPort = socketAUTO_PORT_ALLOCATION_START_NUMBER;\r
+       ulRandomPort += ( ipconfigRAND32() % ulAutoPortRange );\r
+       usNextPortToUse[ socketNEXT_UDP_PORT_NUMBER_INDEX ] = ( uint16_t ) ulRandomPort;\r
+\r
+       #if( ipconfigUSE_TCP == 1 )\r
+       {\r
+               extern uint32_t ulNextInitialSequenceNumber;\r
+\r
+               ulNextInitialSequenceNumber = ipconfigRAND32();\r
+\r
+               /* Determine the first anonymous TCP port number to get assigned. */\r
+               ulRandomPort = socketAUTO_PORT_ALLOCATION_START_NUMBER;\r
+               ulRandomPort += ( ipconfigRAND32() % ulAutoPortRange );\r
+               usNextPortToUse[ socketNEXT_TCP_PORT_NUMBER_INDEX ] = ( uint16_t ) ulRandomPort;\r
+\r
+               vListInitialise( &xBoundTCPSocketsList );\r
+       }\r
+       #endif  /* ipconfigUSE_TCP == 1 */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvDetermineSocketSize( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol, size_t *pxSocketSize )\r
+{\r
+BaseType_t xReturn = pdPASS;\r
+FreeRTOS_Socket_t *pxSocket;\r
+\r
+       /* Asserts must not appear before it has been determined that the network\r
+       task is ready - otherwise the asserts will fail. */\r
+       if( xIPIsNetworkTaskReady() == pdFALSE )\r
+       {\r
+               xReturn = pdFAIL;\r
+       }\r
+       else\r
+       {\r
+               /* Only Ethernet is currently supported. */\r
+               configASSERT( xDomain == FREERTOS_AF_INET );\r
+\r
+               /* Check if the UDP socket-list has been initialised. */\r
+               configASSERT( listLIST_IS_INITIALISED( &xBoundUDPSocketsList ) );\r
+               #if( ipconfigUSE_TCP == 1 )\r
+               {\r
+                       /* Check if the TCP socket-list has been initialised. */\r
+                       configASSERT( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) );\r
+               }\r
+               #endif  /* ipconfigUSE_TCP == 1 */\r
+\r
+               if( xProtocol == FREERTOS_IPPROTO_UDP )\r
+               {\r
+                       if( xType != FREERTOS_SOCK_DGRAM )\r
+                       {\r
+                               xReturn = pdFAIL;\r
+                       }\r
+                       /* In case a UDP socket is created, do not allocate space for TCP data. */\r
+                       *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xUDP );\r
+               }\r
+#if( ipconfigUSE_TCP == 1 )\r
+               else if( xProtocol == FREERTOS_IPPROTO_TCP )\r
+               {\r
+                       if( xType != FREERTOS_SOCK_STREAM )\r
+                       {\r
+                               xReturn = pdFAIL;\r
+                       }\r
+\r
+                       *pxSocketSize = ( sizeof( *pxSocket ) - sizeof( pxSocket->u ) ) + sizeof( pxSocket->u.xTCP );\r
+               }\r
+#endif  /* ipconfigUSE_TCP == 1 */\r
+               else\r
+               {\r
+                       xReturn = pdFAIL;\r
+               }\r
+       }\r
+       /* In case configASSERT() is not used */\r
+       ( void )xDomain;\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* FreeRTOS_socket() allocates and initiates a socket */\r
+Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol )\r
+{\r
+FreeRTOS_Socket_t *pxSocket;\r
+size_t uxSocketSize;\r
+EventGroupHandle_t xEventGroup;\r
+Socket_t xReturn;\r
+\r
+       if( prvDetermineSocketSize( xDomain, xType, xProtocol, &uxSocketSize ) == pdFAIL )\r
+       {\r
+               xReturn = FREERTOS_INVALID_SOCKET;\r
+       }\r
+       else\r
+       {\r
+               /* Allocate the structure that will hold the socket information.  The\r
+               size depends on the type of socket: UDP sockets need less space.  A\r
+               define 'pvPortMallocSocket' will used to allocate the necessary space.\r
+               By default it points to the FreeRTOS function 'pvPortMalloc()'. */\r
+               pxSocket = ( FreeRTOS_Socket_t * ) pvPortMallocSocket( uxSocketSize );\r
+\r
+               if( pxSocket == NULL )\r
+               {\r
+                       pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
+                       iptraceFAILED_TO_CREATE_SOCKET();\r
+               }\r
+               else if( ( xEventGroup = xEventGroupCreate() ) == NULL )\r
+               {\r
+                       vPortFreeSocket( pxSocket );\r
+                       pxSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
+                       iptraceFAILED_TO_CREATE_EVENT_GROUP();\r
+               }\r
+               else\r
+               {\r
+                       /* Clear the entire space to avoid nulling individual entries. */\r
+                       memset( pxSocket, '\0', uxSocketSize );\r
+\r
+                       pxSocket->xEventGroup = xEventGroup;\r
+\r
+                       /* Initialise the socket's members.  The semaphore will be created\r
+                       if the socket is bound to an address, for now the pointer to the\r
+                       semaphore is just set to NULL to show it has not been created. */\r
+                       if( xProtocol == FREERTOS_IPPROTO_UDP )\r
+                       {\r
+                               vListInitialise( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
+\r
+                               #if( ipconfigUDP_MAX_RX_PACKETS > 0 )\r
+                               {\r
+                                       pxSocket->u.xUDP.uxMaxPackets = ( UBaseType_t ) ipconfigUDP_MAX_RX_PACKETS;\r
+                               }\r
+                               #endif /* ipconfigUDP_MAX_RX_PACKETS > 0 */\r
+                       }\r
+\r
+                       vListInitialiseItem( &( pxSocket->xBoundSocketListItem ) );\r
+                       listSET_LIST_ITEM_OWNER( &( pxSocket->xBoundSocketListItem ), ( void * ) pxSocket );\r
+\r
+                       pxSocket->xReceiveBlockTime = ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME;\r
+                       pxSocket->xSendBlockTime    = ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME;\r
+                       pxSocket->ucSocketOptions   = ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;\r
+                       pxSocket->ucProtocol        = ( uint8_t ) xProtocol; /* protocol: UDP or TCP */\r
+\r
+                       #if( ipconfigUSE_TCP == 1 )\r
+                       {\r
+                               if( xProtocol == FREERTOS_IPPROTO_TCP )\r
+                               {\r
+                                       /* StreamSize is expressed in number of bytes */\r
+                                       /* Round up buffer sizes to nearest multiple of MSS */\r
+                                       pxSocket->u.xTCP.usInitMSS    = pxSocket->u.xTCP.usCurMSS = ipconfigTCP_MSS;\r
+                                       pxSocket->u.xTCP.uxRxStreamSize = ( size_t ) ipconfigTCP_RX_BUFFER_LENGTH;\r
+                                       pxSocket->u.xTCP.uxTxStreamSize = ( size_t ) FreeRTOS_round_up( ipconfigTCP_TX_BUFFER_LENGTH, ipconfigTCP_MSS );\r
+                                       /* Use half of the buffer size of the TCP windows */\r
+                                       #if ( ipconfigUSE_TCP_WIN == 1 )\r
+                                       {\r
+                                               pxSocket->u.xTCP.uxRxWinSize  = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxRxStreamSize / 2 ) / ipconfigTCP_MSS );\r
+                                               pxSocket->u.xTCP.uxTxWinSize  = FreeRTOS_max_uint32( 1UL, ( uint32_t ) ( pxSocket->u.xTCP.uxTxStreamSize / 2 ) / ipconfigTCP_MSS );\r
+                                       }\r
+                                       #else\r
+                                       {\r
+                                               pxSocket->u.xTCP.uxRxWinSize  = 1u;\r
+                                               pxSocket->u.xTCP.uxTxWinSize  = 1u;\r
+                                       }\r
+                                       #endif\r
+                                       /* The above values are just defaults, and can be overridden by\r
+                                       calling FreeRTOS_setsockopt().  No buffers will be allocated until a\r
+                                       socket is connected and data is exchanged. */\r
+                               }\r
+                       }\r
+                       #endif  /* ipconfigUSE_TCP == 1 */\r
+               }\r
+\r
+               xReturn = ( Socket_t ) pxSocket;\r
+       }\r
+\r
+       /* Remove compiler warnings in the case the configASSERT() is not defined. */\r
+       ( void ) xDomain;\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+\r
+       SocketSet_t FreeRTOS_CreateSocketSet( void )\r
+       {\r
+       SocketSelect_t *pxSocketSet;\r
+\r
+               pxSocketSet = ( SocketSelect_t * ) pvPortMalloc( sizeof( *pxSocketSet ) );\r
+\r
+               if( pxSocketSet != NULL )\r
+               {\r
+                       memset( pxSocketSet, '\0', sizeof( *pxSocketSet ) );\r
+                       pxSocketSet->xSelectGroup = xEventGroupCreate();\r
+\r
+                       if( pxSocketSet->xSelectGroup == NULL )\r
+                       {\r
+                               vPortFree( ( void* ) pxSocketSet );\r
+                               pxSocketSet = NULL;\r
+                       }\r
+               }\r
+\r
+               return ( SocketSet_t * ) pxSocketSet;\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+\r
+       void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet )\r
+       {\r
+               SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;\r
+\r
+               vEventGroupDelete( pxSocketSet->xSelectGroup );\r
+               vPortFree( ( void* ) pxSocketSet );\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+\r
+       /* Add a socket to a set */\r
+       void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       SocketSelect_t *pxSocketSet = ( SocketSelect_t * ) xSocketSet;\r
+\r
+               configASSERT( pxSocket != NULL );\r
+               configASSERT( xSocketSet != NULL );\r
+\r
+               /* Make sure we're not adding bits which are reserved for internal use,\r
+               such as eSELECT_CALL_IP */\r
+               pxSocket->xSelectBits |= ( xSelectBits & eSELECT_ALL );\r
+\r
+               if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )\r
+               {\r
+                       /* Adding a socket to a socket set. */\r
+                       pxSocket->pxSocketSet = ( SocketSelect_t * ) xSocketSet;\r
+\r
+                       /* Now have the IP-task call vSocketSelect() to see if the set contains\r
+                       any sockets which are 'ready' and set the proper bits.\r
+                       By setting 'bApiCalled = false', vSocketSelect() knows that it was\r
+                       not called from a user API */\r
+                       pxSocketSet->bApiCalled = pdFALSE;\r
+                       prvFindSelectedSocket( pxSocketSet );\r
+               }\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+       /* Clear select bits for a socket\r
+       If the mask becomes 0, remove the socket from the set */\r
+       void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xSelectBits )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+\r
+               configASSERT( pxSocket != NULL );\r
+               configASSERT( xSocketSet != NULL );\r
+\r
+               pxSocket->xSelectBits &= ~( xSelectBits & eSELECT_ALL );\r
+               if( ( pxSocket->xSelectBits & eSELECT_ALL ) != 0 )\r
+               {\r
+                       pxSocket->pxSocketSet = ( SocketSelect_t *)xSocketSet;\r
+               }\r
+               else\r
+               {\r
+                       /* disconnect it from the socket set */\r
+                       pxSocket->pxSocketSet = ( SocketSelect_t *)NULL;\r
+               }\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+\r
+       /* Test if a socket belongs to a socket-set */\r
+       EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet )\r
+       {\r
+       EventBits_t xReturn;\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+\r
+               configASSERT( pxSocket != NULL );\r
+               configASSERT( xSocketSet != NULL );\r
+\r
+               if( xSocketSet == ( SocketSet_t ) pxSocket->pxSocketSet )\r
+               {\r
+                       /* Make sure we're not adding bits which are reserved for internal\r
+                       use. */\r
+                       xReturn = pxSocket->xSocketBits & eSELECT_ALL;\r
+               }\r
+               else\r
+               {\r
+                       xReturn = 0;\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+\r
+       /* The select() statement: wait for an event to occur on any of the sockets\r
+       included in a socket set */\r
+       BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks )\r
+       {\r
+       TimeOut_t xTimeOut;\r
+       TickType_t xRemainingTime;\r
+       SocketSelect_t *pxSocketSet = ( SocketSelect_t*) xSocketSet;\r
+       BaseType_t xResult;\r
+\r
+               configASSERT( xSocketSet != NULL );\r
+\r
+               /* Only in the first round, check for non-blocking */\r
+               xRemainingTime = xBlockTimeTicks;\r
+\r
+               /* Fetch the current time */\r
+               vTaskSetTimeOutState( &xTimeOut );\r
+\r
+               for( ;; )\r
+               {\r
+                       /* Find a socket which might have triggered the bit\r
+                       This function might return immediately or block for a limited time */\r
+                       xResult = ( BaseType_t ) xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_ALL, pdFALSE, pdFALSE, xRemainingTime );\r
+\r
+                       #if( ipconfigSUPPORT_SIGNALS != 0 )\r
+                       {\r
+                               if( ( xResult & eSELECT_INTR ) != 0u )\r
+                               {\r
+                                       xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_INTR );\r
+                                       FreeRTOS_debug_printf( ( "FreeRTOS_select: interrupted\n" ) );\r
+                                       break;\r
+                               }\r
+                       }\r
+                       #endif /* ipconfigSUPPORT_SIGNALS */\r
+\r
+                       /* Have the IP-task find the socket which had an event */\r
+                       pxSocketSet->bApiCalled = pdTRUE;\r
+                       prvFindSelectedSocket( pxSocketSet );\r
+\r
+                       xResult = ( BaseType_t ) xEventGroupGetBits( pxSocketSet->xSelectGroup );\r
+\r
+                       if( xResult != 0 )\r
+                       {\r
+                               break;\r
+                       }\r
+\r
+                       /* Has the timeout been reached? */\r
+                       if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+\r
+       /* Send a message to the IP-task to have it check all sockets belonging to\r
+       'pxSocketSet' */\r
+       static FreeRTOS_Socket_t *prvFindSelectedSocket( SocketSelect_t *pxSocketSet )\r
+       {\r
+       IPStackEvent_t xSelectEvent;\r
+       FreeRTOS_Socket_t *xReturn;\r
+\r
+               xSelectEvent.eEventType = eSocketSelectEvent;\r
+               xSelectEvent.pvData = ( void * ) pxSocketSet;\r
+\r
+               /* while the IP-task works on the request, the API will block on\r
+               'eSELECT_CALL_IP'.  So clear it first. */\r
+               xEventGroupClearBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP );\r
+\r
+               /* Now send the socket select event */\r
+               if( xSendEventStructToIPTask( &xSelectEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )\r
+               {\r
+                       /* Oops, we failed to wake-up the IP task. No use to wait for it. */\r
+                       FreeRTOS_debug_printf( ( "prvFindSelectedSocket: failed\n" ) );\r
+                       xReturn = NULL;\r
+               }\r
+               else\r
+               {\r
+                       /* As soon as the IP-task is ready, it will set 'eSELECT_CALL_IP' to\r
+                       wakeup the calling API */\r
+                       xEventGroupWaitBits( pxSocketSet->xSelectGroup, eSELECT_CALL_IP, pdTRUE, pdFALSE, portMAX_DELAY );\r
+\r
+                       /* Return 'pxSocket' which is set by the IP-task */\r
+                       xReturn = pxSocketSet->pxSocket;\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * FreeRTOS_recvfrom: receive data from a bound socket\r
+ * In this library, the function can only be used with connectionsless sockets\r
+ * (UDP)\r
+ */\r
+int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength )\r
+{\r
+BaseType_t lPacketCount = 0;\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+TickType_t xRemainingTime = ( TickType_t ) 0; /* Obsolete assignment, but some compilers output a warning if its not done. */\r
+BaseType_t xTimed = pdFALSE;\r
+TimeOut_t xTimeOut;\r
+int32_t lReturn;\r
+EventBits_t xEventBits = ( EventBits_t ) 0;\r
+\r
+       if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_UDP, pdTRUE ) == pdFALSE )\r
+       {\r
+               return -pdFREERTOS_ERRNO_EINVAL;\r
+       }\r
+\r
+       lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
+\r
+       /* The function prototype is designed to maintain the expected Berkeley\r
+       sockets standard, but this implementation does not use all the parameters. */\r
+       ( void ) pxSourceAddressLength;\r
+\r
+       while( lPacketCount == 0 )\r
+       {\r
+               if( xTimed == pdFALSE )\r
+               {\r
+                       /* Check to see if the socket is non blocking on the first\r
+                       iteration.  */\r
+                       xRemainingTime = pxSocket->xReceiveBlockTime;\r
+\r
+                       if( xRemainingTime == ( TickType_t ) 0 )\r
+                       {\r
+                               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
+                               {\r
+                                       /* Just check for the interrupt flag. */\r
+                                       xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,\r
+                                               pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );\r
+                               }\r
+                               #endif /* ipconfigSUPPORT_SIGNALS */\r
+                               break;\r
+                       }\r
+\r
+                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
+                       {\r
+                               break;\r
+                       }\r
+\r
+                       /* To ensure this part only executes once. */\r
+                       xTimed = pdTRUE;\r
+\r
+                       /* Fetch the current time. */\r
+                       vTaskSetTimeOutState( &xTimeOut );\r
+               }\r
+\r
+               /* Wait for arrival of data.  While waiting, the IP-task may set the\r
+               'eSOCKET_RECEIVE' bit in 'xEventGroup', if it receives data for this\r
+               socket, thus unblocking this API call. */\r
+               xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_RECEIVE | eSOCKET_INTR,\r
+                       pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
+\r
+               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
+               {\r
+                       if( ( xEventBits & eSOCKET_INTR ) != 0 )\r
+                       {\r
+                               if( ( xEventBits & eSOCKET_RECEIVE ) != 0 )\r
+                               {\r
+                                       /* Shouldn't have cleared the eSOCKET_RECEIVE flag. */\r
+                                       xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );\r
+                               }\r
+                               break;\r
+                       }\r
+               }\r
+               #else\r
+               {\r
+                       ( void ) xEventBits;\r
+               }\r
+               #endif /* ipconfigSUPPORT_SIGNALS */\r
+\r
+               lPacketCount = ( BaseType_t ) listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
+\r
+               if( lPacketCount != 0 )\r
+               {\r
+                       break;\r
+               }\r
+\r
+               /* Has the timeout been reached ? */\r
+               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )\r
+               {\r
+                       break;\r
+               }\r
+       } /* while( lPacketCount == 0 ) */\r
+\r
+       if( lPacketCount != 0 )\r
+       {\r
+               taskENTER_CRITICAL();\r
+               {\r
+                       /* The owner of the list item is the network buffer. */\r
+                       pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
+\r
+                       if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )\r
+                       {\r
+                               /* Remove the network buffer from the list of buffers waiting to\r
+                               be processed by the socket. */\r
+                               uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );\r
+                       }\r
+               }\r
+               taskEXIT_CRITICAL();\r
+\r
+               /* The returned value is the data length, which may have been capped to\r
+               the receive buffer size. */\r
+               lReturn = ( int32_t ) pxNetworkBuffer->xDataLength;\r
+\r
+               if( pxSourceAddress != NULL )\r
+               {\r
+                       pxSourceAddress->sin_port = pxNetworkBuffer->usPort;\r
+                       pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;\r
+               }\r
+\r
+               if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
+               {\r
+                       /* The zero copy flag is not set.  Truncate the length if it won't\r
+                       fit in the provided buffer. */\r
+                       if( lReturn > ( int32_t ) xBufferLength )\r
+                       {\r
+                               iptraceRECVFROM_DISCARDING_BYTES( ( xBufferLength - lReturn ) );\r
+                               lReturn = ( int32_t )xBufferLength;\r
+                       }\r
+\r
+                       /* Copy the received data into the provided buffer, then release the\r
+                       network buffer. */\r
+                       memcpy( pvBuffer, ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( size_t )lReturn );\r
+\r
+                       if( ( xFlags & FREERTOS_MSG_PEEK ) == 0 )\r
+                       {\r
+                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* The zero copy flag was set.  pvBuffer is not a buffer into which\r
+                       the received data can be copied, but a pointer that must be set to\r
+                       point to the buffer in which the received data has already been\r
+                       placed. */\r
+                       *( ( void** ) pvBuffer ) = ( void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ) );\r
+               }\r
+\r
+       }\r
+#if( ipconfigSUPPORT_SIGNALS != 0 )\r
+       else if( ( xEventBits & eSOCKET_INTR ) != 0 )\r
+       {\r
+               lReturn = -pdFREERTOS_ERRNO_EINTR;\r
+               iptraceRECVFROM_INTERRUPTED();\r
+       }\r
+#endif /* ipconfigSUPPORT_SIGNALS */\r
+       else\r
+       {\r
+               lReturn = -pdFREERTOS_ERRNO_EWOULDBLOCK;\r
+               iptraceRECVFROM_TIMEOUT();\r
+       }\r
+\r
+       return lReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength )\r
+{\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };\r
+TimeOut_t xTimeOut;\r
+TickType_t xTicksToWait;\r
+int32_t lReturn = 0;\r
+FreeRTOS_Socket_t *pxSocket;\r
+\r
+       pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+\r
+       /* The function prototype is designed to maintain the expected Berkeley\r
+       sockets standard, but this implementation does not use all the\r
+       parameters. */\r
+       ( void ) xDestinationAddressLength;\r
+       configASSERT( pvBuffer );\r
+\r
+       if( xTotalDataLength <= ( size_t ) ipMAX_UDP_PAYLOAD_LENGTH )\r
+       {\r
+               /* If the socket is not already bound to an address, bind it now.\r
+               Passing NULL as the address parameter tells FreeRTOS_bind() to select\r
+               the address to bind to. */\r
+               if( ( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE ) ||\r
+                       ( FreeRTOS_bind( xSocket, NULL, 0u ) == 0 ) )\r
+               {\r
+                       xTicksToWait = pxSocket->xSendBlockTime;\r
+\r
+                       #if( ipconfigUSE_CALLBACKS != 0 )\r
+                       {\r
+                               if( xIsCallingFromIPTask() != pdFALSE )\r
+                               {\r
+                                       /* If this send function is called from within a call-back\r
+                                       handler it may not block, otherwise chances would be big to\r
+                                       get a deadlock: the IP-task waiting for itself. */\r
+                                       xTicksToWait = ( TickType_t )0;\r
+                               }\r
+                       }\r
+                       #endif /* ipconfigUSE_CALLBACKS */\r
+\r
+                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
+                       {\r
+                               xTicksToWait = ( TickType_t ) 0;\r
+                       }\r
+\r
+                       if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
+                       {\r
+                               /* Zero copy is not set, so obtain a network buffer into\r
+                               which the payload will be copied. */\r
+                               vTaskSetTimeOutState( &xTimeOut );\r
+\r
+                               /* Block until a buffer becomes available, or until a\r
+                               timeout has been reached */\r
+                               pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xTotalDataLength + sizeof( UDPPacket_t ), xTicksToWait );\r
+\r
+                               if( pxNetworkBuffer != NULL )\r
+                               {\r
+                                       memcpy( ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] ), ( void * ) pvBuffer, xTotalDataLength );\r
+\r
+                                       if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdTRUE )\r
+                                       {\r
+                                               /* The entire block time has been used up. */\r
+                                               xTicksToWait = ( TickType_t ) 0;\r
+                                       }\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               /* When zero copy is used, pvBuffer is a pointer to the\r
+                               payload of a buffer that has already been obtained from the\r
+                               stack.  Obtain the network buffer pointer from the buffer. */\r
+                               pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( (void*)pvBuffer );\r
+                       }\r
+\r
+                       if( pxNetworkBuffer != NULL )\r
+                       {\r
+                               pxNetworkBuffer->xDataLength = xTotalDataLength;\r
+                               pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;\r
+                               pxNetworkBuffer->usBoundPort = ( uint16_t ) socketGET_SOCKET_PORT( pxSocket );\r
+                               pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr;\r
+\r
+                               /* The socket options are passed to the IP layer in the\r
+                               space that will eventually get used by the Ethernet header. */\r
+                               pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = pxSocket->ucSocketOptions;\r
+\r
+                               /* Tell the networking task that the packet needs sending. */\r
+                               xStackTxEvent.pvData = pxNetworkBuffer;\r
+\r
+                               /* Ask the IP-task to send this packet */\r
+                               if( xSendEventStructToIPTask( &xStackTxEvent, xTicksToWait ) == pdPASS )\r
+                               {\r
+                                       /* The packet was successfully sent to the IP task. */\r
+                                       lReturn = ( int32_t ) xTotalDataLength;\r
+                                       #if( ipconfigUSE_CALLBACKS == 1 )\r
+                                       {\r
+                                               if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleSent ) )\r
+                                               {\r
+                                                       pxSocket->u.xUDP.pxHandleSent( (Socket_t *)pxSocket, xTotalDataLength );\r
+                                               }\r
+                                       }\r
+                                       #endif /* ipconfigUSE_CALLBACKS */\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* If the buffer was allocated in this function, release\r
+                                       it. */\r
+                                       if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
+                                       {\r
+                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                                       }\r
+                                       iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               /* If errno was available, errno would be set to\r
+                               FREERTOS_ENOPKTS.  As it is, the function must return the\r
+                               number of transmitted bytes, so the calling function knows\r
+                               how     much data was actually sent. */\r
+                               iptraceNO_BUFFER_FOR_SENDTO();\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       iptraceSENDTO_SOCKET_NOT_BOUND();\r
+               }\r
+       }\r
+       else\r
+       {\r
+               /* The data is longer than the available buffer space. */\r
+               iptraceSENDTO_DATA_TOO_LONG();\r
+       }\r
+\r
+       return lReturn;\r
+} /* Tested */\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * FreeRTOS_bind() : binds a sockt to a local port number.  If port 0 is\r
+ * provided, a system provided port number will be assigned.  This function can\r
+ * be used for both UDP and TCP sockets.  The actual binding will be performed\r
+ * by the IP-task to avoid mutual access to the bound-socket-lists\r
+ * (xBoundUDPSocketsList or xBoundTCPSocketsList).\r
+ */\r
+BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr * pxAddress, socklen_t xAddressLength )\r
+{\r
+IPStackEvent_t xBindEvent;\r
+FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+BaseType_t xReturn = 0;\r
+\r
+       ( void ) xAddressLength;\r
+\r
+       if( ( pxSocket == NULL ) || ( pxSocket == FREERTOS_INVALID_SOCKET ) )\r
+       {\r
+               xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+       }\r
+       /* Once a socket is bound to a port, it can not be bound to a different\r
+       port number */\r
+       else if( socketSOCKET_IS_BOUND( pxSocket) != pdFALSE )\r
+       {\r
+               /* The socket is already bound. */\r
+               FreeRTOS_debug_printf( ( "vSocketBind: Socket already bound to %d\n", pxSocket->usLocalPort ) );\r
+               xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+       }\r
+       else\r
+       {\r
+               /* Prepare a messages to the IP-task in order to perform the binding.\r
+               The desired port number will be passed in usLocalPort. */\r
+               xBindEvent.eEventType = eSocketBindEvent;\r
+               xBindEvent.pvData = ( void * ) xSocket;\r
+               if( pxAddress != NULL )\r
+               {\r
+                       pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );\r
+               }\r
+               else\r
+               {\r
+                       /* Caller wants to bind to a random port number. */\r
+                       pxSocket->usLocalPort = 0u;\r
+               }\r
+\r
+               /* portMAX_DELAY is used as a the time-out parameter, as binding *must*\r
+               succeed before the socket can be used.  _RB_ The use of an infinite\r
+               block time needs be changed as it could result in the task hanging. */\r
+               if( xSendEventStructToIPTask( &xBindEvent, ( TickType_t ) portMAX_DELAY ) == pdFAIL )\r
+               {\r
+                       /* Failed to wake-up the IP-task, no use to wait for it */\r
+                       FreeRTOS_debug_printf( ( "FreeRTOS_bind: send event failed\n" ) );\r
+                       xReturn = -pdFREERTOS_ERRNO_ECANCELED;\r
+               }\r
+               else\r
+               {\r
+                       /* The IP-task will set the 'eSOCKET_BOUND' bit when it has done its\r
+                       job. */\r
+                       xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_BOUND, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, portMAX_DELAY );\r
+                       if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )\r
+                       {\r
+                               xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+                       }\r
+               }\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+\r
+/*\r
+ * vSocketBind(): internal version of bind() that should not be called directly.\r
+ * 'xInternal' is used for TCP sockets only: it allows to have several\r
+ * (connected) child sockets bound to the same server port.\r
+ */\r
+BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal )\r
+{\r
+BaseType_t xReturn = 0; /* In Berkeley sockets, 0 means pass for bind(). */\r
+List_t *pxSocketList;\r
+#if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )\r
+       struct freertos_sockaddr xAddress;\r
+#endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND */\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+       {\r
+               pxSocketList = &xBoundTCPSocketsList;\r
+       }\r
+       else\r
+#endif  /* ipconfigUSE_TCP == 1 */\r
+       {\r
+               pxSocketList = &xBoundUDPSocketsList;\r
+       }\r
+\r
+       /* The function prototype is designed to maintain the expected Berkeley\r
+       sockets standard, but this implementation does not use all the parameters. */\r
+       ( void ) uxAddressLength;\r
+\r
+       configASSERT( pxSocket );\r
+       configASSERT( pxSocket != FREERTOS_INVALID_SOCKET );\r
+\r
+       #if( ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 )\r
+       {\r
+               /* pxAddress will be NULL if sendto() was called on a socket without the\r
+               socket being bound to an address.  In this case, automatically allocate\r
+               an address to the socket.  There is a very tiny chance that the allocated\r
+               port will already be in use - if that is the case, then the check below\r
+               [pxListFindListItemWithValue()] will result in an error being returned. */\r
+               if( pxAddress == NULL )\r
+               {\r
+                       pxAddress = &xAddress;\r
+                       /* For now, put it to zero, will be assigned later */\r
+                       pxAddress->sin_port = 0u;\r
+               }\r
+       }\r
+       #endif /* ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND == 1 */\r
+\r
+       /* Sockets must be bound before calling FreeRTOS_sendto() if\r
+       ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND is not set to 1. */\r
+       configASSERT( pxAddress );\r
+\r
+       if( pxAddress != NULL )\r
+       {\r
+               if( pxAddress->sin_port == 0u )\r
+               {\r
+                       pxAddress->sin_port = prvGetPrivatePortNumber( ( BaseType_t ) pxSocket->ucProtocol );\r
+               }\r
+\r
+               /* If vSocketBind() is called from the API FreeRTOS_bind() it has been\r
+               confirmed that the socket was not yet bound to a port.  If it is called\r
+               from the IP-task, no such check is necessary. */\r
+\r
+               /* Check to ensure the port is not already in use.  If the bind is\r
+               called internally, a port MAY be used by more than one socket. */\r
+               if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&\r
+                       ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port ) != NULL ) )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",\r
+                               pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ? "TC" : "UD",\r
+                               FreeRTOS_ntohs( pxAddress->sin_port ) ) );\r
+                       xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;\r
+               }\r
+               else\r
+               {\r
+                       /* Allocate the port number to the socket.\r
+                       This macro will set 'xBoundSocketListItem->xItemValue' */\r
+                       socketSET_SOCKET_PORT( pxSocket, pxAddress->sin_port );\r
+\r
+                       /* And also store it in a socket field 'usLocalPort' in host-byte-order,\r
+                       mostly used for logging and debugging purposes */\r
+                       pxSocket->usLocalPort = FreeRTOS_ntohs( pxAddress->sin_port );\r
+\r
+                       /* Add the socket to the list of bound ports. */\r
+                       {\r
+                               /* If the network driver can iterate through 'xBoundUDPSocketsList',\r
+                               by calling xPortHasUDPSocket() then the IP-task must temporarily\r
+                               suspend the scheduler to keep the list in a consistent state. */\r
+                               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
+                               {\r
+                                       vTaskSuspendAll();\r
+                               }\r
+                               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
+\r
+                               /* Add the socket to 'xBoundUDPSocketsList' or 'xBoundTCPSocketsList' */\r
+                               vListInsertEnd( pxSocketList, &( pxSocket->xBoundSocketListItem ) );\r
+\r
+                               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
+                               {\r
+                                       xTaskResumeAll();\r
+                               }\r
+                               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               xReturn = -pdFREERTOS_ERRNO_EADDRNOTAVAIL;\r
+               FreeRTOS_debug_printf( ( "vSocketBind: Socket no addr\n" ) );\r
+       }\r
+\r
+       if( xReturn != 0 )\r
+       {\r
+               iptraceBIND_FAILED( xSocket, ( FreeRTOS_ntohs( pxAddress->sin_port ) ) );\r
+       }\r
+\r
+       return xReturn;\r
+} /* Tested */\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Close a socket and free the allocated space\r
+ * In case of a TCP socket: the connection will not be closed automatically\r
+ * Subsequent messages for the closed socket will be responded to with a RST\r
+ * The IP-task will actually close the socket, after receiving a 'eSocketCloseEvent' message\r
+ */\r
+BaseType_t FreeRTOS_closesocket( Socket_t xSocket )\r
+{\r
+BaseType_t xResult;\r
+#if( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 )\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * )xSocket;\r
+#endif\r
+IPStackEvent_t xCloseEvent;\r
+xCloseEvent.eEventType = eSocketCloseEvent;\r
+xCloseEvent.pvData = ( void * ) xSocket;\r
+\r
+       if( ( xSocket == NULL ) || ( xSocket == FREERTOS_INVALID_SOCKET ) )\r
+       {\r
+               xResult = 0;\r
+       }\r
+       else\r
+       {\r
+               #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) )\r
+               {\r
+                       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+                       {\r
+                               /* Make sure that IP-task won't call the user callback's anymore */\r
+                               pxSocket->u.xTCP.pxHandleConnected = NULL;\r
+                               pxSocket->u.xTCP.pxHandleReceive = NULL;\r
+                               pxSocket->u.xTCP.pxHandleSent = NULL;\r
+                       }\r
+               }\r
+               #endif  /* ( ( ipconfigUSE_TCP == 1 ) && ( ipconfigUSE_CALLBACKS == 1 ) ) */\r
+\r
+               /* Let the IP task close the socket to keep it synchronised     with the\r
+               packet handling. */\r
+\r
+               /* Note when changing the time-out value below, it must be checked who is calling\r
+               this function. If it is called by the IP-task, a deadlock could occur.\r
+               The IP-task would only call it in case of a user call-back */\r
+               if( xSendEventStructToIPTask( &xCloseEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "FreeRTOS_closesocket: failed\n" ) );\r
+                       xResult = -1;\r
+               }\r
+               else\r
+               {\r
+                       xResult = 1;\r
+               }\r
+       }\r
+\r
+       return xResult;\r
+}\r
+\r
+/* This is the internal version of FreeRTOS_closesocket()\r
+ * It will be called by the IPtask only to avoid problems with synchronicity\r
+ */\r
+void *vSocketClose( FreeRTOS_Socket_t *pxSocket )\r
+{\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+\r
+       #if( ipconfigUSE_TCP == 1 )\r
+       {\r
+               /* For TCP: clean up a little more. */\r
+               if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+               {\r
+                       #if( ipconfigUSE_TCP_WIN == 1 )\r
+                       {\r
+                               if( pxSocket->u.xTCP.pxAckMessage != NULL )\r
+                               {\r
+                                       vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );\r
+                               }\r
+                               /* Free the resources which were claimed by the tcpWin member */\r
+                               vTCPWindowDestroy( &pxSocket->u.xTCP.xTCPWindow );\r
+                       }\r
+                       #endif /* ipconfigUSE_TCP_WIN */\r
+\r
+                       /* Free the input and output streams */\r
+                       if( pxSocket->u.xTCP.rxStream != NULL )\r
+                       {\r
+                               vPortFreeLarge( pxSocket->u.xTCP.rxStream );\r
+                       }\r
+\r
+                       if( pxSocket->u.xTCP.txStream != NULL )\r
+                       {\r
+                               vPortFreeLarge( pxSocket->u.xTCP.txStream );\r
+                       }\r
+\r
+                       /* In case this is a child socket, make sure the child-count of the\r
+                       parent socket is decreased. */\r
+                       prvTCPSetSocketCount( pxSocket );\r
+               }\r
+       }\r
+       #endif  /* ipconfigUSE_TCP == 1 */\r
+\r
+       /* Socket must be unbound first, to ensure no more packets are queued on\r
+       it. */\r
+       if( socketSOCKET_IS_BOUND( pxSocket ) != pdFALSE )\r
+       {\r
+               /* If the network driver can iterate through 'xBoundUDPSocketsList',\r
+               by calling xPortHasUDPSocket(), then the IP-task must temporarily\r
+               suspend the scheduler to keep the list in a consistent state. */\r
+               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
+               {\r
+                       vTaskSuspendAll();\r
+               }\r
+               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
+\r
+               uxListRemove( &( pxSocket->xBoundSocketListItem ) );\r
+\r
+               #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
+               {\r
+                       xTaskResumeAll();\r
+               }\r
+               #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
+       }\r
+\r
+       /* Now the socket is not bound the list of waiting packets can be\r
+       drained. */\r
+       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )\r
+       {\r
+               while( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U )\r
+               {\r
+                       pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &( pxSocket->u.xUDP.xWaitingPacketsList ) );\r
+                       uxListRemove( &( pxNetworkBuffer->xBufferListItem ) );\r
+                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+               }\r
+       }\r
+\r
+       if( pxSocket->xEventGroup )\r
+       {\r
+               vEventGroupDelete( pxSocket->xEventGroup );\r
+       }\r
+\r
+       #if( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+       {\r
+               if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "FreeRTOS_closesocket[%u to %lxip:%u]: buffers %lu socks %lu\n",\r
+                               pxSocket->usLocalPort,\r
+                               pxSocket->u.xTCP.ulRemoteIP,\r
+                               pxSocket->u.xTCP.usRemotePort,\r
+                               uxGetNumberOfFreeNetworkBuffers(),\r
+                               listCURRENT_LIST_LENGTH( &xBoundTCPSocketsList ) ) );\r
+               }\r
+       }\r
+       #endif /* ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_DEBUG_PRINTF != 0 ) */\r
+\r
+       /* Anf finally, after all resources have been freed, free the socket space */\r
+       vPortFreeSocket( pxSocket );\r
+\r
+       return 0;\r
+} /* Tested */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ipconfigUSE_TCP == 1\r
+\r
+       /*\r
+        * When a child socket gets closed, make sure to update the child-count of the\r
+        * parent.  When a listening parent socket is closed, make sure no child-sockets\r
+        * keep a pointer to it.\r
+        */\r
+       static void prvTCPSetSocketCount( FreeRTOS_Socket_t *pxSocketToDelete )\r
+       {\r
+       const ListItem_t *pxIterator;\r
+       const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );\r
+       FreeRTOS_Socket_t *pxOtherSocket;\r
+       uint16_t usLocalPort = pxSocketToDelete->usLocalPort;\r
+\r
+               for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );\r
+                        pxIterator != ( const ListItem_t * ) pxEnd;\r
+                        pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
+               {\r
+                       pxOtherSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
+                       if( ( pxOtherSocket->u.xTCP.ucTCPState == eTCP_LISTEN ) &&\r
+                               ( pxOtherSocket->usLocalPort == usLocalPort ) &&\r
+                               ( pxOtherSocket->u.xTCP.usChildCount ) )\r
+                       {\r
+                               pxOtherSocket->u.xTCP.usChildCount--;\r
+                               FreeRTOS_debug_printf( ( "Lost: Socket %u now has %u / %u child%s\n",\r
+                                       pxOtherSocket->usLocalPort,\r
+                                       pxOtherSocket->u.xTCP.usChildCount,\r
+                                       pxOtherSocket->u.xTCP.usBacklog,\r
+                                       pxOtherSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP == 1 */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength )\r
+{\r
+/* The standard Berkeley function returns 0 for success. */\r
+BaseType_t xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+BaseType_t lOptionValue;\r
+FreeRTOS_Socket_t *pxSocket;\r
+\r
+       pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+\r
+       /* The function prototype is designed to maintain the expected Berkeley\r
+       sockets standard, but this implementation does not use all the parameters. */\r
+       ( void ) lLevel;\r
+       ( void ) xOptionLength;\r
+\r
+       configASSERT( xSocket );\r
+\r
+       switch( lOptionName )\r
+       {\r
+               case FREERTOS_SO_RCVTIMEO       :\r
+                       /* Receive time out. */\r
+                       pxSocket->xReceiveBlockTime = *( ( TickType_t * ) pvOptionValue );\r
+                       xReturn = 0;\r
+                       break;\r
+\r
+               case FREERTOS_SO_SNDTIMEO       :\r
+                       pxSocket->xSendBlockTime = *( ( TickType_t * ) pvOptionValue );\r
+                       if( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_UDP )\r
+                       {\r
+                               /* The send time out is capped for the reason stated in the\r
+                               comments where ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined\r
+                               in FreeRTOSIPConfig.h (assuming an official configuration file\r
+                               is being used. */\r
+                               if( pxSocket->xSendBlockTime > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )\r
+                               {\r
+                                       pxSocket->xSendBlockTime = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               /* For TCP socket, it isn't necessary to limit the blocking time\r
+                               because the FreeRTOS_send() function does not wait for a network\r
+                               buffer to become available. */\r
+                       }\r
+                       xReturn = 0;\r
+                       break;\r
+               #if( ipconfigUDP_MAX_RX_PACKETS > 0 )\r
+                       case FREERTOS_SO_UDP_MAX_RX_PACKETS:\r
+                               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP )\r
+                               {\r
+                                       break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
+                               }\r
+                               pxSocket->u.xUDP.uxMaxPackets = *( ( UBaseType_t * ) pvOptionValue );\r
+                               xReturn = 0;\r
+                               break;\r
+               #endif /* ipconfigUDP_MAX_RX_PACKETS */\r
+\r
+               case FREERTOS_SO_UDPCKSUM_OUT :\r
+                       /* Turn calculating of the UDP checksum on/off for this socket. */\r
+                       lOptionValue = ( BaseType_t ) pvOptionValue;\r
+\r
+                       if( lOptionValue == 0 )\r
+                       {\r
+                               pxSocket->ucSocketOptions &= ( uint8_t ) ~FREERTOS_SO_UDPCKSUM_OUT;\r
+                       }\r
+                       else\r
+                       {\r
+                               pxSocket->ucSocketOptions |= ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT;\r
+                       }\r
+                       xReturn = 0;\r
+                       break;\r
+\r
+               #if( ipconfigUSE_CALLBACKS == 1 )\r
+                       #if( ipconfigUSE_TCP == 1 )\r
+                               case FREERTOS_SO_TCP_CONN_HANDLER:      /* Set a callback for (dis)connection events */\r
+                               case FREERTOS_SO_TCP_RECV_HANDLER:      /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
+                               case FREERTOS_SO_TCP_SENT_HANDLER:      /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
+                       #endif /* ipconfigUSE_TCP */\r
+                               case FREERTOS_SO_UDP_RECV_HANDLER:      /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
+                               case FREERTOS_SO_UDP_SENT_HANDLER:      /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
+                                       {\r
+                                               #if( ipconfigUSE_TCP == 1 )\r
+                                               {\r
+                                                       UBaseType_t uxProtocol;\r
+                                                       if( ( lOptionName == FREERTOS_SO_UDP_RECV_HANDLER ) ||\r
+                                                               ( lOptionName == FREERTOS_SO_UDP_SENT_HANDLER ) )\r
+                                                       {\r
+                                                               uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_UDP;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               uxProtocol = ( UBaseType_t ) FREERTOS_IPPROTO_TCP;\r
+                                                       }\r
+\r
+                                                       if( pxSocket->ucProtocol != ( uint8_t ) uxProtocol )\r
+                                                       {\r
+                                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
+                                                       }\r
+                                               }\r
+                                               #else\r
+                                               {\r
+                                                       /* No need to check if the socket has the right\r
+                                                       protocol, because only UDP socket can be created. */\r
+                                               }\r
+                                               #endif /* ipconfigUSE_TCP */\r
+\r
+                                               switch( lOptionName )\r
+                                               {\r
+                                               #if ipconfigUSE_TCP == 1\r
+                                                       case FREERTOS_SO_TCP_CONN_HANDLER:\r
+                                                               pxSocket->u.xTCP.pxHandleConnected = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPConnected;\r
+                                                               break;\r
+                                                       case FREERTOS_SO_TCP_RECV_HANDLER:\r
+                                                               pxSocket->u.xTCP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPReceive;\r
+                                                               break;\r
+                                                       case FREERTOS_SO_TCP_SENT_HANDLER:\r
+                                                               pxSocket->u.xTCP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnTCPSent;\r
+                                                               break;\r
+                                               #endif /* ipconfigUSE_TCP */\r
+                                               case FREERTOS_SO_UDP_RECV_HANDLER:\r
+                                                       pxSocket->u.xUDP.pxHandleReceive = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPReceive;\r
+                                                       break;\r
+                                               case FREERTOS_SO_UDP_SENT_HANDLER:\r
+                                                       pxSocket->u.xUDP.pxHandleSent = ((F_TCP_UDP_Handler_t *)pvOptionValue)->pxOnUDPSent;\r
+                                                       break;\r
+                                               default:\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+\r
+                                       xReturn = 0;\r
+                                       break;\r
+               #endif /* ipconfigUSE_CALLBACKS */\r
+\r
+               #if( ipconfigUSE_TCP != 0 )\r
+                       #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )\r
+                               /* Each socket has a semaphore on which the using task normally\r
+                               sleeps. */\r
+                               case FREERTOS_SO_SET_SEMAPHORE:\r
+                                       {\r
+                                               pxSocket->pxUserSemaphore = *( ( SemaphoreHandle_t * ) pvOptionValue );\r
+                                       }\r
+                                       xReturn = 0;\r
+                                       break;\r
+                       #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */\r
+                       case FREERTOS_SO_SNDBUF:        /* Set the size of the send buffer, in units of MSS (TCP only) */\r
+                       case FREERTOS_SO_RCVBUF:        /* Set the size of the receive buffer, in units of MSS (TCP only) */\r
+                               {\r
+                                       uint32_t ulNewValue;\r
+\r
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+                                       {\r
+                                               FreeRTOS_debug_printf( ( "Set SO_%sBUF: wrong socket type\n",\r
+                                                       ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );\r
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
+                                       }\r
+\r
+                                       if( ( ( lOptionName == FREERTOS_SO_SNDBUF ) && ( pxSocket->u.xTCP.txStream != NULL ) ) ||\r
+                                               ( ( lOptionName == FREERTOS_SO_RCVBUF ) && ( pxSocket->u.xTCP.rxStream != NULL ) ) )\r
+                                       {\r
+                                               FreeRTOS_debug_printf( ( "Set SO_%sBUF: buffer already created\n",\r
+                                                       ( lOptionName == FREERTOS_SO_SNDBUF ) ? "SND" : "RCV" ) );\r
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
+                                       }\r
+\r
+                                       ulNewValue = *( ( uint32_t * ) pvOptionValue );\r
+\r
+                                       if( lOptionName == FREERTOS_SO_SNDBUF )\r
+                                       {\r
+                                               /* Round up to nearest MSS size */\r
+                                               ulNewValue = FreeRTOS_round_up( ulNewValue, ( uint32_t ) pxSocket->u.xTCP.usInitMSS );\r
+                                               pxSocket->u.xTCP.uxTxStreamSize = ulNewValue;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               pxSocket->u.xTCP.uxRxStreamSize = ulNewValue;\r
+                                       }\r
+                               }\r
+                               xReturn = 0;\r
+                               break;\r
+\r
+                       case FREERTOS_SO_WIN_PROPERTIES:        /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */\r
+                               {\r
+                                       WinProperties_t* pxProps;\r
+\r
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+                                       {\r
+                                               FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: wrong socket type\n" ) );\r
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
+                                       }\r
+\r
+                                       if( ( pxSocket->u.xTCP.txStream != NULL ) || ( pxSocket->u.xTCP.rxStream != NULL ) )\r
+                                       {\r
+                                               FreeRTOS_debug_printf( ( "Set SO_WIN_PROP: buffer already created\n" ) );\r
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
+                                       }\r
+\r
+                                       pxProps = ( ( WinProperties_t * ) pvOptionValue );\r
+                                       FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDBUF, &( pxProps->lTxBufSize ), sizeof( pxProps->lTxBufSize ) );\r
+                                       FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVBUF, &( pxProps->lRxBufSize ), sizeof( pxProps->lRxBufSize ) );\r
+                                       #if( ipconfigUSE_TCP_WIN == 1 )\r
+                                       {\r
+                                               pxSocket->u.xTCP.uxRxWinSize = ( uint32_t )pxProps->lRxWinSize; /* Fixed value: size of the TCP reception window */\r
+                                               pxSocket->u.xTCP.uxTxWinSize = ( uint32_t )pxProps->lTxWinSize; /* Fixed value: size of the TCP transmit window */\r
+                                       }\r
+                                       #else\r
+                                       {\r
+                                               pxSocket->u.xTCP.uxRxWinSize = 1u;\r
+                                               pxSocket->u.xTCP.uxTxWinSize = 1u;\r
+                                       }\r
+                                       #endif\r
+\r
+                                       /* In case the socket has already initialised its tcpWin,\r
+                                       adapt the window size parameters */\r
+                                       if( pxSocket->u.xTCP.xTCPWindow.u.bits.bHasInit != pdFALSE_UNSIGNED )\r
+                                       {\r
+                                               pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxRxWinSize * pxSocket->u.xTCP.usInitMSS;\r
+                                               pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength = pxSocket->u.xTCP.uxTxWinSize * pxSocket->u.xTCP.usInitMSS;\r
+                                       }\r
+                               }\r
+\r
+                               xReturn = 0;\r
+                               break;\r
+\r
+                       case FREERTOS_SO_REUSE_LISTEN_SOCKET:   /* If true, the server-socket will turn into a connected socket */\r
+                               {\r
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+                                       {\r
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
+                                       }\r
+                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
+                                       {\r
+                                               pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               pxSocket->u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED;\r
+                                       }\r
+                               }\r
+                               xReturn = 0;\r
+                               break;\r
+\r
+                       case FREERTOS_SO_CLOSE_AFTER_SEND:              /* As soon as the last byte has been transmitted, finalise the connection */\r
+                               {\r
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+                                       {\r
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
+                                       }\r
+\r
+                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
+                                       {\r
+                                               pxSocket->u.xTCP.bits.bCloseAfterSend = pdTRUE_UNSIGNED;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               pxSocket->u.xTCP.bits.bCloseAfterSend = pdFALSE_UNSIGNED;\r
+                                       }\r
+                               }\r
+                               xReturn = 0;\r
+                               break;\r
+\r
+                       case FREERTOS_SO_SET_FULL_SIZE:         /* Refuse to send packets smaller than MSS  */\r
+                               {\r
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+                                       {\r
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
+                                       }\r
+\r
+                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
+                                       {\r
+                                               pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdTRUE_UNSIGNED;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize = pdFALSE_UNSIGNED;\r
+                                       }\r
+\r
+                                       if( ( pxSocket->u.xTCP.xTCPWindow.u.bits.bSendFullSize == pdFALSE_UNSIGNED ) &&\r
+                                               ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&\r
+                                               ( FreeRTOS_outstanding( pxSocket ) != 0 ) )\r
+                                       {\r
+                                               pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bSendFullSize */\r
+                                               xSendEventToIPTask( eTCPTimerEvent );\r
+                                       }\r
+                               }\r
+                               xReturn = 0;\r
+                               break;\r
+\r
+                       case FREERTOS_SO_STOP_RX:               /* Refuse to receive more packts */\r
+                               {\r
+                                       if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+                                       {\r
+                                               break;  /* will return -pdFREERTOS_ERRNO_EINVAL */\r
+                                       }\r
+\r
+                                       if( *( ( BaseType_t * ) pvOptionValue ) != 0 )\r
+                                       {\r
+                                               pxSocket->u.xTCP.bits.bRxStopped = pdTRUE_UNSIGNED;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               pxSocket->u.xTCP.bits.bRxStopped = pdFALSE_UNSIGNED;\r
+                                       }\r
+\r
+                                       pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
+                                       pxSocket->u.xTCP.usTimeout = 1u; /* to set/clear bRxStopped */\r
+                                       xSendEventToIPTask( eTCPTimerEvent );\r
+                               }\r
+                               xReturn = 0;\r
+                               break;\r
+\r
+               #endif  /* ipconfigUSE_TCP == 1 */\r
+\r
+               default :\r
+                       /* No other options are handled. */\r
+                       xReturn = -pdFREERTOS_ERRNO_ENOPROTOOPT;\r
+                       break;\r
+       }\r
+\r
+       return xReturn;\r
+} /* Tested */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Get a free private ('anonymous') port number */\r
+static uint16_t prvGetPrivatePortNumber( BaseType_t xProtocol )\r
+{\r
+uint16_t usResult;\r
+BaseType_t xIndex;\r
+const List_t *pxList;\r
+\r
+#if ipconfigUSE_TCP == 1\r
+       if( xProtocol == ( BaseType_t ) FREERTOS_IPPROTO_TCP )\r
+       {\r
+               xIndex = socketNEXT_TCP_PORT_NUMBER_INDEX;\r
+               pxList = &xBoundTCPSocketsList;\r
+       }\r
+       else\r
+#endif\r
+       {\r
+               xIndex = socketNEXT_UDP_PORT_NUMBER_INDEX;\r
+               pxList = &xBoundUDPSocketsList;\r
+       }\r
+\r
+       /* Avoid compiler warnings if ipconfigUSE_TCP is not defined. */\r
+       ( void ) xProtocol;\r
+\r
+       /* Assign the next port in the range.  Has it overflowed? */\r
+       /*_RB_ This needs to be randomised rather than sequential. */\r
+       /* _HT_ Agreed, although many OS's use sequential port numbers, see\r
+       https://www.cymru.com/jtk/misc/ephemeralports.html  */\r
+       for ( ;; )\r
+       {\r
+               ++( usNextPortToUse[ xIndex ] );\r
+\r
+               if( usNextPortToUse[ xIndex ] >= socketAUTO_PORT_ALLOCATION_MAX_NUMBER )\r
+               {\r
+                       /* Don't go right back to the start of the dynamic/private port\r
+                       range numbers as any persistent sockets are likely to have been\r
+                       create first so the early port numbers may still be in use. */\r
+                       usNextPortToUse[ xIndex ] = socketAUTO_PORT_ALLOCATION_RESET_NUMBER;\r
+               }\r
+\r
+               usResult = FreeRTOS_htons( usNextPortToUse[ xIndex ] );\r
+\r
+               if( pxListFindListItemWithValue( pxList, ( TickType_t ) usResult ) == NULL )\r
+               {\r
+                       break;\r
+               }\r
+       }\r
+       return usResult;\r
+} /* Tested */\r
+/*-----------------------------------------------------------*/\r
+\r
+/* pxListFindListItemWithValue: find a list item in a bound socket list\r
+'xWantedItemValue' refers to a port number */\r
+static const ListItem_t * pxListFindListItemWithValue( const List_t *pxList, TickType_t xWantedItemValue )\r
+{\r
+const ListItem_t * pxResult = NULL;\r
+\r
+       if( ( xIPIsNetworkTaskReady() != pdFALSE ) && ( pxList != NULL ) )\r
+       {\r
+               const ListItem_t *pxIterator;\r
+               const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( pxList );\r
+               for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );\r
+                        pxIterator != ( const ListItem_t * ) pxEnd;\r
+                        pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
+               {\r
+                       if( listGET_LIST_ITEM_VALUE( pxIterator ) == xWantedItemValue )\r
+                       {\r
+                               pxResult = pxIterator;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       return pxResult;\r
+} /* Tested */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort )\r
+{\r
+const ListItem_t *pxListItem;\r
+FreeRTOS_Socket_t *pxSocket = NULL;\r
+\r
+       /* Looking up a socket is quite simple, find a match with the local port.\r
+\r
+       See if there is a list item associated with the port number on the\r
+       list of bound sockets. */\r
+       pxListItem = pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) uxLocalPort );\r
+\r
+       if( pxListItem != NULL )\r
+       {\r
+               /* The owner of the list item is the socket itself. */\r
+               pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxListItem );\r
+               configASSERT( pxSocket != NULL );\r
+       }\r
+       return pxSocket;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ipconfigINCLUDE_FULL_INET_ADDR == 1\r
+\r
+       uint32_t FreeRTOS_inet_addr( const char * pcIPAddress )\r
+       {\r
+       const uint32_t ulDecimalBase = 10u;\r
+       uint8_t ucOctet[ socketMAX_IP_ADDRESS_OCTETS ];\r
+       const char *pcPointerOnEntering;\r
+       uint32_t ulReturn = 0UL, ulValue;\r
+       UBaseType_t uxOctetNumber;\r
+       BaseType_t xResult = pdPASS;\r
+\r
+               for( uxOctetNumber = 0u; uxOctetNumber < socketMAX_IP_ADDRESS_OCTETS; uxOctetNumber++ )\r
+               {\r
+                       ulValue = 0ul;\r
+                       pcPointerOnEntering = pcIPAddress;\r
+\r
+                       while( ( *pcIPAddress >= '0' ) && ( *pcIPAddress <= '9' ) )\r
+                       {\r
+                               /* Move previous read characters into the next decimal\r
+                               position. */\r
+                               ulValue *= ulDecimalBase;\r
+\r
+                               /* Add the binary value of the ascii character. */\r
+                               ulValue += ( ( uint32_t ) ( *pcIPAddress ) - ( uint32_t ) '0' );\r
+\r
+                               /* Move to next character in the string. */\r
+                               pcIPAddress++;\r
+                       }\r
+\r
+                       /* Check characters were read. */\r
+                       if( pcIPAddress == pcPointerOnEntering )\r
+                       {\r
+                               xResult = pdFAIL;\r
+                       }\r
+\r
+                       /* Check the value fits in an 8-bit number. */\r
+                       if( ulValue > 0xffUL )\r
+                       {\r
+                               xResult = pdFAIL;\r
+                       }\r
+                       else\r
+                       {\r
+                               ucOctet[ uxOctetNumber ] = ( uint8_t ) ulValue;\r
+\r
+                               /* Check the next character is as expected. */\r
+                               if( uxOctetNumber < ( socketMAX_IP_ADDRESS_OCTETS - 1u ) )\r
+                               {\r
+                                       if( *pcIPAddress != '.' )\r
+                                       {\r
+                                               xResult = pdFAIL;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               /* Move past the dot. */\r
+                                               pcIPAddress++;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       if( xResult == pdFAIL )\r
+                       {\r
+                               /* No point going on. */\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if( *pcIPAddress != ( char ) 0 )\r
+               {\r
+                       /* Expected the end of the string. */\r
+                       xResult = pdFAIL;\r
+               }\r
+\r
+               if( uxOctetNumber != socketMAX_IP_ADDRESS_OCTETS )\r
+               {\r
+                       /* Didn't read enough octets. */\r
+                       xResult = pdFAIL;\r
+               }\r
+\r
+               if( xResult == pdPASS )\r
+               {\r
+                       ulReturn = FreeRTOS_inet_addr_quick( ucOctet[ 0 ], ucOctet[ 1 ], ucOctet[ 2 ], ucOctet[ 3 ] );\r
+               }\r
+\r
+               return ulReturn;\r
+       }\r
+\r
+#endif /* ipconfigINCLUDE_FULL_INET_ADDR */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Function to get the local address and IP port */\r
+size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )\r
+{\r
+FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+\r
+       /* IP address of local machine. */\r
+       pxAddress->sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;\r
+\r
+       /* Local port on this machine. */\r
+       pxAddress->sin_port = FreeRTOS_htons( pxSocket->usLocalPort );\r
+\r
+       return sizeof( *pxAddress );\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket )\r
+{\r
+/* _HT_ must work this out, now vSocketWakeUpUser will be called for any important\r
+ * event or transition */\r
+       #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )\r
+       {\r
+               if( pxSocket->pxUserSemaphore != NULL )\r
+               {\r
+                       xSemaphoreGive( pxSocket->pxUserSemaphore );\r
+               }\r
+       }\r
+       #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */\r
+\r
+       #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+       {\r
+               if( pxSocket->pxSocketSet != NULL )\r
+               {\r
+                       EventBits_t xSelectBits = ( pxSocket->xEventBits >> SOCKET_EVENT_BIT_COUNT ) & eSELECT_ALL;\r
+                       if( xSelectBits != 0ul )\r
+                       {\r
+                               pxSocket->xSocketBits |= xSelectBits;\r
+                               xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, xSelectBits );\r
+                       }\r
+               }\r
+\r
+               pxSocket->xEventBits &= eSOCKET_ALL;\r
+       }\r
+       #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
+\r
+       if( ( pxSocket->xEventGroup != NULL ) && ( pxSocket->xEventBits != 0u ) )\r
+       {\r
+               xEventGroupSetBits( pxSocket->xEventGroup, pxSocket->xEventBits );\r
+       }\r
+\r
+       pxSocket->xEventBits = 0ul;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
+\r
+       /* This define makes it possible for network-card drivers to inspect\r
+        * UDP message and see if there is any UDP socket bound to a given port\r
+        * number.\r
+        * This is probably only useful in systems with a minimum of RAM and\r
+        * when lots of anonymous broadcast messages come in\r
+        */\r
+       BaseType_t xPortHasUDPSocket( uint16_t usPortNr )\r
+       {\r
+       BaseType_t xFound = pdFALSE;\r
+\r
+               vTaskSuspendAll();\r
+               {\r
+                       if( ( pxListFindListItemWithValue( &xBoundUDPSocketsList, ( TickType_t ) usPortNr ) != NULL ) )\r
+                       {\r
+                               xFound = pdTRUE;\r
+                       }\r
+               }\r
+               xTaskResumeAll();\r
+\r
+               return xFound;\r
+       }\r
+\r
+#endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket );\r
+       static BaseType_t bMayConnect( FreeRTOS_Socket_t *pxSocket )\r
+       {\r
+               switch( pxSocket->u.xTCP.ucTCPState )\r
+               {\r
+                       case eCLOSED:\r
+                       case eCLOSE_WAIT:       return 0;\r
+                       case eCONNECT_SYN:      return -pdFREERTOS_ERRNO_EINPROGRESS;\r
+                       default:                        return -pdFREERTOS_ERRNO_EAGAIN;\r
+               }\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       static BaseType_t prvTCPConnectStart( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr *pxAddress )\r
+       {\r
+       BaseType_t xResult = 0;\r
+\r
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdFALSE ) == pdFALSE )\r
+               {\r
+                       /* Not a valid socket or wrong type */\r
+                       xResult = -pdFREERTOS_ERRNO_EBADF;\r
+               }\r
+               else if( FreeRTOS_issocketconnected( pxSocket ) > 0 )\r
+               {\r
+                       /* The socket is already connected. */\r
+                       xResult = -pdFREERTOS_ERRNO_EISCONN;\r
+               }\r
+               else if( socketSOCKET_IS_BOUND( pxSocket ) == pdFALSE )\r
+               {\r
+                       /* Bind the socket to the port that the client task will send from.\r
+                       Non-standard, so the error returned is that returned by bind(). */\r
+                       xResult = FreeRTOS_bind( ( Socket_t ) pxSocket, NULL, 0u );\r
+               }\r
+\r
+               if( xResult == 0 )\r
+               {\r
+                       /* Check if it makes any sense to wait for a connect event, this condition\r
+                       might change while sleeping, so it must be checked within each loop */\r
+                       xResult = bMayConnect( pxSocket ); /* -EINPROGRESS, -EAGAIN, or 0 for OK */\r
+\r
+                       /* Start the connect procedure, kernel will start working on it */\r
+                       if( xResult == 0 )\r
+                       {\r
+                               pxSocket->u.xTCP.bits.bConnPrepared = pdFALSE_UNSIGNED;\r
+                               pxSocket->u.xTCP.ucRepCount = 0u;\r
+\r
+                               FreeRTOS_debug_printf( ( "FreeRTOS_connect: %u to %lxip:%u\n",\r
+                                       pxSocket->usLocalPort, FreeRTOS_ntohl( pxAddress->sin_addr ), FreeRTOS_ntohs( pxAddress->sin_port ) ) );\r
+\r
+                               /* Port on remote machine. */\r
+                               pxSocket->u.xTCP.usRemotePort = FreeRTOS_ntohs( pxAddress->sin_port );\r
+\r
+                               /* IP address of remote machine. */\r
+                               pxSocket->u.xTCP.ulRemoteIP = FreeRTOS_ntohl( pxAddress->sin_addr );\r
+\r
+                               /* (client) internal state: socket wants to send a connect. */\r
+                               vTCPStateChange( pxSocket, eCONNECT_SYN );\r
+\r
+                               /* To start an active connect. */\r
+                               pxSocket->u.xTCP.usTimeout = 1u;\r
+\r
+                               if( xSendEventToIPTask( eTCPTimerEvent ) != pdPASS )\r
+                               {\r
+                                       xResult = -pdFREERTOS_ERRNO_ECANCELED;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /*\r
+        * FreeRTOS_connect: socket wants to connect to a remote port\r
+        */\r
+       BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t* ) xClientSocket;\r
+       TickType_t xRemainingTime;\r
+       BaseType_t xTimed = pdFALSE;\r
+       BaseType_t xResult;\r
+       TimeOut_t xTimeOut;\r
+\r
+               ( void ) xAddressLength;\r
+\r
+               xResult = prvTCPConnectStart( pxSocket, pxAddress );\r
+\r
+               if( xResult == 0 )\r
+               {\r
+                       /* And wait for the result */\r
+                       for( ;; )\r
+                       {\r
+                               if( xTimed == pdFALSE )\r
+                               {\r
+                                       /* Only in the first round, check for non-blocking */\r
+                                       xRemainingTime = pxSocket->xReceiveBlockTime;\r
+                                       if( xRemainingTime == ( TickType_t )0 )\r
+                                       {\r
+                                               /* Not yet connected, correct state, non-blocking. */\r
+                                               xResult = -pdFREERTOS_ERRNO_EWOULDBLOCK;\r
+                                               break;\r
+                                       }\r
+\r
+                                       /* Don't get here a second time. */\r
+                                       xTimed = pdTRUE;\r
+\r
+                                       /* Fetch the current time */\r
+                                       vTaskSetTimeOutState( &xTimeOut );\r
+                               }\r
+\r
+                               /* Did it get connected while sleeping ? */\r
+                               xResult = FreeRTOS_issocketconnected( pxSocket );\r
+\r
+                               /* Returns positive when connected, negative means an error */\r
+                               if( xResult < 0 )\r
+                               {\r
+                                       /* Return the error */\r
+                                       break;\r
+                               }\r
+\r
+                               if( xResult > 0 )\r
+                               {\r
+                                       /* Socket now connected, return a zero */\r
+                                       xResult = 0;\r
+                                       break;\r
+                               }\r
+\r
+                               /* Is it allowed to sleep more? */\r
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) )\r
+                               {\r
+                                       xResult = -pdFREERTOS_ERRNO_ETIMEDOUT;\r
+                                       break;\r
+                               }\r
+\r
+                               /* Go sleeping until we get any down-stream event */\r
+                               xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_CONNECT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
+                       }\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /*\r
+        * FreeRTOS_accept: can return a new connected socket\r
+        * if the server socket is in listen mode and receives a connection request\r
+        * The new socket will be bound already to the same port number as the listing\r
+        * socket.\r
+        */\r
+       Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xServerSocket;\r
+       FreeRTOS_Socket_t *pxClientSocket = NULL;\r
+       TickType_t xRemainingTime;\r
+       BaseType_t xTimed = pdFALSE, xAsk = pdFALSE;\r
+       TimeOut_t xTimeOut;\r
+       IPStackEvent_t xAskEvent;\r
+\r
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
+               {\r
+                       /* Not a valid socket or wrong type */\r
+                       pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
+               }\r
+               else if( ( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) &&\r
+                                ( pxSocket->u.xTCP.ucTCPState != eTCP_LISTEN ) )\r
+               {\r
+                       /* Parent socket is not in listening mode */\r
+                       pxClientSocket = ( FreeRTOS_Socket_t * ) FREERTOS_INVALID_SOCKET;\r
+               }\r
+               else\r
+               {\r
+                       /* Loop will stop with breaks. */\r
+                       for( ; ; )\r
+                       {\r
+                               /* Is there a new client? */\r
+                               vTaskSuspendAll();\r
+                               {\r
+                                       if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )\r
+                                       {\r
+                                               pxClientSocket = pxSocket->u.xTCP.pxPeerSocket;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               pxClientSocket = pxSocket;\r
+                                       }\r
+                                       if( pxClientSocket != NULL )\r
+                                       {\r
+                                               pxSocket->u.xTCP.pxPeerSocket = NULL;\r
+\r
+                                               /* Is it still not taken ? */\r
+                                               if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED )\r
+                                               {\r
+                                                       pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       pxClientSocket = NULL;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               xTaskResumeAll();\r
+\r
+                               if( pxClientSocket != NULL )\r
+                               {\r
+                                       if( pxAddress != NULL )\r
+                                       {\r
+                                               /* IP address of remote machine. */\r
+                                               pxAddress->sin_addr = FreeRTOS_ntohl( pxClientSocket->u.xTCP.ulRemoteIP );\r
+\r
+                                               /* Port on remote machine. */\r
+                                               pxAddress->sin_port = FreeRTOS_ntohs( pxClientSocket->u.xTCP.usRemotePort );\r
+                                       }\r
+                                       if( pxAddressLength != NULL )\r
+                                       {\r
+                                               *pxAddressLength = sizeof( *pxAddress );\r
+                                       }\r
+\r
+                                       if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )\r
+                                       {\r
+                                               xAsk = pdTRUE;\r
+                                       }\r
+                               }\r
+\r
+                               if( xAsk != pdFALSE )\r
+                               {\r
+                                       /* Ask to set an event in 'xEventGroup' as soon as a new\r
+                                       client gets connected for this listening socket. */\r
+                                       xAskEvent.eEventType = eTCPAcceptEvent;\r
+                                       xAskEvent.pvData = ( void * ) pxSocket;\r
+                                       xSendEventStructToIPTask( &xAskEvent, portMAX_DELAY );\r
+                               }\r
+\r
+                               if( pxClientSocket != NULL )\r
+                               {\r
+                                       break;\r
+                               }\r
+\r
+                               if( xTimed == pdFALSE )\r
+                               {\r
+                                       /* Only in the first round, check for non-blocking */\r
+                                       xRemainingTime = pxSocket->xReceiveBlockTime;\r
+                                       if( xRemainingTime == ( TickType_t ) 0 )\r
+                                       {\r
+                                               break;\r
+                                       }\r
+\r
+                                       /* Don't get here a second time */\r
+                                       xTimed = pdTRUE;\r
+\r
+                                       /* Fetch the current time */\r
+                                       vTaskSetTimeOutState( &xTimeOut );\r
+                               }\r
+\r
+                               /* Has the timeout been reached? */\r
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
+                               {\r
+                                       break;\r
+                               }\r
+\r
+                               /* Go sleeping until we get any down-stream event */\r
+                               xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_ACCEPT, pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
+                       }\r
+               }\r
+\r
+               return ( Socket_t ) pxClientSocket;\r
+       }\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /*\r
+        * Read incoming data from a TCP socket\r
+        * Only after the last byte has been read, a close error might be returned\r
+        */\r
+       BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags )\r
+       {\r
+       BaseType_t xByteCount;\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       TickType_t xRemainingTime;\r
+       BaseType_t xTimed = pdFALSE;\r
+       TimeOut_t xTimeOut;\r
+       EventBits_t xEventBits = ( EventBits_t ) 0;\r
+\r
+               /* Check if the socket is valid, has type TCP and if it is bound to a\r
+               port. */\r
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
+               {\r
+                       xByteCount = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+               else\r
+               {\r
+                       if( pxSocket->u.xTCP.rxStream != NULL )\r
+                       {\r
+                               xByteCount = ( BaseType_t )uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );\r
+                       }\r
+                       else\r
+                       {\r
+                               xByteCount = 0;\r
+                       }\r
+\r
+                       while( xByteCount == 0 )\r
+                       {\r
+                               switch( pxSocket->u.xTCP.ucTCPState )\r
+                               {\r
+                               case eCLOSED:\r
+                               case eCLOSE_WAIT:       /* (server + client) waiting for a connection termination request from the local user. */\r
+                               case eCLOSING:          /* (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */\r
+                                       if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )\r
+                                       {\r
+                                               /* The no-memory error has priority above the non-connected error.\r
+                                               Both are fatal and will elad to closing the socket. */\r
+                                               xByteCount = -pdFREERTOS_ERRNO_ENOMEM;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               xByteCount = -pdFREERTOS_ERRNO_ENOTCONN;\r
+                                       }\r
+                                       /* Call continue to break out of the switch and also the while\r
+                                       loop. */\r
+                                       continue;\r
+                               default:\r
+                                       break;\r
+                               }\r
+\r
+                               if( xTimed == pdFALSE )\r
+                               {\r
+                                       /* Only in the first round, check for non-blocking. */\r
+                                       xRemainingTime = pxSocket->xReceiveBlockTime;\r
+\r
+                                       if( xRemainingTime == ( TickType_t ) 0 )\r
+                                       {\r
+                                               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
+                                               {\r
+                                                       /* Just check for the interrupt flag. */\r
+                                                       xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_INTR,\r
+                                                               pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, socketDONT_BLOCK );\r
+                                               }\r
+                                               #endif /* ipconfigSUPPORT_SIGNALS */\r
+                                               break;\r
+                                       }\r
+\r
+                                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
+                                       {\r
+                                               break;\r
+                                       }\r
+\r
+                                       /* Don't get here a second time. */\r
+                                       xTimed = pdTRUE;\r
+\r
+                                       /* Fetch the current time. */\r
+                                       vTaskSetTimeOutState( &xTimeOut );\r
+                               }\r
+\r
+                               /* Has the timeout been reached? */\r
+                               if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
+                               {\r
+                                       break;\r
+                               }\r
+\r
+                               /* Block until there is a down-stream event. */\r
+                               xEventBits = xEventGroupWaitBits( pxSocket->xEventGroup,\r
+                                       eSOCKET_RECEIVE | eSOCKET_CLOSED | eSOCKET_INTR,\r
+                                       pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
+                               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
+                               {\r
+                                       if( ( xEventBits & eSOCKET_INTR ) != 0u )\r
+                                       {\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               #else\r
+                               {\r
+                                       ( void ) xEventBits;\r
+                               }\r
+                               #endif /* ipconfigSUPPORT_SIGNALS */\r
+\r
+                               if( pxSocket->u.xTCP.rxStream != NULL )\r
+                               {\r
+                                       xByteCount = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.rxStream );\r
+                               }\r
+                               else\r
+                               {\r
+                                       xByteCount = 0;\r
+                               }\r
+                       }\r
+\r
+               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
+                       if( ( xEventBits & eSOCKET_INTR ) != 0 )\r
+                       {\r
+                               if( ( xEventBits & ( eSOCKET_RECEIVE | eSOCKET_CLOSED ) ) != 0 )\r
+                               {\r
+                                       /* Shouldn't have cleared other flags. */\r
+                                       xEventBits &= ~eSOCKET_INTR;\r
+                                       xEventGroupSetBits( pxSocket->xEventGroup, xEventBits );\r
+                               }\r
+                               xByteCount = -pdFREERTOS_ERRNO_EINTR;\r
+                       }\r
+                       else\r
+               #endif /* ipconfigSUPPORT_SIGNALS */\r
+                       if( xByteCount > 0 )\r
+                       {\r
+                               if( ( xFlags & FREERTOS_ZERO_COPY ) == 0 )\r
+                               {\r
+                                       xByteCount = ( BaseType_t ) uxStreamBufferGet( pxSocket->u.xTCP.rxStream, 0ul, ( uint8_t * ) pvBuffer, ( size_t ) xBufferLength, ( xFlags & FREERTOS_MSG_PEEK ) != 0 );\r
+                                       if( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED )\r
+                                       {\r
+                                               /* We had reached the low-water mark, now see if the flag\r
+                                               can be cleared */\r
+                                               size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );\r
+\r
+                                               if( uxFrontSpace >= pxSocket->u.xTCP.uxEnoughSpace )\r
+                                               {\r
+                                                       pxSocket->u.xTCP.bits.bLowWater = pdFALSE_UNSIGNED;\r
+                                                       pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
+                                                       pxSocket->u.xTCP.usTimeout = 1u; /* because bLowWater is cleared. */\r
+                                                       xSendEventToIPTask( eTCPTimerEvent );\r
+                                               }\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Zero-copy reception of data: pvBuffer is a pointer to a pointer. */\r
+                                       xByteCount = ( BaseType_t ) uxStreamBufferGetPtr( pxSocket->u.xTCP.rxStream, (uint8_t **)pvBuffer );\r
+                               }\r
+                       }\r
+               } /* prvValidSocket() */\r
+\r
+               return xByteCount;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       static int32_t prvTCPSendCheck( FreeRTOS_Socket_t *pxSocket, size_t xDataLength )\r
+       {\r
+       int32_t xResult = 1;\r
+\r
+               /* Is this a socket of type TCP and is it already bound to a port number ? */\r
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
+               {\r
+                       xResult = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+               else if( pxSocket->u.xTCP.bits.bMallocError != pdFALSE_UNSIGNED )\r
+               {\r
+                       xResult = -pdFREERTOS_ERRNO_ENOMEM;\r
+               }\r
+               else if( pxSocket->u.xTCP.ucTCPState == eCLOSED )\r
+               {\r
+                       xResult = -pdFREERTOS_ERRNO_ENOTCONN;\r
+               }\r
+               else if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )\r
+               {\r
+                       /* This TCP connection is closing already, the FIN flag has been sent.\r
+                       Maybe it is still delivering or receiving data.\r
+                       Return OK in order not to get closed/deleted too quickly */\r
+                       xResult = 0;\r
+               }\r
+               else if( xDataLength == 0ul )\r
+               {\r
+                       /* send() is being called to send zero bytes */\r
+                       xResult = 0;\r
+               }\r
+               else if( pxSocket->u.xTCP.txStream == NULL )\r
+               {\r
+                       /* Create the outgoing stream only when it is needed */\r
+                       prvTCPCreateStream( pxSocket, pdFALSE );\r
+\r
+                       if( pxSocket->u.xTCP.txStream == NULL )\r
+                       {\r
+                               xResult = -pdFREERTOS_ERRNO_ENOMEM;\r
+                       }\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /* Get a direct pointer to the circular transmit buffer.\r
+       '*pxLength' will contain the number of bytes that may be written. */\r
+       uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength )\r
+       {\r
+       uint8_t *pucReturn;\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       StreamBuffer_t *pxBuffer = pxSocket->u.xTCP.txStream;\r
+\r
+               if( pxBuffer != NULL )\r
+               {\r
+               BaseType_t xSpace = ( BaseType_t ) uxStreamBufferGetSpace( pxBuffer );\r
+               BaseType_t xRemain = ( BaseType_t ) ( pxBuffer->LENGTH - pxBuffer->uxHead );\r
+\r
+                       *pxLength = FreeRTOS_min_BaseType( xSpace, xRemain );\r
+                       pucReturn = pxBuffer->ucArray + pxBuffer->uxHead;\r
+               }\r
+               else\r
+               {\r
+                       *pxLength = 0;\r
+                       pucReturn = NULL;\r
+               }\r
+\r
+               return pucReturn;\r
+       }\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+       /*\r
+        * Send data using a TCP socket.  It is not necessary to have the socket\r
+        * connected already.  Outgoing data will be stored and delivered as soon as\r
+        * the socket gets connected.\r
+        */\r
+       BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags )\r
+       {\r
+       BaseType_t xByteCount;\r
+       BaseType_t xBytesLeft;\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       TickType_t xRemainingTime;\r
+       BaseType_t xTimed = pdFALSE;\r
+       TimeOut_t xTimeOut;\r
+       BaseType_t xCloseAfterSend;\r
+\r
+               /* Prevent compiler warnings about unused parameters.  The parameter\r
+               may be used in future versions. */\r
+               ( void ) xFlags;\r
+\r
+               xByteCount = ( BaseType_t ) prvTCPSendCheck( pxSocket, uxDataLength );\r
+\r
+               if( xByteCount > 0 )\r
+               {\r
+                       /* xBytesLeft is number of bytes to send, will count to zero. */\r
+                       xBytesLeft = ( BaseType_t ) uxDataLength;\r
+\r
+                       /* xByteCount is number of bytes that can be sent now. */\r
+                       xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
+\r
+                       /* While there are still bytes to be sent. */\r
+                       while( xBytesLeft > 0 )\r
+                       {\r
+                               /* If txStream has space. */\r
+                               if( xByteCount > 0 )\r
+                               {\r
+                                       /* Don't send more than necessary. */\r
+                                       if( xByteCount > xBytesLeft )\r
+                                       {\r
+                                               xByteCount = xBytesLeft;\r
+                                       }\r
+\r
+                                       /* Is the close-after-send flag set and is this really the\r
+                                       last transmission? */\r
+                                       if( ( pxSocket->u.xTCP.bits.bCloseAfterSend != pdFALSE_UNSIGNED ) && ( xByteCount == xBytesLeft ) )\r
+                                       {\r
+                                               xCloseAfterSend = pdTRUE;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               xCloseAfterSend = pdFALSE;\r
+                                       }\r
+\r
+                                       /* The flag 'bCloseAfterSend' can be set before sending data\r
+                                       using setsockopt()\r
+\r
+                                       When the last data packet is being sent out, a FIN flag will\r
+                                       be included to let the peer know that no more data is to be\r
+                                       expected.  The use of 'bCloseAfterSend' is not mandatory, it\r
+                                       is just a faster way of transferring files (e.g. when using\r
+                                       FTP). */\r
+                                       if( xCloseAfterSend != pdFALSE )\r
+                                       {\r
+                                               /* Now suspend the scheduler: sending the last data     and\r
+                                               setting bCloseRequested must be done together */\r
+                                               vTaskSuspendAll();\r
+                                               pxSocket->u.xTCP.bits.bCloseRequested = pdTRUE_UNSIGNED;\r
+                                       }\r
+\r
+                                       xByteCount = ( BaseType_t ) uxStreamBufferAdd( pxSocket->u.xTCP.txStream, 0ul, ( const uint8_t * ) pvBuffer, ( size_t ) xByteCount );\r
+\r
+                                       if( xCloseAfterSend != pdFALSE )\r
+                                       {\r
+                                               /* Now when the IP-task transmits the data, it will also\r
+                                               see     that bCloseRequested is true and include the FIN\r
+                                               flag to start closure of the connection. */\r
+                                               xTaskResumeAll();\r
+                                       }\r
+\r
+                                       /* Send a message to the IP-task so it can work on this\r
+                                       socket.  Data is sent, let the IP-task work on it. */\r
+                                       pxSocket->u.xTCP.usTimeout = 1u;\r
+\r
+                                       if( xIsCallingFromIPTask() == pdFALSE )\r
+                                       {\r
+                                               /* Only send a TCP timer event when not called from the\r
+                                               IP-task. */\r
+                                               xSendEventToIPTask( eTCPTimerEvent );\r
+                                       }\r
+\r
+                                       xBytesLeft -= xByteCount;\r
+\r
+                                       if( xBytesLeft == 0 )\r
+                                       {\r
+                                               break;\r
+                                       }\r
+\r
+                                       /* As there are still bytes left to be sent, increase the\r
+                                       data pointer. */\r
+                                       pvBuffer = ( void * ) ( ( ( const uint8_t * ) pvBuffer) + xByteCount );\r
+                               }\r
+\r
+                               /* Not all bytes have been sent. In case the socket is marked as\r
+                               blocking sleep for a while. */\r
+                               if( xTimed == pdFALSE )\r
+                               {\r
+                                       /* Only in the first round, check for non-blocking. */\r
+                                       xRemainingTime = pxSocket->xSendBlockTime;\r
+\r
+                                       #if( ipconfigUSE_CALLBACKS != 0 )\r
+                                       {\r
+                                               if( xIsCallingFromIPTask() != pdFALSE )\r
+                                               {\r
+                                                       /* If this send function is called from within a\r
+                                                       call-back handler it may not block, otherwise\r
+                                                       chances would be big to get a deadlock: the IP-task\r
+                                                       waiting for     itself. */\r
+                                                       xRemainingTime = ( TickType_t ) 0;\r
+                                               }\r
+                                       }\r
+                                       #endif /* ipconfigUSE_CALLBACKS */\r
+\r
+                                       if( xRemainingTime == ( TickType_t ) 0 )\r
+                                       {\r
+                                               break;\r
+                                       }\r
+\r
+                                       if( ( xFlags & FREERTOS_MSG_DONTWAIT ) != 0 )\r
+                                       {\r
+                                               break;\r
+                                       }\r
+\r
+                                       /* Don't get here a second time. */\r
+                                       xTimed = pdTRUE;\r
+\r
+                                       /* Fetch the current time. */\r
+                                       vTaskSetTimeOutState( &xTimeOut );\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Has the timeout been reached? */\r
+                                       if( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) != pdFALSE )\r
+                                       {\r
+                                               break;\r
+                                       }\r
+                               }\r
+\r
+                               /* Go sleeping until down-stream events are received. */\r
+                               xEventGroupWaitBits( pxSocket->xEventGroup, eSOCKET_SEND | eSOCKET_CLOSED,\r
+                                       pdTRUE /*xClearOnExit*/, pdFALSE /*xWaitAllBits*/, xRemainingTime );\r
+\r
+                               xByteCount = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
+                       }\r
+\r
+                       /* How much was actually sent? */\r
+                       xByteCount = ( ( BaseType_t ) uxDataLength ) - xBytesLeft;\r
+\r
+                       if( xByteCount == 0 )\r
+                       {\r
+                               if( pxSocket->u.xTCP.ucTCPState > eESTABLISHED )\r
+                               {\r
+                                       xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOTCONN;\r
+                               }\r
+                               else\r
+                               {\r
+                                       if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )\r
+                                       {\r
+                                               FreeRTOS_debug_printf( ( "FreeRTOS_send: %u -> %lxip:%d: no space\n",\r
+                                                       pxSocket->usLocalPort,\r
+                                                       pxSocket->u.xTCP.ulRemoteIP,\r
+                                                       pxSocket->u.xTCP.usRemotePort ) );\r
+                                       }\r
+\r
+                                       xByteCount = ( BaseType_t ) -pdFREERTOS_ERRNO_ENOSPC;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return xByteCount;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /*\r
+        * Request to put a socket in listen mode\r
+        */\r
+       BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket;\r
+       BaseType_t xResult = 0;\r
+\r
+               pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+\r
+               /* listen() is allowed for a valid TCP socket in Closed state and already\r
+               bound. */\r
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
+               {\r
+                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
+               }\r
+               else if( ( pxSocket->u.xTCP.ucTCPState != eCLOSED ) && ( pxSocket->u.xTCP.ucTCPState != eCLOSE_WAIT ) )\r
+               {\r
+                       /* Socket is in a wrong state. */\r
+                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
+               }\r
+               else\r
+               {\r
+                       /* Backlog is interpreted here as "the maximum number of child\r
+                       sockets. */\r
+                       pxSocket->u.xTCP.usBacklog = ( uint16_t )FreeRTOS_min_int32( ( int32_t ) 0xffff, ( int32_t ) xBacklog );\r
+\r
+                       /* This cleaning is necessary only if a listening socket is being\r
+                       reused as it might have had a previous connection. */\r
+                       if( pxSocket->u.xTCP.bits.bReuseSocket )\r
+                       {\r
+                               if( pxSocket->u.xTCP.rxStream != NULL )\r
+                               {\r
+                                       vStreamBufferClear( pxSocket->u.xTCP.rxStream );\r
+                               }\r
+\r
+                               if( pxSocket->u.xTCP.txStream != NULL )\r
+                               {\r
+                                       vStreamBufferClear( pxSocket->u.xTCP.txStream );\r
+                               }\r
+\r
+                               memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );\r
+                               memset( &pxSocket->u.xTCP.xTCPWindow, '\0', sizeof( pxSocket->u.xTCP.xTCPWindow ) );\r
+                               memset( &pxSocket->u.xTCP.bits, '\0', sizeof( pxSocket->u.xTCP.bits ) );\r
+\r
+                               /* Now set the bReuseSocket flag again, because the bits have\r
+                               just been cleared. */\r
+                               pxSocket->u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED;\r
+                       }\r
+\r
+                       vTCPStateChange( pxSocket, eTCP_LISTEN );\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /* shutdown - shut down part of a full-duplex connection */\r
+       BaseType_t FreeRTOS_shutdown( Socket_t xSocket, BaseType_t xHow )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       BaseType_t xResult;\r
+\r
+               if( prvValidSocket( pxSocket, FREERTOS_IPPROTO_TCP, pdTRUE ) == pdFALSE )\r
+               {\r
+                       /*_RB_ Is this comment correct?  The socket is not of a type that\r
+                       supports the listen() operation. */\r
+                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
+               }\r
+               else if ( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )\r
+               {\r
+                       /*_RB_ Is this comment correct?  The socket is not of a type that\r
+                       supports the listen() operation. */\r
+                       xResult = -pdFREERTOS_ERRNO_EOPNOTSUPP;\r
+               }\r
+               else\r
+               {\r
+                       pxSocket->u.xTCP.bits.bUserShutdown = pdTRUE_UNSIGNED;\r
+\r
+                       /* Let the IP-task perform the shutdown of the connection. */\r
+                       pxSocket->u.xTCP.usTimeout = 1u;\r
+                       xSendEventToIPTask( eTCPTimerEvent );\r
+                       xResult = 0;\r
+               }\r
+               (void) xHow;\r
+\r
+               return xResult;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /*\r
+        * A TCP timer has expired, now check all TCP sockets for:\r
+        * - Active connect\r
+        * - Send a delayed ACK\r
+        * - Send new data\r
+        * - Send a keep-alive packet\r
+        * - Check for timeout (in non-connected states only)\r
+        */\r
+       TickType_t xTCPTimerCheck( BaseType_t xWillSleep )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket;\r
+       TickType_t xShortest = pdMS_TO_TICKS( ( TickType_t ) ipTCP_TIMER_PERIOD_MS );\r
+       TickType_t xNow = xTaskGetTickCount();\r
+       static TickType_t xLastTime = 0u;\r
+       TickType_t xDelta = xNow - xLastTime;\r
+       ListItem_t* pxEnd = ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );\r
+       ListItem_t *pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );\r
+\r
+               xLastTime = xNow;\r
+\r
+               if( xDelta == 0u )\r
+               {\r
+                       xDelta = 1u;\r
+               }\r
+\r
+               while( pxIterator != pxEnd )\r
+               {\r
+                       pxSocket = ( FreeRTOS_Socket_t * )listGET_LIST_ITEM_OWNER( pxIterator );\r
+                       pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator );\r
+\r
+                       /* Sockets with 'tmout == 0' do not need any regular attention. */\r
+                       if( pxSocket->u.xTCP.usTimeout == 0u )\r
+                       {\r
+                               continue;\r
+                       }\r
+\r
+                       if( xDelta < ( TickType_t ) pxSocket->u.xTCP.usTimeout )\r
+                       {\r
+                               pxSocket->u.xTCP.usTimeout = ( uint16_t ) ( ( ( TickType_t ) pxSocket->u.xTCP.usTimeout ) - xDelta );\r
+                       }\r
+                       else\r
+                       {\r
+                       int rc ;\r
+                               pxSocket->u.xTCP.usTimeout = 0u;\r
+                               rc = xTCPSocketCheck( pxSocket );\r
+\r
+                               /* Within this function, the socket might want to send a delayed\r
+                               ack or send out data or whatever it needs to do. */\r
+                               if( rc < 0 )\r
+                               {\r
+                                       /* Continue because the socket was deleted. */\r
+                                       continue;\r
+                               }\r
+                       }\r
+\r
+                       /* In xEventBits the driver may indicate that the socket has\r
+                       important events for the user.  These are only done just before the\r
+                       IP-task goes to sleep. */\r
+                       if( pxSocket->xEventBits != 0u )\r
+                       {\r
+                               if( xWillSleep != pdFALSE )\r
+                               {\r
+                                       /* The IP-task is about to go to sleep, so messages can be\r
+                                       sent to the socket owners. */\r
+                                       vSocketWakeUpUser( pxSocket );\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Or else make sure this will be called again to wake-up\r
+                                       the sockets' owner. */\r
+                                       xShortest = ( TickType_t ) 0;\r
+                               }\r
+                       }\r
+\r
+                       if( ( pxSocket->u.xTCP.usTimeout != 0u ) && ( xShortest > ( TickType_t ) pxSocket->u.xTCP.usTimeout ) )\r
+                       {\r
+                               xShortest = ( TickType_t ) pxSocket->u.xTCP.usTimeout;\r
+                       }\r
+               }\r
+\r
+               return xShortest;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /*\r
+        * TCP: as multiple sockets may be bound to the same local port number\r
+        * looking up a socket is a little more complex:\r
+        * Both a local port, and a remote port and IP address are being used\r
+        * For a socket in listening mode, the remote port and IP address are both 0\r
+        */\r
+       FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort )\r
+       {\r
+       ListItem_t *pxIterator;\r
+       FreeRTOS_Socket_t *pxResult = NULL, *pxListenSocket = NULL;\r
+       MiniListItem_t *pxEnd = ( MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );\r
+\r
+               /* Parameter not yet supported. */\r
+               ( void ) ulLocalIP;\r
+\r
+               for( pxIterator  = ( ListItem_t * ) listGET_NEXT( pxEnd );\r
+                        pxIterator != ( ListItem_t * ) pxEnd;\r
+                        pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
+               {\r
+                       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
+\r
+                       if( pxSocket->usLocalPort == ( uint16_t ) uxLocalPort )\r
+                       {\r
+                               if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )\r
+                               {\r
+                                       /* If this is a socket listening to uxLocalPort, remember it\r
+                                       in case there is no perfect match. */\r
+                                       pxListenSocket = pxSocket;\r
+                               }\r
+                               else if( ( pxSocket->u.xTCP.usRemotePort == ( uint16_t ) uxRemotePort ) && ( pxSocket->u.xTCP.ulRemoteIP == ulRemoteIP ) )\r
+                               {\r
+                                       /* For sockets not in listening mode, find a match with\r
+                                       xLocalPort, ulRemoteIP AND xRemotePort. */\r
+                                       pxResult = pxSocket;\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+               if( pxResult == NULL )\r
+               {\r
+                       /* An exact match was not found, maybe a listening socket was\r
+                       found. */\r
+                       pxResult = pxListenSocket;\r
+               }\r
+\r
+               return pxResult;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = (FreeRTOS_Socket_t *)xSocket;\r
+\r
+               return pxSocket->u.xTCP.rxStream;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       static StreamBuffer_t *prvTCPCreateStream ( FreeRTOS_Socket_t *pxSocket, BaseType_t xIsInputStream )\r
+       {\r
+       StreamBuffer_t *pxBuffer;\r
+       size_t uxLength;\r
+       size_t uxSize;\r
+\r
+               /* Now that a stream is created, the maximum size is fixed before\r
+               creation, it could still be changed with setsockopt(). */\r
+               if( xIsInputStream != pdFALSE )\r
+               {\r
+                       uxLength = pxSocket->u.xTCP.uxRxStreamSize;\r
+\r
+                       if( pxSocket->u.xTCP.uxLittleSpace == 0ul )\r
+                       {\r
+                               pxSocket->u.xTCP.uxLittleSpace  = ( 1ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why divide by 5?  Can this be changed to a #define? */\r
+                       }\r
+\r
+                       if( pxSocket->u.xTCP.uxEnoughSpace == 0ul )\r
+                       {\r
+                               pxSocket->u.xTCP.uxEnoughSpace = ( 4ul * pxSocket->u.xTCP.uxRxStreamSize ) / 5u; /*_RB_ Why multiply by 4?  Maybe sock80_PERCENT?*/\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       uxLength = pxSocket->u.xTCP.uxTxStreamSize;\r
+               }\r
+\r
+               /* Add an extra 4 (or 8) bytes. */\r
+               uxLength += sizeof( size_t );\r
+\r
+               /* And make the length a multiple of sizeof( size_t ). */\r
+               uxLength &= ~( sizeof( size_t ) - 1u );\r
+\r
+               uxSize = sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) + uxLength;\r
+\r
+               pxBuffer = ( StreamBuffer_t * )pvPortMallocLarge( uxSize );\r
+\r
+               if( pxBuffer == NULL )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) );\r
+                       pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED;\r
+                       vTCPStateChange( pxSocket, eCLOSE_WAIT );\r
+               }\r
+               else\r
+               {\r
+                       /* Clear the markers of the stream */\r
+                       memset( pxBuffer, '\0', sizeof( *pxBuffer ) - sizeof( pxBuffer->ucArray ) );\r
+                       pxBuffer->LENGTH = ( size_t ) uxLength ;\r
+\r
+                       if( xTCPWindowLoggingLevel != 0 )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "prvTCPCreateStream: %cxStream created %lu bytes (total %lu)\n", xIsInputStream ? 'R' : 'T', uxLength, uxSize ) );\r
+                       }\r
+\r
+                       if( xIsInputStream != 0 )\r
+                       {\r
+                               pxSocket->u.xTCP.rxStream = pxBuffer;\r
+                       }\r
+                       else\r
+                       {\r
+                               pxSocket->u.xTCP.txStream = pxBuffer;\r
+                       }\r
+               }\r
+\r
+               return pxBuffer;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /*\r
+        * Add data to the RxStream.  When uxOffset > 0, data has come in out-of-order\r
+        * and will be put in front of the head so it can not be popped by the user.\r
+        */\r
+       int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount )\r
+       {\r
+       StreamBuffer_t *pxStream = pxSocket->u.xTCP.rxStream;\r
+       int32_t xResult;\r
+       #if( ipconfigUSE_CALLBACKS == 1 )\r
+               BaseType_t bHasHandler = ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleReceive );\r
+               const uint8_t *pucBuffer = NULL;\r
+       #endif /* ipconfigUSE_CALLBACKS */\r
+\r
+               /* int32_t uxStreamBufferAdd( pxBuffer, uxOffset, pucData, aCount )\r
+               if( pucData != NULL ) copy data the the buffer\r
+               if( pucData == NULL ) no copying, just advance rxHead\r
+               if( uxOffset != 0 ) Just store data which has come out-of-order\r
+               if( uxOffset == 0 ) Also advance rxHead */\r
+               if( pxStream == NULL )\r
+               {\r
+                       pxStream = prvTCPCreateStream( pxSocket, pdTRUE );\r
+                       if( pxStream == NULL )\r
+                       {\r
+                               return -1;\r
+                       }\r
+               }\r
+\r
+               #if( ipconfigUSE_CALLBACKS == 1 )\r
+               {\r
+                       if( ( bHasHandler != pdFALSE ) && ( uxStreamBufferGetSize( pxStream ) == 0u ) && ( uxOffset == 0ul ) && ( pcData != NULL ) )\r
+                       {\r
+                               /* Data can be passed directly to the user */\r
+                               pucBuffer = pcData;\r
+\r
+                               /* Zero-copy for call-back: no need to add the bytes to the\r
+                               stream, only the pointer will be advanced by uxStreamBufferAdd(). */\r
+                               pcData = NULL;\r
+                       }\r
+               }\r
+               #endif /* ipconfigUSE_CALLBACKS */\r
+\r
+               xResult = ( int32_t ) uxStreamBufferAdd( pxStream, uxOffset, pcData, ( size_t ) ulByteCount );\r
+\r
+               #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+               {\r
+                       if( xResult != ( int32_t ) ulByteCount )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "lTCPAddRxdata: at %ld: %ld/%lu bytes (tail %lu head %lu space %lu front %lu)\n",\r
+                                       uxOffset, xResult, ulByteCount,\r
+                                       pxStream->uxTail,\r
+                                       pxStream->uxHead,\r
+                                       uxStreamBufferFrontSpace( pxStream ),\r
+                                       pxStream->uxFront ) );\r
+                       }\r
+               }\r
+               #endif /* ipconfigHAS_DEBUG_PRINTF */\r
+\r
+               if( uxOffset == 0u )\r
+               {\r
+                       /* Data is being added to rxStream at the head (offs = 0) */\r
+                       #if( ipconfigUSE_CALLBACKS == 1 )\r
+                               if( bHasHandler != pdFALSE )\r
+                               {\r
+                                       /* The socket owner has installed an OnReceive handler. Pass the\r
+                                       Rx data, without copying from the rxStream, to the user. */\r
+                                       for (;;)\r
+                                       {\r
+                                               uint8_t *ucReadPtr = NULL;\r
+                                               uint32_t ulCount;\r
+                                               if( pucBuffer != NULL )\r
+                                               {\r
+                                                       ucReadPtr = ( uint8_t * )pucBuffer;\r
+                                                       ulCount = ulByteCount;\r
+                                                       pucBuffer = NULL;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       ulCount = ( uint32_t ) uxStreamBufferGetPtr( pxStream, &( ucReadPtr ) );\r
+                                               }\r
+\r
+                                               if( ulCount == 0ul )\r
+                                               {\r
+                                                       break;\r
+                                               }\r
+\r
+                                               if( pxSocket->u.xTCP.pxHandleReceive( (Socket_t *)pxSocket, ( void* )ucReadPtr, ( size_t ) ulCount ) != pdFALSE )\r
+                                               {\r
+                                                       uxStreamBufferGet( pxStream, 0ul, NULL, ( size_t ) ulCount, pdFALSE );\r
+                                               }\r
+                                       }\r
+                               } else\r
+                       #endif /* ipconfigUSE_CALLBACKS */\r
+                       {\r
+                               /* See if running out of space. */\r
+                               if( pxSocket->u.xTCP.bits.bLowWater == pdFALSE_UNSIGNED )\r
+                               {\r
+                                       size_t uxFrontSpace = uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );\r
+                                       if( uxFrontSpace <= pxSocket->u.xTCP.uxLittleSpace  )\r
+                                       {\r
+                                               pxSocket->u.xTCP.bits.bLowWater = pdTRUE_UNSIGNED;\r
+                                               pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
+\r
+                                               /* bLowWater was reached, send the changed window size. */\r
+                                               pxSocket->u.xTCP.usTimeout = 1u;\r
+                                               xSendEventToIPTask( eTCPTimerEvent );\r
+                                       }\r
+                               }\r
+\r
+                               /* New incoming data is available, wake up the user.   User's\r
+                               semaphores will be set just before the IP-task goes asleep. */\r
+                               pxSocket->xEventBits |= eSOCKET_RECEIVE;\r
+\r
+                               #if ipconfigSUPPORT_SELECT_FUNCTION == 1\r
+                               {\r
+                                       if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )\r
+                                       {\r
+                                               pxSocket->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );\r
+                                       }\r
+                               }\r
+                               #endif\r
+                       }\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /* Function to get the remote address and IP port */\r
+       BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       BaseType_t xResult;\r
+\r
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+               {\r
+                       xResult = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+               else\r
+               {\r
+                       /* BSD style sockets communicate IP and port addresses in network\r
+                       byte order.\r
+\r
+                       IP address of remote machine. */\r
+                       pxAddress->sin_addr = FreeRTOS_htonl ( pxSocket->u.xTCP.ulRemoteIP );\r
+\r
+                       /* Port on remote machine. */\r
+                       pxAddress->sin_port = FreeRTOS_htons ( pxSocket->u.xTCP.usRemotePort );\r
+\r
+                       xResult = ( BaseType_t ) sizeof( ( *pxAddress ) );\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /* Returns the number of bytes that may be added to txStream */\r
+       BaseType_t FreeRTOS_maywrite( Socket_t xSocket )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       BaseType_t xResult;\r
+\r
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+               {\r
+                       xResult = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+               else if( pxSocket->u.xTCP.ucTCPState != eESTABLISHED )\r
+               {\r
+                       if( ( pxSocket->u.xTCP.ucTCPState < eCONNECT_SYN ) || ( pxSocket->u.xTCP.ucTCPState > eESTABLISHED ) )\r
+                       {\r
+                               xResult = -1;\r
+                       }\r
+                       else\r
+                       {\r
+                               xResult = 0;\r
+                       }\r
+               }\r
+               else if( pxSocket->u.xTCP.txStream == NULL )\r
+               {\r
+                       xResult = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;\r
+               }\r
+               else\r
+               {\r
+                       xResult = ( BaseType_t ) uxStreamBufferGetSpace( pxSocket->u.xTCP.txStream );\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP ==1 )\r
+\r
+       BaseType_t FreeRTOS_tx_space( Socket_t xSocket )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       BaseType_t xReturn;\r
+\r
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+               {\r
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+               else\r
+               {\r
+                       if( pxSocket->u.xTCP.txStream != NULL )\r
+                       {\r
+                               xReturn = ( BaseType_t ) uxStreamBufferGetSpace ( pxSocket->u.xTCP.txStream );\r
+                       }\r
+                       else\r
+                       {\r
+                               xReturn = ( BaseType_t ) pxSocket->u.xTCP.uxTxStreamSize;\r
+                       }\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       BaseType_t FreeRTOS_tx_size( Socket_t xSocket )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       BaseType_t xReturn;\r
+\r
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+               {\r
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+               else\r
+               {\r
+                       if( pxSocket->u.xTCP.txStream != NULL )\r
+                       {\r
+                               xReturn = ( BaseType_t ) uxStreamBufferGetSize ( pxSocket->u.xTCP.txStream );\r
+                       }\r
+                       else\r
+                       {\r
+                               xReturn = 0;\r
+                       }\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /* Returns pdTRUE if TCP socket is connected. */\r
+       BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       BaseType_t xReturn = pdFALSE;\r
+\r
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+               {\r
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+               else\r
+               {\r
+                       if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )\r
+                       {\r
+                               if( pxSocket->u.xTCP.ucTCPState < eCLOSE_WAIT )\r
+                               {\r
+                                       xReturn = pdTRUE;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /* returns the actual size of MSS being used */\r
+       BaseType_t FreeRTOS_mss( Socket_t xSocket )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       BaseType_t xReturn;\r
+\r
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+               {\r
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+               else\r
+               {\r
+                       /* usCurMSS is declared as uint16_t to save space.  FreeRTOS_mss()\r
+                       will often be used in signed native-size expressions cast it to\r
+                       BaseType_t. */\r
+                       xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.usCurMSS );\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /* HT: for internal use only: return the connection status */\r
+       BaseType_t FreeRTOS_connstatus( Socket_t xSocket )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       BaseType_t xReturn;\r
+\r
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+               {\r
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+               else\r
+               {\r
+                       /* Cast it to BaseType_t */\r
+                       xReturn = ( BaseType_t ) ( pxSocket->u.xTCP.ucTCPState );\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /*\r
+        * Returns the number of bytes which can be read.\r
+        */\r
+       BaseType_t FreeRTOS_rx_size( Socket_t xSocket )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       BaseType_t xReturn;\r
+\r
+               if( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP )\r
+               {\r
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+               else if( pxSocket->u.xTCP.rxStream != NULL )\r
+               {\r
+                       xReturn = ( BaseType_t ) uxStreamBufferGetSize( pxSocket->u.xTCP.rxStream );\r
+               }\r
+               else\r
+               {\r
+                       xReturn = 0;\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       void FreeRTOS_netstat( void )\r
+       {\r
+       IPStackEvent_t xAskEvent;\r
+\r
+               /* Ask the IP-task to call vTCPNetStat()\r
+                * to avoid accessing xBoundTCPSocketsList\r
+                */\r
+               xAskEvent.eEventType = eTCPNetStat;\r
+               xAskEvent.pvData = ( void * ) NULL;\r
+               xSendEventStructToIPTask( &xAskEvent, 1000u );\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) )\r
+\r
+       void vTCPNetStat( void )\r
+       {\r
+       /* Show a simple listing of all created sockets and their connections */\r
+       ListItem_t *pxIterator;\r
+       BaseType_t count = 0;\r
+\r
+               if( listLIST_IS_INITIALISED( &xBoundTCPSocketsList ) == pdFALSE )\r
+               {\r
+                       FreeRTOS_printf( ( "PLUS-TCP not initialized\n" ) );\r
+               }\r
+               else\r
+               {\r
+                       FreeRTOS_printf( ( "Prot Port IP-Remote       : Port  R/T Status       Alive  tmout Child\n" ) );\r
+                       for( pxIterator  = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );\r
+                                pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );\r
+                                pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
+                       {\r
+                               FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
+                               #if( ipconfigTCP_KEEP_ALIVE == 1 )\r
+                                       TickType_t age = xTaskGetTickCount() - pxSocket->u.xTCP.xLastAliveTime;\r
+                               #else\r
+                                       TickType_t age = 0u;\r
+                               #endif\r
+                               #if( ipconfigUSE_CALLBACKS == 1 )\r
+                                       void *pxHandleReceive = (void*)pxSocket->u.xTCP.pxHandleReceive;\r
+                               #else\r
+                                       void *pxHandleReceive = (void*)NULL;\r
+                               #endif\r
+                               char ucChildText[16] = "";\r
+                               if (pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN)\r
+                               {\r
+                                       snprintf( ucChildText, sizeof( ucChildText ), " %d/%d",\r
+                                               pxSocket->u.xTCP.usChildCount,\r
+                                               pxSocket->u.xTCP.usBacklog);\r
+                               }\r
+                               if( age > 999999 )\r
+                                       age = 999999;\r
+                               FreeRTOS_printf( ( "TCP %5d %-16lxip:%5d %d/%d %-13.13s %6lu %6u%s\n",\r
+                                       pxSocket->usLocalPort,          /* Local port on this machine */\r
+                                       pxSocket->u.xTCP.ulRemoteIP,    /* IP address of remote machine */\r
+                                       pxSocket->u.xTCP.usRemotePort,  /* Port on remote machine */\r
+                                       pxSocket->u.xTCP.rxStream != NULL,\r
+                                       pxSocket->u.xTCP.txStream != NULL,\r
+                                       FreeRTOS_GetTCPStateName( pxSocket->u.xTCP.ucTCPState ),\r
+                                       age,\r
+                                       pxSocket->u.xTCP.usTimeout,\r
+                                       ucChildText ) );\r
+                                       /* Remove compiler warnings if FreeRTOS_debug_printf() is not defined. */\r
+                                       ( void ) pxHandleReceive;\r
+                               count++;\r
+                       }\r
+\r
+                       for( pxIterator  = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundUDPSocketsList );\r
+                                pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundUDPSocketsList );\r
+                                pxIterator  = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
+                       {\r
+                               /* Local port on this machine */\r
+                               FreeRTOS_printf( ( "UDP Port %5u\n",\r
+                                       FreeRTOS_ntohs( listGET_LIST_ITEM_VALUE( pxIterator ) ) ) );\r
+                               count++;\r
+                       }\r
+\r
+                       FreeRTOS_printf( ( "FreeRTOS_netstat: %lu sockets %lu < %lu < %d buffers free\n",\r
+                               count,\r
+                               uxGetMinimumFreeNetworkBuffers( ),\r
+                               uxGetNumberOfFreeNetworkBuffers( ),\r
+                               ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) );\r
+               }\r
+       }\r
+\r
+#endif /* ( ( ipconfigHAS_PRINTF != 0 ) && ( ipconfigUSE_TCP == 1 ) ) */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+\r
+       void vSocketSelect( SocketSelect_t *pxSocketSet )\r
+       {\r
+       BaseType_t xRound;\r
+       EventBits_t xSocketBits, xBitsToClear;\r
+       #if ipconfigUSE_TCP == 1\r
+               BaseType_t xLastRound = 1;\r
+       #else\r
+               BaseType_t xLastRound = 0;\r
+       #endif\r
+\r
+               /* These flags will be switched on after checking the socket status. */\r
+               EventBits_t xGroupBits = 0;\r
+               pxSocketSet->pxSocket = NULL;\r
+\r
+               for( xRound = 0; xRound <= xLastRound; xRound++ )\r
+               {\r
+                       const ListItem_t *pxIterator;\r
+                       const MiniListItem_t *pxEnd;\r
+                       if( xRound == 0 )\r
+                       {\r
+                               pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundUDPSocketsList );\r
+                       }\r
+               #if ipconfigUSE_TCP == 1\r
+                       else\r
+                       {\r
+                               pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &xBoundTCPSocketsList );\r
+                       }\r
+               #endif /* ipconfigUSE_TCP == 1 */\r
+                       for( pxIterator = ( const ListItem_t * ) ( listGET_NEXT( pxEnd ) );\r
+                                pxIterator != ( const ListItem_t * ) pxEnd;\r
+                                pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
+                       {\r
+                               FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
+                               if( pxSocket->pxSocketSet != pxSocketSet )\r
+                               {\r
+                                       /* Socket does not belong to this select group. */\r
+                                       continue;\r
+                               }\r
+                               xSocketBits = 0;\r
+\r
+                               #if( ipconfigUSE_TCP == 1 )\r
+                                       if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP )\r
+                                       {\r
+                                               /* Check if the socket has already been accepted by the\r
+                                               owner.  If not, it is useless to return it from a\r
+                                               select(). */\r
+                                               BaseType_t bAccepted = pdFALSE;\r
+\r
+                                               if( pxSocket->u.xTCP.bits.bPassQueued == pdFALSE_UNSIGNED )\r
+                                               {\r
+                                                       if( pxSocket->u.xTCP.bits.bPassAccept == pdFALSE_UNSIGNED )\r
+                                                       {\r
+                                                               bAccepted = pdTRUE;\r
+                                                       }\r
+                                               }\r
+\r
+                                               /* Is the set owner interested in READ events? */\r
+                                               if( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 )\r
+                                               {\r
+                                                       if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )\r
+                                                       {\r
+                                                               if( ( pxSocket->u.xTCP.pxPeerSocket != NULL ) && ( pxSocket->u.xTCP.pxPeerSocket->u.xTCP.bits.bPassAccept != 0 ) )\r
+                                                               {\r
+                                                                       xSocketBits |= eSELECT_READ;\r
+                                                               }\r
+                                                       }\r
+                                                       else if( ( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )\r
+                                                       {\r
+                                                               /* This socket has the re-use flag. After connecting it turns into\r
+                                                               aconnected socket. Set the READ event, so that accept() will be called. */\r
+                                                               xSocketBits |= eSELECT_READ;\r
+                                                       }\r
+                                                       else if( ( bAccepted != 0 ) && ( FreeRTOS_recvcount( pxSocket ) > 0 ) )\r
+                                                       {\r
+                                                               xSocketBits |= eSELECT_READ;\r
+                                                       }\r
+                                               }\r
+                                               /* Is the set owner interested in EXCEPTION events? */\r
+                                               if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )\r
+                                               {\r
+                                                       if( ( pxSocket->u.xTCP.ucTCPState == eCLOSE_WAIT ) || ( pxSocket->u.xTCP.ucTCPState == eCLOSED ) )\r
+                                                       {\r
+                                                               xSocketBits |= eSELECT_EXCEPT;\r
+                                                       }\r
+                                               }\r
+\r
+                                               /* Is the set owner interested in WRITE events? */\r
+                                               if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )\r
+                                               {\r
+                                                       BaseType_t bMatch = pdFALSE;\r
+\r
+                                                       if( bAccepted != 0 )\r
+                                                       {\r
+                                                               if( FreeRTOS_tx_space( pxSocket ) > 0 )\r
+                                                               {\r
+                                                                       bMatch = pdTRUE;\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       if( bMatch == pdFALSE )\r
+                                                       {\r
+                                                               if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) &&\r
+                                                                       ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) &&\r
+                                                                       ( pxSocket->u.xTCP.bits.bConnPassed == pdFALSE_UNSIGNED ) )\r
+                                                               {\r
+                                                                       pxSocket->u.xTCP.bits.bConnPassed = pdTRUE_UNSIGNED;\r
+                                                                       bMatch = pdTRUE;\r
+                                                               }\r
+                                                       }\r
+\r
+                                                       if( bMatch != pdFALSE )\r
+                                                       {\r
+                                                               xSocketBits |= eSELECT_WRITE;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       else\r
+                               #endif /* ipconfigUSE_TCP == 1 */\r
+                               {\r
+                                       /* Select events for UDP are simpler. */\r
+                                       if( ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) &&\r
+                                               ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) > 0U ) )\r
+                                       {\r
+                                               xSocketBits |= eSELECT_READ;\r
+                                       }\r
+                                       /* The WRITE and EXCEPT bits are not used for UDP */\r
+                               }       /* if( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP ) */\r
+\r
+                               /* Each socket keeps its own event flags, which are looked-up\r
+                               by FreeRTOS_FD_ISSSET() */\r
+                               pxSocket->xSocketBits = xSocketBits;\r
+\r
+                               /* The ORed value will be used to set the bits in the event\r
+                               group. */\r
+                               xGroupBits |= xSocketBits;\r
+\r
+                       }       /* for( pxIterator ... ) */\r
+               }       /* for( xRound = 0; xRound <= xLastRound; xRound++ ) */\r
+\r
+               xBitsToClear = xEventGroupGetBits( pxSocketSet->xSelectGroup );\r
+\r
+               /* Now set the necessary bits. */\r
+               xBitsToClear = ( xBitsToClear & ~xGroupBits ) & eSELECT_ALL;\r
+\r
+               #if( ipconfigSUPPORT_SIGNALS != 0 )\r
+               {\r
+                       /* Maybe the socketset was signalled, but don't\r
+                       clear the 'eSELECT_INTR' bit here, as it will be used\r
+                       and cleared in FreeRTOS_select(). */\r
+                       xBitsToClear &= ( EventBits_t ) ~eSELECT_INTR;\r
+               }\r
+               #endif /* ipconfigSUPPORT_SIGNALS */\r
+\r
+               if( xBitsToClear != 0 )\r
+               {\r
+                       xEventGroupClearBits( pxSocketSet->xSelectGroup, xBitsToClear );\r
+               }\r
+\r
+               /* Now include eSELECT_CALL_IP to wakeup the caller. */\r
+               xEventGroupSetBits( pxSocketSet->xSelectGroup, xGroupBits | eSELECT_CALL_IP );\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SIGNALS != 0 )\r
+\r
+       /* Send a signal to the task which reads from this socket. */\r
+       BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       BaseType_t xReturn;\r
+\r
+               if( pxSocket == NULL )\r
+               {\r
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+               else\r
+       #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+               if( ( pxSocket->pxSocketSet != NULL ) && ( pxSocket->pxSocketSet->xSelectGroup != NULL ) )\r
+               {\r
+                       xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_INTR );\r
+                       xReturn = 0;\r
+               }\r
+               else\r
+       #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
+               if( pxSocket->xEventGroup != NULL )\r
+               {\r
+                       xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_INTR );\r
+                       xReturn = 0;\r
+               }\r
+               else\r
+               {\r
+                       xReturn = -pdFREERTOS_ERRNO_EINVAL;\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SIGNALS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SIGNALS != 0 )\r
+\r
+       /* Send a signal to the task which reads from this socket (FromISR version). */\r
+       BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken )\r
+       {\r
+       FreeRTOS_Socket_t *pxSocket = ( FreeRTOS_Socket_t * ) xSocket;\r
+       BaseType_t xReturn;\r
+       IPStackEvent_t xEvent;\r
+       extern QueueHandle_t xNetworkEventQueue;\r
+\r
+               configASSERT( pxSocket != NULL );\r
+               configASSERT( pxSocket->ucProtocol == FREERTOS_IPPROTO_TCP );\r
+               configASSERT( pxSocket->xEventGroup );\r
+\r
+               xEvent.eEventType = eSocketSignalEvent;\r
+               xEvent.pvData = ( void * )pxSocket;\r
+\r
+               /* The IP-task will call FreeRTOS_SignalSocket for this socket. */\r
+               xReturn = xQueueSendToBackFromISR( xNetworkEventQueue, &xEvent, pxHigherPriorityTaskWoken );\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SIGNALS */\r
+/*-----------------------------------------------------------*/\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c
new file mode 100644 (file)
index 0000000..0e8786f
--- /dev/null
@@ -0,0 +1,231 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+\r
+/*\r
+ * uxStreamBufferAdd( )\r
+ * Adds data to a stream buffer.  If uxOffset > 0, data will be written at\r
+ * an offset from uxHead while uxHead will not be moved yet.  This possibility\r
+ * will be used when TCP data is received while earlier data is still missing.\r
+ * If 'pucData' equals NULL, the function is called to advance 'uxHead' only.\r
+ */\r
+size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount )\r
+{\r
+size_t uxSpace, uxNextHead, uxFirst;\r
+\r
+       uxSpace = uxStreamBufferGetSpace( pxBuffer );\r
+\r
+       /* If uxOffset > 0, items can be placed in front of uxHead */\r
+       if( uxSpace > uxOffset )\r
+       {\r
+               uxSpace -= uxOffset;\r
+       }\r
+       else\r
+       {\r
+               uxSpace = 0u;\r
+       }\r
+\r
+       /* The number of bytes that can be written is the minimum of the number of\r
+       bytes requested and the number available. */\r
+       uxCount = FreeRTOS_min_uint32( uxSpace, uxCount );\r
+\r
+       if( uxCount != 0u )\r
+       {\r
+               uxNextHead = pxBuffer->uxHead;\r
+\r
+               if( uxOffset != 0u )\r
+               {\r
+                       /* ( uxOffset > 0 ) means: write in front if the uxHead marker */\r
+                       uxNextHead += uxOffset;\r
+                       if( uxNextHead >= pxBuffer->LENGTH )\r
+                       {\r
+                               uxNextHead -= pxBuffer->LENGTH;\r
+                       }\r
+               }\r
+\r
+               if( pucData != NULL )\r
+               {\r
+                       /* Calculate the number of bytes that can be added in the first\r
+                       write - which may be less than the total number of bytes that need\r
+                       to be added if the buffer will wrap back to the beginning. */\r
+                       uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextHead, uxCount );\r
+\r
+                       /* Write as many bytes as can be written in the first write. */\r
+                       memcpy( ( void* ) ( pxBuffer->ucArray + uxNextHead ), pucData, uxFirst );\r
+\r
+                       /* If the number of bytes written was less than the number that\r
+                       could be written in the first write... */\r
+                       if( uxCount > uxFirst )\r
+                       {\r
+                               /* ...then write the remaining bytes to the start of the\r
+                               buffer. */\r
+                               memcpy( ( void * )pxBuffer->ucArray, pucData + uxFirst, uxCount - uxFirst );\r
+                       }\r
+               }\r
+\r
+               if( uxOffset == 0u )\r
+               {\r
+                       /* ( uxOffset == 0 ) means: write at uxHead position */\r
+                       uxNextHead += uxCount;\r
+                       if( uxNextHead >= pxBuffer->LENGTH )\r
+                       {\r
+                               uxNextHead -= pxBuffer->LENGTH;\r
+                       }\r
+                       pxBuffer->uxHead = uxNextHead;\r
+               }\r
+\r
+               if( xStreamBufferLessThenEqual( pxBuffer, pxBuffer->uxFront, uxNextHead ) != pdFALSE )\r
+               {\r
+                       /* Advance the front pointer */\r
+                       pxBuffer->uxFront = uxNextHead;\r
+               }\r
+       }\r
+\r
+       return uxCount;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * uxStreamBufferGet( )\r
+ * 'uxOffset' can be used to read data located at a certain offset from 'lTail'.\r
+ * If 'pucData' equals NULL, the function is called to advance 'lTail' only.\r
+ * if 'xPeek' is pdTRUE, or if 'uxOffset' is non-zero, the 'lTail' pointer will\r
+ * not be advanced.\r
+ */\r
+size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek )\r
+{\r
+size_t uxSize, uxCount, uxFirst, uxNextTail;\r
+\r
+       /* How much data is available? */\r
+       uxSize = uxStreamBufferGetSize( pxBuffer );\r
+\r
+       if( uxSize > uxOffset )\r
+       {\r
+               uxSize -= uxOffset;\r
+       }\r
+       else\r
+       {\r
+               uxSize = 0u;\r
+       }\r
+\r
+       /* Use the minimum of the wanted bytes and the available bytes. */\r
+       uxCount = FreeRTOS_min_uint32( uxSize, uxMaxCount );\r
+\r
+       if( uxCount > 0u )\r
+       {\r
+               uxNextTail = pxBuffer->uxTail;\r
+\r
+               if( uxOffset != 0u )\r
+               {\r
+                       uxNextTail += uxOffset;\r
+                       if( uxNextTail >= pxBuffer->LENGTH )\r
+                       {\r
+                               uxNextTail -= pxBuffer->LENGTH;\r
+                       }\r
+               }\r
+\r
+               if( pucData != NULL )\r
+               {\r
+                       /* Calculate the number of bytes that can be read - which may be\r
+                       less than the number wanted if the data wraps around to the start of\r
+                       the buffer. */\r
+                       uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextTail, uxCount );\r
+\r
+                       /* Obtain the number of bytes it is possible to obtain in the first\r
+                       read. */\r
+                       memcpy( pucData, pxBuffer->ucArray + uxNextTail, uxFirst );\r
+\r
+                       /* If the total number of wanted bytes is greater than the number\r
+                       that could be read in the first read... */\r
+                       if( uxCount > uxFirst )\r
+                       {\r
+                               /*...then read the remaining bytes from the start of the buffer. */\r
+                               memcpy( pucData + uxFirst, pxBuffer->ucArray, uxCount - uxFirst );\r
+                       }\r
+               }\r
+\r
+               if( ( xPeek == pdFALSE ) && ( uxOffset == 0UL ) )\r
+               {\r
+                       /* Move the tail pointer to effecively remove the data read from\r
+                       the buffer. */\r
+                       uxNextTail += uxCount;\r
+\r
+                       if( uxNextTail >= pxBuffer->LENGTH )\r
+                       {\r
+                               uxNextTail -= pxBuffer->LENGTH;\r
+                       }\r
+\r
+                       pxBuffer->uxTail = uxNextTail;\r
+               }\r
+       }\r
+\r
+       return uxCount;\r
+}\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_IP.c
new file mode 100644 (file)
index 0000000..19ddf53
--- /dev/null
@@ -0,0 +1,3359 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*\r
+ * FreeRTOS_TCP_IP.c\r
+ * Module which handles the TCP connections for FreeRTOS+TCP.\r
+ * It depends on  FreeRTOS_TCP_WIN.c, which handles the TCP windowing\r
+ * schemes.\r
+ *\r
+ * Endianness: in this module all ports and IP addresses are stored in\r
+ * host byte-order, except fields in the IP-packets\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_TCP_IP.h"\r
+#include "FreeRTOS_DHCP.h"\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "FreeRTOS_ARP.h"\r
+#include "FreeRTOS_TCP_WIN.h"\r
+\r
+\r
+/* Just make sure the contents doesn't get compiled if TCP is not enabled. */\r
+#if ipconfigUSE_TCP == 1\r
+\r
+/* This compile-time test was moved to here because some macro's\r
+were unknown within 'FreeRTOSIPConfigDefaults.h'.  It tests whether\r
+the defined MTU size can contain at ;east a complete TCP packet. */\r
+\r
+#if ( ( ipconfigTCP_MSS + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) > ipconfigNETWORK_MTU )\r
+       #error The ipconfigTCP_MSS setting in FreeRTOSIPConfig.h is too large.\r
+#endif\r
+\r
+/*\r
+ * The meaning of the TCP flags:\r
+ */\r
+#define ipTCP_FLAG_FIN                 0x0001u /* No more data from sender */\r
+#define ipTCP_FLAG_SYN                 0x0002u /* Synchronize sequence numbers */\r
+#define ipTCP_FLAG_RST                 0x0004u /* Reset the connection */\r
+#define ipTCP_FLAG_PSH                 0x0008u /* Push function: please push buffered data to the recv application */\r
+#define ipTCP_FLAG_ACK                 0x0010u /* Acknowledgment field is significant */\r
+#define ipTCP_FLAG_URG                 0x0020u /* Urgent pointer field is significant */\r
+#define ipTCP_FLAG_ECN                 0x0040u /* ECN-Echo */\r
+#define ipTCP_FLAG_CWR                 0x0080u /* Congestion Window Reduced */\r
+#define ipTCP_FLAG_NS                  0x0100u /* ECN-nonce concealment protection */\r
+#define ipTCP_FLAG_RSV                 0x0E00u /* Reserved, keep 0 */\r
+\r
+/* A mask to filter all protocol flags. */\r
+#define ipTCP_FLAG_CTRL                        0x001Fu\r
+\r
+/*\r
+ * A few values of the TCP options:\r
+ */\r
+#define TCP_OPT_END                            0u   /* End of TCP options list */\r
+#define TCP_OPT_NOOP                   1u   /* "No-operation" TCP option */\r
+#define TCP_OPT_MSS                            2u   /* Maximum segment size TCP option */\r
+#define TCP_OPT_WSOPT                  3u   /* TCP Window Scale Option (3-byte long) */\r
+#define TCP_OPT_SACK_P                 4u   /* Advertize that SACK is permitted */\r
+#define TCP_OPT_SACK_A                 5u   /* SACK option with first/last */\r
+#define TCP_OPT_TIMESTAMP              8u   /* Time-stamp option */\r
+\r
+#define TCP_OPT_MSS_LEN                        4u   /* Length of TCP MSS option. */\r
+#define TCP_OPT_WSOPT_LEN              3u   /* Length of TCP WSOPT option. */\r
+\r
+#define TCP_OPT_TIMESTAMP_LEN  10      /* fixed length of the time-stamp option */\r
+\r
+#ifndef ipconfigTCP_ACK_EARLIER_PACKET\r
+       #define ipconfigTCP_ACK_EARLIER_PACKET          1\r
+#endif\r
+\r
+/*\r
+ * The macro NOW_CONNECTED() is use to determine if the connection makes a\r
+ * transition from connected to non-connected and vice versa.\r
+ * NOW_CONNECTED() returns true when the status has one of these values:\r
+ * eESTABLISHED, eFIN_WAIT_1, eFIN_WAIT_2, eCLOSING, eLAST_ACK, eTIME_WAIT\r
+ * Technically the connection status is closed earlier, but the library wants\r
+ * to prevent that the socket will be deleted before the last ACK has been\r
+ * and thus causing a 'RST' packet on either side.\r
+ */\r
+#define NOW_CONNECTED( status )\\r
+       ( ( status >= eESTABLISHED ) && ( status != eCLOSE_WAIT ) )\r
+\r
+/*\r
+ * The highest 4 bits in the TCP offset byte indicate the total length of the\r
+ * TCP header, divided by 4.\r
+ */\r
+#define VALID_BITS_IN_TCP_OFFSET_BYTE          ( 0xF0u )\r
+\r
+/*\r
+ * Acknowledgements to TCP data packets may be delayed as long as more is being expected.\r
+ * A normal delay would be 200ms.  Here a much shorter delay of 20 ms is being used to\r
+ * gain performance.\r
+ */\r
+#define DELAYED_ACK_SHORT_DELAY_MS                     ( 2 )\r
+#define DELAYED_ACK_LONGER_DELAY_MS                    ( 20 )\r
+\r
+/*\r
+ * The MSS (Maximum Segment Size) will be taken as large as possible. However, packets with\r
+ * an MSS of 1460 bytes won't be transported through the internet.  The MSS will be reduced\r
+ * to 1400 bytes.\r
+ */\r
+#define REDUCED_MSS_THROUGH_INTERNET           ( 1400 )\r
+\r
+/*\r
+ * Each time a new TCP connection is being made, a new Initial Sequence Number shall be used.\r
+ * The variable 'ulNextInitialSequenceNumber' will be incremented with a recommended value\r
+ * of 0x102.\r
+ */\r
+#define INITIAL_SEQUENCE_NUMBER_INCREMENT              ( 0x102UL )\r
+\r
+/*\r
+ * When there are no TCP options, the TCP offset equals 20 bytes, which is stored as\r
+ * the number 5 (words) in the higher niblle of the TCP-offset byte.\r
+ */\r
+#define TCP_OFFSET_LENGTH_BITS                 ( 0xf0u )\r
+#define TCP_OFFSET_STANDARD_LENGTH             ( 0x50u )\r
+\r
+/*\r
+ * Each TCP socket is checked regularly to see if it can send data packets.\r
+ * By default, the maximum number of packets sent during one check is limited to 8.\r
+ * This amount may be further limited by setting the socket's TX window size.\r
+ */\r
+#if( !defined( SEND_REPEATED_COUNT ) )\r
+       #define SEND_REPEATED_COUNT             ( 8 )\r
+#endif /* !defined( SEND_REPEATED_COUNT ) */\r
+\r
+/*\r
+ * Define a maximum perdiod of time (ms) to leave a TCP-socket unattended.\r
+ * When a TCP timer expires, retries and keep-alive messages will be checked.\r
+ */\r
+#ifndef        tcpMAXIMUM_TCP_WAKEUP_TIME_MS\r
+       #define tcpMAXIMUM_TCP_WAKEUP_TIME_MS           20000u\r
+#endif\r
+\r
+/*\r
+ * The names of the different TCP states may be useful in logging.\r
+ */\r
+#if( ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) )\r
+       static const char *pcStateNames[] = {\r
+               "eCLOSED",\r
+               "eTCP_LISTEN",\r
+               "eCONNECT_SYN",\r
+               "eSYN_FIRST",\r
+               "eSYN_RECEIVED",\r
+               "eESTABLISHED",\r
+               "eFIN_WAIT_1",\r
+               "eFIN_WAIT_2",\r
+               "eCLOSE_WAIT",\r
+               "eCLOSING",\r
+               "eLAST_ACK",\r
+               "eTIME_WAIT",\r
+               "eUNKNOWN",\r
+};\r
+#endif /* ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) */\r
+\r
+/*\r
+ * Returns true if the socket must be checked.  Non-active sockets are waiting\r
+ * for user action, either connect() or close().\r
+ */\r
+static BaseType_t prvTCPSocketIsActive( UBaseType_t uxStatus );\r
+\r
+/*\r
+ * Either sends a SYN or calls prvTCPSendRepeated (for regular messages).\r
+ */\r
+static int32_t prvTCPSendPacket( FreeRTOS_Socket_t *pxSocket );\r
+\r
+/*\r
+ * Try to send a series of messages.\r
+ */\r
+static int32_t prvTCPSendRepeated( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer );\r
+\r
+/*\r
+ * Return or send a packet to the other party.\r
+ */\r
+static void prvTCPReturnPacket( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer,\r
+       uint32_t ulLen, BaseType_t xReleaseAfterSend );\r
+\r
+/*\r
+ * Initialise the data structures which keep track of the TCP windowing system.\r
+ */\r
+static void prvTCPCreateWindow( FreeRTOS_Socket_t *pxSocket );\r
+\r
+/*\r
+ * Let ARP look-up the MAC-address of the peer and initialise the first SYN\r
+ * packet.\r
+ */\r
+static BaseType_t prvTCPPrepareConnect( FreeRTOS_Socket_t *pxSocket );\r
+\r
+#if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+       /*\r
+        * For logging and debugging: make a string showing the TCP flags.\r
+        */\r
+       static const char *prvTCPFlagMeaning( UBaseType_t xFlags);\r
+#endif /* ipconfigHAS_DEBUG_PRINTF != 0 */\r
+\r
+/*\r
+ * Parse the TCP option(s) received, if present.\r
+ */\r
+static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );\r
+\r
+/*\r
+ * Set the initial properties in the options fields, like the preferred\r
+ * value of MSS and whether SACK allowed.  Will be transmitted in the state\r
+ * 'eCONNECT_SYN'.\r
+ */\r
+static UBaseType_t prvSetSynAckOptions( FreeRTOS_Socket_t *pxSocket, TCPPacket_t * pxTCPPacket );\r
+\r
+/*\r
+ * For anti-hang protection and TCP keep-alive messages.  Called in two places:\r
+ * after receiving a packet and after a state change.  The socket's alive timer\r
+ * may be reset.\r
+ */\r
+static void prvTCPTouchSocket( FreeRTOS_Socket_t *pxSocket );\r
+\r
+/*\r
+ * Prepare an outgoing message, if anything has to be sent.\r
+ */\r
+static int32_t prvTCPPrepareSend( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer, UBaseType_t uxOptionsLength );\r
+\r
+/*\r
+ * Calculate when this socket needs to be checked to do (re-)transmissions.\r
+ */\r
+static TickType_t prvTCPNextTimeout( FreeRTOS_Socket_t *pxSocket );\r
+\r
+/*\r
+ * The API FreeRTOS_send() adds data to the TX stream.  Add\r
+ * this data to the windowing system to it can be transmitted.\r
+ */\r
+static void prvTCPAddTxData( FreeRTOS_Socket_t *pxSocket );\r
+\r
+/*\r
+ *  Called to handle the closure of a TCP connection.\r
+ */\r
+static BaseType_t prvTCPHandleFin( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );\r
+\r
+#if(   ipconfigUSE_TCP_TIMESTAMPS == 1 )\r
+       static UBaseType_t prvTCPSetTimeStamp( BaseType_t lOffset, FreeRTOS_Socket_t *pxSocket, TCPHeader_t *pxTCPHeader );\r
+#endif\r
+\r
+/*\r
+ * Called from prvTCPHandleState().  Find the TCP payload data and check and\r
+ * return its length.\r
+ */\r
+static BaseType_t prvCheckRxData( NetworkBufferDescriptor_t *pxNetworkBuffer, uint8_t **ppucRecvData );\r
+\r
+/*\r
+ * Called from prvTCPHandleState().  Check if the payload data may be accepted.\r
+ * If so, it will be added to the socket's reception queue.\r
+ */\r
+static BaseType_t prvStoreRxData( FreeRTOS_Socket_t *pxSocket, uint8_t *pucRecvData,\r
+       NetworkBufferDescriptor_t *pxNetworkBuffer, uint32_t ulReceiveLength );\r
+\r
+/*\r
+ * Set the TCP options (if any) for the outgoing packet.\r
+ */\r
+static UBaseType_t prvSetOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );\r
+\r
+/*\r
+ * Called from prvTCPHandleState() as long as the TCP status is eSYN_RECEIVED to\r
+ * eCONNECT_SYN.\r
+ */\r
+static BaseType_t prvHandleSynReceived( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer,\r
+       uint32_t ulReceiveLength, UBaseType_t uxOptionsLength );\r
+\r
+/*\r
+ * Called from prvTCPHandleState() as long as the TCP status is eESTABLISHED.\r
+ */\r
+static BaseType_t prvHandleEstablished( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer,\r
+       uint32_t ulReceiveLength, UBaseType_t uxOptionsLength );\r
+\r
+/*\r
+ * Called from prvTCPHandleState().  There is data to be sent.\r
+ * If ipconfigUSE_TCP_WIN is defined, and if only an ACK must be sent, it will\r
+ * be checked if it would better be postponed for efficiency.\r
+ */\r
+static BaseType_t prvSendData( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer,\r
+       uint32_t ulReceiveLength, BaseType_t xSendLength );\r
+\r
+/*\r
+ * The heart of all: check incoming packet for valid data and acks and do what\r
+ * is necessary in each state.\r
+ */\r
+static BaseType_t prvTCPHandleState( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer );\r
+\r
+/*\r
+ * Reply to a peer with the RST flag on, in case a packet can not be handled.\r
+ */\r
+static BaseType_t prvTCPSendReset( NetworkBufferDescriptor_t *pxNetworkBuffer );\r
+\r
+/*\r
+ * Set the initial value for MSS (Maximum Segment Size) to be used.\r
+ */\r
+static void prvSocketSetMSS( FreeRTOS_Socket_t *pxSocket );\r
+\r
+/*\r
+ * Return either a newly created socket, or the current socket in a connected\r
+ * state (depends on the 'bReuseSocket' flag).\r
+ */\r
+static FreeRTOS_Socket_t *prvHandleListen( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer );\r
+\r
+/*\r
+ * After a listening socket receives a new connection, it may duplicate itself.\r
+ * The copying takes place in prvTCPSocketCopy.\r
+ */\r
+static BaseType_t prvTCPSocketCopy( FreeRTOS_Socket_t *pxNewSocket, FreeRTOS_Socket_t *pxSocket );\r
+\r
+/*\r
+ * prvTCPStatusAgeCheck() will see if the socket has been in a non-connected\r
+ * state for too long.  If so, the socket will be closed, and -1 will be\r
+ * returned.\r
+ */\r
+#if( ipconfigTCP_HANG_PROTECTION == 1 )\r
+       static BaseType_t prvTCPStatusAgeCheck( FreeRTOS_Socket_t *pxSocket );\r
+#endif\r
+\r
+static NetworkBufferDescriptor_t *prvTCPBufferResize( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer,\r
+       int32_t lDataLen, UBaseType_t uxOptionsLength );\r
+\r
+#if( ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) )\r
+       const char *FreeRTOS_GetTCPStateName( UBaseType_t ulState );\r
+#endif\r
+\r
+#if( ipconfigUSE_TCP_WIN != 0 )\r
+       static uint8_t prvWinScaleFactor( FreeRTOS_Socket_t *pxSocket );\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Initial Sequence Number, i.e. the next initial sequence number that will be\r
+used when a new connection is opened.  The value should be randomized to prevent\r
+attacks from outside (spoofing). */\r
+uint32_t ulNextInitialSequenceNumber = 0ul;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* prvTCPSocketIsActive() returns true if the socket must be checked.\r
+ * Non-active sockets are waiting for user action, either connect()\r
+ * or close(). */\r
+static BaseType_t prvTCPSocketIsActive( UBaseType_t uxStatus )\r
+{\r
+       switch( uxStatus )\r
+       {\r
+       case eCLOSED:\r
+       case eCLOSE_WAIT:\r
+       case eFIN_WAIT_2:\r
+       case eCLOSING:\r
+       case eTIME_WAIT:\r
+               return pdFALSE;\r
+       default:\r
+               return pdTRUE;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigTCP_HANG_PROTECTION == 1 )\r
+\r
+       static BaseType_t prvTCPStatusAgeCheck( FreeRTOS_Socket_t *pxSocket )\r
+       {\r
+       BaseType_t xResult;\r
+               switch( pxSocket->u.xTCP.ucTCPState )\r
+               {\r
+               case eESTABLISHED:\r
+                       /* If the 'ipconfigTCP_KEEP_ALIVE' option is enabled, sockets in\r
+                       state ESTABLISHED can be protected using keep-alive messages. */\r
+                       xResult = pdFALSE;\r
+                       break;\r
+               case eCLOSED:\r
+               case eTCP_LISTEN:\r
+               case eCLOSE_WAIT:\r
+                       /* These 3 states may last for ever, up to the owner. */\r
+                       xResult = pdFALSE;\r
+                       break;\r
+               default:\r
+                       /* All other (non-connected) states will get anti-hanging\r
+                       protection. */\r
+                       xResult = pdTRUE;\r
+                       break;\r
+               }\r
+               if( xResult != pdFALSE )\r
+               {\r
+                       /* How much time has past since the last active moment which is\r
+                       defined as A) a state change or B) a packet has arrived. */\r
+                       TickType_t xAge = xTaskGetTickCount( ) - pxSocket->u.xTCP.xLastActTime;\r
+\r
+                       /* ipconfigTCP_HANG_PROTECTION_TIME is in units of seconds. */\r
+                       if( xAge > ( ipconfigTCP_HANG_PROTECTION_TIME * configTICK_RATE_HZ ) )\r
+                       {\r
+                               #if( ipconfigHAS_DEBUG_PRINTF == 1 )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "Inactive socket closed: port %u rem %lxip:%u status %s\n",\r
+                                               pxSocket->usLocalPort,\r
+                                               pxSocket->u.xTCP.ulRemoteIP,\r
+                                               pxSocket->u.xTCP.usRemotePort,\r
+                                               FreeRTOS_GetTCPStateName( ( UBaseType_t ) pxSocket->u.xTCP.ucTCPState ) ) );\r
+                               }\r
+                               #endif /* ipconfigHAS_DEBUG_PRINTF */\r
+\r
+                               /* Move to eCLOSE_WAIT, user may close the socket. */\r
+                               vTCPStateChange( pxSocket, eCLOSE_WAIT );\r
+\r
+                               /* When 'bPassQueued' true, this socket is an orphan until it\r
+                               gets connected. */\r
+                               if( pxSocket->u.xTCP.bits.bPassQueued != pdFALSE_UNSIGNED )\r
+                               {\r
+                                       if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )\r
+                                       {\r
+                                               /* As it did not get connected, and the user can never\r
+                                               accept() it anymore, it will be deleted now.  Called from\r
+                                               the IP-task, so it's safe to call the internal Close\r
+                                               function: vSocketClose(). */\r
+                                               vSocketClose( pxSocket );\r
+                                       }\r
+                                       /* Return a negative value to tell to inform the caller\r
+                                       xTCPTimerCheck()\r
+                                       that the socket got closed and may not be accessed anymore. */\r
+                                       xResult = -1;\r
+                               }\r
+                       }\r
+               }\r
+               return xResult;\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+#endif\r
+\r
+/*\r
+ * As soon as a TCP socket timer expires, this function xTCPSocketCheck\r
+ * will be called (from xTCPTimerCheck)\r
+ * It can send a delayed ACK or new data\r
+ * Sequence of calling (normally) :\r
+ * IP-Task:\r
+ *             xTCPTimerCheck()                                // Check all sockets ( declared in FreeRTOS_Sockets.c )\r
+ *             xTCPSocketCheck()                               // Either send a delayed ACK or call prvTCPSendPacket()\r
+ *             prvTCPSendPacket()                              // Either send a SYN or call prvTCPSendRepeated ( regular messages )\r
+ *             prvTCPSendRepeated()                    // Send at most 8 messages on a row\r
+ *                     prvTCPReturnPacket()            // Prepare for returning\r
+ *                     xNetworkInterfaceOutput()       // Sends data to the NIC ( declared in portable/NetworkInterface/xxx )\r
+ */\r
+BaseType_t xTCPSocketCheck( FreeRTOS_Socket_t *pxSocket )\r
+{\r
+BaseType_t xResult = 0;\r
+BaseType_t xReady = pdFALSE;\r
+\r
+       if( ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) && ( pxSocket->u.xTCP.txStream != NULL ) )\r
+       {\r
+               /* The API FreeRTOS_send() might have added data to the TX stream.  Add\r
+               this data to the windowing system so it can be transmitted. */\r
+               prvTCPAddTxData( pxSocket );\r
+       }\r
+\r
+       #if( ipconfigUSE_TCP_WIN == 1 )\r
+       {\r
+               if( pxSocket->u.xTCP.pxAckMessage != NULL )\r
+               {\r
+                       /* The first task of this regular socket check is to send-out delayed\r
+                       ACK's. */\r
+                       if( pxSocket->u.xTCP.bits.bUserShutdown == pdFALSE_UNSIGNED )\r
+                       {\r
+                               /* Earlier data was received but not yet acknowledged.  This\r
+                               function is called when the TCP timer for the socket expires, the\r
+                               ACK may be sent now. */\r
+                               if( pxSocket->u.xTCP.ucTCPState != eCLOSED )\r
+                               {\r
+                                       if( xTCPWindowLoggingLevel > 1 && ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) )\r
+                                       {\r
+                                               FreeRTOS_debug_printf( ( "Send[%u->%u] del ACK %lu SEQ %lu (len %u)\n",\r
+                                                       pxSocket->usLocalPort,\r
+                                                       pxSocket->u.xTCP.usRemotePort,\r
+                                                       pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber - pxSocket->u.xTCP.xTCPWindow.rx.ulFirstSequenceNumber,\r
+                                                       pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber   - pxSocket->u.xTCP.xTCPWindow.tx.ulFirstSequenceNumber,\r
+                                                       ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) );\r
+                                       }\r
+\r
+                                       prvTCPReturnPacket( pxSocket, pxSocket->u.xTCP.pxAckMessage, ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER, ipconfigZERO_COPY_TX_DRIVER );\r
+\r
+                                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+                                       {\r
+                                               /* The ownership has been passed to the SEND routine,\r
+                                               clear the pointer to it. */\r
+                                               pxSocket->u.xTCP.pxAckMessage = NULL;\r
+                                       }\r
+                                       #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+                               }\r
+                               if( prvTCPNextTimeout( pxSocket ) > 1 )\r
+                               {\r
+                                       /* Tell the code below that this function is ready. */\r
+                                       xReady = pdTRUE;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               /* The user wants to perform an active shutdown(), skip sending\r
+                               the     delayed ACK.  The function prvTCPSendPacket() will send the\r
+                               FIN     along with the ACK's. */\r
+                       }\r
+\r
+                       if( pxSocket->u.xTCP.pxAckMessage != NULL )\r
+                       {\r
+                               vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );\r
+                               pxSocket->u.xTCP.pxAckMessage = NULL;\r
+                       }\r
+               }\r
+       }\r
+       #endif /* ipconfigUSE_TCP_WIN */\r
+\r
+       if( xReady == pdFALSE )\r
+       {\r
+               /* The second task of this regular socket check is sending out data. */\r
+               if( ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) ||\r
+                       ( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN ) )\r
+               {\r
+                       prvTCPSendPacket( pxSocket );\r
+               }\r
+\r
+               /* Set the time-out for the next wakeup for this socket. */\r
+               prvTCPNextTimeout( pxSocket );\r
+\r
+               #if( ipconfigTCP_HANG_PROTECTION == 1 )\r
+               {\r
+                       /* In all (non-connected) states in which keep-alive messages can not be sent\r
+                       the anti-hang protocol will close sockets that are 'hanging'. */\r
+                       xResult = prvTCPStatusAgeCheck( pxSocket );\r
+               }\r
+               #endif\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * prvTCPSendPacket() will be called when the socket time-out has been reached.\r
+ * It is only called by xTCPSocketCheck().\r
+ */\r
+static int32_t prvTCPSendPacket( FreeRTOS_Socket_t *pxSocket )\r
+{\r
+int32_t lResult = 0;\r
+UBaseType_t uxOptionsLength;\r
+TCPPacket_t *pxTCPPacket;\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+\r
+       if( pxSocket->u.xTCP.ucTCPState != eCONNECT_SYN )\r
+       {\r
+               /* The connection is in a state other than SYN. */\r
+               pxNetworkBuffer = NULL;\r
+\r
+               /* prvTCPSendRepeated() will only create a network buffer if necessary,\r
+               i.e. when data must be sent to the peer. */\r
+               lResult = prvTCPSendRepeated( pxSocket, &pxNetworkBuffer );\r
+\r
+               if( pxNetworkBuffer != NULL )\r
+               {\r
+                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if( pxSocket->u.xTCP.ucRepCount >= 3u )\r
+               {\r
+                       /* The connection is in the SYN status. The packet will be repeated\r
+                       to most 3 times.  When there is no response, the socket get the\r
+                       status 'eCLOSE_WAIT'. */\r
+                       FreeRTOS_debug_printf( ( "Connect: giving up %lxip:%u\n",\r
+                               pxSocket->u.xTCP.ulRemoteIP,            /* IP address of remote machine. */\r
+                               pxSocket->u.xTCP.usRemotePort ) );      /* Port on remote machine. */\r
+                       vTCPStateChange( pxSocket, eCLOSE_WAIT );\r
+               }\r
+               else if( ( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) || ( prvTCPPrepareConnect( pxSocket ) == pdTRUE ) )\r
+               {\r
+                       /* Or else, if the connection has been prepared, or can be prepared\r
+                       now, proceed to send the packet with the SYN flag.\r
+                       prvTCPPrepareConnect() prepares 'xPacket' and returns pdTRUE if\r
+                       the Ethernet address of the peer or the gateway is found. */\r
+                       pxTCPPacket = ( TCPPacket_t * )pxSocket->u.xTCP.xPacket.u.ucLastPacket;\r
+\r
+                       #if( ipconfigUSE_TCP_TIMESTAMPS == 1 )\r
+                       {\r
+                               /* When TCP time stamps are enabled, but they will only be applied\r
+                               if the peer is outside the netmask, usually on the internet.\r
+                               Packages sent on a LAN are usually too big to carry time stamps. */\r
+                               if( ( ( pxSocket->u.xTCP.ulRemoteIP ^ FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) ) & xNetworkAddressing.ulNetMask ) != 0ul )\r
+                               {\r
+                                       pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps = pdTRUE_UNSIGNED;\r
+                               }\r
+                       }\r
+                       #endif\r
+\r
+                       /* About to send a SYN packet.  Call prvSetSynAckOptions() to set\r
+                       the proper options: The size of MSS and whether SACK's are\r
+                       allowed. */\r
+                       uxOptionsLength = prvSetSynAckOptions( pxSocket, pxTCPPacket );\r
+\r
+                       /* Return the number of bytes to be sent. */\r
+                       lResult = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );\r
+\r
+                       /* Set the TCP offset field:  ipSIZE_OF_TCP_HEADER equals 20 and\r
+                       uxOptionsLength is always a multiple of 4.  The complete expression\r
+                       would be:\r
+                       ucTCPOffset = ( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) / 4 ) << 4 */\r
+                       pxTCPPacket->xTCPHeader.ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );\r
+\r
+                       /* Repeat Count is used for a connecting socket, to limit the number\r
+                       of tries. */\r
+                       pxSocket->u.xTCP.ucRepCount++;\r
+\r
+                       /* Send the SYN message to make a connection.  The messages is\r
+                       stored in the socket field 'xPacket'.  It will be wrapped in a\r
+                       pseudo network buffer descriptor before it will be sent. */\r
+                       prvTCPReturnPacket( pxSocket, NULL, ( uint32_t ) lResult, pdFALSE );\r
+               }\r
+       }\r
+\r
+       /* Return the total number of bytes sent. */\r
+       return lResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * prvTCPSendRepeated will try to send a series of messages, as long as there is\r
+ * data to be sent and as long as the transmit window isn't full.\r
+ */\r
+static int32_t prvTCPSendRepeated( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer )\r
+{\r
+UBaseType_t uxIndex;\r
+int32_t lResult = 0;\r
+UBaseType_t uxOptionsLength = 0u;\r
+int32_t xSendLength;\r
+\r
+       for( uxIndex = 0u; uxIndex < ( UBaseType_t ) SEND_REPEATED_COUNT; uxIndex++ )\r
+       {\r
+               /* prvTCPPrepareSend() might allocate a network buffer if there is data\r
+               to be sent. */\r
+               xSendLength = prvTCPPrepareSend( pxSocket, ppxNetworkBuffer, uxOptionsLength );\r
+               if( xSendLength <= 0 )\r
+               {\r
+                       break;\r
+               }\r
+\r
+               /* And return the packet to the peer. */\r
+               prvTCPReturnPacket( pxSocket, *ppxNetworkBuffer, ( uint32_t ) xSendLength, ipconfigZERO_COPY_TX_DRIVER );\r
+\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       *ppxNetworkBuffer = NULL;\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+               lResult += xSendLength;\r
+       }\r
+\r
+       /* Return the total number of bytes sent. */\r
+       return lResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Return (or send) a packet the the peer.  The data is stored in pxBuffer,\r
+ * which may either point to a real network buffer or to a TCP socket field\r
+ * called 'xTCP.xPacket'.   A temporary xNetworkBuffer will be used to pass\r
+ * the data to the NIC.\r
+ */\r
+static void prvTCPReturnPacket( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer, uint32_t ulLen, BaseType_t xReleaseAfterSend )\r
+{\r
+TCPPacket_t * pxTCPPacket;\r
+IPHeader_t *pxIPHeader;\r
+EthernetHeader_t *pxEthernetHeader;\r
+uint32_t ulFrontSpace, ulSpace, ulSourceAddress, ulWinSize;\r
+TCPWindow_t *pxTCPWindow;\r
+NetworkBufferDescriptor_t xTempBuffer;\r
+/* For sending, a pseudo network buffer will be used, as explained above. */\r
+\r
+       if( pxNetworkBuffer == NULL )\r
+       {\r
+               memset( &xTempBuffer, '\0', sizeof( xTempBuffer ) );\r
+               pxNetworkBuffer = &xTempBuffer;\r
+\r
+               xTempBuffer.pucEthernetBuffer = pxSocket->u.xTCP.xPacket.u.ucLastPacket;\r
+               xTempBuffer.xDataLength = sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket );\r
+       }\r
+\r
+       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       {\r
+               if( xReleaseAfterSend == pdFALSE )\r
+               {\r
+                       pxNetworkBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, ( BaseType_t ) pxNetworkBuffer->xDataLength );\r
+                       if( pxNetworkBuffer == NULL )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "prvTCPReturnPacket: duplicate failed\n" ) );\r
+                       }\r
+                       xReleaseAfterSend = pdTRUE;\r
+               }\r
+       }\r
+       #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+       if( pxNetworkBuffer != NULL )\r
+       {\r
+               pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+               pxIPHeader = &pxTCPPacket->xIPHeader;\r
+               pxEthernetHeader = &pxTCPPacket->xEthernetHeader;\r
+\r
+               /* Fill the packet, using hton translations. */\r
+               if( pxSocket != NULL )\r
+               {\r
+                       /* Calculate the space in the RX buffer in order to advertise the\r
+                       size of this socket's reception window. */\r
+                       pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );\r
+\r
+                       if( pxSocket->u.xTCP.rxStream != NULL )\r
+                       {\r
+                               /* An RX stream was created already, see how much space is\r
+                               available. */\r
+                               ulFrontSpace = ( uint32_t ) uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* No RX stream has been created, the full stream size is\r
+                               available. */\r
+                               ulFrontSpace = ( uint32_t ) pxSocket->u.xTCP.uxRxStreamSize;\r
+                       }\r
+\r
+                       /* Take the minimum of the RX buffer space and the RX window size. */\r
+                       ulSpace = FreeRTOS_min_uint32( pxSocket->u.xTCP.ulRxCurWinSize, pxTCPWindow->xSize.ulRxWindowLength );\r
+\r
+                       if( ( pxSocket->u.xTCP.bits.bLowWater != pdFALSE_UNSIGNED ) || ( pxSocket->u.xTCP.bits.bRxStopped != pdFALSE_UNSIGNED ) )\r
+                       {\r
+                               /* The low-water mark was reached, meaning there was little\r
+                               space left.  The socket will wait until the application has read\r
+                               or flushed the incoming data, and 'zero-window' will be\r
+                               advertised. */\r
+                               ulSpace = 0u;\r
+                       }\r
+\r
+                       /* If possible, advertise an RX window size of at least 1 MSS, otherwise\r
+                       the peer might start 'zero window probing', i.e. sending small packets\r
+                       (1, 2, 4, 8... bytes). */\r
+                       if( ( ulSpace < pxSocket->u.xTCP.usCurMSS ) && ( ulFrontSpace >= pxSocket->u.xTCP.usCurMSS ) )\r
+                       {\r
+                               ulSpace = pxSocket->u.xTCP.usCurMSS;\r
+                       }\r
+\r
+                       /* Avoid overflow of the 16-bit win field. */\r
+                       #if( ipconfigUSE_TCP_WIN != 0 )\r
+                       {\r
+                               ulWinSize = ( ulSpace >> pxSocket->u.xTCP.ucMyWinScaleFactor );\r
+                       }\r
+                       #else\r
+                       {\r
+                               ulWinSize = ulSpace;\r
+                       }\r
+                       #endif\r
+                       if( ulWinSize > 0xfffcUL )\r
+                       {\r
+                               ulWinSize = 0xfffcUL;\r
+                       }\r
+\r
+                       pxTCPPacket->xTCPHeader.usWindow = FreeRTOS_htons( ( uint16_t ) ulWinSize );\r
+\r
+                       #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+                       {\r
+                               if( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE )\r
+                               {\r
+                                       if( ( xTCPWindowLoggingLevel != 0 ) && ( pxSocket->u.xTCP.bits.bWinChange != pdFALSE_UNSIGNED ) )\r
+                                       {\r
+                                       size_t uxFrontSpace;\r
+\r
+                                               if(pxSocket->u.xTCP.rxStream != NULL)\r
+                                               {\r
+                                                       uxFrontSpace =  uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream ) ;\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       uxFrontSpace = 0u;\r
+                                               }\r
+\r
+                                               FreeRTOS_debug_printf( ( "%s: %lxip:%u: [%lu < %lu] winSize %ld\n",\r
+                                               pxSocket->u.xTCP.bits.bLowWater ? "STOP" : "GO ",\r
+                                                       pxSocket->u.xTCP.ulRemoteIP,\r
+                                                       pxSocket->u.xTCP.usRemotePort,\r
+                                                       pxSocket->u.xTCP.bits.bLowWater ? pxSocket->u.xTCP.uxLittleSpace : uxFrontSpace, pxSocket->u.xTCP.uxEnoughSpace,\r
+                                                       (int32_t) ( pxTCPWindow->rx.ulHighestSequenceNumber - pxTCPWindow->rx.ulCurrentSequenceNumber ) ) );\r
+                                       }\r
+                               }\r
+                       }\r
+                       #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */\r
+\r
+                       /* The new window size has been advertised, switch off the flag. */\r
+                       pxSocket->u.xTCP.bits.bWinChange = pdFALSE_UNSIGNED;\r
+\r
+                       /* Later on, when deciding to delay an ACK, a precise estimate is needed\r
+                       of the free RX space.  At this moment, 'ulHighestRxAllowed' would be the\r
+                       highest sequence number minus 1 that the socket will accept. */\r
+                       pxSocket->u.xTCP.ulHighestRxAllowed = pxTCPWindow->rx.ulCurrentSequenceNumber + ulSpace;\r
+\r
+                       #if( ipconfigTCP_KEEP_ALIVE == 1 )\r
+                               if( pxSocket->u.xTCP.bits.bSendKeepAlive != pdFALSE_UNSIGNED )\r
+                               {\r
+                                       /* Sending a keep-alive packet, send the current sequence number\r
+                                       minus 1, which will     be recognised as a keep-alive packet an\r
+                                       responded to by acknowledging the last byte. */\r
+                                       pxSocket->u.xTCP.bits.bSendKeepAlive = pdFALSE_UNSIGNED;\r
+                                       pxSocket->u.xTCP.bits.bWaitKeepAlive = pdTRUE_UNSIGNED;\r
+\r
+                                       pxTCPPacket->xTCPHeader.ulSequenceNumber = pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber - 1UL;\r
+                                       pxTCPPacket->xTCPHeader.ulSequenceNumber = FreeRTOS_htonl( pxTCPPacket->xTCPHeader.ulSequenceNumber );\r
+                               }\r
+                               else\r
+                       #endif\r
+                       {\r
+                               pxTCPPacket->xTCPHeader.ulSequenceNumber = FreeRTOS_htonl( pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber );\r
+\r
+                               if( ( pxTCPPacket->xTCPHeader.ucTCPFlags & ( uint8_t ) ipTCP_FLAG_FIN ) != 0u )\r
+                               {\r
+                                       /* Suppress FIN in case this packet carries earlier data to be\r
+                                       retransmitted. */\r
+                                       uint32_t ulDataLen = ( uint32_t ) ( ulLen - ( ipSIZE_OF_TCP_HEADER + ipSIZE_OF_IPv4_HEADER ) );\r
+                                       if( ( pxTCPWindow->ulOurSequenceNumber + ulDataLen ) != pxTCPWindow->tx.ulFINSequenceNumber )\r
+                                       {\r
+                                               pxTCPPacket->xTCPHeader.ucTCPFlags &= ( ( uint8_t ) ~ipTCP_FLAG_FIN );\r
+                                               FreeRTOS_debug_printf( ( "Suppress FIN for %lu + %lu < %lu\n",\r
+                                                       pxTCPWindow->ulOurSequenceNumber - pxTCPWindow->tx.ulFirstSequenceNumber,\r
+                                                       ulDataLen,\r
+                                                       pxTCPWindow->tx.ulFINSequenceNumber - pxTCPWindow->tx.ulFirstSequenceNumber ) );\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       /* Tell which sequence number is expected next time */\r
+                       pxTCPPacket->xTCPHeader.ulAckNr = FreeRTOS_htonl( pxTCPWindow->rx.ulCurrentSequenceNumber );\r
+               }\r
+               else\r
+               {\r
+                       /* Sending data without a socket, probably replying with a RST flag\r
+                       Just swap the two sequence numbers. */\r
+                       vFlip_32( pxTCPPacket->xTCPHeader.ulSequenceNumber, pxTCPPacket->xTCPHeader.ulAckNr );\r
+               }\r
+\r
+               pxIPHeader->ucTimeToLive           = ( uint8_t ) ipconfigTCP_TIME_TO_LIVE;\r
+               pxIPHeader->usLength               = FreeRTOS_htons( ulLen );\r
+               if( ( pxSocket == NULL ) || ( *ipLOCAL_IP_ADDRESS_POINTER == 0ul ) )\r
+               {\r
+                       /* When pxSocket is NULL, this function is called by prvTCPSendReset()\r
+                       and the IP-addresses must be swapped.\r
+                       Also swap the IP-addresses in case the IP-tack doesn't have an\r
+                       IP-address yet, i.e. when ( *ipLOCAL_IP_ADDRESS_POINTER == 0ul ). */\r
+                       ulSourceAddress = pxIPHeader->ulDestinationIPAddress;\r
+               }\r
+               else\r
+               {\r
+                       ulSourceAddress = *ipLOCAL_IP_ADDRESS_POINTER;\r
+               }\r
+               pxIPHeader->ulDestinationIPAddress = pxIPHeader->ulSourceIPAddress;\r
+               pxIPHeader->ulSourceIPAddress = ulSourceAddress;\r
+               vFlip_16( pxTCPPacket->xTCPHeader.usSourcePort, pxTCPPacket->xTCPHeader.usDestinationPort );\r
+\r
+               /* Just an increasing number. */\r
+               pxIPHeader->usIdentification = FreeRTOS_htons( usPacketIdentifier );\r
+               usPacketIdentifier++;\r
+               pxIPHeader->usFragmentOffset = 0u;\r
+\r
+               #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )\r
+               {\r
+                       /* calculate the IP header checksum, in case the driver won't do that. */\r
+                       pxIPHeader->usHeaderChecksum = 0x00u;\r
+                       pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0u, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );\r
+                       pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );\r
+\r
+                       /* calculate the TCP checksum for an outgoing packet. */\r
+                       usGenerateProtocolChecksum( (uint8_t*)pxTCPPacket, pdTRUE );\r
+\r
+                       /* A calculated checksum of 0 must be inverted as 0 means the checksum\r
+                       is disabled. */\r
+                       if( pxTCPPacket->xTCPHeader.usChecksum == 0x00u )\r
+                       {\r
+                               pxTCPPacket->xTCPHeader.usChecksum = 0xffffU;\r
+                       }\r
+               }\r
+               #endif\r
+\r
+               #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+               {\r
+                       pxNetworkBuffer->pxNextBuffer = NULL;\r
+               }\r
+               #endif\r
+\r
+               /* Important: tell NIC driver how many bytes must be sent. */\r
+               pxNetworkBuffer->xDataLength = ulLen + ipSIZE_OF_ETH_HEADER;\r
+\r
+               /* Fill in the destination MAC addresses. */\r
+               memcpy( ( void * ) &( pxEthernetHeader->xDestinationAddress ), ( void * ) &( pxEthernetHeader->xSourceAddress ),\r
+                       sizeof( pxEthernetHeader->xDestinationAddress ) );\r
+\r
+               /* The source MAC addresses is fixed to 'ipLOCAL_MAC_ADDRESS'. */\r
+               memcpy( ( void * ) &( pxEthernetHeader->xSourceAddress ), ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );\r
+\r
+               #if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
+               {\r
+                       if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
+                       {\r
+                       BaseType_t xIndex;\r
+\r
+                               for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )\r
+                               {\r
+                                       pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;\r
+                               }\r
+                               pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;\r
+                       }\r
+               }\r
+               #endif\r
+\r
+               /* Send! */\r
+               xNetworkInterfaceOutput( pxNetworkBuffer, xReleaseAfterSend );\r
+\r
+               if( xReleaseAfterSend == pdFALSE )\r
+               {\r
+                       /* Swap-back some fields, as pxBuffer probably points to a socket field\r
+                       containing the packet header. */\r
+                       vFlip_16( pxTCPPacket->xTCPHeader.usSourcePort, pxTCPPacket->xTCPHeader.usDestinationPort);\r
+                       pxTCPPacket->xIPHeader.ulSourceIPAddress = pxTCPPacket->xIPHeader.ulDestinationIPAddress;\r
+                       memcpy( pxEthernetHeader->xSourceAddress.ucBytes, pxEthernetHeader->xDestinationAddress.ucBytes, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );\r
+               }\r
+               else\r
+               {\r
+                       /* Nothing to do: the buffer has been passed to DMA and will be released after use */\r
+               }\r
+       } /* if( pxNetworkBuffer != NULL ) */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * The SYN event is very important: the sequence numbers, which have a kind of\r
+ * random starting value, are being synchronised.  The sliding window manager\r
+ * (in FreeRTOS_TCP_WIN.c) needs to know them, along with the Maximum Segment\r
+ * Size (MSS) in use.\r
+ */\r
+static void prvTCPCreateWindow( FreeRTOS_Socket_t *pxSocket )\r
+{\r
+       if( xTCPWindowLoggingLevel )\r
+               FreeRTOS_debug_printf( ( "Limits (using): TCP Win size %lu Water %lu <= %lu <= %lu\n",\r
+                       pxSocket->u.xTCP.uxRxWinSize * ipconfigTCP_MSS,\r
+                       pxSocket->u.xTCP.uxLittleSpace ,\r
+                       pxSocket->u.xTCP.uxEnoughSpace,\r
+                       pxSocket->u.xTCP.uxRxStreamSize ) );\r
+       vTCPWindowCreate(\r
+               &pxSocket->u.xTCP.xTCPWindow,\r
+               ipconfigTCP_MSS * pxSocket->u.xTCP.uxRxWinSize,\r
+               ipconfigTCP_MSS * pxSocket->u.xTCP.uxTxWinSize,\r
+               pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber,\r
+               pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber,\r
+               ( uint32_t ) pxSocket->u.xTCP.usInitMSS );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Connecting sockets have a special state: eCONNECT_SYN.  In this phase,\r
+ * the Ethernet address of the target will be found using ARP.  In case the\r
+ * target IP address is not within the netmask, the hardware address of the\r
+ * gateway will be used.\r
+ */\r
+static BaseType_t prvTCPPrepareConnect( FreeRTOS_Socket_t *pxSocket )\r
+{\r
+TCPPacket_t *pxTCPPacket;\r
+IPHeader_t *pxIPHeader;\r
+eARPLookupResult_t eReturned;\r
+uint32_t ulRemoteIP;\r
+MACAddress_t xEthAddress;\r
+BaseType_t xReturn = pdTRUE;\r
+\r
+       #if( ipconfigHAS_PRINTF != 0 )\r
+       {\r
+               /* Only necessary for nicer logging. */\r
+               memset( xEthAddress.ucBytes, '\0', sizeof( xEthAddress.ucBytes ) );\r
+       }\r
+       #endif /* ipconfigHAS_PRINTF != 0 */\r
+\r
+       ulRemoteIP = FreeRTOS_htonl( pxSocket->u.xTCP.ulRemoteIP );\r
+\r
+       /* Determine the ARP cache status for the requested IP address. */\r
+       eReturned = eARPGetCacheEntry( &( ulRemoteIP ), &( xEthAddress ) );\r
+\r
+       switch( eReturned )\r
+       {\r
+               case eARPCacheHit:              /* An ARP table lookup found a valid entry. */\r
+                       break;                          /* We can now prepare the SYN packet. */\r
+               case eARPCacheMiss:             /* An ARP table lookup did not find a valid entry. */\r
+               case eCantSendPacket:   /* There is no IP address, or an ARP is still in progress. */\r
+               default:\r
+                       /* Count the number of times it couldn't find the ARP address. */\r
+                       pxSocket->u.xTCP.ucRepCount++;\r
+       \r
+                       FreeRTOS_debug_printf( ( "ARP for %lxip (using %lxip): rc=%d %02X:%02X:%02X %02X:%02X:%02X\n",\r
+                               pxSocket->u.xTCP.ulRemoteIP,\r
+                               FreeRTOS_htonl( ulRemoteIP ),\r
+                               eReturned,\r
+                               xEthAddress.ucBytes[ 0 ],\r
+                               xEthAddress.ucBytes[ 1 ],\r
+                               xEthAddress.ucBytes[ 2 ],\r
+                               xEthAddress.ucBytes[ 3 ],\r
+                               xEthAddress.ucBytes[ 4 ],\r
+                               xEthAddress.ucBytes[ 5 ] ) );\r
+       \r
+                       /* And issue a (new) ARP request */\r
+                       FreeRTOS_OutputARPRequest( ulRemoteIP );\r
+       \r
+                       xReturn = pdFALSE;\r
+                       break;\r
+       }\r
+\r
+       if( xReturn != pdFALSE )\r
+       {\r
+               /* The MAC-address of the peer (or gateway) has been found,\r
+               now prepare the initial TCP packet and some fields in the socket. */\r
+               pxTCPPacket = ( TCPPacket_t * )pxSocket->u.xTCP.xPacket.u.ucLastPacket;\r
+               pxIPHeader = &pxTCPPacket->xIPHeader;\r
+\r
+               /* Reset the retry counter to zero... */\r
+               pxSocket->u.xTCP.ucRepCount = 0u;\r
+\r
+               /* ...and remember that the connect/SYN data are prepared. */\r
+               pxSocket->u.xTCP.bits.bConnPrepared = pdTRUE_UNSIGNED;\r
+\r
+               /* Now that the Ethernet address is known, the initial packet can be\r
+               prepared. */\r
+               memset( pxSocket->u.xTCP.xPacket.u.ucLastPacket, '\0', sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );\r
+\r
+               /* Write the Ethernet address in Source, because it will be swapped by\r
+               prvTCPReturnPacket(). */\r
+               memcpy( &pxTCPPacket->xEthernetHeader.xSourceAddress, &xEthAddress, sizeof( xEthAddress ) );\r
+\r
+               /* 'ipIPv4_FRAME_TYPE' is already in network-byte-order. */\r
+               pxTCPPacket->xEthernetHeader.usFrameType = ipIPv4_FRAME_TYPE;\r
+\r
+               pxIPHeader->ucVersionHeaderLength = 0x45u;\r
+               pxIPHeader->usLength = FreeRTOS_htons( sizeof( TCPPacket_t ) - sizeof( pxTCPPacket->xEthernetHeader ) );\r
+               pxIPHeader->ucTimeToLive = ( uint8_t ) ipconfigTCP_TIME_TO_LIVE;\r
+\r
+               pxIPHeader->ucProtocol = ( uint8_t ) ipPROTOCOL_TCP;\r
+\r
+               /* Addresses and ports will be stored swapped because prvTCPReturnPacket\r
+               will swap them back while replying. */\r
+               pxIPHeader->ulDestinationIPAddress = *ipLOCAL_IP_ADDRESS_POINTER;\r
+               pxIPHeader->ulSourceIPAddress = FreeRTOS_htonl( pxSocket->u.xTCP.ulRemoteIP );\r
+\r
+               pxTCPPacket->xTCPHeader.usSourcePort = FreeRTOS_htons( pxSocket->u.xTCP.usRemotePort );\r
+               pxTCPPacket->xTCPHeader.usDestinationPort = FreeRTOS_htons( pxSocket->usLocalPort );\r
+\r
+               /* We are actively connecting, so the peer's Initial Sequence Number (ISN)\r
+               isn't known yet. */\r
+               pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = 0ul;\r
+\r
+               /* Start with ISN (Initial Sequence Number). */\r
+               pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulNextInitialSequenceNumber;\r
+\r
+               /* And increment it with 268 for the next new connection, which is\r
+               recommended value. */\r
+               ulNextInitialSequenceNumber += 0x102UL;\r
+\r
+               /* The TCP header size is 20 bytes, divided by 4 equals 5, which is put in\r
+               the high nibble of the TCP offset field. */\r
+               pxTCPPacket->xTCPHeader.ucTCPOffset = 0x50u;\r
+\r
+               /* Only set the SYN flag. */\r
+               pxTCPPacket->xTCPHeader.ucTCPFlags = ipTCP_FLAG_SYN;\r
+\r
+               /* Set the values of usInitMSS / usCurMSS for this socket. */\r
+               prvSocketSetMSS( pxSocket );\r
+\r
+               /* For now this is also the advertised window size. */\r
+               pxSocket->u.xTCP.ulRxCurWinSize = pxSocket->u.xTCP.usInitMSS;\r
+\r
+               /* The initial sequence numbers at our side are known.  Later\r
+               vTCPWindowInit() will be called to fill in the peer's sequence numbers, but\r
+               first wait for a SYN+ACK reply. */\r
+               prvTCPCreateWindow( pxSocket );\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* For logging and debugging: make a string showing the TCP flags\r
+*/\r
+#if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+\r
+       static const char *prvTCPFlagMeaning( UBaseType_t xFlags)\r
+       {\r
+               static char retString[10];\r
+               snprintf(retString, sizeof( retString ), "%c%c%c%c%c%c%c%c%c",\r
+                       ( xFlags & ipTCP_FLAG_FIN )  ? 'F' : '.',       /* 0x0001: No more data from sender */\r
+                       ( xFlags & ipTCP_FLAG_SYN )  ? 'S' : '.',       /* 0x0002: Synchronize sequence numbers */\r
+                       ( xFlags & ipTCP_FLAG_RST )  ? 'R' : '.',       /* 0x0004: Reset the connection */\r
+                       ( xFlags & ipTCP_FLAG_PSH )  ? 'P' : '.',       /* 0x0008: Push function: please push buffered data to the recv application */\r
+                       ( xFlags & ipTCP_FLAG_ACK )  ? 'A' : '.',       /* 0x0010: Acknowledgment field is significant */\r
+                       ( xFlags & ipTCP_FLAG_URG )  ? 'U' : '.',       /* 0x0020: Urgent pointer field is significant */\r
+                       ( xFlags & ipTCP_FLAG_ECN )  ? 'E' : '.',       /* 0x0040: ECN-Echo */\r
+                       ( xFlags & ipTCP_FLAG_CWR )  ? 'C' : '.',       /* 0x0080: Congestion Window Reduced */\r
+                       ( xFlags & ipTCP_FLAG_NS )   ? 'N' : '.');      /* 0x0100: ECN-nonce concealment protection */\r
+               return retString;\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+#endif /* ipconfigHAS_DEBUG_PRINTF */\r
+\r
+/*\r
+ * Parse the TCP option(s) received, if present.  It has already been verified\r
+ * that: ((pxTCPHeader->ucTCPOffset & 0xf0) > 0x50), meaning that the TP header\r
+ * is longer than the usual 20 (5 x 4) bytes.\r
+ */\r
+static void prvCheckOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )\r
+{\r
+TCPPacket_t * pxTCPPacket;\r
+TCPHeader_t * pxTCPHeader;\r
+const unsigned char *pucPtr;\r
+const unsigned char *pucLast;\r
+TCPWindow_t *pxTCPWindow;\r
+UBaseType_t uxNewMSS;\r
+\r
+       pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+       pxTCPHeader = &pxTCPPacket->xTCPHeader;\r
+\r
+       /* A character pointer to iterate through the option data */\r
+       pucPtr = pxTCPHeader->ucOptdata;\r
+       pucLast = pucPtr + (((pxTCPHeader->ucTCPOffset >> 4) - 5) << 2);\r
+       pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;\r
+\r
+       /* The comparison with pucLast is only necessary in case the option data are\r
+       corrupted, we don't like to run into invalid memory and crash. */\r
+       while( pucPtr < pucLast )\r
+       {\r
+               if( pucPtr[ 0 ] == TCP_OPT_END )\r
+               {\r
+                       /* End of options. */\r
+                       return;\r
+               }\r
+               if( pucPtr[ 0 ] == TCP_OPT_NOOP)\r
+               {\r
+                       pucPtr++;\r
+\r
+                       /* NOP option, inserted to make the length a multiple of 4. */\r
+               }\r
+#if( ipconfigUSE_TCP_WIN != 0 )\r
+               else if( ( pucPtr[ 0 ] == TCP_OPT_WSOPT ) && ( pucPtr[ 1 ] == TCP_OPT_WSOPT_LEN ) )\r
+               {\r
+                       pxSocket->u.xTCP.ucPeerWinScaleFactor = pucPtr[ 2 ];\r
+                       pxSocket->u.xTCP.bits.bWinScaling = pdTRUE_UNSIGNED;\r
+                       pucPtr += TCP_OPT_WSOPT_LEN;\r
+               }\r
+#endif /* ipconfigUSE_TCP_WIN */\r
+               else if( ( pucPtr[ 0 ] == TCP_OPT_MSS ) && ( pucPtr[ 1 ] == TCP_OPT_MSS_LEN ) )\r
+               {\r
+                       /* An MSS option with the correct option length.  FreeRTOS_htons()\r
+                       is not needed here because usChar2u16() already returns a host\r
+                       endian number. */\r
+                       uxNewMSS = usChar2u16( pucPtr + 2 );\r
+\r
+                       if( pxSocket->u.xTCP.usInitMSS != uxNewMSS )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "MSS change %u -> %lu\n", pxSocket->u.xTCP.usInitMSS, uxNewMSS ) );\r
+                       }\r
+\r
+                       if( pxSocket->u.xTCP.usInitMSS > uxNewMSS )\r
+                       {\r
+                               /* our MSS was bigger than the MSS of the other party: adapt it. */\r
+                               pxSocket->u.xTCP.bits.bMssChange = pdTRUE_UNSIGNED;\r
+                               if( ( pxTCPWindow != NULL ) && ( pxSocket->u.xTCP.usCurMSS > uxNewMSS ) )\r
+                               {\r
+                                       /* The peer advertises a smaller MSS than this socket was\r
+                                       using.  Use that as well. */\r
+                                       FreeRTOS_debug_printf( ( "Change mss %d => %lu\n", pxSocket->u.xTCP.usCurMSS, uxNewMSS ) );\r
+                                       pxSocket->u.xTCP.usCurMSS = ( uint16_t ) uxNewMSS;\r
+                               }\r
+                               pxTCPWindow->xSize.ulRxWindowLength = ( ( uint32_t ) uxNewMSS ) * ( pxTCPWindow->xSize.ulRxWindowLength / ( ( uint32_t ) uxNewMSS ) );\r
+                               pxTCPWindow->usMSSInit = ( uint16_t ) uxNewMSS;\r
+                               pxTCPWindow->usMSS = ( uint16_t ) uxNewMSS;\r
+                               pxSocket->u.xTCP.usInitMSS = ( uint16_t ) uxNewMSS;\r
+                               pxSocket->u.xTCP.usCurMSS = ( uint16_t ) uxNewMSS;\r
+                       }\r
+\r
+                       #if( ipconfigUSE_TCP_WIN != 1 )\r
+                               /* Without scaled windows, MSS is the only interesting option. */\r
+                               break;\r
+                       #else\r
+                               /* Or else we continue to check another option: selective ACK. */\r
+                               pucPtr += TCP_OPT_MSS_LEN;\r
+                       #endif  /* ipconfigUSE_TCP_WIN != 1 */\r
+               }\r
+               else\r
+               {\r
+                       /* All other options have a length field, so that we easily\r
+                       can skip past them. */\r
+                       int len = ( int )pucPtr[ 1 ];\r
+                       if( len == 0 )\r
+                       {\r
+                               /* If the length field is zero, the options are malformed\r
+                               and we don't process them further. */\r
+                               break;\r
+                       }\r
+\r
+                       #if( ipconfigUSE_TCP_WIN == 1 )\r
+                       {\r
+                               /* Selective ACK: the peer has received a packet but it is missing earlier\r
+                               packets.  At least this packet does not need retransmission anymore\r
+                               ulTCPWindowTxSack( ) takes care of this administration. */\r
+                               if( pucPtr[0] == TCP_OPT_SACK_A )\r
+                               {\r
+                                       len -= 2;\r
+                                       pucPtr += 2;\r
+\r
+                                       while( len >= 8 )\r
+                                       {\r
+                                       uint32_t ulFirst = ulChar2u32( pucPtr );\r
+                                       uint32_t ulLast  = ulChar2u32( pucPtr + 4 );\r
+                                       uint32_t ulCount = ulTCPWindowTxSack( &pxSocket->u.xTCP.xTCPWindow, ulFirst, ulLast );\r
+                                               /* ulTCPWindowTxSack( ) returns the number of bytes which have been acked\r
+                                               starting from the head position.\r
+                                               Advance the tail pointer in txStream. */\r
+                                               if( ( pxSocket->u.xTCP.txStream  != NULL ) && ( ulCount > 0 ) )\r
+                                               {\r
+                                                       /* Just advancing the tail index, 'ulCount' bytes have been confirmed. */\r
+                                                       uxStreamBufferGet( pxSocket->u.xTCP.txStream, 0, NULL, ( size_t ) ulCount, pdFALSE );\r
+                                                       pxSocket->xEventBits |= eSOCKET_SEND;\r
+\r
+                                                       #if ipconfigSUPPORT_SELECT_FUNCTION == 1\r
+                                                       {\r
+                                                               if( pxSocket->xSelectBits & eSELECT_WRITE )\r
+                                                               {\r
+                                                                       /* The field 'xEventBits' is used to store regular socket events (at most 8),\r
+                                                                       as well as 'select events', which will be left-shifted */\r
+                                                                       pxSocket->xEventBits |= ( eSELECT_WRITE << SOCKET_EVENT_BIT_COUNT );\r
+                                                               }\r
+                                                       }\r
+                                                       #endif\r
+\r
+                                                       /* In case the socket owner has installed an OnSent handler,\r
+                                                       call it now. */\r
+                                                       #if( ipconfigUSE_CALLBACKS == 1 )\r
+                                                       {\r
+                                                               if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleSent ) )\r
+                                                               {\r
+                                                                       pxSocket->u.xTCP.pxHandleSent( (Socket_t *)pxSocket, ulCount );\r
+                                                               }\r
+                                                       }\r
+                                                       #endif /* ipconfigUSE_CALLBACKS == 1  */\r
+                                               }\r
+                                               pucPtr += 8;\r
+                                               len -= 8;\r
+                                       }\r
+                                       /* len should be 0 by now. */\r
+                               }\r
+                               #if     ipconfigUSE_TCP_TIMESTAMPS == 1\r
+                                       else if( pucPtr[0] == TCP_OPT_TIMESTAMP )\r
+                                       {\r
+                                               len -= 2;       /* Skip option and length byte. */\r
+                                               pucPtr += 2;\r
+                                               pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps = pdTRUE_UNSIGNED;\r
+                                               pxSocket->u.xTCP.xTCPWindow.rx.ulTimeStamp = ulChar2u32( pucPtr );\r
+                                               pxSocket->u.xTCP.xTCPWindow.tx.ulTimeStamp = ulChar2u32( pucPtr + 4 );\r
+                                       }\r
+                               #endif  /* ipconfigUSE_TCP_TIMESTAMPS == 1 */\r
+                       }\r
+                       #endif  /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+                       pucPtr += len;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN != 0 )\r
+\r
+       static uint8_t prvWinScaleFactor( FreeRTOS_Socket_t *pxSocket )\r
+       {\r
+       size_t uxWinSize;\r
+       uint8_t ucFactor;\r
+\r
+               /* 'xTCP.uxRxWinSize' is the size of the reception window in units of MSS. */\r
+               uxWinSize = pxSocket->u.xTCP.uxRxWinSize * ( size_t ) pxSocket->u.xTCP.usInitMSS;\r
+               ucFactor = 0u;\r
+               while( uxWinSize > 0xfffful )\r
+               {\r
+                       /* Divide by two and increase the binary factor by 1. */\r
+                       uxWinSize >>= 1;\r
+                       ucFactor++;\r
+               }\r
+\r
+               FreeRTOS_debug_printf( ( "prvWinScaleFactor: uxRxWinSize %lu MSS %lu Factor %u\n",\r
+                       pxSocket->u.xTCP.uxRxWinSize,\r
+                       pxSocket->u.xTCP.usInitMSS,\r
+                       ucFactor ) );\r
+\r
+               return ucFactor;\r
+       }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * When opening a TCP connection, while SYN's are being sent, the  parties may\r
+ * communicate what MSS (Maximum Segment Size) they intend to use.   MSS is the\r
+ * nett size of the payload, always smaller than MTU.\r
+*/\r
+static UBaseType_t prvSetSynAckOptions( FreeRTOS_Socket_t *pxSocket, TCPPacket_t * pxTCPPacket )\r
+{\r
+TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;\r
+uint16_t usMSS = pxSocket->u.xTCP.usInitMSS;\r
+UBaseType_t uxOptionsLength;\r
+\r
+       /* We send out the TCP Maximum Segment Size option with our SYN[+ACK]. */\r
+\r
+       pxTCPHeader->ucOptdata[ 0 ] = ( uint8_t ) TCP_OPT_MSS;\r
+       pxTCPHeader->ucOptdata[ 1 ] = ( uint8_t ) TCP_OPT_MSS_LEN;\r
+       pxTCPHeader->ucOptdata[ 2 ] = ( uint8_t ) ( usMSS >> 8 );\r
+       pxTCPHeader->ucOptdata[ 3 ] = ( uint8_t ) ( usMSS & 0xffu );\r
+\r
+       #if( ipconfigUSE_TCP_WIN != 0 )\r
+       {\r
+               pxSocket->u.xTCP.ucMyWinScaleFactor = prvWinScaleFactor( pxSocket );\r
+\r
+               pxTCPHeader->ucOptdata[ 4 ] = TCP_OPT_NOOP;\r
+               pxTCPHeader->ucOptdata[ 5 ] = ( uint8_t ) ( TCP_OPT_WSOPT );\r
+               pxTCPHeader->ucOptdata[ 6 ] = ( uint8_t ) ( TCP_OPT_WSOPT_LEN );\r
+               pxTCPHeader->ucOptdata[ 7 ] = ( uint8_t ) pxSocket->u.xTCP.ucMyWinScaleFactor;\r
+               uxOptionsLength = 8u;\r
+       }\r
+       #else\r
+       {\r
+               uxOptionsLength = 4u;\r
+       }\r
+       #endif\r
+\r
+       #if( ipconfigUSE_TCP_WIN == 0 )\r
+       {\r
+               return uxOptionsLength;\r
+       }\r
+       #else\r
+       {\r
+               #if( ipconfigUSE_TCP_TIMESTAMPS == 1 )\r
+                       if( pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps )\r
+                       {\r
+                               uxOptionsLength += prvTCPSetTimeStamp( uxOptionsLength, pxSocket, &pxTCPPacket->xTCPHeader );\r
+                               pxTCPHeader->ucOptdata[ uxOptionsLength + 0 ] = TCP_OPT_SACK_P; /* 4: Sack-Permitted Option. */\r
+                               pxTCPHeader->ucOptdata[ uxOptionsLength + 1 ] = 2u;\r
+                               uxOptionsLength += 2u;\r
+                       }\r
+                       else\r
+               #endif\r
+               {\r
+                       pxTCPHeader->ucOptdata[ uxOptionsLength + 0 ] = TCP_OPT_NOOP;\r
+                       pxTCPHeader->ucOptdata[ uxOptionsLength + 1 ] = TCP_OPT_NOOP;\r
+                       pxTCPHeader->ucOptdata[ uxOptionsLength + 2 ] = TCP_OPT_SACK_P; /* 4: Sack-Permitted Option. */\r
+                       pxTCPHeader->ucOptdata[ uxOptionsLength + 3 ] = 2;      /* 2: length of this option. */\r
+                       uxOptionsLength += 4u;\r
+               }\r
+               return uxOptionsLength; /* bytes, not words. */\r
+       }\r
+       #endif  /* ipconfigUSE_TCP_WIN == 0 */\r
+}\r
+\r
+/*\r
+ * For anti-hanging protection and TCP keep-alive messages.  Called in two\r
+ * places: after receiving a packet and after a state change.  The socket's\r
+ * alive timer may be reset.\r
+ */\r
+static void prvTCPTouchSocket( FreeRTOS_Socket_t *pxSocket )\r
+{\r
+       #if( ipconfigTCP_HANG_PROTECTION == 1 )\r
+       {\r
+               pxSocket->u.xTCP.xLastActTime = xTaskGetTickCount( );\r
+       }\r
+       #endif\r
+\r
+       #if( ipconfigTCP_KEEP_ALIVE == 1 )\r
+       {\r
+               pxSocket->u.xTCP.bits.bWaitKeepAlive = pdFALSE_UNSIGNED;\r
+               pxSocket->u.xTCP.bits.bSendKeepAlive = pdFALSE_UNSIGNED;\r
+               pxSocket->u.xTCP.ucKeepRepCount = 0u;\r
+               pxSocket->u.xTCP.xLastAliveTime = xTaskGetTickCount();\r
+       }\r
+       #endif\r
+\r
+       ( void ) pxSocket;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Changing to a new state. Centralised here to do specific actions such as\r
+ * resetting the alive timer, calling the user's OnConnect handler to notify\r
+ * that a socket has got (dis)connected, and setting bit to unblock a call to\r
+ * FreeRTOS_select()\r
+ */\r
+void vTCPStateChange( FreeRTOS_Socket_t *pxSocket, enum eTCP_STATE eTCPState )\r
+{\r
+FreeRTOS_Socket_t *xParent = NULL;\r
+BaseType_t bBefore = ( BaseType_t ) NOW_CONNECTED( pxSocket->u.xTCP.ucTCPState );      /* Was it connected ? */\r
+BaseType_t bAfter  = ( BaseType_t ) NOW_CONNECTED( eTCPState );                                                /* Is it connected now ? */\r
+#if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+       BaseType_t xPreviousState = ( BaseType_t ) pxSocket->u.xTCP.ucTCPState;\r
+#endif\r
+#if( ipconfigUSE_CALLBACKS == 1 )\r
+       FreeRTOS_Socket_t *xConnected = NULL;\r
+#endif\r
+\r
+       /* Has the connected status changed? */\r
+       if( bBefore != bAfter )\r
+       {\r
+               /* Is the socket connected now ? */\r
+               if( bAfter != pdFALSE )\r
+               {\r
+                       /* if bPassQueued is true, this socket is an orphan until it gets connected. */\r
+                       if( pxSocket->u.xTCP.bits.bPassQueued != pdFALSE_UNSIGNED )\r
+                       {\r
+                               /* Now that it is connected, find it's parent. */\r
+                               if( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED )\r
+                               {\r
+                                       xParent = pxSocket;\r
+                               }\r
+                               else\r
+                               {\r
+                                       xParent = pxSocket->u.xTCP.pxPeerSocket;\r
+                                       configASSERT( xParent != NULL );\r
+                               }\r
+                               if( xParent != NULL )\r
+                               {\r
+                                       if( xParent->u.xTCP.pxPeerSocket == NULL )\r
+                                       {\r
+                                               xParent->u.xTCP.pxPeerSocket = pxSocket;\r
+                                       }\r
+\r
+                                       xParent->xEventBits |= eSOCKET_ACCEPT;\r
+\r
+                                       #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+                                       {\r
+                                               /* Library support FreeRTOS_select().  Receiving a new\r
+                                               connection is being translated as a READ event. */\r
+                                               if( ( xParent->xSelectBits & eSELECT_READ ) != 0 )\r
+                                               {\r
+                                                       xParent->xEventBits |= ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT );\r
+                                               }\r
+                                       }\r
+                                       #endif\r
+\r
+                                       #if( ipconfigUSE_CALLBACKS == 1 )\r
+                                       {\r
+                                               if( ( ipconfigIS_VALID_PROG_ADDRESS( xParent->u.xTCP.pxHandleConnected ) != pdFALSE ) &&\r
+                                                       ( xParent->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) )\r
+                                               {\r
+                                                       /* The listening socket does not become connected itself, in stead\r
+                                                       a child socket is created.\r
+                                                       Postpone a call the OnConnect event until the end of this function. */\r
+                                                       xConnected = xParent;\r
+                                               }\r
+                                       }\r
+                                       #endif\r
+                               }\r
+\r
+                               /* Don't need to access the parent socket anymore, so the\r
+                               reference 'pxPeerSocket' may be cleared. */\r
+                               pxSocket->u.xTCP.pxPeerSocket = NULL;\r
+                               pxSocket->u.xTCP.bits.bPassQueued = pdFALSE_UNSIGNED;\r
+\r
+                               /* When true, this socket may be returned in a call to accept(). */\r
+                               pxSocket->u.xTCP.bits.bPassAccept = pdTRUE_UNSIGNED;\r
+                       }\r
+                       else\r
+                       {\r
+                               pxSocket->xEventBits |= eSOCKET_CONNECT;\r
+\r
+                               #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+                               {\r
+                                       if( pxSocket->xSelectBits & eSELECT_WRITE )\r
+                                       {\r
+                                               pxSocket->xEventBits |= ( eSELECT_WRITE << SOCKET_EVENT_BIT_COUNT );\r
+                                       }\r
+                               }\r
+                               #endif\r
+                       }\r
+               }\r
+               else  /* bAfter == pdFALSE, connection is closed. */\r
+               {\r
+                       /* Notify/wake-up the socket-owner by setting a semaphore. */\r
+                       pxSocket->xEventBits |= eSOCKET_CLOSED;\r
+\r
+                       #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+                       {\r
+                               if( ( pxSocket->xSelectBits & eSELECT_EXCEPT ) != 0 )\r
+                               {\r
+                                       pxSocket->xEventBits |= ( eSELECT_EXCEPT << SOCKET_EVENT_BIT_COUNT );\r
+                               }\r
+                       }\r
+                       #endif\r
+               }\r
+               #if( ipconfigUSE_CALLBACKS == 1 )\r
+               {\r
+                       if( ( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleConnected ) != pdFALSE ) && ( xConnected == NULL ) )\r
+                       {\r
+                               /* The 'connected' state has changed, call the user handler. */\r
+                               xConnected = pxSocket;\r
+                       }\r
+               }\r
+               #endif /* ipconfigUSE_CALLBACKS */\r
+\r
+               if( prvTCPSocketIsActive( ( UBaseType_t ) pxSocket->u.xTCP.ucTCPState ) == pdFALSE )\r
+               {\r
+                       /* Now the socket isn't in an active state anymore so it\r
+                       won't need further attention of the IP-task.\r
+                       Setting time-out to zero means that the socket won't get checked during\r
+                       timer events. */\r
+                       pxSocket->u.xTCP.usTimeout = 0u;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if( eTCPState == eCLOSED )\r
+               {\r
+                       /* Socket goes to status eCLOSED because of a RST.\r
+                       When nobody owns the socket yet, delete it. */\r
+                       if( ( pxSocket->u.xTCP.bits.bPassQueued != pdFALSE_UNSIGNED ) ||\r
+                               ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "vTCPStateChange: Closing socket\n" ) );\r
+                               if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED )\r
+                               {\r
+                                       FreeRTOS_closesocket( pxSocket );\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* Fill in the new state. */\r
+       pxSocket->u.xTCP.ucTCPState = ( uint8_t ) eTCPState;\r
+\r
+       /* Touch the alive timers because moving to another state. */\r
+       prvTCPTouchSocket( pxSocket );\r
+\r
+       #if( ipconfigHAS_DEBUG_PRINTF == 1 )\r
+       {\r
+       if( ( xTCPWindowLoggingLevel >= 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE ) )\r
+               FreeRTOS_debug_printf( ( "Socket %d -> %lxip:%u State %s->%s\n",\r
+                       pxSocket->usLocalPort,\r
+                       pxSocket->u.xTCP.ulRemoteIP,\r
+                       pxSocket->u.xTCP.usRemotePort,\r
+                       FreeRTOS_GetTCPStateName( ( UBaseType_t ) xPreviousState ),\r
+                       FreeRTOS_GetTCPStateName( ( UBaseType_t ) eTCPState ) ) );\r
+       }\r
+       #endif /* ipconfigHAS_DEBUG_PRINTF */\r
+\r
+       #if( ipconfigUSE_CALLBACKS == 1 )\r
+       {\r
+               if( xConnected != NULL )\r
+               {\r
+                       /* The 'connected' state has changed, call the OnConnect handler of the parent. */\r
+                       xConnected->u.xTCP.pxHandleConnected( ( Socket_t * ) xConnected, bAfter );\r
+               }\r
+       }\r
+       #endif\r
+       if( xParent != NULL )\r
+       {\r
+               vSocketWakeUpUser( xParent );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static NetworkBufferDescriptor_t *prvTCPBufferResize( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer,\r
+       int32_t lDataLen, UBaseType_t uxOptionsLength )\r
+{\r
+NetworkBufferDescriptor_t *pxReturn;\r
+int32_t lNeeded;\r
+BaseType_t xResize;\r
+\r
+       if( xBufferAllocFixedSize != pdFALSE )\r
+       {\r
+               /* Network buffers are created with a fixed size and can hold the largest\r
+               MTU. */\r
+               lNeeded = ( int32_t ) ipTOTAL_ETHERNET_FRAME_SIZE;\r
+               /* and therefore, the buffer won't be too small.\r
+               Only ask for a new network buffer in case none was supplied. */\r
+               xResize = ( pxNetworkBuffer == NULL );\r
+       }\r
+       else\r
+       {\r
+               /* Network buffers are created with a variable size. See if it must\r
+               grow. */\r
+               lNeeded = FreeRTOS_max_int32( ( int32_t ) sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ),\r
+                       ( int32_t ) ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength ) + lDataLen );\r
+               /* In case we were called from a TCP timer event, a buffer must be\r
+               created.  Otherwise, test 'xDataLength' of the provided buffer. */\r
+               if( ( pxNetworkBuffer == NULL ) || ( pxNetworkBuffer->xDataLength < (size_t)lNeeded ) )\r
+               {\r
+                       xResize = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       xResize = pdFALSE;\r
+               }\r
+       }\r
+\r
+       if( xResize != pdFALSE )\r
+       {\r
+               /* The caller didn't provide a network buffer or the provided buffer is\r
+               too small.  As we must send-out a data packet, a buffer will be created\r
+               here. */\r
+               pxReturn = pxGetNetworkBufferWithDescriptor( ( uint32_t ) lNeeded, 0u );\r
+\r
+               if( pxReturn != NULL )\r
+               {\r
+                       /* Copy the existing data to the new created buffer. */\r
+                       if( pxNetworkBuffer )\r
+                       {\r
+                               /* Either from the previous buffer... */\r
+                               memcpy( pxReturn->pucEthernetBuffer, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );\r
+\r
+                               /* ...and release it. */\r
+                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Or from the socket field 'xTCP.xPacket'. */\r
+                               memcpy( pxReturn->pucEthernetBuffer, pxSocket->u.xTCP.xPacket.u.ucLastPacket, sizeof( pxSocket->u.xTCP.xPacket.u.ucLastPacket ) );\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               /* xResize is false, the network buffer provided was big enough. */\r
+               pxReturn = pxNetworkBuffer;\r
+\r
+               /* Thanks to Andrey Ivanov from swissEmbedded for reporting that the\r
+               xDataLength member must get the correct length too! */\r
+               pxNetworkBuffer->xDataLength = ( size_t ) ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength ) + ( size_t ) lDataLen;\r
+       }\r
+\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Prepare an outgoing message, in case anything has to be sent.\r
+ */\r
+static int32_t prvTCPPrepareSend( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer, UBaseType_t uxOptionsLength )\r
+{\r
+int32_t lDataLen;\r
+uint8_t *pucEthernetBuffer, *pucSendData;\r
+TCPPacket_t *pxTCPPacket;\r
+size_t uxOffset;\r
+uint32_t ulDataGot, ulDistance;\r
+TCPWindow_t *pxTCPWindow;\r
+NetworkBufferDescriptor_t *pxNewBuffer;\r
+int32_t lStreamPos;\r
+\r
+       if( ( *ppxNetworkBuffer ) != NULL )\r
+       {\r
+               /* A network buffer descriptor was already supplied */\r
+               pucEthernetBuffer = ( *ppxNetworkBuffer )->pucEthernetBuffer;\r
+       }\r
+       else\r
+       {\r
+               /* For now let it point to the last packet header */\r
+               pucEthernetBuffer = pxSocket->u.xTCP.xPacket.u.ucLastPacket;\r
+       }\r
+\r
+       pxTCPPacket = ( TCPPacket_t * ) pucEthernetBuffer;\r
+       pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );\r
+       lDataLen = 0;\r
+       lStreamPos = 0;\r
+       pxTCPPacket->xTCPHeader.ucTCPFlags |= ipTCP_FLAG_ACK;\r
+\r
+       if( pxSocket->u.xTCP.txStream != NULL )\r
+       {\r
+               /* ulTCPWindowTxGet will return the amount of data which may be sent\r
+               along with the position in the txStream.\r
+               Why check for MSS > 1 ?\r
+               Because some TCP-stacks (like uIP) use it for flow-control. */\r
+               if( pxSocket->u.xTCP.usCurMSS > 1u )\r
+               {\r
+                       lDataLen = ( int32_t ) ulTCPWindowTxGet( pxTCPWindow, pxSocket->u.xTCP.ulWindowSize, &lStreamPos );\r
+               }\r
+\r
+               if( lDataLen > 0 )\r
+               {\r
+                       /* Check if the current network buffer is big enough, if not,\r
+                       resize it. */\r
+                       pxNewBuffer = prvTCPBufferResize( pxSocket, *ppxNetworkBuffer, lDataLen, uxOptionsLength );\r
+\r
+                       if( pxNewBuffer != NULL )\r
+                       {\r
+                               *ppxNetworkBuffer = pxNewBuffer;\r
+                               pucEthernetBuffer = pxNewBuffer->pucEthernetBuffer;\r
+                               pxTCPPacket = ( TCPPacket_t * ) ( pucEthernetBuffer );\r
+\r
+                               pucSendData = pucEthernetBuffer + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength;\r
+\r
+                               /* Translate the position in txStream to an offset from the tail\r
+                               marker. */\r
+                               uxOffset = uxStreamBufferDistance( pxSocket->u.xTCP.txStream, pxSocket->u.xTCP.txStream->uxTail, ( size_t ) lStreamPos );\r
+\r
+                               /* Here data is copied from the txStream in 'peek' mode.  Only\r
+                               when the packets are acked, the tail marker will be updated. */\r
+                               ulDataGot = ( uint32_t ) uxStreamBufferGet( pxSocket->u.xTCP.txStream, uxOffset, pucSendData, ( size_t ) lDataLen, pdTRUE );\r
+\r
+                               #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+                               {\r
+                                       if( ulDataGot != ( uint32_t ) lDataLen )\r
+                                       {\r
+                                               FreeRTOS_debug_printf( ( "uxStreamBufferGet: pos %lu offs %lu only %lu != %lu\n",\r
+                                                       lStreamPos, uxOffset, ulDataGot, lDataLen ) );\r
+                                       }\r
+                               }\r
+                               #endif\r
+\r
+                               /* If the owner of the socket requests a closure, add the FIN\r
+                               flag to the last packet. */\r
+                               if( ( pxSocket->u.xTCP.bits.bCloseRequested != pdFALSE_UNSIGNED ) && ( pxSocket->u.xTCP.bits.bFinSent == pdFALSE_UNSIGNED ) )\r
+                               {\r
+                                       ulDistance = ( uint32_t ) uxStreamBufferDistance( pxSocket->u.xTCP.txStream, ( size_t ) lStreamPos, pxSocket->u.xTCP.txStream->uxHead );\r
+\r
+                                       if( ulDistance == ulDataGot )\r
+                                       {\r
+                                               #if (ipconfigHAS_DEBUG_PRINTF == 1)\r
+                                               {\r
+                                               /* the order of volatile accesses is undefined\r
+                                                       so such workaround */\r
+                                                       size_t uxHead = pxSocket->u.xTCP.txStream->uxHead;\r
+                                                       size_t uxMid = pxSocket->u.xTCP.txStream->uxMid;\r
+                                                       size_t uxTail = pxSocket->u.xTCP.txStream->uxTail;\r
+\r
+                                                       FreeRTOS_debug_printf( ( "CheckClose %lu <= %lu (%lu <= %lu <= %lu)\n", ulDataGot, ulDistance,\r
+                                                               uxTail, uxMid, uxHead ) );\r
+                                               }\r
+                                               #endif\r
+                                               /* Although the socket sends a FIN, it will stay in\r
+                                               ESTABLISHED until all current data has been received or\r
+                                               delivered. */\r
+                                               pxTCPPacket->xTCPHeader.ucTCPFlags |= ipTCP_FLAG_FIN;\r
+                                               pxTCPWindow->tx.ulFINSequenceNumber = pxTCPWindow->ulOurSequenceNumber + ( uint32_t ) lDataLen;\r
+                                               pxSocket->u.xTCP.bits.bFinSent = pdTRUE_UNSIGNED;\r
+                                       }\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               lDataLen = -1;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if( ( lDataLen >= 0 ) && ( pxSocket->u.xTCP.ucTCPState == eESTABLISHED ) )\r
+       {\r
+               /* See if the socket owner wants to shutdown this connection. */\r
+               if( ( pxSocket->u.xTCP.bits.bUserShutdown != pdFALSE_UNSIGNED ) &&\r
+                       ( xTCPWindowTxDone( pxTCPWindow ) != pdFALSE ) )\r
+               {\r
+                       pxSocket->u.xTCP.bits.bUserShutdown = pdFALSE_UNSIGNED;\r
+                       pxTCPPacket->xTCPHeader.ucTCPFlags |= ipTCP_FLAG_FIN;\r
+                       pxSocket->u.xTCP.bits.bFinSent = pdTRUE_UNSIGNED;\r
+                       pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
+                       pxTCPWindow->tx.ulFINSequenceNumber = pxTCPWindow->tx.ulCurrentSequenceNumber;\r
+                       vTCPStateChange( pxSocket, eFIN_WAIT_1 );\r
+               }\r
+\r
+               #if( ipconfigTCP_KEEP_ALIVE != 0 )\r
+               {\r
+                       if( pxSocket->u.xTCP.ucKeepRepCount > 3u )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "keep-alive: giving up %lxip:%u\n",\r
+                                       pxSocket->u.xTCP.ulRemoteIP,                    /* IP address of remote machine. */\r
+                                       pxSocket->u.xTCP.usRemotePort ) );      /* Port on remote machine. */\r
+                               vTCPStateChange( pxSocket, eCLOSE_WAIT );\r
+                               lDataLen = -1;\r
+                       }\r
+                       if( ( lDataLen == 0 ) && ( pxSocket->u.xTCP.bits.bWinChange == pdFALSE_UNSIGNED ) )\r
+                       {\r
+                               /* If there is no data to be sent, and no window-update message,\r
+                               we might want to send a keep-alive message. */\r
+                               TickType_t xAge = xTaskGetTickCount( ) - pxSocket->u.xTCP.xLastAliveTime;\r
+                               TickType_t xMax;\r
+                               xMax = ( ( TickType_t ) ipconfigTCP_KEEP_ALIVE_INTERVAL * configTICK_RATE_HZ );\r
+                               if( pxSocket->u.xTCP.ucKeepRepCount )\r
+                               {\r
+                                       xMax = ( 3u * configTICK_RATE_HZ );\r
+                               }\r
+                               if( xAge > xMax )\r
+                               {\r
+                                       pxSocket->u.xTCP.xLastAliveTime = xTaskGetTickCount( );\r
+                                       if( xTCPWindowLoggingLevel )\r
+                                               FreeRTOS_debug_printf( ( "keep-alive: %lxip:%u count %u\n",\r
+                                                       pxSocket->u.xTCP.ulRemoteIP,\r
+                                                       pxSocket->u.xTCP.usRemotePort,\r
+                                                       pxSocket->u.xTCP.ucKeepRepCount ) );\r
+                                       pxSocket->u.xTCP.bits.bSendKeepAlive = pdTRUE_UNSIGNED;\r
+                                       pxSocket->u.xTCP.usTimeout = ( ( uint16_t ) pdMS_TO_TICKS( 2500 ) );\r
+                                       pxSocket->u.xTCP.ucKeepRepCount++;\r
+                               }\r
+                       }\r
+               }\r
+               #endif /* ipconfigTCP_KEEP_ALIVE */\r
+       }\r
+\r
+       /* Anything to send, a change of the advertised window size, or maybe send a\r
+       keep-alive message? */\r
+       if( ( lDataLen > 0 ) ||\r
+               ( pxSocket->u.xTCP.bits.bWinChange != pdFALSE_UNSIGNED ) ||\r
+               ( pxSocket->u.xTCP.bits.bSendKeepAlive != pdFALSE_UNSIGNED ) )\r
+       {\r
+               pxTCPPacket->xTCPHeader.ucTCPFlags &= ( ( uint8_t ) ~ipTCP_FLAG_PSH );\r
+               pxTCPPacket->xTCPHeader.ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );\r
+\r
+               pxTCPPacket->xTCPHeader.ucTCPFlags |= ( uint8_t ) ipTCP_FLAG_ACK;\r
+\r
+               if( lDataLen != 0l )\r
+               {\r
+                       pxTCPPacket->xTCPHeader.ucTCPFlags |= ( uint8_t ) ipTCP_FLAG_PSH;\r
+               }\r
+\r
+               #if     ipconfigUSE_TCP_TIMESTAMPS == 1\r
+               {\r
+                       if( uxOptionsLength == 0u )\r
+                       {\r
+                               if( pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps )\r
+                               {\r
+                                       TCPPacket_t * pxTCPPacket = ( TCPPacket_t * ) ( pucEthernetBuffer );\r
+                                       uxOptionsLength = prvTCPSetTimeStamp( 0, pxSocket, &pxTCPPacket->xTCPHeader );\r
+                               }\r
+                       }\r
+               }\r
+               #endif\r
+\r
+               lDataLen += ( int32_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );\r
+       }\r
+\r
+       return lDataLen;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Calculate after how much time this socket needs to be checked again.\r
+ */\r
+static TickType_t prvTCPNextTimeout ( FreeRTOS_Socket_t *pxSocket )\r
+{\r
+TickType_t ulDelayMs = ( TickType_t ) tcpMAXIMUM_TCP_WAKEUP_TIME_MS;\r
+\r
+       if( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN )\r
+       {\r
+               /* The socket is actively connecting to a peer. */\r
+               if( pxSocket->u.xTCP.bits.bConnPrepared )\r
+               {\r
+                       /* Ethernet address has been found, use progressive timeout for\r
+                       active connect(). */\r
+                       if( pxSocket->u.xTCP.ucRepCount < 3u )\r
+                       {\r
+                               ulDelayMs = ( 3000UL << ( pxSocket->u.xTCP.ucRepCount - 1u ) );\r
+                       }\r
+                       else\r
+                       {\r
+                               ulDelayMs = 11000UL;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* Still in the ARP phase: check every half second. */\r
+                       ulDelayMs = 500UL;\r
+               }\r
+\r
+               FreeRTOS_debug_printf( ( "Connect[%lxip:%u]: next timeout %u: %lu ms\n",\r
+                       pxSocket->u.xTCP.ulRemoteIP, pxSocket->u.xTCP.usRemotePort,\r
+                       pxSocket->u.xTCP.ucRepCount, ulDelayMs ) );\r
+               pxSocket->u.xTCP.usTimeout = ( uint16_t )pdMS_TO_MIN_TICKS( ulDelayMs );\r
+       }\r
+       else if( pxSocket->u.xTCP.usTimeout == 0u )\r
+       {\r
+               /* Let the sliding window mechanism decide what time-out is appropriate. */\r
+               BaseType_t xResult = xTCPWindowTxHasData( &pxSocket->u.xTCP.xTCPWindow, pxSocket->u.xTCP.ulWindowSize, &ulDelayMs );\r
+               if( ulDelayMs == 0u )\r
+               {\r
+                       if( xResult != ( BaseType_t )0 )\r
+                       {\r
+                               ulDelayMs = 1UL;\r
+                       }\r
+                       else\r
+                       {\r
+                               ulDelayMs = tcpMAXIMUM_TCP_WAKEUP_TIME_MS;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* ulDelayMs contains the time to wait before a re-transmission. */\r
+               }\r
+               pxSocket->u.xTCP.usTimeout = ( uint16_t )pdMS_TO_MIN_TICKS( ulDelayMs );\r
+       }\r
+       else\r
+       {\r
+               /* field '.usTimeout' has already been set (by the\r
+               keep-alive/delayed-ACK mechanism). */\r
+       }\r
+\r
+       /* Return the number of clock ticks before the timer expires. */\r
+       return ( TickType_t ) pxSocket->u.xTCP.usTimeout;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTCPAddTxData( FreeRTOS_Socket_t *pxSocket )\r
+{\r
+int32_t lCount, lLength;\r
+\r
+       /* A txStream has been created already, see if the socket has new data for\r
+       the sliding window.\r
+\r
+       uxStreamBufferMidSpace() returns the distance between rxHead and rxMid.  It\r
+       contains new Tx data which has not been passed to the sliding window yet.\r
+       The oldest data not-yet-confirmed can be found at rxTail. */\r
+       lLength = ( int32_t ) uxStreamBufferMidSpace( pxSocket->u.xTCP.txStream );\r
+\r
+       if( lLength > 0 )\r
+       {\r
+               /* All data between txMid and rxHead will now be passed to the sliding\r
+               window manager, so it can start transmitting them.\r
+\r
+               Hand over the new data to the sliding window handler.  It will be\r
+               split-up in chunks of 1460 bytes each (or less, depending on\r
+               ipconfigTCP_MSS). */\r
+               lCount = lTCPWindowTxAdd(       &pxSocket->u.xTCP.xTCPWindow,\r
+                                                               ( uint32_t ) lLength,\r
+                                                               ( int32_t ) pxSocket->u.xTCP.txStream->uxMid,\r
+                                                               ( int32_t ) pxSocket->u.xTCP.txStream->LENGTH );\r
+\r
+               /* Move the rxMid pointer forward up to rxHead. */\r
+               if( lCount > 0 )\r
+               {\r
+                       vStreamBufferMoveMid( pxSocket->u.xTCP.txStream, ( size_t ) lCount );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * prvTCPHandleFin() will be called to handle socket closure\r
+ * The Closure starts when either a FIN has been received and accepted,\r
+ * Or when the socket has sent a FIN flag to the peer\r
+ * Before being called, it has been checked that both reception and transmission\r
+ * are complete.\r
+ */\r
+static BaseType_t prvTCPHandleFin( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )\r
+{\r
+TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;\r
+uint8_t ucTCPFlags = pxTCPHeader->ucTCPFlags;\r
+TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;\r
+BaseType_t xSendLength = 0;\r
+uint32_t ulAckNr = FreeRTOS_ntohl( pxTCPHeader->ulAckNr );\r
+\r
+       if( ( ucTCPFlags & ipTCP_FLAG_FIN ) != 0u )\r
+       {\r
+               pxTCPWindow->rx.ulCurrentSequenceNumber = pxTCPWindow->rx.ulFINSequenceNumber + 1u;\r
+       }\r
+       if( pxSocket->u.xTCP.bits.bFinSent == pdFALSE_UNSIGNED )\r
+       {\r
+               /* We haven't yet replied with a FIN, do so now. */\r
+               pxTCPWindow->tx.ulFINSequenceNumber = pxTCPWindow->tx.ulCurrentSequenceNumber;\r
+               pxSocket->u.xTCP.bits.bFinSent = pdTRUE_UNSIGNED;\r
+       }\r
+       else\r
+       {\r
+               /* We did send a FIN already, see if it's ACK'd. */\r
+               if( ulAckNr == pxTCPWindow->tx.ulFINSequenceNumber + 1u )\r
+               {\r
+                       pxSocket->u.xTCP.bits.bFinAcked = pdTRUE_UNSIGNED;\r
+               }\r
+       }\r
+\r
+       if( pxSocket->u.xTCP.bits.bFinAcked == pdFALSE_UNSIGNED )\r
+       {\r
+               pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->tx.ulFINSequenceNumber;\r
+               pxTCPHeader->ucTCPFlags = ipTCP_FLAG_ACK | ipTCP_FLAG_FIN;\r
+\r
+               /* And wait for the final ACK. */\r
+               vTCPStateChange( pxSocket, eLAST_ACK );\r
+       }\r
+       else\r
+       {\r
+               /* Our FIN has been ACK'd, the outgoing sequence number is now fixed. */\r
+               pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->tx.ulFINSequenceNumber + 1u;\r
+               if( pxSocket->u.xTCP.bits.bFinRecv == pdFALSE_UNSIGNED )\r
+               {\r
+                       /* We have sent out a FIN but the peer hasn't replied with a FIN\r
+                       yet. Do nothing for the moment. */\r
+                       pxTCPHeader->ucTCPFlags = 0u;\r
+               }\r
+               else\r
+               {\r
+                       if( pxSocket->u.xTCP.bits.bFinLast == pdFALSE_UNSIGNED )\r
+                       {\r
+                               /* This is the third of the three-way hand shake: the last\r
+                               ACK. */\r
+                               pxTCPHeader->ucTCPFlags = ipTCP_FLAG_ACK;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* The other party started the closure, so we just wait for the\r
+                               last ACK. */\r
+                               pxTCPHeader->ucTCPFlags = 0u;\r
+                       }\r
+\r
+                       /* And wait for the user to close this socket. */\r
+                       vTCPStateChange( pxSocket, eCLOSE_WAIT );\r
+               }\r
+       }\r
+\r
+       pxTCPWindow->ulOurSequenceNumber = pxTCPWindow->tx.ulCurrentSequenceNumber;\r
+\r
+       if( pxTCPHeader->ucTCPFlags != 0u )\r
+       {\r
+               xSendLength = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + pxTCPWindow->ucOptionLength );\r
+       }\r
+\r
+       pxTCPHeader->ucTCPOffset = ( uint8_t ) ( ( ipSIZE_OF_TCP_HEADER + pxTCPWindow->ucOptionLength ) << 2 );\r
+\r
+       if( xTCPWindowLoggingLevel != 0 )\r
+       {\r
+               FreeRTOS_debug_printf( ( "TCP: send FIN+ACK (ack %lu, cur/nxt %lu/%lu) ourSeqNr %lu | Rx %lu\n",\r
+                       ulAckNr - pxTCPWindow->tx.ulFirstSequenceNumber,\r
+                       pxTCPWindow->tx.ulCurrentSequenceNumber - pxTCPWindow->tx.ulFirstSequenceNumber,\r
+                       pxTCPWindow->ulNextTxSequenceNumber - pxTCPWindow->tx.ulFirstSequenceNumber,\r
+                       pxTCPWindow->ulOurSequenceNumber - pxTCPWindow->tx.ulFirstSequenceNumber,\r
+                       pxTCPWindow->rx.ulCurrentSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber ) );\r
+       }\r
+\r
+       return xSendLength;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if    ipconfigUSE_TCP_TIMESTAMPS == 1\r
+\r
+       static UBaseType_t prvTCPSetTimeStamp( BaseType_t lOffset, FreeRTOS_Socket_t *pxSocket, TCPHeader_t *pxTCPHeader )\r
+       {\r
+       uint32_t ulTimes[2];\r
+       uint8_t *ucOptdata = &( pxTCPHeader->ucOptdata[ lOffset ] );\r
+\r
+               ulTimes[0]   = ( xTaskGetTickCount ( ) * 1000u ) / configTICK_RATE_HZ;\r
+               ulTimes[0]   = FreeRTOS_htonl( ulTimes[0] );\r
+               ulTimes[1]   = FreeRTOS_htonl( pxSocket->u.xTCP.xTCPWindow.rx.ulTimeStamp );\r
+               ucOptdata[0] = ( uint8_t ) TCP_OPT_TIMESTAMP;\r
+               ucOptdata[1] = ( uint8_t ) TCP_OPT_TIMESTAMP_LEN;\r
+               memcpy( &(ucOptdata[2] ), ulTimes, 8u );\r
+               ucOptdata[10] = ( uint8_t ) TCP_OPT_NOOP;\r
+               ucOptdata[11] = ( uint8_t ) TCP_OPT_NOOP;\r
+               /* Do not return the same timestamps 2 times. */\r
+               pxSocket->u.xTCP.xTCPWindow.rx.ulTimeStamp = 0ul;\r
+               return 12u;\r
+       }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * prvCheckRxData(): called from prvTCPHandleState()\r
+ *\r
+ * The first thing that will be done is find the TCP payload data\r
+ * and check the length of this data.\r
+ */\r
+static BaseType_t prvCheckRxData( NetworkBufferDescriptor_t *pxNetworkBuffer, uint8_t **ppucRecvData )\r
+{\r
+TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+TCPHeader_t *pxTCPHeader = &( pxTCPPacket->xTCPHeader );\r
+int32_t lLength, lTCPHeaderLength, lReceiveLength, lUrgentLength;\r
+\r
+       /* Determine the length and the offset of the user-data sent to this\r
+       node.\r
+\r
+       The size of the TCP header is given in a multiple of 4-byte words (single\r
+       byte, needs no ntoh() translation).  A shift-right 2: is the same as\r
+       (offset >> 4) * 4. */\r
+    lTCPHeaderLength = ( BaseType_t ) ( ( pxTCPHeader->ucTCPOffset & VALID_BITS_IN_TCP_OFFSET_BYTE ) >> 2 );\r
+\r
+       /* Let pucRecvData point to the first byte received. */\r
+       *ppucRecvData = pxNetworkBuffer->pucEthernetBuffer + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER + lTCPHeaderLength;\r
+\r
+       /* Calculate lReceiveLength - the length of the TCP data received.  This is\r
+       equal to the total packet length minus:\r
+       ( LinkLayer length (14) + IP header length (20) + size of TCP header(20 +) ).*/\r
+       lReceiveLength = ( ( int32_t ) pxNetworkBuffer->xDataLength ) - ( int32_t ) ipSIZE_OF_ETH_HEADER;\r
+       lLength =  ( int32_t )FreeRTOS_htons( pxTCPPacket->xIPHeader.usLength );\r
+\r
+       if( lReceiveLength > lLength )\r
+       {\r
+               /* More bytes were received than the reported length, often because of\r
+               padding bytes at the end. */\r
+               lReceiveLength = lLength;\r
+       }\r
+\r
+       /* Subtract the size of the TCP and IP headers and the actual data size is\r
+       known. */\r
+       if( lReceiveLength > ( lTCPHeaderLength + ( int32_t ) ipSIZE_OF_IPv4_HEADER ) )\r
+       {\r
+               lReceiveLength -= ( lTCPHeaderLength + ( int32_t ) ipSIZE_OF_IPv4_HEADER );\r
+       }\r
+       else\r
+       {\r
+               lReceiveLength = 0;\r
+       }\r
+\r
+       /* Urgent Pointer:\r
+       This field communicates the current value of the urgent pointer as a\r
+       positive offset from the sequence number in this segment.  The urgent\r
+       pointer points to the sequence number of the octet following the urgent\r
+       data.  This field is only be interpreted in segments with the URG control\r
+       bit set. */\r
+       if( ( pxTCPHeader->ucTCPFlags & ipTCP_FLAG_URG ) != 0u )\r
+       {\r
+               /* Although we ignore the urgent data, we have to skip it. */\r
+               lUrgentLength = ( int32_t ) FreeRTOS_htons( pxTCPHeader->usUrgent );\r
+               *ppucRecvData += lUrgentLength;\r
+               lReceiveLength -= FreeRTOS_min_int32( lReceiveLength, lUrgentLength );\r
+       }\r
+\r
+       return ( BaseType_t ) lReceiveLength;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * prvStoreRxData(): called from prvTCPHandleState()\r
+ *\r
+ * The second thing is to do is check if the payload data may be accepted\r
+ * If so, they will be added to the reception queue.\r
+ */\r
+static BaseType_t prvStoreRxData( FreeRTOS_Socket_t *pxSocket, uint8_t *pucRecvData,\r
+       NetworkBufferDescriptor_t *pxNetworkBuffer, uint32_t ulReceiveLength )\r
+{\r
+TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;\r
+TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;\r
+uint32_t ulSequenceNumber, ulSpace;\r
+int32_t lOffset, lStored;\r
+BaseType_t xResult = 0;\r
+\r
+       ulSequenceNumber = FreeRTOS_ntohl( pxTCPHeader->ulSequenceNumber );\r
+\r
+       if( ( ulReceiveLength > 0u ) && ( pxSocket->u.xTCP.ucTCPState >= eSYN_RECEIVED ) )\r
+       {\r
+               /* See if way may accept the data contents and forward it to the socket\r
+               owner.\r
+\r
+               If it can't be "accept"ed it may have to be stored and send a selective\r
+               ack (SACK) option to confirm it.  In that case, xTCPWindowRxStore() will be\r
+               called later to store an out-of-order packet (in case lOffset is\r
+               negative). */\r
+               if ( pxSocket->u.xTCP.rxStream )\r
+               {\r
+                       ulSpace = ( uint32_t )uxStreamBufferGetSpace ( pxSocket->u.xTCP.rxStream );\r
+               }\r
+               else\r
+               {\r
+                       ulSpace = ( uint32_t )pxSocket->u.xTCP.uxRxStreamSize;\r
+               }\r
+\r
+               lOffset = lTCPWindowRxCheck( pxTCPWindow, ulSequenceNumber, ulReceiveLength, ulSpace );\r
+\r
+               if( lOffset >= 0 )\r
+               {\r
+                       /* New data has arrived and may be made available to the user.  See\r
+                       if the head marker in rxStream may be advanced, only if lOffset == 0.\r
+                       In case the low-water mark is reached, bLowWater will be set\r
+                       "low-water" here stands for "little space". */\r
+                       lStored = lTCPAddRxdata( pxSocket, ( uint32_t ) lOffset, pucRecvData, ulReceiveLength );\r
+\r
+                       if( lStored != ( int32_t ) ulReceiveLength )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "lTCPAddRxdata: stored %ld / %lu bytes??\n", lStored, ulReceiveLength ) );\r
+\r
+                               /* Received data could not be stored.  The socket's flag\r
+                               bMallocError has been set.  The socket now has the status\r
+                               eCLOSE_WAIT and a RST packet will be sent back. */\r
+                               prvTCPSendReset( pxNetworkBuffer );\r
+                               xResult = -1;\r
+                       }\r
+               }\r
+\r
+               /* After a missing packet has come in, higher packets may be passed to\r
+               the user. */\r
+               #if( ipconfigUSE_TCP_WIN == 1 )\r
+               {\r
+                       /* Now lTCPAddRxdata() will move the rxHead pointer forward\r
+                       so data becomes available to the user immediately\r
+                       In case the low-water mark is reached, bLowWater will be set. */\r
+                       if( ( xResult == 0 ) && ( pxTCPWindow->ulUserDataLength > 0 ) )\r
+                       {\r
+                               lTCPAddRxdata( pxSocket, 0ul, NULL, pxTCPWindow->ulUserDataLength );\r
+                               pxTCPWindow->ulUserDataLength = 0;\r
+                       }\r
+               }\r
+               #endif /* ipconfigUSE_TCP_WIN */\r
+       }\r
+       else\r
+       {\r
+               pxTCPWindow->ucOptionLength = 0u;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Set the TCP options (if any) for the outgoing packet. */\r
+static UBaseType_t prvSetOptions( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )\r
+{\r
+TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;\r
+TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;\r
+UBaseType_t uxOptionsLength = pxTCPWindow->ucOptionLength;\r
+\r
+       #if(    ipconfigUSE_TCP_WIN == 1 )\r
+               if( uxOptionsLength != 0u )\r
+               {\r
+                       /* TCP options must be sent because a packet which is out-of-order\r
+                       was received. */\r
+                       if( xTCPWindowLoggingLevel >= 0 )\r
+                               FreeRTOS_debug_printf( ( "SACK[%d,%d]: optlen %lu sending %lu - %lu\n",\r
+                                       pxSocket->usLocalPort,\r
+                                       pxSocket->u.xTCP.usRemotePort,\r
+                                       uxOptionsLength,\r
+                                       FreeRTOS_ntohl( pxTCPWindow->ulOptionsData[ 1 ] ) - pxSocket->u.xTCP.xTCPWindow.rx.ulFirstSequenceNumber,\r
+                                       FreeRTOS_ntohl( pxTCPWindow->ulOptionsData[ 2 ] ) - pxSocket->u.xTCP.xTCPWindow.rx.ulFirstSequenceNumber ) );\r
+                       memcpy( pxTCPHeader->ucOptdata, pxTCPWindow->ulOptionsData, ( size_t ) uxOptionsLength );\r
+\r
+                       /* The header length divided by 4, goes into the higher nibble,\r
+                       effectively a shift-left 2. */\r
+                       pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );\r
+               }\r
+               else\r
+       #endif  /* ipconfigUSE_TCP_WIN */\r
+       if( ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) && ( pxSocket->u.xTCP.bits.bMssChange != pdFALSE_UNSIGNED ) )\r
+       {\r
+               /* TCP options must be sent because the MSS has changed. */\r
+               pxSocket->u.xTCP.bits.bMssChange = pdFALSE_UNSIGNED;\r
+               if( xTCPWindowLoggingLevel >= 0 )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "MSS: sending %d\n", pxSocket->u.xTCP.usCurMSS ) );\r
+               }\r
+\r
+               pxTCPHeader->ucOptdata[ 0 ] = TCP_OPT_MSS;\r
+               pxTCPHeader->ucOptdata[ 1 ] = TCP_OPT_MSS_LEN;\r
+               pxTCPHeader->ucOptdata[ 2 ] = ( uint8_t ) ( ( pxSocket->u.xTCP.usCurMSS ) >> 8 );\r
+               pxTCPHeader->ucOptdata[ 3 ] = ( uint8_t ) ( ( pxSocket->u.xTCP.usCurMSS ) & 0xffu );\r
+               uxOptionsLength = 4u;\r
+               pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );\r
+       }\r
+\r
+       #if(    ipconfigUSE_TCP_TIMESTAMPS == 1 )\r
+       {\r
+               if( pxSocket->u.xTCP.xTCPWindow.u.bits.bTimeStamps )\r
+               {\r
+                       uxOptionsLength += prvTCPSetTimeStamp( uxOptionsLength, pxSocket, pxTCPHeader );\r
+               }\r
+       }\r
+       #endif  /* ipconfigUSE_TCP_TIMESTAMPS == 1 */\r
+\r
+       return uxOptionsLength;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * prvHandleSynReceived(): called from prvTCPHandleState()\r
+ *\r
+ * Called from the states: eSYN_RECEIVED and eCONNECT_SYN\r
+ * If the flags received are correct, the socket will move to eESTABLISHED.\r
+ */\r
+static BaseType_t prvHandleSynReceived( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer,\r
+       uint32_t ulReceiveLength, UBaseType_t uxOptionsLength )\r
+{\r
+TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( (*ppxNetworkBuffer)->pucEthernetBuffer );\r
+TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;\r
+TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;\r
+uint8_t ucTCPFlags = pxTCPHeader->ucTCPFlags;\r
+uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxTCPHeader->ulSequenceNumber );\r
+BaseType_t xSendLength = 0;\r
+\r
+       /* Either expect a ACK or a SYN+ACK. */\r
+       uint16_t usExpect = ( uint16_t ) ipTCP_FLAG_ACK;\r
+       if( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN )\r
+       {\r
+               usExpect |= ( uint16_t ) ipTCP_FLAG_SYN;\r
+       }\r
+\r
+       if( ( ucTCPFlags & 0x17u ) != usExpect )\r
+       {\r
+               /* eSYN_RECEIVED: flags 0010 expected, not 0002. */\r
+               /* eSYN_RECEIVED: flags ACK  expected, not SYN. */\r
+               FreeRTOS_debug_printf( ( "%s: flags %04X expected, not %04X\n",\r
+                       pxSocket->u.xTCP.ucTCPState == eSYN_RECEIVED ? "eSYN_RECEIVED" : "eCONNECT_SYN",\r
+                       usExpect, ucTCPFlags ) );\r
+               vTCPStateChange( pxSocket, eCLOSE_WAIT );\r
+               pxTCPHeader->ucTCPFlags |= ipTCP_FLAG_RST;\r
+               xSendLength = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );\r
+               pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );\r
+       }\r
+       else\r
+       {\r
+               pxTCPWindow->usPeerPortNumber = pxSocket->u.xTCP.usRemotePort;\r
+               pxTCPWindow->usOurPortNumber = pxSocket->usLocalPort;\r
+\r
+               if( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN )\r
+               {\r
+                       TCPPacket_t *pxLastTCPPacket = ( TCPPacket_t * ) ( pxSocket->u.xTCP.xPacket.u.ucLastPacket );\r
+\r
+                       /* Clear the SYN flag in lastPacket. */\r
+                       pxLastTCPPacket->xTCPHeader.ucTCPFlags = ipTCP_FLAG_ACK;\r
+\r
+                       /* This socket was the one connecting actively so now perofmr the\r
+                       synchronisation. */\r
+                       vTCPWindowInit( &pxSocket->u.xTCP.xTCPWindow,\r
+                               ulSequenceNumber, pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber, ( uint32_t ) pxSocket->u.xTCP.usCurMSS );\r
+                       pxTCPWindow->rx.ulCurrentSequenceNumber = pxTCPWindow->rx.ulHighestSequenceNumber = ulSequenceNumber + 1u;\r
+                       pxTCPWindow->tx.ulCurrentSequenceNumber++; /* because we send a TCP_SYN [ | TCP_ACK ]; */\r
+                       pxTCPWindow->ulNextTxSequenceNumber++;\r
+               }\r
+               else if( ulReceiveLength == 0u )\r
+               {\r
+                       pxTCPWindow->rx.ulCurrentSequenceNumber = ulSequenceNumber;\r
+               }\r
+\r
+               /* The SYN+ACK has been confirmed, increase the next sequence number by\r
+               1. */\r
+               pxTCPWindow->ulOurSequenceNumber = pxTCPWindow->tx.ulFirstSequenceNumber + 1u;\r
+\r
+               #if( ipconfigUSE_TCP_WIN == 1 )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "TCP: %s %d => %lxip:%d set ESTAB (scaling %u)\n",\r
+                               pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN ? "active" : "passive",\r
+                               pxSocket->usLocalPort,\r
+                               pxSocket->u.xTCP.ulRemoteIP,\r
+                               pxSocket->u.xTCP.usRemotePort,\r
+                               ( unsigned ) pxSocket->u.xTCP.bits.bWinScaling ) );\r
+               }\r
+               #endif /* ipconfigUSE_TCP_WIN */\r
+\r
+               if( ( pxSocket->u.xTCP.ucTCPState == eCONNECT_SYN ) || ( ulReceiveLength != 0u ) )\r
+               {\r
+                       pxTCPHeader->ucTCPFlags = ipTCP_FLAG_ACK;\r
+                       xSendLength = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );\r
+                       pxTCPHeader->ucTCPOffset = ( uint8_t ) ( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );\r
+               }\r
+               #if( ipconfigUSE_TCP_WIN != 0 )\r
+               {\r
+                       if( pxSocket->u.xTCP.bits.bWinScaling == pdFALSE_UNSIGNED )\r
+                       {\r
+                               /* The other party did not send a scaling factor.\r
+                               A shifting factor in this side must be canceled. */\r
+                               pxSocket->u.xTCP.ucMyWinScaleFactor = 0;\r
+                               pxSocket->u.xTCP.ucPeerWinScaleFactor = 0;\r
+                       }\r
+               }\r
+               #endif /* ipconfigUSE_TCP_WIN */\r
+               /* This was the third step of connecting: SYN, SYN+ACK, ACK     so now the\r
+               connection is established. */\r
+               vTCPStateChange( pxSocket, eESTABLISHED );\r
+       }\r
+\r
+       return xSendLength;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * prvHandleEstablished(): called from prvTCPHandleState()\r
+ *\r
+ * Called if the status is eESTABLISHED.  Data reception has been handled\r
+ * earlier.  Here the ACK's from peer will be checked, and if a FIN is received,\r
+ * the code will check if it may be accepted, i.e. if all expected data has been\r
+ * completely received.\r
+ */\r
+static BaseType_t prvHandleEstablished( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer,\r
+       uint32_t ulReceiveLength, UBaseType_t uxOptionsLength )\r
+{\r
+TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( (*ppxNetworkBuffer)->pucEthernetBuffer );\r
+TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;\r
+TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;\r
+uint8_t ucTCPFlags = pxTCPHeader->ucTCPFlags;\r
+uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxTCPHeader->ulSequenceNumber ), ulCount;\r
+BaseType_t xSendLength = 0, xMayClose = pdFALSE, bRxComplete, bTxDone;\r
+int32_t lDistance, lSendResult;\r
+\r
+       /* Remember the window size the peer is advertising. */\r
+       pxSocket->u.xTCP.ulWindowSize = FreeRTOS_ntohs( pxTCPHeader->usWindow );\r
+       #if( ipconfigUSE_TCP_WIN != 0 )\r
+       {\r
+               pxSocket->u.xTCP.ulWindowSize =\r
+                       ( pxSocket->u.xTCP.ulWindowSize << pxSocket->u.xTCP.ucPeerWinScaleFactor );\r
+       }\r
+       #endif\r
+\r
+       if( ( ucTCPFlags & ( uint8_t ) ipTCP_FLAG_ACK ) != 0u )\r
+       {\r
+               ulCount = ulTCPWindowTxAck( pxTCPWindow, FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulAckNr ) );\r
+\r
+               /* ulTCPWindowTxAck() returns the number of bytes which have been acked,\r
+               starting at 'tx.ulCurrentSequenceNumber'.  Advance the tail pointer in\r
+               txStream. */\r
+               if( ( pxSocket->u.xTCP.txStream != NULL ) && ( ulCount > 0u ) )\r
+               {\r
+                       /* Just advancing the tail index, 'ulCount' bytes have been\r
+                       confirmed, and because there is new space in the txStream, the\r
+                       user/owner should be woken up. */\r
+                       /* _HT_ : only in case the socket's waiting? */\r
+                       if( uxStreamBufferGet( pxSocket->u.xTCP.txStream, 0u, NULL, ( size_t ) ulCount, pdFALSE ) != 0u )\r
+                       {\r
+                               pxSocket->xEventBits |= eSOCKET_SEND;\r
+\r
+                               #if ipconfigSUPPORT_SELECT_FUNCTION == 1\r
+                               {\r
+                                       if( ( pxSocket->xSelectBits & eSELECT_WRITE ) != 0 )\r
+                                       {\r
+                                               pxSocket->xEventBits |= ( eSELECT_WRITE << SOCKET_EVENT_BIT_COUNT );\r
+                                       }\r
+                               }\r
+                               #endif\r
+                               /* In case the socket owner has installed an OnSent handler,\r
+                               call it now. */\r
+                               #if( ipconfigUSE_CALLBACKS == 1 )\r
+                               {\r
+                                       if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleSent ) )\r
+                                       {\r
+                                               pxSocket->u.xTCP.pxHandleSent( (Socket_t *)pxSocket, ulCount );\r
+                                       }\r
+                               }\r
+                               #endif /* ipconfigUSE_CALLBACKS == 1  */\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* If this socket has a stream for transmission, add the data to the\r
+       outgoing segment(s). */\r
+       if( pxSocket->u.xTCP.txStream != NULL )\r
+       {\r
+               prvTCPAddTxData( pxSocket );\r
+       }\r
+\r
+       pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber = pxTCPWindow->tx.ulCurrentSequenceNumber;\r
+\r
+       if( ( pxSocket->u.xTCP.bits.bFinAccepted != pdFALSE_UNSIGNED ) || ( ( ucTCPFlags & ( uint8_t ) ipTCP_FLAG_FIN ) != 0u ) )\r
+       {\r
+               /* Peer is requesting to stop, see if we're really finished. */\r
+               xMayClose = pdTRUE;\r
+\r
+               /* Checks are only necessary if we haven't sent a FIN yet. */\r
+               if( pxSocket->u.xTCP.bits.bFinSent == pdFALSE_UNSIGNED )\r
+               {\r
+                       /* xTCPWindowTxDone returns true when all Tx queues are empty. */\r
+                       bRxComplete = xTCPWindowRxEmpty( pxTCPWindow );\r
+                       bTxDone     = xTCPWindowTxDone( pxTCPWindow );\r
+\r
+                       if( ( bRxComplete == 0 ) || ( bTxDone == 0 ) )\r
+                       {\r
+                               /* Refusing FIN: Rx incomp 1 optlen 4 tx done 1. */\r
+                               FreeRTOS_debug_printf( ( "Refusing FIN[%u,%u]: RxCompl %lu tx done %ld\n",\r
+                                       pxSocket->usLocalPort,\r
+                                       pxSocket->u.xTCP.usRemotePort,\r
+                                       bRxComplete, bTxDone ) );\r
+                               xMayClose = pdFALSE;\r
+                       }\r
+                       else\r
+                       {\r
+                               lDistance = ( int32_t ) ( ulSequenceNumber + ulReceiveLength - pxTCPWindow->rx.ulCurrentSequenceNumber );\r
+\r
+                               if( lDistance > 1 )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "Refusing FIN: Rx not complete %ld (cur %lu high %lu)\n",\r
+                                               lDistance, pxTCPWindow->rx.ulCurrentSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber,\r
+                                               pxTCPWindow->rx.ulHighestSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber ) );\r
+\r
+                                       xMayClose = pdFALSE;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if( xTCPWindowLoggingLevel > 0 )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "TCP: FIN received, mayClose = %ld (Rx %lu Len %ld, Tx %lu)\n",\r
+                               xMayClose, ulSequenceNumber - pxSocket->u.xTCP.xTCPWindow.rx.ulFirstSequenceNumber, ulReceiveLength,\r
+                               pxTCPWindow->tx.ulCurrentSequenceNumber - pxSocket->u.xTCP.xTCPWindow.tx.ulFirstSequenceNumber ) );\r
+               }\r
+\r
+               if( xMayClose != pdFALSE )\r
+               {\r
+                       pxSocket->u.xTCP.bits.bFinAccepted = pdTRUE_UNSIGNED;\r
+                       xSendLength = prvTCPHandleFin( pxSocket, *ppxNetworkBuffer );\r
+               }\r
+       }\r
+\r
+       if( xMayClose == pdFALSE )\r
+       {\r
+               pxTCPHeader->ucTCPFlags = ipTCP_FLAG_ACK;\r
+\r
+               if( ulReceiveLength != 0u )\r
+               {\r
+                       xSendLength = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );\r
+                       /* TCP-offsett equals '( ( length / 4 ) << 4 )', resulting in a shift-left 2 */\r
+                       pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );\r
+\r
+                       if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )\r
+                       {\r
+                               pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->tx.ulFINSequenceNumber;\r
+                       }\r
+               }\r
+\r
+               /* Now get data to be transmitted. */\r
+               /* _HT_ patch: since the MTU has be fixed at 1500 in stead of 1526, TCP\r
+               can not send-out both TCP options and also a full packet. Sending\r
+               options (SACK) is always more urgent than sending data, which can be\r
+               sent later. */\r
+               if( uxOptionsLength == 0u )\r
+               {\r
+                       /* prvTCPPrepareSend might allocate a bigger network buffer, if\r
+                       necessary. */\r
+                       lSendResult = prvTCPPrepareSend( pxSocket, ppxNetworkBuffer, uxOptionsLength );\r
+                       if( lSendResult > 0 )\r
+                       {\r
+                               xSendLength = ( BaseType_t ) lSendResult;\r
+                       }\r
+               }\r
+       }\r
+\r
+       return xSendLength;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Called from prvTCPHandleState().  There is data to be sent.  If\r
+ * ipconfigUSE_TCP_WIN is defined, and if only an ACK must be sent, it will be\r
+ * checked if it would better be postponed for efficiency.\r
+ */\r
+static BaseType_t prvSendData( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer,\r
+       uint32_t ulReceiveLength, BaseType_t xSendLength )\r
+{\r
+TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( (*ppxNetworkBuffer)->pucEthernetBuffer );\r
+TCPHeader_t *pxTCPHeader = &pxTCPPacket->xTCPHeader;\r
+TCPWindow_t *pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;\r
+/* Find out what window size we may advertised. */\r
+uint32_t ulFrontSpace;\r
+int32_t lRxSpace;\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       #if( ipconfigTCP_ACK_EARLIER_PACKET == 0 )\r
+               const int32_t lMinLength = 0;\r
+       #else\r
+               int32_t lMinLength;\r
+       #endif\r
+#endif\r
+       pxSocket->u.xTCP.ulRxCurWinSize = pxTCPWindow->xSize.ulRxWindowLength -\r
+                                                                        ( pxTCPWindow->rx.ulHighestSequenceNumber - pxTCPWindow->rx.ulCurrentSequenceNumber );\r
+\r
+       /* Free space in rxStream. */\r
+       if( pxSocket->u.xTCP.rxStream != NULL )\r
+       {\r
+               ulFrontSpace = ( uint32_t ) uxStreamBufferFrontSpace( pxSocket->u.xTCP.rxStream );\r
+       }\r
+       else\r
+       {\r
+               ulFrontSpace = ( uint32_t ) pxSocket->u.xTCP.uxRxStreamSize;\r
+       }\r
+\r
+       pxSocket->u.xTCP.ulRxCurWinSize = FreeRTOS_min_uint32( ulFrontSpace, pxSocket->u.xTCP.ulRxCurWinSize );\r
+\r
+       /* Set the time-out field, so that we'll be called by the IP-task in case no\r
+       next message will be received. */\r
+       lRxSpace = (int32_t)( pxSocket->u.xTCP.ulHighestRxAllowed - pxTCPWindow->rx.ulCurrentSequenceNumber );\r
+       #if ipconfigUSE_TCP_WIN == 1\r
+       {\r
+\r
+               #if( ipconfigTCP_ACK_EARLIER_PACKET != 0 )\r
+               {\r
+                       lMinLength = ( ( int32_t ) 2 ) * ( ( int32_t ) pxSocket->u.xTCP.usCurMSS );\r
+               }\r
+               #endif /* ipconfigTCP_ACK_EARLIER_PACKET */\r
+\r
+               /* In case we're receiving data continuously, we might postpone sending\r
+               an ACK to gain performance. */\r
+               if( ( ulReceiveLength > 0 ) &&                                                  /* Data was sent to this socket. */\r
+                       ( lRxSpace >= lMinLength ) &&                                           /* There is Rx space for more data. */\r
+                       ( pxSocket->u.xTCP.bits.bFinSent == pdFALSE_UNSIGNED ) &&       /* Not in a closure phase. */\r
+                       ( xSendLength == ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) ) && /* No Tx data or options to be sent. */\r
+                       ( pxSocket->u.xTCP.ucTCPState == eESTABLISHED ) &&      /* Connection established. */\r
+                       ( pxTCPHeader->ucTCPFlags == ipTCP_FLAG_ACK ) )         /* There are no other flags than an ACK. */\r
+               {\r
+                       if( pxSocket->u.xTCP.pxAckMessage != *ppxNetworkBuffer )\r
+                       {\r
+                               /* There was still a delayed in queue, delete it. */\r
+                               if( pxSocket->u.xTCP.pxAckMessage != 0 )\r
+                               {\r
+                                       vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );\r
+                               }\r
+\r
+                               pxSocket->u.xTCP.pxAckMessage = *ppxNetworkBuffer;\r
+                       }\r
+                       if( ( ulReceiveLength < ( uint32_t ) pxSocket->u.xTCP.usCurMSS ) ||     /* Received a small message. */\r
+                               ( lRxSpace < ( int32_t ) ( 2U * pxSocket->u.xTCP.usCurMSS ) ) ) /* There are less than 2 x MSS space in the Rx buffer. */\r
+                       {\r
+                               pxSocket->u.xTCP.usTimeout = ( uint16_t ) pdMS_TO_MIN_TICKS( DELAYED_ACK_SHORT_DELAY_MS );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Normally a delayed ACK should wait 200 ms for a next incoming\r
+                               packet.  Only wait 20 ms here to gain performance.  A slow ACK\r
+                               for full-size message. */\r
+                               pxSocket->u.xTCP.usTimeout = ( uint16_t ) pdMS_TO_MIN_TICKS( DELAYED_ACK_LONGER_DELAY_MS );\r
+                       }\r
+\r
+                       if( ( xTCPWindowLoggingLevel > 1 ) && ( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE ) )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "Send[%u->%u] del ACK %lu SEQ %lu (len %lu) tmout %u d %lu\n",\r
+                                       pxSocket->usLocalPort,\r
+                                       pxSocket->u.xTCP.usRemotePort,\r
+                                       pxTCPWindow->rx.ulCurrentSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber,\r
+                                       pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber - pxTCPWindow->tx.ulFirstSequenceNumber,\r
+                                       xSendLength,\r
+                                       pxSocket->u.xTCP.usTimeout, lRxSpace ) );\r
+                       }\r
+\r
+                       *ppxNetworkBuffer = NULL;\r
+                       xSendLength = 0;\r
+               }\r
+               else if( pxSocket->u.xTCP.pxAckMessage != NULL )\r
+               {\r
+                       /* As an ACK is not being delayed, remove any earlier delayed ACK\r
+                       message. */\r
+                       if( pxSocket->u.xTCP.pxAckMessage != *ppxNetworkBuffer )\r
+                       {\r
+                               vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage );\r
+                       }\r
+\r
+                       pxSocket->u.xTCP.pxAckMessage = NULL;\r
+               }\r
+       }\r
+       #else\r
+       {\r
+               /* Remove compiler warnings. */\r
+               ( void ) ulReceiveLength;\r
+               ( void ) pxTCPHeader;\r
+               ( void ) lRxSpace;\r
+       }\r
+       #endif /* ipconfigUSE_TCP_WIN */\r
+\r
+       if( xSendLength != 0 )\r
+       {\r
+               if( ( xTCPWindowLoggingLevel > 1 ) && ( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) != pdFALSE ) )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "Send[%u->%u] imm ACK %lu SEQ %lu (len %lu)\n",\r
+                               pxSocket->usLocalPort,\r
+                               pxSocket->u.xTCP.usRemotePort,\r
+                               pxTCPWindow->rx.ulCurrentSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber,\r
+                               pxTCPWindow->ulOurSequenceNumber - pxTCPWindow->tx.ulFirstSequenceNumber,\r
+                               xSendLength ) );\r
+               }\r
+\r
+               /* Set the parameter 'xReleaseAfterSend' to the value of\r
+               ipconfigZERO_COPY_TX_DRIVER. */\r
+               prvTCPReturnPacket( pxSocket, *ppxNetworkBuffer, ( uint32_t ) xSendLength, ipconfigZERO_COPY_TX_DRIVER );\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       /* The driver has taken ownership of the Network Buffer. */\r
+                       *ppxNetworkBuffer = NULL;\r
+               }\r
+               #endif\r
+       }\r
+\r
+       return xSendLength;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * prvTCPHandleState()\r
+ * is the most important function of this TCP stack\r
+ * We've tried to keep it (relatively short) by putting a lot of code in\r
+ * the static functions above:\r
+ *\r
+ *             prvCheckRxData()\r
+ *             prvStoreRxData()\r
+ *             prvSetOptions()\r
+ *             prvHandleSynReceived()\r
+ *             prvHandleEstablished()\r
+ *             prvSendData()\r
+ *\r
+ * As these functions are declared static, and they're called from one location\r
+ * only, most compilers will inline them, thus avoiding a call and return.\r
+ */\r
+static BaseType_t prvTCPHandleState( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t **ppxNetworkBuffer )\r
+{\r
+TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( (*ppxNetworkBuffer)->pucEthernetBuffer );\r
+TCPHeader_t *pxTCPHeader = &( pxTCPPacket->xTCPHeader );\r
+BaseType_t xSendLength = 0;\r
+uint32_t ulReceiveLength;      /* Number of bytes contained in the TCP message. */\r
+uint8_t *pucRecvData;\r
+uint32_t ulSequenceNumber = FreeRTOS_ntohl (pxTCPHeader->ulSequenceNumber);\r
+\r
+       /* uxOptionsLength: the size of the options to be sent (always a multiple of\r
+       4 bytes)\r
+       1. in the SYN phase, we shall communicate the MSS\r
+       2. in case of a SACK, Selective ACK, ack a segment which comes in\r
+       out-of-order. */\r
+UBaseType_t uxOptionsLength = 0u;\r
+uint8_t ucTCPFlags = pxTCPHeader->ucTCPFlags;\r
+TCPWindow_t *pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );\r
+\r
+       /* First get the length and the position of the received data, if any.\r
+       pucRecvData will point to the first byte of the TCP payload. */\r
+       ulReceiveLength = ( uint32_t ) prvCheckRxData( *ppxNetworkBuffer, &pucRecvData );\r
+\r
+       if( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED )\r
+       {\r
+               if ( pxTCPWindow->rx.ulCurrentSequenceNumber == ulSequenceNumber + 1u )\r
+               {\r
+                       /* This is most probably a keep-alive message from peer.  Setting\r
+                       'bWinChange' doesn't cause a window-size-change, the flag is used\r
+                       here to force sending an immediate ACK. */\r
+                       pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;\r
+               }\r
+       }\r
+\r
+       /* Keep track of the highest sequence number that might be expected within\r
+       this connection. */\r
+       if( ( ( int32_t ) ( ulSequenceNumber + ulReceiveLength - pxTCPWindow->rx.ulHighestSequenceNumber ) ) > 0 )\r
+       {\r
+               pxTCPWindow->rx.ulHighestSequenceNumber = ulSequenceNumber + ulReceiveLength;\r
+       }\r
+\r
+       /* Storing data may result in a fatal error if malloc() fails. */\r
+       if( prvStoreRxData( pxSocket, pucRecvData, *ppxNetworkBuffer, ulReceiveLength ) < 0 )\r
+       {\r
+               xSendLength = -1;\r
+       }\r
+       else\r
+       {\r
+               uxOptionsLength = prvSetOptions( pxSocket, *ppxNetworkBuffer );\r
+\r
+               if( ( pxSocket->u.xTCP.ucTCPState == eSYN_RECEIVED ) && ( ( ucTCPFlags & ipTCP_FLAG_CTRL ) == ipTCP_FLAG_SYN ) )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK\n" ) );\r
+\r
+                       /* In eSYN_RECEIVED a simple ACK is expected, but apparently the\r
+                       'SYN+ACK' didn't arrive.  Step back to the previous state in which\r
+                       a first incoming SYN is handled.  The SYN was counted already so\r
+                       decrease it first. */\r
+                       vTCPStateChange( pxSocket, eSYN_FIRST );\r
+               }\r
+\r
+               if( ( ( ucTCPFlags & ipTCP_FLAG_FIN ) != 0u ) && ( pxSocket->u.xTCP.bits.bFinRecv == pdFALSE_UNSIGNED ) )\r
+               {\r
+                       /* It's the first time a FIN has been received, remember its\r
+                       sequence number. */\r
+                       pxTCPWindow->rx.ulFINSequenceNumber = ulSequenceNumber + ulReceiveLength;\r
+                       pxSocket->u.xTCP.bits.bFinRecv = pdTRUE_UNSIGNED;\r
+\r
+                       /* Was peer the first one to send a FIN? */\r
+                       if( pxSocket->u.xTCP.bits.bFinSent == pdFALSE_UNSIGNED )\r
+                       {\r
+                               /* If so, don't send the-last-ACK. */\r
+                               pxSocket->u.xTCP.bits.bFinLast = pdTRUE_UNSIGNED;\r
+                       }\r
+               }\r
+\r
+               switch (pxSocket->u.xTCP.ucTCPState)\r
+               {\r
+               case eCLOSED:           /* (server + client) no connection state at all. */\r
+                       /* Nothing to do for a closed socket, except waiting for the\r
+                       owner. */\r
+                       break;\r
+\r
+               case eTCP_LISTEN:       /* (server) waiting for a connection request from\r
+                                                       any remote TCP and port. */\r
+                       /* The listen state was handled in xProcessReceivedTCPPacket().\r
+                       Should not come here. */\r
+                       break;\r
+\r
+               case eSYN_FIRST:        /* (server) Just received a SYN request for a server\r
+                                                       socket. */\r
+                       {\r
+                               /* A new socket has been created, reply with a SYN+ACK.\r
+                               Acknowledge with seq+1 because the SYN is seen as pseudo data\r
+                               with len = 1. */\r
+                               uxOptionsLength = prvSetSynAckOptions( pxSocket, pxTCPPacket );\r
+                               pxTCPHeader->ucTCPFlags = ipTCP_FLAG_SYN | ipTCP_FLAG_ACK;\r
+\r
+                               xSendLength = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + uxOptionsLength );\r
+\r
+                               /* Set the TCP offset field:  ipSIZE_OF_TCP_HEADER equals 20 and\r
+                               uxOptionsLength is a multiple of 4.  The complete expression is:\r
+                               ucTCPOffset = ( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) / 4 ) << 4 */\r
+                               pxTCPHeader->ucTCPOffset = ( uint8_t )( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );\r
+                               vTCPStateChange( pxSocket, eSYN_RECEIVED );\r
+\r
+                               pxTCPWindow->rx.ulCurrentSequenceNumber = pxTCPWindow->rx.ulHighestSequenceNumber = ulSequenceNumber + 1u;\r
+                               pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->ulNextTxSequenceNumber = pxTCPWindow->tx.ulFirstSequenceNumber + 1u; /* because we send a TCP_SYN. */\r
+                       }\r
+                       break;\r
+\r
+               case eCONNECT_SYN:      /* (client) also called SYN_SENT: we've just send a\r
+                                                       SYN, expect     a SYN+ACK and send a ACK now. */\r
+                       /* Fall through */\r
+               case eSYN_RECEIVED:     /* (server) we've had a SYN, replied with SYN+SCK\r
+                                                       expect a ACK and do nothing. */\r
+                       xSendLength = prvHandleSynReceived( pxSocket, ppxNetworkBuffer, ulReceiveLength, uxOptionsLength );\r
+                       break;\r
+\r
+               case eESTABLISHED:      /* (server + client) an open connection, data\r
+                                                       received can be delivered to the user. The normal\r
+                                                       state for the data transfer phase of the connection\r
+                                                       The closing states are also handled here with the\r
+                                                       use of some flags. */\r
+                       xSendLength = prvHandleEstablished( pxSocket, ppxNetworkBuffer, ulReceiveLength, uxOptionsLength );\r
+                       break;\r
+\r
+               case eLAST_ACK:         /* (server + client) waiting for an acknowledgement\r
+                                                       of the connection termination request previously\r
+                                                       sent to the remote TCP (which includes an\r
+                                                       acknowledgement of its connection termination\r
+                                                       request). */\r
+                       /* Fall through */\r
+               case eFIN_WAIT_1:       /* (server + client) waiting for a connection termination request from the remote TCP,\r
+                                                        * or an acknowledgement of the connection termination request previously sent. */\r
+                       /* Fall through */\r
+               case eFIN_WAIT_2:       /* (server + client) waiting for a connection termination request from the remote TCP. */\r
+                       xSendLength = prvTCPHandleFin( pxSocket, *ppxNetworkBuffer );\r
+                       break;\r
+\r
+               case eCLOSE_WAIT:       /* (server + client) waiting for a connection\r
+                                                       termination request from the local user.  Nothing to\r
+                                                       do, connection is closed, wait for owner to close\r
+                                                       this socket. */\r
+                       break;\r
+\r
+               case eCLOSING:          /* (server + client) waiting for a connection\r
+                                                       termination request acknowledgement from the remote\r
+                                                       TCP. */\r
+                       break;\r
+\r
+               case eTIME_WAIT:        /* (either server or client) waiting for enough time\r
+                                                       to pass to be sure the remote TCP received the\r
+                                                       acknowledgement of its connection termination\r
+                                                       request. [According to RFC 793 a connection can stay\r
+                                                       in TIME-WAIT for a maximum of four minutes known as\r
+                                                       a MSL (maximum segment lifetime).]  These states are\r
+                                                       implemented implicitly by settings flags like\r
+                                                       'bFinSent', 'bFinRecv', and 'bFinAcked'. */\r
+                       break;\r
+               default:\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if( xSendLength > 0 )\r
+       {\r
+               xSendLength = prvSendData( pxSocket, ppxNetworkBuffer, ulReceiveLength, xSendLength );\r
+       }\r
+\r
+       return xSendLength;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvTCPSendReset( NetworkBufferDescriptor_t *pxNetworkBuffer )\r
+{\r
+       #if( ipconfigIGNORE_UNKNOWN_PACKETS == 0 )\r
+       {\r
+       TCPPacket_t *pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+       const BaseType_t xSendLength = ( BaseType_t ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + 0u );    /* Plus 0 options. */\r
+\r
+               pxTCPPacket->xTCPHeader.ucTCPFlags = ipTCP_FLAG_ACK | ipTCP_FLAG_RST;\r
+               pxTCPPacket->xTCPHeader.ucTCPOffset = ( ipSIZE_OF_TCP_HEADER + 0u ) << 2;\r
+\r
+               prvTCPReturnPacket( NULL, pxNetworkBuffer, ( uint32_t ) xSendLength, pdFALSE );\r
+       }\r
+       #endif /* !ipconfigIGNORE_UNKNOWN_PACKETS */\r
+\r
+       /* Remove compiler warnings if ipconfigIGNORE_UNKNOWN_PACKETS == 1. */\r
+       ( void ) pxNetworkBuffer;\r
+\r
+       /* The packet was not consumed. */\r
+       return pdFAIL;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSocketSetMSS( FreeRTOS_Socket_t *pxSocket )\r
+{\r
+uint32_t ulMSS = ipconfigTCP_MSS;\r
+\r
+       if( ( ( FreeRTOS_ntohl( pxSocket->u.xTCP.ulRemoteIP ) ^ *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) != 0ul )\r
+       {\r
+               /* Data for this peer will pass through a router, and maybe through\r
+               the internet.  Limit the MSS to 1400 bytes or less. */\r
+               ulMSS = FreeRTOS_min_uint32( ( uint32_t ) REDUCED_MSS_THROUGH_INTERNET, ulMSS );\r
+       }\r
+\r
+       FreeRTOS_debug_printf( ( "prvSocketSetMSS: %lu bytes for %lxip:%u\n", ulMSS, pxSocket->u.xTCP.ulRemoteIP, pxSocket->u.xTCP.usRemotePort ) );\r
+\r
+       pxSocket->u.xTCP.usInitMSS = pxSocket->u.xTCP.usCurMSS = ( uint16_t ) ulMSS;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ *     FreeRTOS_TCP_IP has only 2 public functions, this is the second one:\r
+ *     xProcessReceivedTCPPacket()\r
+ *             prvTCPHandleState()\r
+ *                     prvTCPPrepareSend()\r
+ *                             prvTCPReturnPacket()\r
+ *                             xNetworkInterfaceOutput()       // Sends data to the NIC\r
+ *             prvTCPSendRepeated()\r
+ *                     prvTCPReturnPacket()            // Prepare for returning\r
+ *                     xNetworkInterfaceOutput()       // Sends data to the NIC\r
+*/\r
+BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer )\r
+{\r
+FreeRTOS_Socket_t *pxSocket;\r
+TCPPacket_t * pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+uint16_t ucTCPFlags = pxTCPPacket->xTCPHeader.ucTCPFlags;\r
+uint32_t ulLocalIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulDestinationIPAddress );\r
+uint16_t xLocalPort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usDestinationPort );\r
+uint32_t ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress );\r
+uint16_t xRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort );\r
+BaseType_t xResult = pdPASS;\r
+\r
+       /* Find the destination socket, and if not found: return a socket listing to\r
+       the destination PORT. */\r
+       pxSocket = ( FreeRTOS_Socket_t * ) pxTCPSocketLookup( ulLocalIP, xLocalPort, ulRemoteIP, xRemotePort );\r
+\r
+       if( ( pxSocket == NULL ) || ( prvTCPSocketIsActive( ( UBaseType_t ) pxSocket->u.xTCP.ucTCPState ) == pdFALSE ) )\r
+       {\r
+               /* A TCP messages is received but either there is no socket with the\r
+               given port number or the there is a socket, but it is in one of these\r
+               non-active states:  eCLOSED, eCLOSE_WAIT, eFIN_WAIT_2, eCLOSING, or\r
+               eTIME_WAIT. */\r
+\r
+               FreeRTOS_debug_printf( ( "TCP: No active socket on port %d (%lxip:%d)\n", xLocalPort, ulRemoteIP, xRemotePort ) );\r
+\r
+               /* Send a RST to all packets that can not be handled.  As a result\r
+               the other party will get a ECONN error.  There are two exceptions:\r
+               1) A packet that already has the RST flag set.\r
+               2) A packet that only has the ACK flag set.\r
+               A packet with only the ACK flag set might be the last ACK in\r
+               a three-way hand-shake that closes a connection. */\r
+               if( ( ( ucTCPFlags & ipTCP_FLAG_CTRL ) != ipTCP_FLAG_ACK ) &&\r
+                       ( ( ucTCPFlags & ipTCP_FLAG_RST ) == 0u ) )\r
+               {\r
+                       prvTCPSendReset( pxNetworkBuffer );\r
+               }\r
+\r
+               /* The packet can't be handled. */\r
+               xResult = pdFAIL;\r
+       }\r
+       else\r
+       {\r
+               pxSocket->u.xTCP.ucRepCount = 0u;\r
+\r
+               if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN )\r
+               {\r
+                       /* The matching socket is in a listening state.  Test if the peer\r
+                       has set the SYN flag. */\r
+                       if( ( ucTCPFlags & ipTCP_FLAG_CTRL ) != ipTCP_FLAG_SYN )\r
+                       {\r
+                               /* What happens: maybe after a reboot, a client doesn't know the\r
+                               connection had gone.  Send a RST in order to get a new connect\r
+                               request. */\r
+                               #if( ipconfigHAS_DEBUG_PRINTF == 1 )\r
+                               {\r
+                               FreeRTOS_debug_printf( ( "TCP: Server can't handle flags: %s from %lxip:%u to port %u\n",\r
+                                       prvTCPFlagMeaning( ( UBaseType_t ) ucTCPFlags ), ulRemoteIP, xRemotePort, xLocalPort ) );\r
+                               }\r
+                               #endif /* ipconfigHAS_DEBUG_PRINTF */\r
+\r
+                               if( ( ucTCPFlags & ipTCP_FLAG_RST ) == 0u )\r
+                               {\r
+                                       prvTCPSendReset( pxNetworkBuffer );\r
+                               }\r
+                               xResult = pdFAIL;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* prvHandleListen() will either return a newly created socket\r
+                               (if bReuseSocket is false), otherwise it returns the current\r
+                               socket which will later get connected. */\r
+                               pxSocket = prvHandleListen( pxSocket, pxNetworkBuffer );\r
+\r
+                               if( pxSocket == NULL )\r
+                               {\r
+                                       xResult = pdFAIL;\r
+                               }\r
+                       }\r
+               }       /* if( pxSocket->u.xTCP.ucTCPState == eTCP_LISTEN ). */\r
+               else\r
+               {\r
+                       /* This is not a socket in listening mode. Check for the RST\r
+                       flag. */\r
+                       if( ( ucTCPFlags & ipTCP_FLAG_RST ) != 0u )\r
+                       {\r
+                               /* The target socket is not in a listening state, any RST packet\r
+                               will cause the socket to be closed. */\r
+                               FreeRTOS_debug_printf( ( "TCP: RST received from %lxip:%u for %u\n", ulRemoteIP, xRemotePort, xLocalPort ) );\r
+                               /* _HT_: should indicate that 'ECONNRESET' must be returned to the used during next API. */\r
+                               vTCPStateChange( pxSocket, eCLOSED );\r
+\r
+                               /* The packet cannot be handled. */\r
+                               xResult = pdFAIL;\r
+                       }\r
+                       else if( ( ( ucTCPFlags & ipTCP_FLAG_CTRL ) == ipTCP_FLAG_SYN ) && ( pxSocket->u.xTCP.ucTCPState >= eESTABLISHED ) )\r
+                       {\r
+                               /* SYN flag while this socket is already connected. */\r
+                               FreeRTOS_debug_printf( ( "TCP: SYN unexpected from %lxip:%u\n", ulRemoteIP, xRemotePort ) );\r
+\r
+                               /* The packet cannot be handled. */\r
+                               xResult = pdFAIL;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Update the copy of the TCP header only (skipping eth and IP\r
+                               headers).  It might be used later on, whenever data must be sent\r
+                               to the peer. */\r
+                               const BaseType_t lOffset = ( BaseType_t ) ( ipSIZE_OF_ETH_HEADER + ipSIZE_OF_IPv4_HEADER );\r
+                               memcpy( pxSocket->u.xTCP.xPacket.u.ucLastPacket + lOffset, pxNetworkBuffer->pucEthernetBuffer + lOffset, ipSIZE_OF_TCP_HEADER );\r
+                       }\r
+               }\r
+       }\r
+\r
+       if( xResult != pdFAIL )\r
+       {\r
+               /* Touch the alive timers because we received a message for this\r
+               socket. */\r
+               prvTCPTouchSocket( pxSocket );\r
+\r
+               /* Parse the TCP option(s), if present. */\r
+               /* _HT_ : if we're in the SYN phase, and peer does not send a MSS option,\r
+               then we MUST assume an MSS size of 536 bytes for backward compatibility. */\r
+\r
+               /* When there are no TCP options, the TCP offset equals 20 bytes, which is stored as\r
+               the number 5 (words) in the higher niblle of the TCP-offset byte. */\r
+               if( ( pxTCPPacket->xTCPHeader.ucTCPOffset & TCP_OFFSET_LENGTH_BITS ) > TCP_OFFSET_STANDARD_LENGTH )\r
+               {\r
+                       prvCheckOptions( pxSocket, pxNetworkBuffer );\r
+               }\r
+\r
+\r
+               #if( ipconfigUSE_TCP_WIN == 1 )\r
+               {\r
+                       pxSocket->u.xTCP.ulWindowSize = FreeRTOS_ntohs( pxTCPPacket->xTCPHeader.usWindow );\r
+                       pxSocket->u.xTCP.ulWindowSize =\r
+                               ( pxSocket->u.xTCP.ulWindowSize << pxSocket->u.xTCP.ucPeerWinScaleFactor );\r
+               }\r
+               #endif\r
+\r
+               /* In prvTCPHandleState() the incoming messages will be handled\r
+               depending on the current state of the connection. */\r
+               if( prvTCPHandleState( pxSocket, &pxNetworkBuffer ) > 0 )\r
+               {\r
+                       /* prvTCPHandleState() has sent a message, see if there are more to\r
+                       be transmitted. */\r
+                       #if( ipconfigUSE_TCP_WIN == 1 )\r
+                       {\r
+                               prvTCPSendRepeated( pxSocket, &pxNetworkBuffer );\r
+                       }\r
+                       #endif /* ipconfigUSE_TCP_WIN */\r
+               }\r
+\r
+               if( pxNetworkBuffer != NULL )\r
+               {\r
+                       /* We must check if the buffer is unequal to NULL, because the\r
+                       socket might keep a reference to it in case a delayed ACK must be\r
+                       sent. */\r
+                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                       pxNetworkBuffer = NULL;\r
+               }\r
+\r
+               /* And finally, calculate when this socket wants to be woken up. */\r
+               prvTCPNextTimeout ( pxSocket );\r
+               /* Return pdPASS to tell that the network buffer is 'consumed'. */\r
+               xResult = pdPASS;\r
+       }\r
+\r
+       /* pdPASS being returned means the buffer has been consumed. */\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static FreeRTOS_Socket_t *prvHandleListen( FreeRTOS_Socket_t *pxSocket, NetworkBufferDescriptor_t *pxNetworkBuffer )\r
+{\r
+TCPPacket_t * pxTCPPacket = ( TCPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+FreeRTOS_Socket_t *pxReturn;\r
+\r
+       /* A pure SYN (without ACK) has come in, create a new socket to answer\r
+       it. */\r
+       if( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED )\r
+       {\r
+               /* The flag bReuseSocket indicates that the same instance of the\r
+               listening socket should be used for the connection. */\r
+               pxReturn = pxSocket;\r
+               pxSocket->u.xTCP.bits.bPassQueued = pdTRUE_UNSIGNED;\r
+               pxSocket->u.xTCP.pxPeerSocket = pxSocket;\r
+       }\r
+       else\r
+       {\r
+               /* The socket does not have the bReuseSocket flag set meaning create a\r
+               new socket when a connection comes in. */\r
+               pxReturn = NULL;\r
+\r
+               if( pxSocket->u.xTCP.usChildCount >= pxSocket->u.xTCP.usBacklog )\r
+               {\r
+                       FreeRTOS_printf( ( "Check: Socket %u already has %u / %u child%s\n",\r
+                               pxSocket->usLocalPort,\r
+                               pxSocket->u.xTCP.usChildCount,\r
+                               pxSocket->u.xTCP.usBacklog,\r
+                               pxSocket->u.xTCP.usChildCount == 1 ? "" : "ren" ) );\r
+                       prvTCPSendReset( pxNetworkBuffer );\r
+               }\r
+               else\r
+               {\r
+                       FreeRTOS_Socket_t *pxNewSocket = (FreeRTOS_Socket_t *)\r
+                               FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );\r
+\r
+                       if( ( pxNewSocket == NULL ) || ( pxNewSocket == FREERTOS_INVALID_SOCKET ) )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "TCP: Listen: new socket failed\n" ) );\r
+                               prvTCPSendReset( pxNetworkBuffer );\r
+                       }\r
+                       else if( prvTCPSocketCopy( pxNewSocket, pxSocket ) != pdFALSE )\r
+                       {\r
+                               /* The socket will be connected immediately, no time for the\r
+                               owner to setsockopt's, therefore copy properties of the server\r
+                               socket to the new socket.  Only the binding might fail (due to\r
+                               lack of resources). */\r
+                               pxReturn = pxNewSocket;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if( pxReturn != NULL )\r
+       {\r
+               pxReturn->u.xTCP.usRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort );\r
+               pxReturn->u.xTCP.ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress );\r
+               pxReturn->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulNextInitialSequenceNumber;\r
+\r
+               /* Here is the SYN action. */\r
+               pxReturn->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = FreeRTOS_ntohl( pxTCPPacket->xTCPHeader.ulSequenceNumber );\r
+               prvSocketSetMSS( pxReturn );\r
+\r
+               prvTCPCreateWindow( pxReturn );\r
+\r
+               /* It is recommended to increase the ISS for each new connection with a value of 0x102. */\r
+               ulNextInitialSequenceNumber += INITIAL_SEQUENCE_NUMBER_INCREMENT;\r
+\r
+               vTCPStateChange( pxReturn, eSYN_FIRST );\r
+\r
+               /* Make a copy of the header up to the TCP header.  It is needed later\r
+               on, whenever data must be sent to the peer. */\r
+               memcpy( pxReturn->u.xTCP.xPacket.u.ucLastPacket, pxNetworkBuffer->pucEthernetBuffer, sizeof( pxReturn->u.xTCP.xPacket.u.ucLastPacket ) );\r
+       }\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Duplicates a socket after a listening socket receives a connection.\r
+ */\r
+static BaseType_t prvTCPSocketCopy( FreeRTOS_Socket_t *pxNewSocket, FreeRTOS_Socket_t *pxSocket )\r
+{\r
+struct freertos_sockaddr xAddress;\r
+\r
+       pxNewSocket->xReceiveBlockTime = pxSocket->xReceiveBlockTime;\r
+       pxNewSocket->xSendBlockTime = pxSocket->xSendBlockTime;\r
+       pxNewSocket->ucSocketOptions = pxSocket->ucSocketOptions;\r
+       pxNewSocket->u.xTCP.uxRxStreamSize = pxSocket->u.xTCP.uxRxStreamSize;\r
+       pxNewSocket->u.xTCP.uxTxStreamSize = pxSocket->u.xTCP.uxTxStreamSize;\r
+       pxNewSocket->u.xTCP.uxLittleSpace = pxSocket->u.xTCP.uxLittleSpace;\r
+       pxNewSocket->u.xTCP.uxEnoughSpace = pxSocket->u.xTCP.uxEnoughSpace;\r
+       pxNewSocket->u.xTCP.uxRxWinSize  = pxSocket->u.xTCP.uxRxWinSize;\r
+       pxNewSocket->u.xTCP.uxTxWinSize  = pxSocket->u.xTCP.uxTxWinSize;\r
+\r
+       #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )\r
+       {\r
+               pxNewSocket->pxUserSemaphore = pxSocket->pxUserSemaphore;\r
+       }\r
+       #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */\r
+\r
+       #if( ipconfigUSE_CALLBACKS == 1 )\r
+       {\r
+               /* In case call-backs are used, copy them from parent to child. */\r
+               pxNewSocket->u.xTCP.pxHandleConnected = pxSocket->u.xTCP.pxHandleConnected;\r
+               pxNewSocket->u.xTCP.pxHandleReceive = pxSocket->u.xTCP.pxHandleReceive;\r
+               pxNewSocket->u.xTCP.pxHandleSent = pxSocket->u.xTCP.pxHandleSent;\r
+       }\r
+       #endif /* ipconfigUSE_CALLBACKS */\r
+\r
+       #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+       {\r
+               /* Child socket of listening sockets will inherit the Socket Set\r
+               Otherwise the owner has no chance of including it into the set. */\r
+               if( pxSocket->pxSocketSet )\r
+               {\r
+                       pxNewSocket->pxSocketSet = pxSocket->pxSocketSet;\r
+                       pxNewSocket->xSelectBits = pxSocket->xSelectBits | eSELECT_READ | eSELECT_EXCEPT;\r
+               }\r
+       }\r
+       #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
+\r
+       /* And bind it to the same local port as its parent. */\r
+       xAddress.sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;\r
+       xAddress.sin_port = FreeRTOS_htons( pxSocket->usLocalPort );\r
+\r
+       #if( ipconfigTCP_HANG_PROTECTION == 1 )\r
+       {\r
+               /* Only when there is anti-hanging protection, a socket may become an\r
+               orphan temporarily.  Once this socket is really connected, the owner of\r
+               the server socket will be notified. */\r
+\r
+               /* When bPassQueued is true, the socket is an orphan until it gets\r
+               connected. */\r
+               pxNewSocket->u.xTCP.bits.bPassQueued = pdTRUE_UNSIGNED;\r
+               pxNewSocket->u.xTCP.pxPeerSocket = pxSocket;\r
+       }\r
+       #else\r
+       {\r
+               /* A reference to the new socket may be stored and the socket is marked\r
+               as 'passable'. */\r
+\r
+               /* When bPassAccept is true, this socket may be returned in a call to\r
+               accept(). */\r
+               pxNewSocket->u.xTCP.bits.bPassAccept = pdTRUE_UNSIGNED;\r
+               if(pxSocket->u.xTCP.pxPeerSocket == NULL )\r
+               {\r
+                       pxSocket->u.xTCP.pxPeerSocket = pxNewSocket;\r
+               }\r
+       }\r
+       #endif\r
+\r
+       pxSocket->u.xTCP.usChildCount++;\r
+\r
+       FreeRTOS_debug_printf( ( "Gain: Socket %u now has %u / %u child%s\n",\r
+               pxSocket->usLocalPort,\r
+               pxSocket->u.xTCP.usChildCount,\r
+               pxSocket->u.xTCP.usBacklog,\r
+               pxSocket->u.xTCP.usChildCount == 1u ? "" : "ren" ) );\r
+\r
+       /* Now bind the child socket to the same port as the listening socket. */\r
+       if( vSocketBind ( pxNewSocket, &xAddress, sizeof( xAddress ), pdTRUE ) != 0 )\r
+       {\r
+               FreeRTOS_debug_printf( ( "TCP: Listen: new socket bind error\n" ) );\r
+               vSocketClose( pxNewSocket );\r
+               return pdFALSE;\r
+       }\r
+\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) )\r
+\r
+       const char *FreeRTOS_GetTCPStateName( UBaseType_t ulState )\r
+       {\r
+               if( ulState >= ( UBaseType_t ) ARRAY_SIZE( pcStateNames ) )\r
+               {\r
+                       ulState = ( UBaseType_t ) ARRAY_SIZE( pcStateNames ) - 1u;\r
+               }\r
+               return pcStateNames[ ulState ];\r
+       }\r
+\r
+#endif /* ( ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) ) */\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * In the API accept(), the user asks is there is a new client?  As API's can\r
+ * not walk through the xBoundTCPSocketsList the IP-task will do this.\r
+ */\r
+BaseType_t xTCPCheckNewClient( FreeRTOS_Socket_t *pxSocket )\r
+{\r
+TickType_t xLocalPort = FreeRTOS_htons( pxSocket->usLocalPort );\r
+ListItem_t *pxIterator;\r
+FreeRTOS_Socket_t *pxFound;\r
+BaseType_t xResult = pdFALSE;\r
+\r
+       /* Here xBoundTCPSocketsList can be accessed safely IP-task is the only one\r
+       who has access. */\r
+       for( pxIterator = ( ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList );\r
+               pxIterator != ( ListItem_t * ) listGET_END_MARKER( &xBoundTCPSocketsList );\r
+               pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ) )\r
+       {\r
+               if( listGET_LIST_ITEM_VALUE( pxIterator ) == xLocalPort )\r
+               {\r
+                       pxFound = ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
+                       if( ( pxFound->ucProtocol == FREERTOS_IPPROTO_TCP ) && ( pxFound->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) )\r
+                       {\r
+                               pxSocket->u.xTCP.pxPeerSocket = pxFound;\r
+                               FreeRTOS_debug_printf( ( "xTCPCheckNewClient[0]: client on port %u\n", pxSocket->usLocalPort ) );\r
+                               xResult = pdTRUE;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#endif /* ipconfigUSE_TCP == 1 */\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_TCP_WIN.c
new file mode 100644 (file)
index 0000000..85e9480
--- /dev/null
@@ -0,0 +1,2009 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*\r
+ * FreeRTOS_TCP_WIN.c\r
+ * Module which handles the TCP windowing schemes for FreeRTOS+TCP.  Many\r
+ * functions have two versions - one for FreeRTOS+TCP (full) and one for\r
+ * FreeRTOS+TCP (lite).\r
+ *\r
+ * In this module all ports and IP addresses and sequence numbers are\r
+ * being stored in host byte-order.\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "FreeRTOS_TCP_WIN.h"\r
+\r
+/* Constants used for Smoothed Round Trip Time (SRTT). */\r
+#define        winSRTT_INCREMENT_NEW           2\r
+#define winSRTT_INCREMENT_CURRENT      6\r
+#define        winSRTT_DECREMENT_NEW           1\r
+#define winSRTT_DECREMENT_CURRENT      7\r
+#define winSRTT_CAP_mS                         50\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       #define xTCPWindowRxNew( pxWindow, ulSequenceNumber, lCount ) xTCPWindowNew( pxWindow, ulSequenceNumber, lCount, pdTRUE )\r
+\r
+       #define xTCPWindowTxNew( pxWindow, ulSequenceNumber, lCount ) xTCPWindowNew( pxWindow, ulSequenceNumber, lCount, pdFALSE )\r
+\r
+       /* The code to send a single Selective ACK (SACK):\r
+        * NOP (0x01), NOP (0x01), SACK (0x05), LEN (0x0a),\r
+        * followed by a lower and a higher sequence number,\r
+        * where LEN is 2 + 2*4 = 10 bytes. */\r
+       #if( ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN )\r
+               #define OPTION_CODE_SINGLE_SACK         ( 0x0101050aUL )\r
+       #else\r
+               #define OPTION_CODE_SINGLE_SACK         ( 0x0a050101UL )\r
+       #endif\r
+\r
+       /* Normal retransmission:\r
+        * A packet will be retransmitted after a Retransmit Time-Out (RTO).\r
+        * Fast retransmission:\r
+        * When 3 packets with a higher sequence number have been acknowledged\r
+        * by the peer, it is very unlikely a current packet will ever arrive.\r
+        * It will be retransmitted far before the RTO.\r
+        */\r
+       #define DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT           ( 3u )\r
+\r
+       /* If there have been several retransmissions (4), decrease the\r
+        * size of the transmission window to at most 2 times MSS.\r
+        */\r
+       #define MAX_TRANSMIT_COUNT_USING_LARGE_WINDOW           ( 4u )\r
+\r
+#endif /* configUSE_TCP_WIN */\r
+/*-----------------------------------------------------------*/\r
+\r
+extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere );\r
+\r
+/*\r
+ * All TCP sockets share a pool of segment descriptors (TCPSegment_t)\r
+ * Available descriptors are stored in the 'xSegmentList'\r
+ * When a socket owns a descriptor, it will either be stored in\r
+ * 'xTxSegments' or 'xRxSegments'\r
+ * As soon as a package has been confirmed, the descriptor will be returned\r
+ * to the segment pool\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static BaseType_t prvCreateSectors( void );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/*\r
+ * Find a segment with a given sequence number in the list of received\r
+ * segments: 'pxWindow->xRxSegments'.\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static TCPSegment_t *xTCPWindowRxFind( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/*\r
+ * Allocate a new segment\r
+ * The socket will borrow all segments from a common pool: 'xSegmentList',\r
+ * which is a list of 'TCPSegment_t'\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static TCPSegment_t *xTCPWindowNew( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, int32_t lCount, BaseType_t xIsForRx );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/* When the peer has a close request (FIN flag), the driver will check if\r
+ * there are missing packets in the Rx-queue\r
+ * It will accept the closure of the connection if both conditions are true:\r
+ * - the Rx-queue is empty\r
+ * - we've ACK'd the highest Rx sequence number seen\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/*\r
+ * Detaches and returns the head of a queue\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static TCPSegment_t *xTCPWindowGetHead( List_t *pxList );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/*\r
+ * Returns the head of a queue but it won't be detached\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static TCPSegment_t *xTCPWindowPeekHead( List_t *pxList );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/*\r
+ *  Free entry pxSegment because it's not used anymore\r
+ *     The ownership will be passed back to the segment pool\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static void vTCPWindowFree( TCPSegment_t *pxSegment );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/*\r
+ * A segment has been received with sequence number 'ulSequenceNumber', where\r
+ * 'ulCurrentSequenceNumber == ulSequenceNumber', which means that exactly this\r
+ * segment was expected.  xTCPWindowRxConfirm() will check if there is already\r
+ * another segment with a sequence number between (ulSequenceNumber) and\r
+ * (ulSequenceNumber+xLength).  Normally none will be found, because the next Rx\r
+ * segment should have a sequence number equal to '(ulSequenceNumber+xLength)'.\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static TCPSegment_t *xTCPWindowRxConfirm( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/*\r
+ * FreeRTOS+TCP stores data in circular buffers.  Calculate the next position to\r
+ * store.\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static int32_t lTCPIncrementTxPosition( int32_t lPosition, int32_t lMax, int32_t lCount );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/*\r
+ * This function will look if there is new transmission data.  It will return\r
+ * true if there is data to be sent.\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/*\r
+ * An acknowledge was received.  See if some outstanding data may be removed\r
+ * from the transmission queue(s).\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static uint32_t prvTCPWindowTxCheckAck( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/*\r
+ * A higher Tx block has been acknowledged.  Now iterate through the xWaitQueue\r
+ * to find a possible condition for a FAST retransmission.\r
+ */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static uint32_t prvTCPWindowFastRetransmit( TCPWindow_t *pxWindow, uint32_t ulFirst );\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* TCP segement pool. */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static TCPSegment_t *xTCPSegments = NULL;\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+/* List of free TCP segments. */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static List_t xSegmentList;\r
+#endif\r
+\r
+/* Logging verbosity level. */\r
+BaseType_t xTCPWindowLoggingLevel = 0;\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       /* Some 32-bit arithmetic: comparing sequence numbers */\r
+       static portINLINE BaseType_t xSequenceLessThanOrEqual( uint32_t a, uint32_t b );\r
+       static portINLINE BaseType_t xSequenceLessThanOrEqual( uint32_t a, uint32_t b )\r
+       {\r
+               /* Test if a <= b\r
+               Return true if the unsigned subtraction of (b-a) doesn't generate an\r
+               arithmetic overflow. */\r
+               return ( ( b - a ) & 0x80000000UL ) == 0UL;\r
+       }\r
+#endif /* ipconfigUSE_TCP_WIN */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static portINLINE BaseType_t xSequenceLessThan( uint32_t a, uint32_t b );\r
+       static portINLINE BaseType_t xSequenceLessThan( uint32_t a, uint32_t b )\r
+       {\r
+               /* Test if a < b */\r
+               return ( ( b - a - 1UL ) & 0x80000000UL ) == 0UL;\r
+       }\r
+#endif /* ipconfigUSE_TCP_WIN */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a, uint32_t b );\r
+       static portINLINE BaseType_t xSequenceGreaterThan( uint32_t a, uint32_t b )\r
+       {\r
+               /* Test if a > b */\r
+               return ( ( a - b - 1UL ) & 0x80000000UL ) == 0UL;\r
+       }\r
+#endif /* ipconfigUSE_TCP_WIN */\r
+\r
+/*-----------------------------------------------------------*/\r
+static portINLINE BaseType_t xSequenceGreaterThanOrEqual( uint32_t a, uint32_t b );\r
+static portINLINE BaseType_t xSequenceGreaterThanOrEqual( uint32_t a, uint32_t b )\r
+{\r
+       /* Test if a >= b */\r
+       return ( ( a - b ) & 0x80000000UL ) == 0UL;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       static portINLINE void vListInsertFifo( List_t * const pxList, ListItem_t * const pxNewListItem );\r
+       static portINLINE void vListInsertFifo( List_t * const pxList, ListItem_t * const pxNewListItem )\r
+       {\r
+               vListInsertGeneric( pxList, pxNewListItem, &pxList->xListEnd );\r
+       }\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE void vTCPTimerSet( TCPTimer_t *pxTimer );\r
+static portINLINE void vTCPTimerSet( TCPTimer_t *pxTimer )\r
+{\r
+       pxTimer->ulBorn = xTaskGetTickCount ( );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE uint32_t ulTimerGetAge( TCPTimer_t *pxTimer );\r
+static portINLINE uint32_t ulTimerGetAge( TCPTimer_t *pxTimer )\r
+{\r
+       return ( ( xTaskGetTickCount() - pxTimer->ulBorn ) * portTICK_PERIOD_MS );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* _HT_ GCC (using the settings that I'm using) checks for every public function if it is\r
+preceded by a prototype. Later this prototype will be located in list.h? */\r
+\r
+extern void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere );\r
+\r
+void vListInsertGeneric( List_t * const pxList, ListItem_t * const pxNewListItem, MiniListItem_t * const pxWhere )\r
+{\r
+       /* Insert a new list item into pxList, it does not sort the list,\r
+       but it puts the item just before xListEnd, so it will be the last item\r
+       returned by listGET_HEAD_ENTRY() */\r
+       pxNewListItem->pxNext = (struct xLIST_ITEM * configLIST_VOLATILE)pxWhere;\r
+       pxNewListItem->pxPrevious = pxWhere->pxPrevious;\r
+       pxWhere->pxPrevious->pxNext = pxNewListItem;\r
+       pxWhere->pxPrevious = pxNewListItem;\r
+\r
+       /* Remember which list the item is in. */\r
+       pxNewListItem->pvContainer = ( void * ) pxList;\r
+\r
+       ( pxList->uxNumberOfItems )++;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       static BaseType_t prvCreateSectors( void )\r
+       {\r
+       BaseType_t xIndex, xReturn;\r
+\r
+               /* Allocate space for 'xTCPSegments' and store them in 'xSegmentList'. */\r
+\r
+               vListInitialise( &xSegmentList );\r
+               xTCPSegments = ( TCPSegment_t * ) pvPortMallocLarge( ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) );\r
+\r
+               if( xTCPSegments == NULL )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "prvCreateSectors: malloc %lu failed\n",\r
+                               ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) ) );\r
+\r
+                       xReturn = pdFAIL;\r
+               }\r
+               else\r
+               {\r
+                       /* Clear the allocated space. */\r
+                       memset( xTCPSegments, '\0', ipconfigTCP_WIN_SEG_COUNT * sizeof( xTCPSegments[ 0 ] ) );\r
+\r
+                       for( xIndex = 0; xIndex < ipconfigTCP_WIN_SEG_COUNT; xIndex++ )\r
+                       {\r
+                               /* Could call vListInitialiseItem here but all data has been\r
+                               nulled already.  Set the owner to a segment descriptor. */\r
+                               listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xListItem ), ( void* ) &( xTCPSegments[ xIndex ] ) );\r
+                               listSET_LIST_ITEM_OWNER( &( xTCPSegments[ xIndex ].xQueueItem ), ( void* ) &( xTCPSegments[ xIndex ] ) );\r
+\r
+                               /* And add it to the pool of available segments */\r
+                               vListInsertFifo( &xSegmentList, &( xTCPSegments[xIndex].xListItem ) );\r
+                       }\r
+\r
+                       xReturn = pdPASS;\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       static TCPSegment_t *xTCPWindowRxFind( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber )\r
+       {\r
+       const ListItem_t *pxIterator;\r
+       const MiniListItem_t* pxEnd;\r
+       TCPSegment_t *pxSegment, *pxReturn = NULL;\r
+\r
+               /* Find a segment with a given sequence number in the list of received\r
+               segments. */\r
+\r
+               pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &pxWindow->xRxSegments );\r
+\r
+               for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );\r
+                        pxIterator != ( const ListItem_t * ) pxEnd;\r
+                        pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
+               {\r
+                       pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
+\r
+                       if( pxSegment->ulSequenceNumber == ulSequenceNumber )\r
+                       {\r
+                               pxReturn = pxSegment;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               return pxReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       static TCPSegment_t *xTCPWindowNew( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, int32_t lCount, BaseType_t xIsForRx )\r
+       {\r
+       TCPSegment_t *pxSegment;\r
+       ListItem_t * pxItem;\r
+\r
+               /* Allocate a new segment.  The socket will borrow all segments from a\r
+               common pool: 'xSegmentList', which is a list of 'TCPSegment_t' */\r
+               if( listLIST_IS_EMPTY( &xSegmentList ) != pdFALSE )\r
+               {\r
+                       /* If the TCP-stack runs out of segments, you might consider\r
+                       increasing 'ipconfigTCP_WIN_SEG_COUNT'. */\r
+                       FreeRTOS_debug_printf( ( "xTCPWindow%cxNew: Error: all segments occupied\n", xIsForRx ? 'R' : 'T' ) );\r
+                       pxSegment = NULL;\r
+               }\r
+               else\r
+               {\r
+                       /* Pop the item at the head of the list.  Semaphore protection is\r
+                       not required as only the IP task will call these functions.  */\r
+                       pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( &xSegmentList );\r
+                       pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxItem );\r
+\r
+                       configASSERT( pxItem != NULL );\r
+                       configASSERT( pxSegment != NULL );\r
+\r
+                       /* Remove the item from xSegmentList. */\r
+                       uxListRemove( pxItem );\r
+\r
+                       /* Add it to either the connections' Rx or Tx queue. */\r
+                       vListInsertFifo( xIsForRx ? &pxWindow->xRxSegments : &pxWindow->xTxSegments, pxItem );\r
+\r
+                       /* And set the segment's timer to zero */\r
+                       vTCPTimerSet( &pxSegment->xTransmitTimer );\r
+\r
+                       pxSegment->u.ulFlags = 0;\r
+                       pxSegment->u.bits.bIsForRx = ( xIsForRx != 0 );\r
+                       pxSegment->lMaxLength = lCount;\r
+                       pxSegment->lDataLength = lCount;\r
+                       pxSegment->ulSequenceNumber = ulSequenceNumber;\r
+                       #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+                       {\r
+                       static UBaseType_t xLowestLength = ipconfigTCP_WIN_SEG_COUNT;\r
+                       UBaseType_t xLength = listCURRENT_LIST_LENGTH( &xSegmentList );\r
+\r
+                               if( xLowestLength > xLength )\r
+                               {\r
+                                       xLowestLength = xLength;\r
+                               }\r
+                       }\r
+                       #endif /* ipconfigHAS_DEBUG_PRINTF */\r
+               }\r
+\r
+               return pxSegment;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow )\r
+       {\r
+       BaseType_t xReturn;\r
+\r
+               /* When the peer has a close request (FIN flag), the driver will check\r
+               if there are missing packets in the Rx-queue.  It will accept the\r
+               closure of the connection if both conditions are true:\r
+                 - the Rx-queue is empty\r
+                 - the highest Rx sequence number has been ACK'ed */\r
+               if( listLIST_IS_EMPTY( ( &pxWindow->xRxSegments ) ) == pdFALSE )\r
+               {\r
+                       /* Rx data has been stored while earlier packets were missing. */\r
+                       xReturn = pdFALSE;\r
+               }\r
+               else if( xSequenceGreaterThanOrEqual( pxWindow->rx.ulCurrentSequenceNumber, pxWindow->rx.ulHighestSequenceNumber ) != pdFALSE )\r
+               {\r
+                       /* No Rx packets are being stored and the highest sequence number\r
+                       that has been received has been ACKed. */\r
+                       xReturn = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       FreeRTOS_debug_printf( ( "xTCPWindowRxEmpty: cur %lu highest %lu (empty)\n",\r
+                               ( pxWindow->rx.ulCurrentSequenceNumber - pxWindow->rx.ulFirstSequenceNumber ),\r
+                               ( pxWindow->rx.ulHighestSequenceNumber - pxWindow->rx.ulFirstSequenceNumber ) ) );\r
+                       xReturn = pdFALSE;\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       static TCPSegment_t *xTCPWindowGetHead( List_t *pxList )\r
+       {\r
+       TCPSegment_t *pxSegment;\r
+       ListItem_t * pxItem;\r
+\r
+               /* Detaches and returns the head of a queue. */\r
+               if( listLIST_IS_EMPTY( pxList ) != pdFALSE )\r
+               {\r
+                       pxSegment = NULL;\r
+               }\r
+               else\r
+               {\r
+                       pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( pxList );\r
+                       pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxItem );\r
+\r
+                       uxListRemove( pxItem );\r
+               }\r
+\r
+               return pxSegment;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       static TCPSegment_t *xTCPWindowPeekHead( List_t *pxList )\r
+       {\r
+       ListItem_t *pxItem;\r
+       TCPSegment_t *pxReturn;\r
+\r
+               /* Returns the head of a queue but it won't be detached. */\r
+               if( listLIST_IS_EMPTY( pxList ) != pdFALSE )\r
+               {\r
+                       pxReturn = NULL;\r
+               }\r
+               else\r
+               {\r
+                       pxItem = ( ListItem_t * ) listGET_HEAD_ENTRY( pxList );\r
+                       pxReturn = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxItem );\r
+               }\r
+\r
+               return pxReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       static void vTCPWindowFree( TCPSegment_t *pxSegment )\r
+       {\r
+               /*  Free entry pxSegment because it's not used any more.  The ownership\r
+               will be passed back to the segment pool.\r
+\r
+               Unlink it from one of the queues, if any. */\r
+               if( listLIST_ITEM_CONTAINER( &( pxSegment->xQueueItem ) ) != NULL )\r
+               {\r
+                       uxListRemove( &( pxSegment->xQueueItem ) );\r
+               }\r
+\r
+               pxSegment->ulSequenceNumber = 0u;\r
+               pxSegment->lDataLength = 0l;\r
+               pxSegment->u.ulFlags = 0u;\r
+\r
+               /* Take it out of xRxSegments/xTxSegments */\r
+               if( listLIST_ITEM_CONTAINER( &( pxSegment->xListItem ) ) != NULL )\r
+               {\r
+                       uxListRemove( &( pxSegment->xListItem ) );\r
+               }\r
+\r
+               /* Return it to xSegmentList */\r
+               vListInsertFifo( &xSegmentList, &( pxSegment->xListItem ) );\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       void vTCPWindowDestroy( TCPWindow_t *pxWindow )\r
+       {\r
+       List_t * pxSegments;\r
+       BaseType_t xRound;\r
+       TCPSegment_t *pxSegment;\r
+\r
+               /*  Destroy a window.  A TCP window doesn't serve any more.  Return all\r
+               owned segments to the pool.  In order to save code, it will make 2 rounds,\r
+               one to remove the segments from xRxSegments, and a second round to clear\r
+               xTxSegments*/\r
+               for( xRound = 0; xRound < 2; xRound++ )\r
+               {\r
+                       if( xRound != 0 )\r
+                       {\r
+                               pxSegments = &( pxWindow->xRxSegments );\r
+                       }\r
+                       else\r
+                       {\r
+                               pxSegments = &( pxWindow->xTxSegments );\r
+                       }\r
+\r
+                       if( listLIST_IS_INITIALISED( pxSegments ) != pdFALSE )\r
+                       {\r
+                               while( listCURRENT_LIST_LENGTH( pxSegments ) > 0U )\r
+                               {\r
+                                       pxSegment = ( TCPSegment_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxSegments );\r
+                                       vTCPWindowFree( pxSegment );\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+void vTCPWindowCreate( TCPWindow_t *pxWindow, uint32_t ulRxWindowLength,\r
+       uint32_t ulTxWindowLength, uint32_t ulAckNumber, uint32_t ulSequenceNumber, uint32_t ulMSS )\r
+{\r
+       /* Create and initialize a window. */\r
+\r
+       #if( ipconfigUSE_TCP_WIN == 1 )\r
+       {\r
+               if( xTCPSegments == NULL )\r
+               {\r
+                       prvCreateSectors();\r
+               }\r
+\r
+               vListInitialise( &( pxWindow->xTxSegments ) );\r
+               vListInitialise( &( pxWindow->xRxSegments ) );\r
+\r
+               vListInitialise( &( pxWindow->xPriorityQueue ) );       /* Priority queue: segments which must be sent immediately */\r
+               vListInitialise( &( pxWindow->xTxQueue ) );                     /* Transmit queue: segments queued for transmission */\r
+               vListInitialise( &( pxWindow->xWaitQueue ) );           /* Waiting queue:  outstanding segments */\r
+       }\r
+       #endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+       if( xTCPWindowLoggingLevel != 0 )\r
+       {\r
+               FreeRTOS_debug_printf( ( "vTCPWindowCreate: for WinLen = Rx/Tx: %lu/%lu\n",\r
+                       ulRxWindowLength, ulTxWindowLength ) );\r
+       }\r
+\r
+       pxWindow->xSize.ulRxWindowLength = ulRxWindowLength;\r
+       pxWindow->xSize.ulTxWindowLength = ulTxWindowLength;\r
+\r
+       vTCPWindowInit( pxWindow, ulAckNumber, ulSequenceNumber, ulMSS );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vTCPWindowInit( TCPWindow_t *pxWindow, uint32_t ulAckNumber, uint32_t ulSequenceNumber, uint32_t ulMSS )\r
+{\r
+const int32_t l500ms = 500;\r
+\r
+       pxWindow->u.ulFlags = 0ul;\r
+       pxWindow->u.bits.bHasInit = pdTRUE_UNSIGNED;\r
+\r
+       if( ulMSS != 0ul )\r
+       {\r
+               if( pxWindow->usMSSInit != 0u )\r
+               {\r
+                       pxWindow->usMSSInit = ( uint16_t ) ulMSS;\r
+               }\r
+\r
+               if( ( ulMSS < ( uint32_t ) pxWindow->usMSS ) || ( pxWindow->usMSS == 0u ) )\r
+               {\r
+                       pxWindow->xSize.ulRxWindowLength = ( pxWindow->xSize.ulRxWindowLength / ulMSS ) * ulMSS;\r
+                       pxWindow->usMSS = ( uint16_t ) ulMSS;\r
+               }\r
+       }\r
+\r
+       #if( ipconfigUSE_TCP_WIN == 0 )\r
+       {\r
+               pxWindow->xTxSegment.lMaxLength = ( int32_t ) pxWindow->usMSS;\r
+       }\r
+       #endif /* ipconfigUSE_TCP_WIN == 1 */\r
+\r
+       /*Start with a timeout of 2 * 500 ms (1 sec). */\r
+       pxWindow->lSRTT = l500ms;\r
+\r
+       /* Just for logging, to print relative sequence numbers. */\r
+       pxWindow->rx.ulFirstSequenceNumber = ulAckNumber;\r
+\r
+       /* The segment asked for in the next transmission. */\r
+       pxWindow->rx.ulCurrentSequenceNumber = ulAckNumber;\r
+\r
+       /* The right-hand side of the receive window. */\r
+       pxWindow->rx.ulHighestSequenceNumber = ulAckNumber;\r
+\r
+       pxWindow->tx.ulFirstSequenceNumber = ulSequenceNumber;\r
+\r
+       /* The segment asked for in next transmission. */\r
+       pxWindow->tx.ulCurrentSequenceNumber = ulSequenceNumber;\r
+\r
+       /* The sequence number given to the next outgoing byte to be added is\r
+       maintained by lTCPWindowTxAdd(). */\r
+       pxWindow->ulNextTxSequenceNumber = ulSequenceNumber;\r
+\r
+       /* The right-hand side of the transmit window. */\r
+       pxWindow->tx.ulHighestSequenceNumber = ulSequenceNumber;\r
+       pxWindow->ulOurSequenceNumber = ulSequenceNumber;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*=============================================================================\r
+ *\r
+ *                ######        #    #\r
+ *                 #    #       #    #\r
+ *                 #    #       #    #\r
+ *                 #    #        ####\r
+ *                 ######         ##\r
+ *                 #  ##         ####\r
+ *                 #   #        #    #\r
+ *                 #    #       #    #\r
+ *                ###  ##       #    #\r
+ * Rx functions\r
+ *\r
+ *=============================================================================*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       static TCPSegment_t *xTCPWindowRxConfirm( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength )\r
+       {\r
+       TCPSegment_t *pxBest = NULL;\r
+       const ListItem_t *pxIterator;\r
+       uint32_t ulNextSequenceNumber = ulSequenceNumber + ulLength;\r
+       const MiniListItem_t* pxEnd = ( const MiniListItem_t* ) listGET_END_MARKER( &pxWindow->xRxSegments );\r
+       TCPSegment_t *pxSegment;\r
+\r
+               /* A segment has been received with sequence number 'ulSequenceNumber',\r
+               where 'ulCurrentSequenceNumber == ulSequenceNumber', which means that\r
+               exactly this segment was expected.  xTCPWindowRxConfirm() will check if\r
+               there is already another segment with a sequence number between (ulSequenceNumber)\r
+               and (ulSequenceNumber+ulLength).  Normally none will be found, because\r
+               the next RX segment should have a sequence number equal to\r
+               '(ulSequenceNumber+ulLength)'. */\r
+\r
+               /* Iterate through all RX segments that are stored: */\r
+               for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );\r
+                        pxIterator != ( const ListItem_t * ) pxEnd;\r
+                        pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator ) )\r
+               {\r
+                       pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
+                       /* And see if there is a segment for which:\r
+                       'ulSequenceNumber' <= 'pxSegment->ulSequenceNumber' < 'ulNextSequenceNumber'\r
+                       If there are more matching segments, the one with the lowest sequence number\r
+                       shall be taken */\r
+                       if( ( xSequenceGreaterThanOrEqual( pxSegment->ulSequenceNumber, ulSequenceNumber ) != 0 ) &&\r
+                               ( xSequenceLessThan( pxSegment->ulSequenceNumber, ulNextSequenceNumber ) != 0 ) )\r
+                       {\r
+                               if( ( pxBest == NULL ) || ( xSequenceLessThan( pxSegment->ulSequenceNumber, pxBest->ulSequenceNumber ) != 0 ) )\r
+                               {\r
+                                       pxBest = pxSegment;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if( ( pxBest != NULL ) &&\r
+                       ( ( pxBest->ulSequenceNumber != ulSequenceNumber ) || ( pxBest->lDataLength != ( int32_t ) ulLength ) ) )\r
+               {\r
+                       FreeRTOS_flush_logging();\r
+                       FreeRTOS_debug_printf( ( "xTCPWindowRxConfirm[%u]: search %lu (+%ld=%lu) found %lu (+%ld=%lu)\n",\r
+                               pxWindow->usPeerPortNumber,\r
+                               ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,\r
+                               ulLength,\r
+                               ulSequenceNumber + ulLength - pxWindow->rx.ulFirstSequenceNumber,\r
+                               pxBest->ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,\r
+                               pxBest->lDataLength,\r
+                               pxBest->ulSequenceNumber + ( ( uint32_t ) pxBest->lDataLength ) - pxWindow->rx.ulFirstSequenceNumber ) );\r
+               }\r
+\r
+               return pxBest;\r
+       }\r
+\r
+#endif /* ipconfgiUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       int32_t lTCPWindowRxCheck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength, uint32_t ulSpace )\r
+       {\r
+       uint32_t ulCurrentSequenceNumber, ulLast, ulSavedSequenceNumber;\r
+       int32_t lReturn, lDistance;\r
+       TCPSegment_t *pxFound;\r
+\r
+               /* If lTCPWindowRxCheck( ) returns == 0, the packet will be passed\r
+               directly to user (segment is expected).  If it returns a positive\r
+               number, an earlier packet is missing, but this packet may be stored.\r
+               If negative, the packet has already been stored, or it is out-of-order,\r
+               or there is not enough space.\r
+\r
+               As a side-effect, pxWindow->ulUserDataLength will get set to non-zero,\r
+               if more Rx data may be passed to the user after this packet. */\r
+\r
+               ulCurrentSequenceNumber = pxWindow->rx.ulCurrentSequenceNumber;\r
+\r
+               /* For Selective Ack (SACK), used when out-of-sequence data come in. */\r
+               pxWindow->ucOptionLength = 0u;\r
+\r
+               /* Non-zero if TCP-windows contains data which must be popped. */\r
+               pxWindow->ulUserDataLength = 0ul;\r
+\r
+               if( ulCurrentSequenceNumber == ulSequenceNumber )\r
+               {\r
+                       /* This is the packet with the lowest sequence number we're waiting\r
+                       for.  It can be passed directly to the rx stream. */\r
+                       if( ulLength > ulSpace )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "lTCPWindowRxCheck: Refuse %lu bytes, due to lack of space (%lu)\n", ulLength, ulSpace ) );\r
+                               lReturn = -1;\r
+                       }\r
+                       else\r
+                       {\r
+                               ulCurrentSequenceNumber += ulLength;\r
+\r
+                               if( listCURRENT_LIST_LENGTH( &( pxWindow->xRxSegments ) ) != 0 )\r
+                               {\r
+                                       ulSavedSequenceNumber = ulCurrentSequenceNumber;\r
+\r
+                                       /* See if (part of) this segment has been stored already,\r
+                                       but this rarely happens. */\r
+                                       pxFound = xTCPWindowRxConfirm( pxWindow, ulSequenceNumber, ulLength );\r
+                                       if( pxFound != NULL )\r
+                                       {\r
+                                               ulCurrentSequenceNumber = pxFound->ulSequenceNumber + ( ( uint32_t ) pxFound->lDataLength );\r
+\r
+                                               /* Remove it because it will be passed to user directly. */\r
+                                               vTCPWindowFree( pxFound );\r
+                                       }\r
+\r
+                                       /*  Check for following segments that are already in the\r
+                                       queue and increment ulCurrentSequenceNumber. */\r
+                                       while( ( pxFound = xTCPWindowRxFind( pxWindow, ulCurrentSequenceNumber ) ) != NULL )\r
+                                       {\r
+                                               ulCurrentSequenceNumber += ( uint32_t ) pxFound->lDataLength;\r
+\r
+                                               /* As all packet below this one have been passed to the\r
+                                               user it can be discarded. */\r
+                                               vTCPWindowFree( pxFound );\r
+                                       }\r
+\r
+                                       if( ulSavedSequenceNumber != ulCurrentSequenceNumber )\r
+                                       {\r
+                                               /*  After the current data-package, there is more data\r
+                                               to be popped. */\r
+                                               pxWindow->ulUserDataLength = ulCurrentSequenceNumber - ulSavedSequenceNumber;\r
+\r
+                                               if( xTCPWindowLoggingLevel >= 1 )\r
+                                               {\r
+                                                       FreeRTOS_debug_printf( ( "lTCPWindowRxCheck[%d,%d]: retran %lu (Found %lu bytes at %lu cnt %ld)\n",\r
+                                                               pxWindow->usPeerPortNumber, pxWindow->usOurPortNumber,\r
+                                                               ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,\r
+                                                               pxWindow->ulUserDataLength,\r
+                                                               ulSavedSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,\r
+                                                               listCURRENT_LIST_LENGTH( &pxWindow->xRxSegments ) ) );\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               pxWindow->rx.ulCurrentSequenceNumber = ulCurrentSequenceNumber;\r
+\r
+                               /* Packet was expected, may be passed directly to the socket\r
+                               buffer or application.  Store the packet at offset 0. */\r
+                               lReturn = 0;\r
+                       }\r
+               }\r
+               else if( ulCurrentSequenceNumber == ( ulSequenceNumber + 1UL ) )\r
+               {\r
+                       /* Looks like a TCP keep-alive message.  Do not accept/store Rx data\r
+                       ulUserDataLength = 0. Not packet out-of-sync.  Just reply to it. */\r
+                       lReturn = -1;\r
+               }\r
+               else\r
+               {\r
+                       /* The packet is not the one expected.  See if it falls within the Rx\r
+                       window so it can be stored. */\r
+\r
+                       /*  An "out-of-sequence" segment was received, must have missed one.\r
+                       Prepare a SACK (Selective ACK). */\r
+                       ulLast = ulSequenceNumber + ulLength;\r
+                       lDistance = ( int32_t ) ( ulLast - ulCurrentSequenceNumber );\r
+\r
+                       if( lDistance <= 0 )\r
+                       {\r
+                               /* An earlier has been received, must be a retransmission of a\r
+                               packet that has been accepted already.  No need to send out a\r
+                               Selective ACK (SACK). */\r
+                               lReturn = -1;\r
+                       }\r
+                       else if( lDistance > ( int32_t ) ulSpace )\r
+                       {\r
+                               /* The new segment is ahead of rx.ulCurrentSequenceNumber.  The\r
+                               sequence number of this packet is too far ahead, ignore it. */\r
+                               FreeRTOS_debug_printf( ( "lTCPWindowRxCheck: Refuse %lu+%lu bytes, due to lack of space (%lu)\n", lDistance, ulLength, ulSpace ) );\r
+                               lReturn = -1;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* See if there is more data in a contiguous block to make the\r
+                               SACK describe a longer range of data. */\r
+\r
+                               /* TODO: SACK's may also be delayed for a short period\r
+                                * This is useful because subsequent packets will be SACK'd with\r
+                                * single one message\r
+                                */\r
+                               while( ( pxFound = xTCPWindowRxFind( pxWindow, ulLast ) ) != NULL )\r
+                               {\r
+                                       ulLast += ( uint32_t ) pxFound->lDataLength;\r
+                               }\r
+\r
+                               if( xTCPWindowLoggingLevel >= 1 )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "lTCPWindowRxCheck[%d,%d]: seqnr %lu exp %lu (dist %ld) SACK to %lu\n",\r
+                                               pxWindow->usPeerPortNumber, pxWindow->usOurPortNumber,\r
+                                               ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,\r
+                                               ulCurrentSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,\r
+                                               ( BaseType_t ) ( ulSequenceNumber - ulCurrentSequenceNumber ),  /* want this signed */\r
+                                               ulLast - pxWindow->rx.ulFirstSequenceNumber ) );\r
+                               }\r
+\r
+                               /* Now prepare the SACK message.\r
+                               Code OPTION_CODE_SINGLE_SACK already in network byte order. */\r
+                               pxWindow->ulOptionsData[0] = OPTION_CODE_SINGLE_SACK;\r
+\r
+                               /* First sequence number that we received. */\r
+                               pxWindow->ulOptionsData[1] = FreeRTOS_htonl( ulSequenceNumber );\r
+\r
+                               /* Last + 1 */\r
+                               pxWindow->ulOptionsData[2] = FreeRTOS_htonl( ulLast );\r
+\r
+                               /* Which make 12 (3*4) option bytes. */\r
+                               pxWindow->ucOptionLength = 3 * sizeof( pxWindow->ulOptionsData[ 0 ] );\r
+\r
+                               pxFound = xTCPWindowRxFind( pxWindow, ulSequenceNumber );\r
+\r
+                               if( pxFound != NULL )\r
+                               {\r
+                                       /* This out-of-sequence packet has been received for a\r
+                                       second time.  It is already stored but do send a SACK\r
+                                       again. */\r
+                                       lReturn = -1;\r
+                               }\r
+                               else\r
+                               {\r
+                                       pxFound = xTCPWindowRxNew( pxWindow, ulSequenceNumber, ( int32_t ) ulLength );\r
+\r
+                                       if( pxFound == NULL )\r
+                                       {\r
+                                               /* Can not send a SACK, because the segment cannot be\r
+                                               stored. */\r
+                                               pxWindow->ucOptionLength = 0u;\r
+\r
+                                               /* Needs to be stored but there is no segment\r
+                                               available. */\r
+                                               lReturn = -1;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if( xTCPWindowLoggingLevel != 0 )\r
+                                               {\r
+                                                       FreeRTOS_debug_printf( ( "lTCPWindowRxCheck[%u,%u]: seqnr %lu (cnt %lu)\n",\r
+                                                               pxWindow->usPeerPortNumber, pxWindow->usOurPortNumber, ulSequenceNumber - pxWindow->rx.ulFirstSequenceNumber,\r
+                                                               listCURRENT_LIST_LENGTH( &pxWindow->xRxSegments ) ) );\r
+                                                       FreeRTOS_flush_logging( );\r
+                                               }\r
+\r
+                                               /* Return a positive value.  The packet may be accepted\r
+                                               and stored but an earlier packet is still missing. */\r
+                                               lReturn = ( int32_t ) ( ulSequenceNumber - ulCurrentSequenceNumber );\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return lReturn;\r
+       }\r
+\r
+#endif /* ipconfgiUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+/*=============================================================================\r
+ *\r
+ *                    #########   #    #\r
+ *                    #   #   #   #    #\r
+ *                        #       #    #\r
+ *                        #        ####\r
+ *                        #         ##\r
+ *                        #        ####\r
+ *                        #       #    #\r
+ *                        #       #    #\r
+ *                      #####     #    #\r
+ *\r
+ * Tx functions\r
+ *\r
+ *=============================================================================*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       static int32_t lTCPIncrementTxPosition( int32_t lPosition, int32_t lMax, int32_t lCount )\r
+       {\r
+               /* +TCP stores data in circular buffers.  Calculate the next position to\r
+               store. */\r
+               lPosition += lCount;\r
+               if( lPosition >= lMax )\r
+               {\r
+                       lPosition -= lMax;\r
+               }\r
+\r
+               return lPosition;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       int32_t lTCPWindowTxAdd( TCPWindow_t *pxWindow, uint32_t ulLength, int32_t lPosition, int32_t lMax )\r
+       {\r
+       int32_t lBytesLeft = ( int32_t ) ulLength, lToWrite;\r
+       int32_t lDone = 0;\r
+       TCPSegment_t *pxSegment = pxWindow->pxHeadSegment;\r
+\r
+               /* Puts a message in the Tx-window (after buffer size has been\r
+               verified). */\r
+               if( pxSegment != NULL )\r
+               {\r
+                       if( pxSegment->lDataLength < pxSegment->lMaxLength )\r
+                       {\r
+                               if( ( pxSegment->u.bits.bOutstanding == pdFALSE_UNSIGNED ) && ( pxSegment->lDataLength != 0 ) )\r
+                               {\r
+                                       /* Adding data to a segment that was already in the TX queue.  It\r
+                                       will be filled-up to a maximum of MSS (maximum segment size). */\r
+                                       lToWrite = FreeRTOS_min_int32( lBytesLeft, pxSegment->lMaxLength - pxSegment->lDataLength );\r
+\r
+                                       pxSegment->lDataLength += lToWrite;\r
+\r
+                                       if( pxSegment->lDataLength >= pxSegment->lMaxLength )\r
+                                       {\r
+                                               /* This segment is full, don't add more bytes. */\r
+                                               pxWindow->pxHeadSegment = NULL;\r
+                                       }\r
+\r
+                                       lBytesLeft -= lToWrite;\r
+\r
+                                       /* ulNextTxSequenceNumber is the sequence number of the next byte to\r
+                                       be stored for transmission. */\r
+                                       pxWindow->ulNextTxSequenceNumber += ( uint32_t ) lToWrite;\r
+\r
+                                       /* Increased the return value. */\r
+                                       lDone += lToWrite;\r
+\r
+                                       /* Some detailed logging, for those who're interested. */\r
+                                       if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != 0 ) )\r
+                                       {\r
+                                               FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: Add %4lu bytes for seqNr %lu len %4lu (nxt %lu) pos %lu\n",\r
+                                                       ulLength,\r
+                                                       pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                                       pxSegment->lDataLength,\r
+                                                       pxWindow->ulNextTxSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                                       pxSegment->lStreamPos ) );\r
+                                               FreeRTOS_flush_logging( );\r
+                                       }\r
+\r
+                                       /* Calculate the next position in the circular data buffer, knowing\r
+                                       its maximum length 'lMax'. */\r
+                                       lPosition = lTCPIncrementTxPosition( lPosition, lMax, lToWrite );\r
+                               }\r
+                       }\r
+               }\r
+\r
+               while( lBytesLeft > 0 )\r
+               {\r
+                       /* The current transmission segment is full, create new segments as\r
+                       needed. */\r
+                       pxSegment = xTCPWindowTxNew( pxWindow, pxWindow->ulNextTxSequenceNumber, pxWindow->usMSS );\r
+\r
+                       if( pxSegment != NULL )\r
+                       {\r
+                               /* Store as many as needed, but no more than the maximum\r
+                               (MSS). */\r
+                               lToWrite = FreeRTOS_min_int32( lBytesLeft, pxSegment->lMaxLength );\r
+\r
+                               pxSegment->lDataLength = lToWrite;\r
+                               pxSegment->lStreamPos = lPosition;\r
+                               lBytesLeft -= lToWrite;\r
+                               lPosition = lTCPIncrementTxPosition( lPosition, lMax, lToWrite );\r
+                               pxWindow->ulNextTxSequenceNumber += ( uint32_t ) lToWrite;\r
+                               lDone += lToWrite;\r
+\r
+                               /* Link this segment in the Tx-Queue. */\r
+                               vListInsertFifo( &( pxWindow->xTxQueue ), &( pxSegment->xQueueItem ) );\r
+\r
+                               /* Let 'pxHeadSegment' point to this segment if there is still\r
+                               space. */\r
+                               if( pxSegment->lDataLength < pxSegment->lMaxLength )\r
+                               {\r
+                                       pxWindow->pxHeadSegment = pxSegment;\r
+                               }\r
+                               else\r
+                               {\r
+                                       pxWindow->pxHeadSegment = NULL;\r
+                               }\r
+\r
+                               if( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != 0 )\r
+                               {\r
+                                       if( ( xTCPWindowLoggingLevel >= 3 ) ||\r
+                                               ( ( xTCPWindowLoggingLevel >= 2 ) && ( pxWindow->pxHeadSegment != NULL ) ) )\r
+                                       {\r
+                                               FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: New %4ld bytes for seqNr %lu len %4lu (nxt %lu) pos %lu\n",\r
+                                                       ulLength,\r
+                                                       pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                                       pxSegment->lDataLength,\r
+                                                       pxWindow->ulNextTxSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                                       pxSegment->lStreamPos ) );\r
+                                               FreeRTOS_flush_logging( );\r
+                                       }\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               /* A sever situation: running out of segments for transmission.\r
+                               No more data can be sent at the moment. */\r
+                               if( lDone != 0 )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: Sorry all buffers full (cancel %ld bytes)\n", lBytesLeft ) );\r
+                               }\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               return lDone;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       BaseType_t xTCPWindowTxDone( TCPWindow_t *pxWindow )\r
+       {\r
+               return listLIST_IS_EMPTY( ( &pxWindow->xTxSegments) );\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize )\r
+       {\r
+       uint32_t ulTxOutstanding;\r
+       BaseType_t xHasSpace;\r
+       TCPSegment_t *pxSegment;\r
+\r
+               /* This function will look if there is new transmission data.  It will\r
+               return true if there is data to be sent. */\r
+\r
+               pxSegment = xTCPWindowPeekHead( &( pxWindow->xTxQueue ) );\r
+\r
+               if( pxSegment == NULL )\r
+               {\r
+                       xHasSpace = pdFALSE;\r
+               }\r
+               else\r
+               {\r
+                       /* How much data is outstanding, i.e. how much data has been sent\r
+                       but not yet acknowledged ? */\r
+                       if( pxWindow->tx.ulHighestSequenceNumber >= pxWindow->tx.ulCurrentSequenceNumber )\r
+                       {\r
+                               ulTxOutstanding = pxWindow->tx.ulHighestSequenceNumber - pxWindow->tx.ulCurrentSequenceNumber;\r
+                       }\r
+                       else\r
+                       {\r
+                               ulTxOutstanding = 0UL;\r
+                       }\r
+\r
+                       /* Subtract this from the peer's space. */\r
+                       ulWindowSize -= FreeRTOS_min_uint32( ulWindowSize, ulTxOutstanding );\r
+\r
+                       /* See if the next segment may be sent. */\r
+                       if( ulWindowSize >= ( uint32_t ) pxSegment->lDataLength )\r
+                       {\r
+                               xHasSpace = pdTRUE;\r
+                       }\r
+                       else\r
+                       {\r
+                               xHasSpace = pdFALSE;\r
+                       }\r
+\r
+                       /* If 'xHasSpace', it looks like the peer has at least space for 1\r
+                       more new segment of size MSS.  xSize.ulTxWindowLength is the self-imposed\r
+                       limitation of the transmission window (in case of many resends it\r
+                       may be decreased). */\r
+                       if( ( ulTxOutstanding != 0UL ) && ( pxWindow->xSize.ulTxWindowLength < ulTxOutstanding + ( ( uint32_t ) pxSegment->lDataLength ) ) )\r
+                       {\r
+                               xHasSpace = pdFALSE;\r
+                       }\r
+               }\r
+\r
+               return xHasSpace;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       BaseType_t xTCPWindowTxHasData( TCPWindow_t *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay )\r
+       {\r
+       TCPSegment_t *pxSegment;\r
+       BaseType_t xReturn;\r
+       TickType_t ulAge, ulMaxAge;\r
+\r
+               *pulDelay = 0u;\r
+\r
+               if( listLIST_IS_EMPTY( &pxWindow->xPriorityQueue ) == pdFALSE )\r
+               {\r
+                       /* No need to look at retransmissions or new transmission as long as\r
+                       there are priority segments.  *pulDelay equals zero, meaning it must\r
+                       be sent out immediately. */\r
+                       xReturn = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       pxSegment = xTCPWindowPeekHead( &( pxWindow->xWaitQueue ) );\r
+\r
+                       if( pxSegment != NULL )\r
+                       {\r
+                               /* There is an outstanding segment, see if it is time to resend\r
+                               it. */\r
+                               ulAge = ulTimerGetAge( &pxSegment->xTransmitTimer );\r
+\r
+                               /* After a packet has been sent for the first time, it will wait\r
+                               '1 * lSRTT' ms for an ACK. A second time it will wait '2 * lSRTT' ms,\r
+                               each time doubling the time-out */\r
+                               ulMaxAge = ( 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );\r
+\r
+                               if( ulMaxAge > ulAge )\r
+                               {\r
+                                       /* A segment must be sent after this amount of msecs */\r
+                                       *pulDelay = ulMaxAge - ulAge;\r
+                               }\r
+\r
+                               xReturn = pdTRUE;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* No priority segment, no outstanding data, see if there is new\r
+                               transmission data. */\r
+                               pxSegment = xTCPWindowPeekHead( &pxWindow->xTxQueue );\r
+\r
+                               /* See if it fits in the peer's reception window. */\r
+                               if( pxSegment == NULL )\r
+                               {\r
+                                       xReturn = pdFALSE;\r
+                               }\r
+                               else if( prvTCPWindowTxHasSpace( pxWindow, ulWindowSize ) == pdFALSE )\r
+                               {\r
+                                       /* Too many outstanding messages. */\r
+                                       xReturn = pdFALSE;\r
+                               }\r
+                               else if( ( pxWindow->u.bits.bSendFullSize != pdFALSE_UNSIGNED ) && ( pxSegment->lDataLength < pxSegment->lMaxLength ) )\r
+                               {\r
+                                       /* 'bSendFullSize' is a special optimisation.  If true, the\r
+                                       driver will only sent completely filled packets (of MSS\r
+                                       bytes). */\r
+                                       xReturn = pdFALSE;\r
+                               }\r
+                               else\r
+                               {\r
+                                       xReturn = pdTRUE;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       uint32_t ulTCPWindowTxGet( TCPWindow_t *pxWindow, uint32_t ulWindowSize, int32_t *plPosition )\r
+       {\r
+       TCPSegment_t *pxSegment;\r
+       uint32_t ulMaxTime;\r
+       uint32_t ulReturn  = ~0UL;\r
+\r
+\r
+               /* Fetches data to be sent-out now.\r
+\r
+               Priority messages: segments with a resend need no check current sliding\r
+               window size. */\r
+               pxSegment = xTCPWindowGetHead( &( pxWindow->xPriorityQueue ) );\r
+               pxWindow->ulOurSequenceNumber = pxWindow->tx.ulHighestSequenceNumber;\r
+\r
+               if( pxSegment == NULL )\r
+               {\r
+                       /* Waiting messages: outstanding messages with a running timer\r
+                       neither check peer's reception window size because these packets\r
+                       have been sent earlier. */\r
+                       pxSegment = xTCPWindowPeekHead( &( pxWindow->xWaitQueue ) );\r
+\r
+                       if( pxSegment != NULL )\r
+                       {\r
+                               /* Do check the timing. */\r
+                               ulMaxTime = ( 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );\r
+\r
+                               if( ulTimerGetAge( &pxSegment->xTransmitTimer ) > ulMaxTime )\r
+                               {\r
+                                       /* A normal (non-fast) retransmission.  Move it from the\r
+                                       head of the waiting queue. */\r
+                                       pxSegment = xTCPWindowGetHead( &( pxWindow->xWaitQueue ) );\r
+                                       pxSegment->u.bits.ucDupAckCount = pdFALSE_UNSIGNED;\r
+\r
+                                       /* Some detailed logging. */\r
+                                       if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != 0 ) )\r
+                                       {\r
+                                               FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: WaitQueue %ld bytes for sequence number %lu (%lX)\n",\r
+                                                       pxWindow->usPeerPortNumber,\r
+                                                       pxWindow->usOurPortNumber,\r
+                                                       pxSegment->lDataLength,\r
+                                                       pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                                       pxSegment->ulSequenceNumber ) );\r
+                                               FreeRTOS_flush_logging( );\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       pxSegment = NULL;\r
+                               }\r
+                       }\r
+\r
+                       if( pxSegment == NULL )\r
+                       {\r
+                               /* New messages: sent-out for the first time.  Check current\r
+                               sliding window size of peer. */\r
+                               pxSegment = xTCPWindowPeekHead( &( pxWindow->xTxQueue ) );\r
+\r
+                               if( pxSegment == NULL )\r
+                               {\r
+                                       /* No segments queued. */\r
+                                       ulReturn = 0UL;\r
+                               }\r
+                               else if( ( pxWindow->u.bits.bSendFullSize != pdFALSE_UNSIGNED ) && ( pxSegment->lDataLength < pxSegment->lMaxLength ) )\r
+                               {\r
+                                       /* A segment has been queued but the driver waits until it\r
+                                       has a full size of MSS. */\r
+                                       ulReturn = 0;\r
+                               }\r
+                               else if( prvTCPWindowTxHasSpace( pxWindow, ulWindowSize ) == pdFALSE )\r
+                               {\r
+                                       /* Peer has no more space at this moment. */\r
+                                       ulReturn = 0;\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Move it out of the Tx queue. */\r
+                                       pxSegment = xTCPWindowGetHead( &( pxWindow->xTxQueue ) );\r
+\r
+                                       /* Don't let pxHeadSegment point to this segment any more,\r
+                                       so no more data will be added. */\r
+                                       if( pxWindow->pxHeadSegment == pxSegment )\r
+                                       {\r
+                                               pxWindow->pxHeadSegment = NULL;\r
+                                       }\r
+\r
+                                       /* pxWindow->tx.highest registers the highest sequence\r
+                                       number in our transmission window. */\r
+                                       pxWindow->tx.ulHighestSequenceNumber = pxSegment->ulSequenceNumber + ( ( uint32_t ) pxSegment->lDataLength );\r
+\r
+                                       /* ...and more detailed logging */\r
+                                       if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )\r
+                                       {\r
+                                               FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: XmitQueue %ld bytes for sequence number %lu (ws %lu)\n",\r
+                                                       pxWindow->usPeerPortNumber,\r
+                                                       pxWindow->usOurPortNumber,\r
+                                                       pxSegment->lDataLength,\r
+                                                       pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                                       ulWindowSize ) );\r
+                                               FreeRTOS_flush_logging( );\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* There is a priority segment. It doesn't need any checking for\r
+                       space or timeouts. */\r
+                       if( xTCPWindowLoggingLevel != 0 )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u,%u]: PrioQueue %ld bytes for sequence number %lu (ws %lu)\n",\r
+                                       pxWindow->usPeerPortNumber,\r
+                                       pxWindow->usOurPortNumber,\r
+                                       pxSegment->lDataLength,\r
+                                       pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                       ulWindowSize ) );\r
+                               FreeRTOS_flush_logging( );\r
+                       }\r
+               }\r
+\r
+               /* See if it has already been determined to return 0. */\r
+               if( ulReturn != 0UL )\r
+               {\r
+                       configASSERT( listLIST_ITEM_CONTAINER( &(pxSegment->xQueueItem ) ) == NULL );\r
+\r
+                       /* Now that the segment will be transmitted, add it to the tail of\r
+                       the waiting queue. */\r
+                       vListInsertFifo( &pxWindow->xWaitQueue, &pxSegment->xQueueItem );\r
+\r
+                       /* And mark it as outstanding. */\r
+                       pxSegment->u.bits.bOutstanding = pdTRUE_UNSIGNED;\r
+\r
+                       /* Administer the transmit count, needed for fast\r
+                       retransmissions. */\r
+                       ( pxSegment->u.bits.ucTransmitCount )++;\r
+\r
+                       /* If there have been several retransmissions (4), decrease the\r
+                       size of the transmission window to at most 2 times MSS. */\r
+                       if( pxSegment->u.bits.ucTransmitCount == MAX_TRANSMIT_COUNT_USING_LARGE_WINDOW )\r
+                       {\r
+                               if( pxWindow->xSize.ulTxWindowLength > ( 2U * pxWindow->usMSS ) )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "ulTCPWindowTxGet[%u - %d]: Change Tx window: %lu -> %u\n",\r
+                                               pxWindow->usPeerPortNumber, pxWindow->usOurPortNumber,\r
+                                               pxWindow->xSize.ulTxWindowLength, 2 * pxWindow->usMSS ) );\r
+                                       pxWindow->xSize.ulTxWindowLength = ( 2UL * pxWindow->usMSS );\r
+                               }\r
+                       }\r
+\r
+                       /* Clear the transmit timer. */\r
+                       vTCPTimerSet( &( pxSegment->xTransmitTimer ) );\r
+\r
+                       pxWindow->ulOurSequenceNumber = pxSegment->ulSequenceNumber;\r
+\r
+                       /* Inform the caller where to find the data within the queue. */\r
+                       *plPosition = pxSegment->lStreamPos;\r
+\r
+                       /* And return the length of the data segment */\r
+                       ulReturn = ( uint32_t ) pxSegment->lDataLength;\r
+               }\r
+\r
+               return ulReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       static uint32_t prvTCPWindowTxCheckAck( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast )\r
+       {\r
+       uint32_t ulBytesConfirmed = 0u;\r
+       uint32_t ulSequenceNumber = ulFirst, ulDataLength;\r
+       const ListItem_t *pxIterator;\r
+       const MiniListItem_t *pxEnd = ( const MiniListItem_t* )listGET_END_MARKER( &pxWindow->xTxSegments );\r
+       BaseType_t xDoUnlink;\r
+       TCPSegment_t *pxSegment;\r
+               /* An acknowledgement or a selective ACK (SACK) was received.  See if some outstanding data\r
+               may be removed from the transmission queue(s).\r
+               All TX segments for which\r
+               ( ( ulSequenceNumber >= ulFirst ) && ( ulSequenceNumber < ulLast ) in a\r
+               contiguous block.  Note that the segments are stored in xTxSegments in a\r
+               strict sequential order. */\r
+\r
+               /* SRTT[i] = (1-a) * SRTT[i-1] + a * RTT\r
+\r
+               0 < a < 1; usually a = 1/8\r
+\r
+               RTO = 2 * SRTT\r
+\r
+               where:\r
+                 RTT is Round Trip Time\r
+                 SRTT is Smoothed RTT\r
+                 RTO is Retransmit timeout\r
+\r
+                A Smoothed RTT will increase quickly, but it is conservative when\r
+                becoming smaller. */\r
+\r
+               for(\r
+                               pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );\r
+                               ( pxIterator != ( const ListItem_t * ) pxEnd ) && ( xSequenceLessThan( ulSequenceNumber, ulLast ) != 0 );\r
+                       )\r
+               {\r
+                       xDoUnlink = pdFALSE;\r
+                       pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
+\r
+                       /* Move to the next item because the current item might get\r
+                       removed. */\r
+                       pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator );\r
+\r
+                       /* Continue if this segment does not fall within the ACK'd range. */\r
+                       if( xSequenceGreaterThan( ulSequenceNumber, pxSegment->ulSequenceNumber ) != pdFALSE )\r
+                       {\r
+                               continue;\r
+                       }\r
+\r
+                       /* Is it ready? */\r
+                       if( ulSequenceNumber != pxSegment->ulSequenceNumber )\r
+                       {\r
+                               break;\r
+                       }\r
+\r
+                       ulDataLength = ( uint32_t ) pxSegment->lDataLength;\r
+\r
+                       if( pxSegment->u.bits.bAcked == pdFALSE_UNSIGNED )\r
+                       {\r
+                               if( xSequenceGreaterThan( pxSegment->ulSequenceNumber + ( uint32_t )ulDataLength, ulLast ) != pdFALSE )\r
+                               {\r
+                                       /* What happens?  Only part of this segment was accepted,\r
+                                       probably due to WND limits\r
+\r
+                                         AAAAAAA BBBBBBB << acked\r
+                                         aaaaaaa aaaa    << sent */\r
+                                       #if( ipconfigHAS_DEBUG_PRINTF != 0 )\r
+                                       {\r
+                                               uint32_t ulFirstSeq = pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber;\r
+                                               FreeRTOS_debug_printf( ( "prvTCPWindowTxCheckAck[%u.%u]: %lu - %lu Partial sequence number %lu - %lu\n",\r
+                                                       pxWindow->usPeerPortNumber,\r
+                                                       pxWindow->usOurPortNumber,\r
+                                                       ulFirstSeq - pxWindow->tx.ulFirstSequenceNumber,\r
+                                                       ulLast - pxWindow->tx.ulFirstSequenceNumber,\r
+                                                       ulFirstSeq, ulFirstSeq + ulDataLength ) );\r
+                                       }\r
+                                       #endif /* ipconfigHAS_DEBUG_PRINTF */\r
+                                       break;\r
+                               }\r
+\r
+                               /* This segment is fully ACK'd, set the flag. */\r
+                               pxSegment->u.bits.bAcked = pdTRUE_UNSIGNED;\r
+\r
+                               /* Calculate the RTT only if the segment was sent-out for the\r
+                               first time and if this is the last ACK'd segment in a range. */\r
+                               if( ( pxSegment->u.bits.ucTransmitCount == 1 ) && ( ( pxSegment->ulSequenceNumber + ulDataLength ) == ulLast ) )\r
+                               {\r
+                                       int32_t mS = ( int32_t ) ulTimerGetAge( &( pxSegment->xTransmitTimer ) );\r
+\r
+                                       if( pxWindow->lSRTT >= mS )\r
+                                       {\r
+                                               /* RTT becomes smaller: adapt slowly. */\r
+                                               pxWindow->lSRTT = ( ( winSRTT_DECREMENT_NEW * mS ) + ( winSRTT_DECREMENT_CURRENT * pxWindow->lSRTT ) ) / ( winSRTT_DECREMENT_NEW + winSRTT_DECREMENT_CURRENT );\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               /* RTT becomes larger: adapt quicker */\r
+                                               pxWindow->lSRTT = ( ( winSRTT_INCREMENT_NEW * mS ) + ( winSRTT_INCREMENT_CURRENT * pxWindow->lSRTT ) ) / ( winSRTT_INCREMENT_NEW + winSRTT_INCREMENT_CURRENT );\r
+                                       }\r
+\r
+                                       /* Cap to the minimum of 50ms. */\r
+                                       if( pxWindow->lSRTT < winSRTT_CAP_mS )\r
+                                       {\r
+                                               pxWindow->lSRTT = winSRTT_CAP_mS;\r
+                                       }\r
+                               }\r
+\r
+                               /* Unlink it from the 3 queues, but do not destroy it (yet). */\r
+                               xDoUnlink = pdTRUE;\r
+                       }\r
+\r
+                       /* pxSegment->u.bits.bAcked is now true.  Is it located at the left\r
+                       side of the transmission queue?  If so, it may be freed. */\r
+                       if( ulSequenceNumber == pxWindow->tx.ulCurrentSequenceNumber )\r
+                       {\r
+                               if( ( xTCPWindowLoggingLevel >= 2 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "prvTCPWindowTxCheckAck: %lu - %lu Ready sequence number %lu\n",\r
+                                               ulFirst - pxWindow->tx.ulFirstSequenceNumber,\r
+                                               ulLast - pxWindow->tx.ulFirstSequenceNumber,\r
+                                               pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber ) );\r
+                               }\r
+\r
+                               /* Increase the left-hand value of the transmission window. */\r
+                               pxWindow->tx.ulCurrentSequenceNumber += ulDataLength;\r
+\r
+                               /* This function will return the number of bytes that the tail\r
+                               of txStream may be advanced. */\r
+                               ulBytesConfirmed += ulDataLength;\r
+\r
+                               /* All segments below tx.ulCurrentSequenceNumber may be freed. */\r
+                               vTCPWindowFree( pxSegment );\r
+\r
+                               /* No need to unlink it any more. */\r
+                               xDoUnlink = pdFALSE;\r
+                       }\r
+\r
+                       if( ( xDoUnlink != pdFALSE ) && ( listLIST_ITEM_CONTAINER( &( pxSegment->xQueueItem ) ) != NULL ) )\r
+                       {\r
+                               /* Remove item from its queues. */\r
+                               uxListRemove( &pxSegment->xQueueItem );\r
+                       }\r
+\r
+                       ulSequenceNumber += ulDataLength;\r
+               }\r
+\r
+               return ulBytesConfirmed;\r
+       }\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       static uint32_t prvTCPWindowFastRetransmit( TCPWindow_t *pxWindow, uint32_t ulFirst )\r
+       {\r
+       const ListItem_t *pxIterator;\r
+       const MiniListItem_t* pxEnd;\r
+       TCPSegment_t *pxSegment;\r
+       uint32_t ulCount = 0UL;\r
+\r
+               /* A higher Tx block has been acknowledged.  Now iterate through the\r
+                xWaitQueue to find a possible condition for a FAST retransmission. */\r
+\r
+               pxEnd = ( const MiniListItem_t* ) listGET_END_MARKER( &( pxWindow->xWaitQueue ) );\r
+\r
+               for( pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxEnd );\r
+                        pxIterator != ( const ListItem_t * ) pxEnd; )\r
+               {\r
+                       /* Get the owner, which is a TCP segment. */\r
+                       pxSegment = ( TCPSegment_t * ) listGET_LIST_ITEM_OWNER( pxIterator );\r
+\r
+                       /* Hop to the next item before the current gets unlinked. */\r
+                       pxIterator  = ( const ListItem_t * ) listGET_NEXT( pxIterator );\r
+\r
+                       /* Fast retransmission:\r
+                       When 3 packets with a higher sequence number have been acknowledged\r
+                       by the peer, it is very unlikely a current packet will ever arrive.\r
+                       It will be retransmitted far before the RTO. */\r
+                       if( ( pxSegment->u.bits.bAcked == pdFALSE_UNSIGNED ) &&\r
+                               ( xSequenceLessThan( pxSegment->ulSequenceNumber, ulFirst ) != pdFALSE ) &&\r
+                               ( ++( pxSegment->u.bits.ucDupAckCount ) == DUPLICATE_ACKS_BEFORE_FAST_RETRANSMIT ) )\r
+                       {\r
+                               pxSegment->u.bits.ucTransmitCount = pdFALSE_UNSIGNED;\r
+\r
+                               /* Not clearing 'ucDupAckCount' yet as more SACK's might come in\r
+                               which might lead to a second fast rexmit. */\r
+                               if( ( xTCPWindowLoggingLevel >= 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "prvTCPWindowFastRetransmit: Requeue sequence number %lu < %lu\n",\r
+                                               pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                               ulFirst - pxWindow->tx.ulFirstSequenceNumber ) );\r
+                                       FreeRTOS_flush_logging( );\r
+                               }\r
+\r
+                               /* Remove it from xWaitQueue. */\r
+                               uxListRemove( &pxSegment->xQueueItem );\r
+\r
+                               /* Add this segment to the priority queue so it gets\r
+                               retransmitted immediately. */\r
+                               vListInsertFifo( &( pxWindow->xPriorityQueue ), &( pxSegment->xQueueItem ) );\r
+                               ulCount++;\r
+                       }\r
+               }\r
+\r
+               return ulCount;\r
+       }\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       uint32_t ulTCPWindowTxAck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber )\r
+       {\r
+       uint32_t ulFirstSequence, ulReturn;\r
+\r
+               /* Receive a normal ACK. */\r
+\r
+               ulFirstSequence = pxWindow->tx.ulCurrentSequenceNumber;\r
+\r
+               if( xSequenceLessThanOrEqual( ulSequenceNumber, ulFirstSequence ) != pdFALSE )\r
+               {\r
+                       ulReturn = 0UL;\r
+               }\r
+               else\r
+               {\r
+                       ulReturn = prvTCPWindowTxCheckAck( pxWindow, ulFirstSequence, ulSequenceNumber );\r
+               }\r
+\r
+               return ulReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+\r
+       uint32_t ulTCPWindowTxSack( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast )\r
+       {\r
+       uint32_t ulAckCount = 0UL;\r
+       uint32_t ulCurrentSequenceNumber = pxWindow->tx.ulCurrentSequenceNumber;\r
+\r
+               /* Receive a SACK option. */\r
+               ulAckCount = prvTCPWindowTxCheckAck( pxWindow, ulFirst, ulLast );\r
+               prvTCPWindowFastRetransmit( pxWindow, ulFirst );\r
+\r
+               if( ( xTCPWindowLoggingLevel >= 1 ) && ( xSequenceGreaterThan( ulFirst, ulCurrentSequenceNumber ) != pdFALSE ) )\r
+               {\r
+                       FreeRTOS_debug_printf( ( "ulTCPWindowTxSack[%u,%u]: from %lu to %lu (ack = %lu)\n",\r
+                               pxWindow->usPeerPortNumber,\r
+                               pxWindow->usOurPortNumber,\r
+                               ulFirst - pxWindow->tx.ulFirstSequenceNumber,\r
+                               ulLast - pxWindow->tx.ulFirstSequenceNumber,\r
+                               pxWindow->tx.ulCurrentSequenceNumber - pxWindow->tx.ulFirstSequenceNumber ) );\r
+                       FreeRTOS_flush_logging( );\r
+               }\r
+\r
+               return ulAckCount;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 1 */\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+#####   #                      #####   ####  ######\r
+# # #   #                      # # #  #    #  #    #\r
+  #                              #   #     #  #    #\r
+  #   ###   #####  #    #        #   #        #    #\r
+  #     #   #    # #    #        #   #        #####\r
+  #     #   #    # #    # ####   #   #        #\r
+  #     #   #    # #    #        #   #     #  #\r
+  #     #   #    #  ####         #    #    #  #\r
+ #### ##### #    #     #        ####   ####  ####\r
+                      #\r
+                   ###\r
+*/\r
+#if( ipconfigUSE_TCP_WIN == 0 )\r
+\r
+       int32_t lTCPWindowRxCheck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength, uint32_t ulSpace )\r
+       {\r
+       int32_t iReturn;\r
+\r
+               /* Data was received at 'ulSequenceNumber'.  See if it was expected\r
+               and if there is enough space to store the new data. */\r
+               if( ( pxWindow->rx.ulCurrentSequenceNumber != ulSequenceNumber ) || ( ulSpace < ulLength ) )\r
+               {\r
+                       iReturn = -1;\r
+               }\r
+               else\r
+               {\r
+                       pxWindow->rx.ulCurrentSequenceNumber += ( uint32_t ) ulLength;\r
+                       iReturn = 0;\r
+               }\r
+\r
+               return iReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 0 )\r
+\r
+       int32_t lTCPWindowTxAdd( TCPWindow_t *pxWindow, uint32_t ulLength, int32_t lPosition, int32_t lMax )\r
+       {\r
+       TCPSegment_t *pxSegment = &( pxWindow->xTxSegment );\r
+       int32_t lResult;\r
+\r
+               /* Data is being scheduled for transmission. */\r
+\r
+               /* lMax would indicate the size of the txStream. */\r
+               ( void ) lMax;\r
+               /* This is tiny TCP: there is only 1 segment for outgoing data.\r
+               As long as 'lDataLength' is unequal to zero, the segment is still occupied. */\r
+               if( pxSegment->lDataLength > 0 )\r
+               {\r
+                       lResult = 0L;\r
+               }\r
+               else\r
+               {\r
+                       if( ulLength > ( uint32_t ) pxSegment->lMaxLength )\r
+                       {\r
+                               if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: can only store %ld / %ld bytes\n", ulLength, pxSegment->lMaxLength ) );\r
+                               }\r
+\r
+                               ulLength = ( uint32_t ) pxSegment->lMaxLength;\r
+                       }\r
+\r
+                       if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )\r
+                       {\r
+                               FreeRTOS_debug_printf( ( "lTCPWindowTxAdd: SeqNr %ld (%ld) Len %ld\n",\r
+                                       pxWindow->ulNextTxSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                       pxWindow->tx.ulCurrentSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                       ulLength ) );\r
+                       }\r
+\r
+                       /* The sequence number of the first byte in this packet. */\r
+                       pxSegment->ulSequenceNumber = pxWindow->ulNextTxSequenceNumber;\r
+                       pxSegment->lDataLength = ( int32_t ) ulLength;\r
+                       pxSegment->lStreamPos = lPosition;\r
+                       pxSegment->u.ulFlags = 0UL;\r
+                       vTCPTimerSet( &( pxSegment->xTransmitTimer ) );\r
+\r
+                       /* Increase the sequence number of the next data to be stored for\r
+                       transmission. */\r
+                       pxWindow->ulNextTxSequenceNumber += ulLength;\r
+                       lResult = ( int32_t )ulLength;\r
+               }\r
+\r
+               return lResult;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 0 )\r
+\r
+       uint32_t ulTCPWindowTxGet( TCPWindow_t *pxWindow, uint32_t ulWindowSize, int32_t *plPosition )\r
+       {\r
+       TCPSegment_t *pxSegment = &( pxWindow->xTxSegment );\r
+       uint32_t ulLength = ( uint32_t ) pxSegment->lDataLength;\r
+       uint32_t ulMaxTime;\r
+\r
+               if( ulLength != 0UL )\r
+               {\r
+                       /* _HT_ Still under investigation */\r
+                       ( void ) ulWindowSize;\r
+\r
+                       if( pxSegment->u.bits.bOutstanding != pdFALSE_UNSIGNED )\r
+                       {\r
+                               /* As 'ucTransmitCount' has a minimum of 1, take 2 * RTT */\r
+                               ulMaxTime = ( ( uint32_t ) 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );\r
+\r
+                               if( ulTimerGetAge( &( pxSegment->xTransmitTimer ) ) < ulMaxTime )\r
+                               {\r
+                                       ulLength = 0ul;\r
+                               }\r
+                       }\r
+\r
+                       if( ulLength != 0ul )\r
+                       {\r
+                               pxSegment->u.bits.bOutstanding = pdTRUE_UNSIGNED;\r
+                               pxSegment->u.bits.ucTransmitCount++;\r
+                               vTCPTimerSet (&pxSegment->xTransmitTimer);\r
+                               pxWindow->ulOurSequenceNumber = pxSegment->ulSequenceNumber;\r
+                               *plPosition = pxSegment->lStreamPos;\r
+                       }\r
+               }\r
+\r
+               return ulLength;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 0 )\r
+\r
+       BaseType_t xTCPWindowTxDone( TCPWindow_t *pxWindow )\r
+       {\r
+       BaseType_t xReturn;\r
+\r
+               /* Has the outstanding data been sent because user wants to shutdown? */\r
+               if( pxWindow->xTxSegment.lDataLength == 0 )\r
+               {\r
+                       xReturn = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       xReturn = pdFALSE;\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 0 )\r
+\r
+       static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize );\r
+       static BaseType_t prvTCPWindowTxHasSpace( TCPWindow_t *pxWindow, uint32_t ulWindowSize )\r
+       {\r
+       BaseType_t xReturn;\r
+\r
+               if( ulWindowSize >= pxWindow->usMSSInit )\r
+               {\r
+                       xReturn = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       xReturn = pdFALSE;\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 0 )\r
+\r
+       BaseType_t xTCPWindowTxHasData( TCPWindow_t *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay )\r
+       {\r
+       TCPSegment_t *pxSegment = &( pxWindow->xTxSegment );\r
+       BaseType_t xReturn;\r
+       TickType_t ulAge, ulMaxAge;\r
+\r
+               /* Check data to be sent. */\r
+               *pulDelay = ( TickType_t ) 0;\r
+               if( pxSegment->lDataLength == 0 )\r
+               {\r
+                       /* Got nothing to send right now. */\r
+                       xReturn = pdFALSE;\r
+               }\r
+               else\r
+               {\r
+                       if( pxSegment->u.bits.bOutstanding != pdFALSE_UNSIGNED )\r
+                       {\r
+                               ulAge = ulTimerGetAge ( &pxSegment->xTransmitTimer );\r
+                               ulMaxAge = ( ( TickType_t ) 1u << pxSegment->u.bits.ucTransmitCount ) * ( ( uint32_t ) pxWindow->lSRTT );\r
+\r
+                               if( ulMaxAge > ulAge )\r
+                               {\r
+                                       *pulDelay = ulMaxAge - ulAge;\r
+                               }\r
+\r
+                               xReturn = pdTRUE;\r
+                       }\r
+                       else if( prvTCPWindowTxHasSpace( pxWindow, ulWindowSize ) == pdFALSE )\r
+                       {\r
+                               /* Too many outstanding messages. */\r
+                               xReturn = pdFALSE;\r
+                       }\r
+                       else\r
+                       {\r
+                               xReturn = pdTRUE;\r
+                       }\r
+               }\r
+\r
+               return xReturn;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 0 )\r
+\r
+       uint32_t ulTCPWindowTxAck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber )\r
+       {\r
+       TCPSegment_t *pxSegment = &( pxWindow->xTxSegment );\r
+       uint32_t ulDataLength = ( uint32_t ) pxSegment->lDataLength;\r
+\r
+               /* Receive a normal ACK */\r
+\r
+               if( ulDataLength != 0ul )\r
+               {\r
+                       if( ulSequenceNumber < ( pxWindow->tx.ulCurrentSequenceNumber + ulDataLength ) )\r
+                       {\r
+                               if( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "win_tx_ack: acked %ld expc %ld len %ld\n",\r
+                                               ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                               pxWindow->tx.ulCurrentSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                               ulDataLength ) );\r
+                               }\r
+\r
+                               /* Nothing to send right now. */\r
+                               ulDataLength = 0ul;\r
+                       }\r
+                       else\r
+                       {\r
+                               pxWindow->tx.ulCurrentSequenceNumber += ulDataLength;\r
+\r
+                               if( ( xTCPWindowLoggingLevel != 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxWindow->usOurPortNumber ) != pdFALSE ) )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "win_tx_ack: acked seqnr %ld len %ld\n",\r
+                                               ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber,\r
+                                               ulDataLength ) );\r
+                               }\r
+\r
+                               pxSegment->lDataLength = 0;\r
+                       }\r
+               }\r
+\r
+               return ulDataLength;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 0 )\r
+\r
+       BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow )\r
+       {\r
+               /* Return true if 'ulCurrentSequenceNumber >= ulHighestSequenceNumber'\r
+               'ulCurrentSequenceNumber' is the highest sequence number stored,\r
+               'ulHighestSequenceNumber' is the highest sequence number seen. */\r
+               return xSequenceGreaterThanOrEqual( pxWindow->rx.ulCurrentSequenceNumber, pxWindow->rx.ulHighestSequenceNumber );\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_TCP_WIN == 0 )\r
+\r
+       /* Destroy a window (always returns NULL) */\r
+       void vTCPWindowDestroy( TCPWindow_t *pxWindow )\r
+       {\r
+               /* As in tiny TCP there are no shared segments descriptors, there is\r
+               nothing to release. */\r
+               ( void ) pxWindow;\r
+       }\r
+\r
+#endif /* ipconfigUSE_TCP_WIN == 0 */\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_UDP_IP.c
new file mode 100644 (file)
index 0000000..3595bbd
--- /dev/null
@@ -0,0 +1,420 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_ARP.h"\r
+#include "FreeRTOS_DHCP.h"\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+#if( ipconfigUSE_DNS == 1 )\r
+       #include "FreeRTOS_DNS.h"\r
+#endif\r
+\r
+/* The expected IP version and header length coded into the IP header itself. */\r
+#define ipIP_VERSION_AND_HEADER_LENGTH_BYTE ( ( uint8_t ) 0x45 )\r
+\r
+/* Part of the Ethernet and IP headers are always constant when sending an IPv4\r
+UDP packet.  This array defines the constant parts, allowing this part of the\r
+packet to be filled in using a simple memcpy() instead of individual writes. */\r
+UDPPacketHeader_t xDefaultPartUDPPacketHeader =\r
+{\r
+       /* .ucBytes : */\r
+       {\r
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     /* Ethernet source MAC address. */\r
+               0x08, 0x00,                                                     /* Ethernet frame type. */\r
+               ipIP_VERSION_AND_HEADER_LENGTH_BYTE,    /* ucVersionHeaderLength. */\r
+               0x00,                                                                   /* ucDifferentiatedServicesCode. */\r
+               0x00, 0x00,                                                     /* usLength. */\r
+               0x00, 0x00,                                                     /* usIdentification. */\r
+               0x00, 0x00,                                                     /* usFragmentOffset. */\r
+               ipconfigUDP_TIME_TO_LIVE,                               /* ucTimeToLive */\r
+               ipPROTOCOL_UDP,                                                 /* ucProtocol. */\r
+               0x00, 0x00,                                                     /* usHeaderChecksum. */\r
+               0x00, 0x00, 0x00, 0x00                                  /* Source IP address. */\r
+       }\r
+};\r
+/*-----------------------------------------------------------*/\r
+\r
+void vProcessGeneratedUDPPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+UDPPacket_t *pxUDPPacket;\r
+IPHeader_t *pxIPHeader;\r
+eARPLookupResult_t eReturned;\r
+uint32_t ulIPAddress = pxNetworkBuffer->ulIPAddress;\r
+\r
+       /* Map the UDP packet onto the start of the frame. */\r
+       pxUDPPacket = ( UDPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;\r
+\r
+       /* Determine the ARP cache status for the requested IP address. */\r
+       eReturned = eARPGetCacheEntry( &( ulIPAddress ), &( pxUDPPacket->xEthernetHeader.xDestinationAddress ) );\r
+\r
+       if( eReturned != eCantSendPacket )\r
+       {\r
+               if( eReturned == eARPCacheHit )\r
+               {\r
+                       #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )\r
+                               uint8_t ucSocketOptions;\r
+                       #endif\r
+                       iptraceSENDING_UDP_PACKET( pxNetworkBuffer->ulIPAddress );\r
+\r
+                       /* Create short cuts to the data within the packet. */\r
+                       pxIPHeader = &( pxUDPPacket->xIPHeader );\r
+\r
+               #if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )\r
+                       /* Is it possible that the packet is not actually a UDP packet\r
+                       after all, but an ICMP packet. */\r
+                       if( pxNetworkBuffer->usPort != ipPACKET_CONTAINS_ICMP_DATA )\r
+               #endif /* ipconfigSUPPORT_OUTGOING_PINGS */\r
+                       {\r
+                       UDPHeader_t *pxUDPHeader;\r
+\r
+                               pxUDPHeader = &( pxUDPPacket->xUDPHeader );\r
+\r
+                               pxUDPHeader->usDestinationPort = pxNetworkBuffer->usPort;\r
+                               pxUDPHeader->usSourcePort = pxNetworkBuffer->usBoundPort;\r
+                               pxUDPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( UDPHeader_t ) );\r
+                               pxUDPHeader->usLength = FreeRTOS_htons( pxUDPHeader->usLength );\r
+                               pxUDPHeader->usChecksum = 0u;\r
+                       }\r
+\r
+                       /* memcpy() the constant parts of the header information into\r
+                       the     correct location within the packet.  This fills in:\r
+                               xEthernetHeader.xSourceAddress\r
+                               xEthernetHeader.usFrameType\r
+                               xIPHeader.ucVersionHeaderLength\r
+                               xIPHeader.ucDifferentiatedServicesCode\r
+                               xIPHeader.usLength\r
+                               xIPHeader.usIdentification\r
+                               xIPHeader.usFragmentOffset\r
+                               xIPHeader.ucTimeToLive\r
+                               xIPHeader.ucProtocol\r
+                       and\r
+                               xIPHeader.usHeaderChecksum\r
+                       */\r
+\r
+                       /* Save options now, as they will be overwritten by memcpy */\r
+                       #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )\r
+                       {\r
+                               ucSocketOptions = pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ];\r
+                       }\r
+                       #endif\r
+\r
+                       memcpy( ( void *) &( pxUDPPacket->xEthernetHeader.xSourceAddress ), ( void * ) xDefaultPartUDPPacketHeader.ucBytes, sizeof( xDefaultPartUDPPacketHeader ) );\r
+\r
+               #if ipconfigSUPPORT_OUTGOING_PINGS == 1\r
+                       if( pxNetworkBuffer->usPort == ipPACKET_CONTAINS_ICMP_DATA )\r
+                       {\r
+                               pxIPHeader->ucProtocol = ipPROTOCOL_ICMP;\r
+                               pxIPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( IPHeader_t ) );\r
+                       }\r
+                       else\r
+               #endif /* ipconfigSUPPORT_OUTGOING_PINGS */\r
+                       {\r
+                               pxIPHeader->usLength = ( uint16_t ) ( pxNetworkBuffer->xDataLength + sizeof( IPHeader_t ) + sizeof( UDPHeader_t ) );\r
+                       }\r
+\r
+                       /* The total transmit size adds on the Ethernet header. */\r
+                       pxNetworkBuffer->xDataLength = pxIPHeader->usLength + sizeof( EthernetHeader_t );\r
+                       pxIPHeader->usLength = FreeRTOS_htons( pxIPHeader->usLength );\r
+                       pxIPHeader->ulDestinationIPAddress = pxNetworkBuffer->ulIPAddress;\r
+\r
+                       #if( ipconfigUSE_LLMNR == 1 )\r
+                       {\r
+                               /* LLMNR messages are typically used on a LAN and they're\r
+                                * not supposed to cross routers */\r
+                               if( pxNetworkBuffer->ulIPAddress == ipLLMNR_IP_ADDR )\r
+                               {\r
+                                       pxIPHeader->ucTimeToLive = 0x01;\r
+                               }\r
+                       }\r
+                       #endif\r
+\r
+                       #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )\r
+                       {\r
+                               pxIPHeader->usHeaderChecksum = 0u;\r
+                               pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );\r
+                               pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );\r
+\r
+                               if( ( ucSocketOptions & ( uint8_t ) FREERTOS_SO_UDPCKSUM_OUT ) != 0u )\r
+                               {\r
+                                       usGenerateProtocolChecksum( (uint8_t*)pxUDPPacket, pdTRUE );\r
+                               }\r
+                               else\r
+                               {\r
+                                       pxUDPPacket->xUDPHeader.usChecksum = 0u;\r
+                               }\r
+                       }\r
+                       #endif\r
+               }\r
+               else if( eReturned == eARPCacheMiss )\r
+               {\r
+                       /* Add an entry to the ARP table with a null hardware address.\r
+                       This allows the ARP timer to know that an ARP reply is\r
+                       outstanding, and perform retransmissions if necessary. */\r
+                       vARPRefreshCacheEntry( NULL, ulIPAddress );\r
+\r
+                       /* Generate an ARP for the required IP address. */\r
+                       iptracePACKET_DROPPED_TO_GENERATE_ARP( pxNetworkBuffer->ulIPAddress );\r
+                       pxNetworkBuffer->ulIPAddress = ulIPAddress;\r
+                       vARPGenerateRequestPacket( pxNetworkBuffer );\r
+               }\r
+               else\r
+               {\r
+                       /* The lookup indicated that an ARP request has already been\r
+                       sent out for the queried IP address. */\r
+                       eReturned = eCantSendPacket;\r
+               }\r
+       }\r
+\r
+       if( eReturned != eCantSendPacket )\r
+       {\r
+               /* The network driver is responsible for freeing the network buffer\r
+               after the packet has been sent. */\r
+\r
+               #if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
+               {\r
+                       if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
+                       {\r
+                       BaseType_t xIndex;\r
+\r
+                               for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )\r
+                               {\r
+                                       pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;\r
+                               }\r
+                               pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;\r
+                       }\r
+               }\r
+               #endif\r
+\r
+               xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );\r
+       }\r
+       else\r
+       {\r
+               /* The packet can't be sent (DHCP not completed?).  Just drop the\r
+               packet. */\r
+               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer, uint16_t usPort )\r
+{\r
+BaseType_t xReturn = pdPASS;\r
+FreeRTOS_Socket_t *pxSocket;\r
+\r
+UDPPacket_t *pxUDPPacket = (UDPPacket_t *) pxNetworkBuffer->pucEthernetBuffer;\r
+\r
+       pxSocket = pxUDPSocketLookup( usPort );\r
+\r
+       if( pxSocket )\r
+       {\r
+\r
+               /* When refreshing the ARP cache with received UDP packets we must be\r
+               careful;  hundreds of broadcast messages may pass and if we're not\r
+               handling them, no use to fill the ARP cache with those IP addresses. */\r
+               vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );\r
+\r
+               #if( ipconfigUSE_CALLBACKS == 1 )\r
+               {\r
+                       /* Did the owner of this socket register a reception handler ? */\r
+                       if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleReceive ) )\r
+                       {\r
+                               struct freertos_sockaddr xSourceAddress, destinationAddress;\r
+                               void *pcData = ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );\r
+                               FOnUDPReceive_t xHandler = ( FOnUDPReceive_t ) pxSocket->u.xUDP.pxHandleReceive;\r
+                               xSourceAddress.sin_port = pxNetworkBuffer->usPort;\r
+                               xSourceAddress.sin_addr = pxNetworkBuffer->ulIPAddress;\r
+                               destinationAddress.sin_port = usPort;\r
+                               destinationAddress.sin_addr = pxUDPPacket->xIPHeader.ulDestinationIPAddress;\r
+\r
+                               if( xHandler( ( Socket_t * ) pxSocket, ( void* ) pcData, ( size_t ) pxNetworkBuffer->xDataLength,\r
+                                       &xSourceAddress, &destinationAddress ) != pdFALSE )\r
+                               {\r
+                                       xReturn = pdFAIL; /* xHandler has consumed the data, do not add it to .xWaitingPacketsList'. */\r
+                               }\r
+                       }\r
+               }\r
+               #endif /* ipconfigUSE_CALLBACKS */\r
+\r
+               #if( ipconfigUDP_MAX_RX_PACKETS > 0 )\r
+               {\r
+                       if( xReturn == pdPASS )\r
+                       {\r
+                               if ( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) >= pxSocket->u.xUDP.uxMaxPackets )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "xProcessReceivedUDPPacket: buffer full %ld >= %ld port %u\n",\r
+                                               listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ),\r
+                                               pxSocket->u.xUDP.uxMaxPackets, pxSocket->usLocalPort ) );\r
+                                       xReturn = pdFAIL; /* we did not consume or release the buffer */\r
+                               }\r
+                       }\r
+               }\r
+               #endif\r
+\r
+               if( xReturn == pdPASS )\r
+               {\r
+                       vTaskSuspendAll();\r
+                       {\r
+                               if( xReturn == pdPASS )\r
+                               {\r
+                                       taskENTER_CRITICAL();\r
+                                       {\r
+                                               /* Add the network packet to the list of packets to be\r
+                                               processed by the socket. */\r
+                                               vListInsertEnd( &( pxSocket->u.xUDP.xWaitingPacketsList ), &( pxNetworkBuffer->xBufferListItem ) );\r
+                                       }\r
+                                       taskEXIT_CRITICAL();\r
+                               }\r
+                       }\r
+                       xTaskResumeAll();\r
+\r
+                       /* Set the socket's receive event */\r
+                       if( pxSocket->xEventGroup != NULL )\r
+                       {\r
+                               xEventGroupSetBits( pxSocket->xEventGroup, eSOCKET_RECEIVE );\r
+                       }\r
+\r
+                       #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+                       {\r
+                               if( ( pxSocket->pxSocketSet != NULL ) && ( ( pxSocket->xSelectBits & eSELECT_READ ) != 0 ) )\r
+                               {\r
+                                       xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, eSELECT_READ );\r
+                               }\r
+                       }\r
+                       #endif\r
+\r
+                       #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )\r
+                       {\r
+                               if( pxSocket->pxUserSemaphore != NULL )\r
+                               {\r
+                                       xSemaphoreGive( pxSocket->pxUserSemaphore );\r
+                               }\r
+                       }\r
+                       #endif\r
+\r
+                       #if( ipconfigUSE_DHCP == 1 )\r
+                       {\r
+                               if( xIsDHCPSocket( pxSocket ) )\r
+                               {\r
+                                       xSendEventToIPTask( eDHCPEvent );\r
+                               }\r
+                       }\r
+                       #endif\r
+               }\r
+       }\r
+       else\r
+       {\r
+               /* There is no socket listening to the target port, but still it might\r
+               be for this node. */\r
+\r
+               #if( ipconfigUSE_DNS == 1 )\r
+                       /* A DNS reply, check for the source port.  Although the DNS client\r
+                       does open a UDP socket to send a messages, this socket will be\r
+                       closed after a short timeout.  Messages that come late (after the\r
+                       socket is closed) will be treated here. */\r
+                       if( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usSourcePort ) == ipDNS_PORT )\r
+                       {\r
+                               vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );\r
+                               xReturn = ( BaseType_t )ulDNSHandlePacket( pxNetworkBuffer );\r
+                       }\r
+                       else\r
+               #endif\r
+\r
+               #if( ipconfigUSE_LLMNR == 1 )\r
+                       /* A LLMNR request, check for the destination port. */\r
+                       if( ( usPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) ||\r
+                               ( pxUDPPacket->xUDPHeader.usSourcePort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) )\r
+                       {\r
+                               vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );\r
+                               xReturn = ( BaseType_t )ulDNSHandlePacket( pxNetworkBuffer );\r
+                       }\r
+                       else\r
+               #endif /* ipconfigUSE_LLMNR */\r
+\r
+               #if( ipconfigUSE_NBNS == 1 )\r
+                       /* a NetBIOS request, check for the destination port */\r
+                       if( ( usPort == FreeRTOS_ntohs( ipNBNS_PORT ) ) ||\r
+                               ( pxUDPPacket->xUDPHeader.usSourcePort == FreeRTOS_ntohs( ipNBNS_PORT ) ) )\r
+                       {\r
+                               vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );\r
+                               xReturn = ( BaseType_t )ulNBNSHandlePacket( pxNetworkBuffer );\r
+                       }\r
+                       else\r
+               #endif /* ipconfigUSE_NBNS */\r
+               {\r
+                       xReturn = pdFAIL;\r
+               }\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/History.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/History.txt
new file mode 100644 (file)
index 0000000..57125a5
--- /dev/null
@@ -0,0 +1,131 @@
+Changes since the 160112 release\r
+\r
+FTP : now has ipconfigFTP_HAS_USER_PROPERTIES_HOOK\r
+Each user can be assigned a different root directory and different access rights.\r
+Read-only access for FTP is now possible.\r
+\r
+Adapted to comply a bit more to MISRA rules.\r
+The introduction of unsigned true/false, e.g. pdTRUE_UNSIGNED.\r
+\r
+'ipBUFFER_PADDING' now configurable (expert option).\r
+\r
+Added ipconfigFTP_HAS_USER_PROPERTIES_HOOK.\r
+ipconfigHAS_TX_CRC_OFFLOADING\r
+Improve support for read only file systems in the FTP server.\r
+\r
+Depending on priorities: FreeRTOS_accept() could fail if the priority of the application task is higher than the priority of the IP-task. Now with a higher priority FreeRTOS_accept() will still work correctly.\r
+\r
+Depending on the tick rate: A TCP socket could freeze (stop working) when the FreeRTOS tick rate was lower than 1,000 Hz. Now also tested with 100 Hz.\r
+\r
+When "ipconfigZERO_COPY_TX_DRIVER = 0", sometime xNetworkInterfaceOutput() was called to send out a small TCP ACK. The network buffer would refer to space on the TCP socket ("lastPacket"), which was not 8-byte aligned. Repaired: from now on the buffer will have a proper 8-byte alignment.\r
+\r
+"#if __cplusplus" is been replaced with the more proper test "#ifdef __cplusplus".\r
+\r
+\r
+\r
+These are the recent commits:\r
+565 Initial check-in of +TCP/multi\r
+566 LPC18xx : updated and re-tested the TCP and FAT drivers\r
+569 +TCP : protocols: Added an installable application hook: "CheckDrivesHook"\r
+570 +TCP : will now work properly when configTICK_RATE_HZ < 1000\r
+571 +TCP : will now work properly when configTICK_RATE_HZ < 1000\r
+572 +TCP : FreeRTOS_recvfrom now recognises "FREERTOS_MSG_PEEK"\r
+573 +FAT : Zynq : writing may fail if it goes too fast. Introduced pauses but not yet satisfied\r
+\r
+\r
+Changes between 160112 and 160111 releases\r
+\r
+       + Updated the STM32 network driver so checksums are calculated by the\r
+         hardware.\r
+       + Implemented a simple "quit" command in the TCP command console.\r
+\r
+Changes between 150825 and 160111 releases\r
+\r
+       + New device support:  Demo applications and example drivers are provided\r
+         for Atmel SAM4E and ST STM32F4 microcontrollers.\r
+       + Various updates to improve compliance with the FreeRTOS coding standard.\r
+       + Added a command console example that uses TCP/IP for input and output (the\r
+         pre-existing command console example uses UDP/IP).\r
+       + Updated the UDP logging example so it will send log messages to the local\r
+         UDP broadcast address if a specific IP address is not provided.  This\r
+         simplifies configuration, but note not all switches and routers will pass\r
+         broadcast messages.\r
+       + Add TCP echo client and TCP echo server examples to the Zynq demo.\r
+       + Minor updates to the Zynq network driver.\r
+       + Update the Zynq project to use version 2015.4 of the Xilinx SDK.\r
+       + Introduce FreeRTOS_SignalSocket(), which can be used to interrupt a task\r
+         that is blocked while reading from a socket ( FreeRTOS_recv[from] ).\r
+       + Make use of FreeRTOS_SignalSocket() in the FTP and HTTP servers.\r
+       + Major updates to the NTP client, although this is not included in any of\r
+         the pre-configured demo applications yet.\r
+       + Added support for DHCP zero pad option.\r
+       + Added uxGetMinimumIPQueueSpace(), a function to monitor the minimum amount\r
+         of space on the message queue.\r
+       + Better handling of zero length files in the FTP server.\r
+       + Fixed a bug reported by Andrey Ivanov from swissEmbedded that affects\r
+         users of 'ipconfigZERO_COPY_TX_DRIVER'.\r
+\r
+\r
+Changes between 150825 150825 (?)\r
+\r
+       + Added xApplicationDHCPUserHook() so a user defined hook will be\r
+         called at certain points in the DHCP process if\r
+         ipconfigDHCP_USES_USER_HOOK is set to 1.\r
+       + Added FreeRTOS_get_tx_head() to improve TCP zero copy behaviour - for\r
+         expert use only.\r
+       + RST is no longer sent if only the ACK flag is set.\r
+       + Previously, an immediate ACK was only sent when buffer space was\r
+         exhausted.  Now, to improve performance, it is possible to send an\r
+         immediate ACK earlier - dependent on the ipconfigTCP_ACK_EARLIER_PACKET\r
+         setting.\r
+       + LLMNR and NBNS requests can now be sent to locate other devices -\r
+         previously these protocols would only be replied to, not generated.\r
+       + Added Auto-IP functionality (still in test) in case DHCP fails.  Dependent\r
+         on the ipconfigDHCP_FALL_BACK_LINK_LAYER_ADDRESS and\r
+         ipconfigARP_USE_CLASH_DETECTION settings.\r
+       + Added NTP code and demo.\r
+       + FTP can now STOR and RETR zero-length files.\r
+       + Added LLMNR demo to Win32 demo - so now the Win32 responds to\r
+         "ping RTOSDemo".\r
+\r
+Changes between 141019 and 150825\r
+\r
+       + Added FTP server, which uses the new FreeRTOS+FAT component.\r
+       + Added basic HTTP server, which uses the new FreeRTOS+FAT component.\r
+       + Multiple definitions that are now common with FreeRTOS+FAT have been moved\r
+         into FreeRTOS's ProjDefs.h header file, and so prefixed with 'pd'.\r
+       + Introduced ipconfigZERO_COPY_TX_DRIVER, which defines who is responsible\r
+         for freeing a buffer sent to to the MAC driver for transmission, and\r
+         facilitates the development of zero copy drivers.\r
+       + Introduced the FREERTOS_MSG_DONTWAIT flag.  The flag can be used as a\r
+         simpler and faster alternative to using FreeRTOS_setsockopt() to set the\r
+         send or receive timeout to 0.\r
+       + A few functions that were previously all lower case are now mixed case, as\r
+         lower case function names are only used when they are equivalent to a\r
+         a Berkeley sockets API function of the same name.\r
+       + Introduced uxGetMinimumFreeNetworkBuffers() to return the minimum number\r
+         of network buffers that have ever existed since the application started\r
+         executing.\r
+       + Introduce ipconfigETHERNET_MINIMUM_PACKET_BYTES to allow the application\r
+         writer to set their own minimum buffer size should the hardware not be\r
+         capable of padding under-sized Ethernet frames.\r
+       + vNetworkBufferRelease() renamed vReleaseNetworkBuffer() - just for\r
+         consistency with the names of other functions in the same file.\r
+       + Grouped DHCP status data into a structure.\r
+       + DHCP is now tried both with and without the broadcast flag.\r
+       + Replaced occurrences of configASSERT_VOID() with configASSERT().\r
+       + ipconfigDNS_USE_CALLBACKS introduced to allow FreeRTOS_gethostbyname() to\r
+         be used without blocking.\r
+       + Fix: LLMNR and NBNS behaviour when the reply is in a larger buffer than the\r
+         request, and BufferAllocation_2 was used.\r
+       + Introduced ipMAX_IP_TASK_SLEEP_TIME to allow the application writer to\r
+         override the default value of 10 seconds.\r
+       + Fix:  Correct error in *pxUDPPayloadBuffer_to_NetworkBuffer().\r
+       + FreeRTOS_recv() now recognises the FREERTOS_ZERO_COPY flag, which, when\r
+         set, the void *pvBuffer parameter is interpreted as void **pvBuffer.\r
+       + FreeRTOS_listen() now returns an error code.  Previously it always\r
+         returned 0.\r
+       + Fix:  Previously if a listening socket was reused, and a connection\r
+         failed, the TCP/IP stack closed the socket, now the socket is correctly\r
+         left unclosed as it is owned by the application.\r
+       + Various other formatting and minor fix alterations.
\ No newline at end of file
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/ReadMe.url b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/ReadMe.url
new file mode 100644 (file)
index 0000000..8a8017f
--- /dev/null
@@ -0,0 +1,5 @@
+[{000214A0-0000-0000-C000-000000000046}]\r
+Prop3=19,2\r
+[InternetShortcut]\r
+URL=http://www.freertos.org/tcp\r
+IDList=\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOSIPConfigDefaults.h
new file mode 100644 (file)
index 0000000..79af074
--- /dev/null
@@ -0,0 +1,577 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef FREERTOS_DEFAULT_IP_CONFIG_H\r
+#define FREERTOS_DEFAULT_IP_CONFIG_H\r
+\r
+/* The error numbers defined in this file will be moved to the core FreeRTOS\r
+code in future versions of FreeRTOS - at which time the following header file\r
+will be removed. */\r
+#include "FreeRTOS_errno_TCP.h"\r
+\r
+/* This file provides default values for configuration options that are missing\r
+from the FreeRTOSIPConfig.h configuration header file. */\r
+\r
+\r
+/* Ensure defined configuration constants are using the most up to date naming. */\r
+#ifdef tcpconfigIP_TIME_TO_LIVE\r
+       #error now called: ipconfigTCP_TIME_TO_LIVE\r
+#endif\r
+\r
+#ifdef updconfigIP_TIME_TO_LIVE\r
+       #error now called: ipconfigUDP_TIME_TO_LIVE\r
+#endif\r
+\r
+#ifdef ipFILLER_SIZE\r
+       #error now called: ipconfigPACKET_FILLER_SIZE\r
+#endif\r
+\r
+#ifdef dnsMAX_REQUEST_ATTEMPTS\r
+       #error now called: ipconfigDNS_REQUEST_ATTEMPTS\r
+#endif\r
+\r
+#ifdef ipconfigUDP_TASK_PRIORITY\r
+       #error now called: ipconfigIP_TASK_PRIORITY\r
+#endif\r
+\r
+#ifdef ipconfigUDP_TASK_STACK_SIZE_WORDS\r
+       #error now called: ipconfigIP_TASK_STACK_SIZE_WORDS\r
+#endif\r
+\r
+#ifdef ipconfigDRIVER_INCLUDED_RX_IP_FILTERING\r
+       #error now called: ipconfigETHERNET_DRIVER_FILTERS_PACKETS\r
+#endif\r
+\r
+#ifdef ipconfigMAX_SEND_BLOCK_TIME_TICKS\r
+       #error now called: ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS\r
+#endif\r
+\r
+#ifdef ipconfigUSE_RECEIVE_CONNECT_CALLBACKS\r
+       #error now called: ipconfigUSE_CALLBACKS\r
+#endif\r
+\r
+#ifdef ipconfigNUM_NETWORK_BUFFERS\r
+       #error now called: ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS\r
+#endif\r
+\r
+#ifdef ipconfigTCP_HANG_PROT\r
+       #error now called: ipconfigTCP_HANG_PROTECTION\r
+#endif\r
+\r
+#ifdef ipconfigTCP_HANG_PROT_TIME\r
+       #error now called: ipconfigTCP_HANG_PROTECTION_TIME\r
+#endif\r
+\r
+#ifdef FreeRTOS_lprintf\r
+       #error now called: FreeRTOS_debug_printf\r
+#endif\r
+\r
+#if ( ipconfigEVENT_QUEUE_LENGTH < ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 ) )\r
+       #error The ipconfigEVENT_QUEUE_LENGTH parameter must be at least ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5\r
+#endif\r
+\r
+#if ( ipconfigNETWORK_MTU < 46 )\r
+       #error ipconfigNETWORK_MTU must be at least 46.\r
+#endif\r
+\r
+#ifdef ipconfigBUFFER_ALLOC_FIXED_SIZE\r
+       #error ipconfigBUFFER_ALLOC_FIXED_SIZE was dropped and replaced by a const value, declared in BufferAllocation[12].c\r
+#endif\r
+\r
+#ifdef ipconfigNIC_SEND_PASSES_DMA\r
+       #error now called: ipconfigZERO_COPY_TX_DRIVER\r
+#endif\r
+\r
+#ifdef HAS_TX_CRC_OFFLOADING\r
+       /* _HT_ As these macro names have changed, throw an error\r
+       if they're still defined. */\r
+       #error now called: ipconfigHAS_TX_CRC_OFFLOADING\r
+#endif\r
+\r
+#ifdef HAS_RX_CRC_OFFLOADING\r
+       #error now called: ipconfigHAS_RX_CRC_OFFLOADING\r
+#endif\r
+\r
+#ifdef ipconfigTCP_RX_BUF_LEN\r
+       #error ipconfigTCP_RX_BUF_LEN is now called ipconfigTCP_RX_BUFFER_LENGTH\r
+#endif\r
+\r
+#ifdef ipconfigTCP_TX_BUF_LEN\r
+       #error ipconfigTCP_TX_BUF_LEN is now called ipconfigTCP_TX_BUFFER_LENGTH\r
+#endif\r
+\r
+#ifdef ipconfigDHCP_USES_USER_HOOK\r
+       #error ipconfigDHCP_USES_USER_HOOK and its associated callback have been superceeded - see http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html#ipconfigUSE_DHCP_HOOK\r
+#endif\r
+\r
+#ifndef ipconfigUSE_TCP\r
+       #define ipconfigUSE_TCP                                         ( 1 )\r
+#endif\r
+\r
+#if    ipconfigUSE_TCP\r
+\r
+       /* Include support for TCP scaling windows */\r
+       #ifndef ipconfigUSE_TCP_WIN\r
+               #define ipconfigUSE_TCP_WIN                             ( 1 )\r
+       #endif\r
+\r
+       #ifndef ipconfigTCP_WIN_SEG_COUNT\r
+               #define ipconfigTCP_WIN_SEG_COUNT               ( 256 )\r
+       #endif\r
+\r
+       #ifndef ipconfigIGNORE_UNKNOWN_PACKETS\r
+               /* When non-zero, TCP will not send RST packets in reply to\r
+               TCP packets which are unknown, or out-of-order. */\r
+               #define ipconfigIGNORE_UNKNOWN_PACKETS  ( 0 )\r
+       #endif\r
+#endif\r
+\r
+/*\r
+ * For debuging/logging: check if the port number is used for telnet\r
+ * Some events will not be logged for telnet connections\r
+ * because it would produce logging about the transmission of the logging...\r
+ * This macro will only be used if FreeRTOS_debug_printf() is defined for logging\r
+ */\r
+#ifndef ipconfigTCP_MAY_LOG_PORT\r
+       #define ipconfigTCP_MAY_LOG_PORT(xPort)                 ( ( xPort ) != 23u )\r
+#endif\r
+\r
+\r
+#ifndef        ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME\r
+       #define ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME portMAX_DELAY\r
+#endif\r
+\r
+#ifndef        ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME\r
+       #define ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME    portMAX_DELAY\r
+#endif\r
+\r
+/*\r
+ * FreeRTOS debug logging routine (proposal)\r
+ * The macro will be called in the printf() style. Users can define\r
+ * their own logging routine as:\r
+ *\r
+ *     #define FreeRTOS_debug_printf( MSG )                    my_printf MSG\r
+ *\r
+ * The FreeRTOS_debug_printf() must be thread-safe but does not have to be\r
+ * interrupt-safe.\r
+ */\r
+#ifdef ipconfigHAS_DEBUG_PRINTF\r
+       #if( ipconfigHAS_DEBUG_PRINTF == 0 )\r
+               #ifdef FreeRTOS_debug_printf\r
+                       #error Do not define FreeRTOS_debug_print if ipconfigHAS_DEBUG_PRINTF is set to 0\r
+               #endif /* ifdef FreeRTOS_debug_printf */\r
+       #endif /* ( ipconfigHAS_DEBUG_PRINTF == 0 ) */\r
+#endif /* ifdef ipconfigHAS_DEBUG_PRINTF */\r
+\r
+#ifndef FreeRTOS_debug_printf\r
+    #define FreeRTOS_debug_printf( MSG )               do{} while(0)\r
+       #define ipconfigHAS_DEBUG_PRINTF                        0\r
+#endif\r
+\r
+/*\r
+ * FreeRTOS general logging routine (proposal)\r
+ * Used in some utility functions such as FreeRTOS_netstat() and FreeRTOS_PrintARPCache()\r
+ *\r
+ *     #define FreeRTOS_printf( MSG )                  my_printf MSG\r
+ *\r
+ * The FreeRTOS_printf() must be thread-safe but does not have to be interrupt-safe\r
+ */\r
+#ifdef ipconfigHAS_PRINTF\r
+       #if( ipconfigHAS_PRINTF == 0 )\r
+               #ifdef FreeRTOS_printf\r
+                       #error Do not define FreeRTOS_print if ipconfigHAS_PRINTF is set to 0\r
+               #endif /* ifdef FreeRTOS_debug_printf */\r
+       #endif /* ( ipconfigHAS_PRINTF == 0 ) */\r
+#endif /* ifdef ipconfigHAS_PRINTF */\r
+\r
+#ifndef FreeRTOS_printf\r
+    #define FreeRTOS_printf( MSG )                             do{} while(0)\r
+       #define ipconfigHAS_PRINTF                                      0\r
+#endif\r
+\r
+/*\r
+ * In cases where a lot of logging is produced, FreeRTOS_flush_logging( )\r
+ * will be called to give the logging module a chance to flush the data\r
+ * An example of this is the netstat command, which produces many lines of logging\r
+ */\r
+#ifndef FreeRTOS_flush_logging\r
+    #define FreeRTOS_flush_logging( )                  do{} while(0)\r
+#endif\r
+\r
+/* Malloc functions. Within most applications of FreeRTOS, the couple\r
+ * pvPortMalloc()/vPortFree() will be used.\r
+ * If there is also SDRAM, the user may decide to use a different memory\r
+ * allocator:\r
+ * MallocLarge is used to allocate large TCP buffers (for Rx/Tx)\r
+ * MallocSocket is used to allocate the space for the sockets\r
+ */\r
+#ifndef pvPortMallocLarge\r
+       #define pvPortMallocLarge( x )                          pvPortMalloc( x )\r
+#endif\r
+\r
+#ifndef vPortFreeLarge\r
+       #define vPortFreeLarge(ptr)                                     vPortFree(ptr)\r
+#endif\r
+\r
+#ifndef pvPortMallocSocket\r
+       #define pvPortMallocSocket( x )                         pvPortMalloc( x )\r
+#endif\r
+\r
+#ifndef vPortFreeSocket\r
+       #define vPortFreeSocket(ptr)                            vPortFree(ptr)\r
+#endif\r
+\r
+/*\r
+ * At several places within the library, random numbers are needed:\r
+ * - DHCP:    For creating a DHCP transaction number\r
+ * - TCP:     Set the Initial Sequence Number: this is the value of the first outgoing\r
+ *            sequence number being used when connecting to a peer.\r
+ *            Having a well randomised ISN is important to avoid spoofing\r
+ * - UDP/TCP: for setting the first port number to be used, in case a socket\r
+ *            uses a 'random' or anonymous port number\r
+ */\r
+#ifndef ipconfigRAND32\r
+       #define ipconfigRAND32() rand()\r
+#endif\r
+/* --------------------------------------------------------\r
+ * End of: HT Added some macro defaults for the PLUS-UDP project\r
+ * -------------------------------------------------------- */\r
+\r
+#ifndef ipconfigUSE_NETWORK_EVENT_HOOK\r
+       #define ipconfigUSE_NETWORK_EVENT_HOOK 0\r
+#endif\r
+\r
+#ifndef ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS\r
+       #define ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS ( pdMS_TO_TICKS( 20 ) )\r
+#endif\r
+\r
+#ifndef ipconfigARP_CACHE_ENTRIES\r
+       #define ipconfigARP_CACHE_ENTRIES               10\r
+#endif\r
+\r
+#ifndef ipconfigMAX_ARP_RETRANSMISSIONS\r
+       #define ipconfigMAX_ARP_RETRANSMISSIONS ( 5u )\r
+#endif\r
+\r
+#ifndef ipconfigMAX_ARP_AGE\r
+       #define ipconfigMAX_ARP_AGE                     150u\r
+#endif\r
+\r
+#ifndef ipconfigUSE_ARP_REVERSED_LOOKUP\r
+       #define ipconfigUSE_ARP_REVERSED_LOOKUP         0\r
+#endif\r
+\r
+#ifndef ipconfigUSE_ARP_REMOVE_ENTRY\r
+       #define ipconfigUSE_ARP_REMOVE_ENTRY            0\r
+#endif\r
+\r
+#ifndef ipconfigINCLUDE_FULL_INET_ADDR\r
+       #define ipconfigINCLUDE_FULL_INET_ADDR  1\r
+#endif\r
+\r
+#ifndef ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS\r
+       #define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS          45\r
+#endif\r
+\r
+#ifndef ipconfigEVENT_QUEUE_LENGTH\r
+       #define ipconfigEVENT_QUEUE_LENGTH              ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + 5 )\r
+#endif\r
+\r
+#ifndef ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND\r
+       #define ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND 1\r
+#endif\r
+\r
+#ifndef ipconfigUDP_TIME_TO_LIVE\r
+       #define ipconfigUDP_TIME_TO_LIVE                128\r
+#endif\r
+\r
+#ifndef ipconfigTCP_TIME_TO_LIVE\r
+       #define ipconfigTCP_TIME_TO_LIVE                128\r
+#endif\r
+\r
+#ifndef ipconfigUDP_MAX_RX_PACKETS\r
+       /* Make postive to define the maximum number of packets which will be buffered\r
+        * for each UDP socket.\r
+        * Can be overridden with the socket option FREERTOS_SO_UDP_MAX_RX_PACKETS\r
+        */\r
+       #define ipconfigUDP_MAX_RX_PACKETS              0u\r
+#endif\r
+\r
+#ifndef ipconfigUSE_DHCP\r
+       #define ipconfigUSE_DHCP                                1\r
+#endif\r
+\r
+#ifndef ipconfigUSE_DHCP_HOOK\r
+       #define ipconfigUSE_DHCP_HOOK           0\r
+#endif\r
+\r
+#ifndef ipconfigDHCP_FALL_BACK_AUTO_IP\r
+       /*\r
+        * Only applicable when DHCP is in use:\r
+        * If no DHCP server responds, use "Auto-IP" : the\r
+        * device will allocate a random LinkLayer IP address.\r
+        */\r
+       #define ipconfigDHCP_FALL_BACK_AUTO_IP          ( 0 )\r
+#endif\r
+\r
+#if( ipconfigDHCP_FALL_BACK_AUTO_IP != 0 )\r
+       #define ipconfigARP_USE_CLASH_DETECTION         1\r
+#endif\r
+\r
+#ifndef ipconfigARP_USE_CLASH_DETECTION\r
+       #define ipconfigARP_USE_CLASH_DETECTION         0\r
+#endif\r
+\r
+#ifndef ipconfigNETWORK_MTU\r
+       #define ipconfigNETWORK_MTU             1500\r
+#endif\r
+\r
+#ifndef ipconfigTCP_MSS\r
+       #define ipconfigTCP_MSS         ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER - ipSIZE_OF_TCP_HEADER )\r
+#endif\r
+\r
+/* Each TCP socket has circular stream buffers for Rx and Tx, which\r
+ * have a fixed maximum size.\r
+ * The defaults for these size are defined here, although\r
+ * they can be overridden at runtime by using the setsockopt() call */\r
+#ifndef ipconfigTCP_RX_BUFFER_LENGTH\r
+       #define ipconfigTCP_RX_BUFFER_LENGTH                    ( 4u * ipconfigTCP_MSS )        /* defaults to 5840 bytes */\r
+#endif\r
+\r
+/* Define the size of Tx stream buffer for TCP sockets */\r
+#ifndef ipconfigTCP_TX_BUFFER_LENGTH\r
+#      define ipconfigTCP_TX_BUFFER_LENGTH                     ( 4u * ipconfigTCP_MSS )        /* defaults to 5840 bytes */\r
+#endif\r
+\r
+#ifndef ipconfigMAXIMUM_DISCOVER_TX_PERIOD\r
+       #ifdef _WINDOWS_\r
+               #define ipconfigMAXIMUM_DISCOVER_TX_PERIOD              ( pdMS_TO_TICKS( 999 ) )\r
+       #else\r
+               #define ipconfigMAXIMUM_DISCOVER_TX_PERIOD              ( pdMS_TO_TICKS( 30000 ) )\r
+       #endif /* _WINDOWS_ */\r
+#endif /* ipconfigMAXIMUM_DISCOVER_TX_PERIOD */\r
+\r
+#ifndef ipconfigUSE_DNS\r
+       #define ipconfigUSE_DNS                                         1\r
+#endif\r
+\r
+#ifndef ipconfigDNS_REQUEST_ATTEMPTS\r
+       #define ipconfigDNS_REQUEST_ATTEMPTS            5\r
+#endif\r
+\r
+#ifndef ipconfigUSE_DNS_CACHE\r
+       #define ipconfigUSE_DNS_CACHE                           0\r
+#endif\r
+\r
+#if( ipconfigUSE_DNS_CACHE != 0 )\r
+       #ifndef ipconfigDNS_CACHE_NAME_LENGTH\r
+               #define ipconfigDNS_CACHE_NAME_LENGTH           ( 16 )\r
+       #endif\r
+\r
+       #ifndef ipconfigDNS_CACHE_ENTRIES\r
+               #define ipconfigDNS_CACHE_ENTRIES                       0\r
+       #endif\r
+#endif /* ipconfigUSE_DNS_CACHE != 0 */\r
+\r
+#ifndef ipconfigCHECK_IP_QUEUE_SPACE\r
+       #define ipconfigCHECK_IP_QUEUE_SPACE                    0\r
+#endif\r
+\r
+#ifndef ipconfigUSE_LLMNR\r
+       /* Include support for LLMNR: Link-local Multicast Name Resolution (non-Microsoft) */\r
+       #define ipconfigUSE_LLMNR                                       ( 0 )\r
+#endif\r
+\r
+#if( !defined( ipconfigUSE_DNS ) )\r
+       #if( ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) )\r
+               /* LLMNR and NBNS depend on DNS because those protocols share a lot of code. */\r
+               #error When either LLMNR or NBNS is used, ipconfigUSE_DNS must be defined\r
+       #endif\r
+#endif\r
+\r
+#ifndef ipconfigREPLY_TO_INCOMING_PINGS\r
+       #define ipconfigREPLY_TO_INCOMING_PINGS         1\r
+#endif\r
+\r
+#ifndef ipconfigSUPPORT_OUTGOING_PINGS\r
+       #define ipconfigSUPPORT_OUTGOING_PINGS          0\r
+#endif\r
+\r
+#ifndef ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES\r
+       #define ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES 1\r
+#endif\r
+\r
+#ifndef ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES\r
+       #define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES     1\r
+#endif\r
+\r
+#ifndef configINCLUDE_TRACE_RELATED_CLI_COMMANDS\r
+       #define ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS 0\r
+#else\r
+       #define ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS configINCLUDE_TRACE_RELATED_CLI_COMMANDS\r
+#endif\r
+\r
+#ifndef ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM\r
+       #define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM  ( 0 )\r
+#endif\r
+\r
+#ifndef ipconfigETHERNET_DRIVER_FILTERS_PACKETS\r
+       #define ipconfigETHERNET_DRIVER_FILTERS_PACKETS ( 0 )\r
+#endif\r
+\r
+#ifndef ipconfigWATCHDOG_TIMER\r
+       /* This macro will be called in every loop the IP-task makes.  It may be\r
+       replaced by user-code that triggers a watchdog */\r
+       #define ipconfigWATCHDOG_TIMER()\r
+#endif\r
+\r
+#ifndef ipconfigUSE_CALLBACKS\r
+       #define ipconfigUSE_CALLBACKS                   ( 0 )\r
+#endif\r
+\r
+#if( ipconfigUSE_CALLBACKS != 0 )\r
+       #ifndef ipconfigIS_VALID_PROG_ADDRESS\r
+               /* Replace this macro with a test returning non-zero if the memory pointer to by x\r
+                * is valid memory which can contain executable code\r
+                * In fact this is an extra safety measure: if a handler points to invalid memory,\r
+                * it will not be called\r
+                */\r
+               #define ipconfigIS_VALID_PROG_ADDRESS(x)                ( ( x ) != NULL )\r
+       #endif\r
+#endif\r
+\r
+#ifndef ipconfigHAS_INLINE_FUNCTIONS\r
+       #define ipconfigHAS_INLINE_FUNCTIONS    ( 1 )\r
+#endif\r
+\r
+#ifndef portINLINE\r
+       #define portINLINE inline\r
+#endif\r
+\r
+#ifndef ipconfigZERO_COPY_TX_DRIVER\r
+       /* When non-zero, the buffers passed to the SEND routine may be passed\r
+       to DMA. As soon as sending is ready, the buffers must be released by\r
+       calling vReleaseNetworkBufferAndDescriptor(), */\r
+       #define ipconfigZERO_COPY_TX_DRIVER             ( 0 )\r
+#endif\r
+\r
+#ifndef ipconfigZERO_COPY_RX_DRIVER\r
+       /* This define doesn't mean much to the driver, except that it makes\r
+       sure that pxPacketBuffer_to_NetworkBuffer() will be included. */\r
+       #define ipconfigZERO_COPY_RX_DRIVER             ( 0 )\r
+#endif\r
+\r
+#ifndef ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM\r
+       #define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 0\r
+#endif\r
+\r
+#ifndef ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM\r
+       #define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 0\r
+#endif\r
+\r
+#ifndef ipconfigDHCP_REGISTER_HOSTNAME\r
+       #define ipconfigDHCP_REGISTER_HOSTNAME 0\r
+#endif\r
+\r
+#ifndef ipconfigSOCKET_HAS_USER_SEMAPHORE\r
+       #define ipconfigSOCKET_HAS_USER_SEMAPHORE 0\r
+#endif\r
+\r
+#ifndef ipconfigSUPPORT_SELECT_FUNCTION\r
+       #define ipconfigSUPPORT_SELECT_FUNCTION 0\r
+#endif\r
+\r
+#ifndef ipconfigTCP_KEEP_ALIVE\r
+       #define ipconfigTCP_KEEP_ALIVE 0\r
+#endif\r
+\r
+#ifndef ipconfigDNS_USE_CALLBACKS\r
+       #define ipconfigDNS_USE_CALLBACKS 0\r
+#endif\r
+\r
+#ifndef ipconfigSUPPORT_SIGNALS\r
+       #define ipconfigSUPPORT_SIGNALS                         0\r
+#endif\r
+\r
+#ifndef ipconfigUSE_NBNS\r
+       #define ipconfigUSE_NBNS 0\r
+#endif\r
+\r
+#ifndef ipconfigTCP_HANG_PROTECTION\r
+       #define ipconfigTCP_HANG_PROTECTION  0\r
+#endif\r
+\r
+#ifndef ipconfigTCP_IP_SANITY\r
+       #define ipconfigTCP_IP_SANITY 0\r
+#endif\r
+\r
+#ifndef ipconfigARP_STORES_REMOTE_ADDRESSES\r
+       #define ipconfigARP_STORES_REMOTE_ADDRESSES 0\r
+#endif\r
+\r
+#ifndef ipconfigBUFFER_PADDING\r
+       /* Expert option: define a value for 'ipBUFFER_PADDING'.\r
+       When 'ipconfigBUFFER_PADDING' equals 0,\r
+       'ipBUFFER_PADDING' will get a default value of 8 + 2 bytes. */\r
+       #define ipconfigBUFFER_PADDING 0\r
+#endif\r
+\r
+#ifndef ipconfigPACKET_FILLER_SIZE\r
+       #define ipconfigPACKET_FILLER_SIZE 2\r
+#endif\r
+\r
+#endif /* FREERTOS_DEFAULT_IP_CONFIG_H */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_ARP.h
new file mode 100644 (file)
index 0000000..5caad67
--- /dev/null
@@ -0,0 +1,173 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef FREERTOS_ARP_H\r
+#define FREERTOS_ARP_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* Application level configuration options. */\r
+#include "FreeRTOSIPConfig.h"\r
+#include "FreeRTOSIPConfigDefaults.h"\r
+#include "IPTraceMacroDefaults.h"\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Miscellaneous structure and definitions. */\r
+/*-----------------------------------------------------------*/\r
+\r
+typedef struct xARP_CACHE_TABLE_ROW\r
+{\r
+       uint32_t ulIPAddress;           /* The IP address of an ARP cache entry. */\r
+       MACAddress_t xMACAddress;  /* The MAC address of an ARP cache entry. */\r
+       uint8_t ucAge;                          /* A value that is periodically decremented but can also be refreshed by active communication.  The ARP cache entry is removed if the value reaches zero. */\r
+    uint8_t ucValid;                   /* pdTRUE: xMACAddress is valid, pdFALSE: waiting for ARP reply */\r
+} ARPCacheRow_t;\r
+\r
+typedef enum\r
+{\r
+       eARPCacheMiss = 0,                      /* 0 An ARP table lookup did not find a valid entry. */\r
+       eARPCacheHit,                           /* 1 An ARP table lookup found a valid entry. */\r
+       eCantSendPacket                         /* 2 There is no IP address, or an ARP is still in progress, so the packet cannot be sent. */\r
+} eARPLookupResult_t;\r
+\r
+typedef enum\r
+{\r
+       eNotFragment = 0,                       /* The IP packet being sent is not part of a fragment. */\r
+       eFirstFragment,                         /* The IP packet being sent is the first in a set of fragmented packets. */\r
+       eFollowingFragment                      /* The IP packet being sent is part of a set of fragmented packets. */\r
+} eIPFragmentStatus_t;\r
+\r
+/*\r
+ * If ulIPAddress is already in the ARP cache table then reset the age of the\r
+ * entry back to its maximum value.  If ulIPAddress is not already in the ARP\r
+ * cache table then add it - replacing the oldest current entry if there is not\r
+ * a free space available.\r
+ */\r
+void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress, const uint32_t ulIPAddress );\r
+\r
+#if( ipconfigARP_USE_CLASH_DETECTION != 0 )\r
+       /* Becomes non-zero if another device responded to a gratuitos ARP message. */\r
+       extern BaseType_t xARPHadIPClash;\r
+       /* MAC-address of the other device containing the same IP-address. */\r
+       extern MACAddress_t xARPClashMacAddress;\r
+#endif /* ipconfigARP_USE_CLASH_DETECTION */\r
+\r
+#if( ipconfigUSE_ARP_REMOVE_ENTRY != 0 )\r
+\r
+       /*\r
+        * In some rare cases, it might be useful to remove a ARP cache entry of a\r
+        * known MAC address to make sure it gets refreshed.\r
+        */\r
+       uint32_t ulARPRemoveCacheEntryByMac( const MACAddress_t * pxMACAddress );\r
+\r
+#endif /* ipconfigUSE_ARP_REMOVE_ENTRY != 0 */\r
+\r
+/*\r
+ * Look for ulIPAddress in the ARP cache.  If the IP address exists, copy the\r
+ * associated MAC address into pxMACAddress, refresh the ARP cache entry's\r
+ * age, and return eARPCacheHit.  If the IP address does not exist in the ARP\r
+ * cache return eARPCacheMiss.  If the packet cannot be sent for any reason\r
+ * (maybe DHCP is still in process, or the addressing needs a gateway but there\r
+ * isn't a gateway defined) then return eCantSendPacket.\r
+ */\r
+eARPLookupResult_t eARPGetCacheEntry( uint32_t *pulIPAddress, MACAddress_t * const pxMACAddress );\r
+\r
+#if( ipconfigUSE_ARP_REVERSED_LOOKUP != 0 )\r
+\r
+       /* Lookup an IP-address if only the MAC-address is known */\r
+       eARPLookupResult_t eARPGetCacheEntryByMac( MACAddress_t * const pxMACAddress, uint32_t *pulIPAddress );\r
+\r
+#endif\r
+/*\r
+ * Reduce the age count in each entry within the ARP cache.  An entry is no\r
+ * longer considered valid and is deleted if its age reaches zero.\r
+ */\r
+void vARPAgeCache( void );\r
+\r
+/*\r
+ * Send out an ARP request for the IP address contained in pxNetworkBuffer, and\r
+ * add an entry into the ARP table that indicates that an ARP reply is\r
+ * outstanding so re-transmissions can be generated.\r
+ */\r
+void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer );\r
+\r
+/*\r
+ * After DHCP is ready and when changing IP address, force a quick send of our new IP\r
+ * address\r
+ */\r
+void vARPSendGratuitous( void );\r
+\r
+#ifdef __cplusplus\r
+} // extern "C"\r
+#endif\r
+\r
+#endif /* FREERTOS_ARP_H */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DHCP.h
new file mode 100644 (file)
index 0000000..b432e3c
--- /dev/null
@@ -0,0 +1,119 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef FREERTOS_DHCP_H\r
+#define FREERTOS_DHCP_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* Application level configuration options. */\r
+#include "FreeRTOSIPConfig.h"\r
+#include "IPTraceMacroDefaults.h"\r
+\r
+/* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */\r
+typedef enum eDHCP_PHASE\r
+{\r
+       eDHCPPhasePreDiscover,  /* Driver is about to send a DHCP discovery. */\r
+       eDHCPPhasePreRequest,   /* Driver is about to request DHCP an IP address. */\r
+#if( ipconfigDHCP_SEND_DISCOVER_AFTER_AUTO_IP != 0 )\r
+       eDHCPPhasePreLLA,               /* Driver is about to try get an LLA address */\r
+#endif /* ipconfigDHCP_SEND_DISCOVER_AFTER_AUTO_IP */\r
+} eDHCPCallbackPhase_t;\r
+\r
+/* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */\r
+typedef enum eDHCP_ANSWERS\r
+{\r
+       eDHCPContinue,                  /* Continue the DHCP process */\r
+       eDHCPUseDefaults,               /* Stop DHCP and use the static defaults. */\r
+       eDHCPStopNoChanges,             /* Stop DHCP and continue with current settings. */\r
+} eDHCPCallbackAnswer_t;\r
+\r
+/*\r
+ * NOT A PUBLIC API FUNCTION.\r
+ */\r
+void vDHCPProcess( BaseType_t xReset );\r
+\r
+/* Internal call: returns true if socket is the current DHCP socket */\r
+BaseType_t xIsDHCPSocket( Socket_t xSocket );\r
+\r
+/* Prototype of the hook (or callback) function that must be provided by the\r
+application if ipconfigUSE_DHCP_HOOK is set to 1.  See the following URL for\r
+usage information:\r
+http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Configuration.html#ipconfigUSE_DHCP_HOOK\r
+*/\r
+eDHCPCallbackAnswer_t xApplicationDHCPHook( eDHCPCallbackPhase_t eDHCPPhase, uint32_t ulIPAddress );\r
+\r
+#ifdef __cplusplus\r
+}      /* extern "C" */\r
+#endif\r
+\r
+#endif /* FREERTOS_DHCP_H */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_DNS.h
new file mode 100644 (file)
index 0000000..4514491
--- /dev/null
@@ -0,0 +1,165 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef FREERTOS_DNS_H\r
+#define FREERTOS_DNS_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* Application level configuration options. */\r
+#include "FreeRTOSIPConfig.h"\r
+#include "IPTraceMacroDefaults.h"\r
+\r
+\r
+/* The Link-local Multicast Name Resolution (LLMNR)\r
+ * is included.\r
+ * Note that a special MAC address is required in addition to the NIC's actual\r
+ * MAC address: 01:00:5E:00:00:FC\r
+ *\r
+ * The target IP address will be 224.0.0.252\r
+ */\r
+#if( ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN )\r
+       #define ipLLMNR_IP_ADDR                 0xE00000FC\r
+#else\r
+       #define ipLLMNR_IP_ADDR                 0xFC0000E0\r
+#endif /* ipconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN */\r
+\r
+#define        ipLLMNR_PORT    5355 /* Standard LLMNR port. */\r
+#define        ipDNS_PORT              53      /* Standard DNS port. */\r
+#define        ipDHCP_CLIENT   67\r
+#define        ipDHCP_SERVER   68\r
+#define        ipNBNS_PORT             137     /* NetBIOS Name Service. */\r
+#define        ipNBDGM_PORT    138 /* Datagram Service, not included. */\r
+\r
+/*\r
+ * The following function should be provided by the user and return true if it\r
+ * matches the domain name.\r
+ */\r
+extern BaseType_t xApplicationDNSQueryHook( const char *pcName );\r
+\r
+/*\r
+ * LLMNR is very similar to DNS, so is handled by the DNS routines.\r
+ */\r
+uint32_t ulDNSHandlePacket( NetworkBufferDescriptor_t *pxNetworkBuffer );\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       extern const MACAddress_t xLLMNR_MacAdress;\r
+#endif /* ipconfigUSE_LLMNR */\r
+\r
+#if( ipconfigUSE_NBNS != 0 )\r
+\r
+       /*\r
+        * Inspect a NetBIOS Names-Service message.  If the name matches with ours\r
+        * (xApplicationDNSQueryHook returns true) an answer will be sent back.\r
+        * Note that LLMNR is a better protocol for name services on a LAN as it is\r
+        * less polluted\r
+        */\r
+       uint32_t ulNBNSHandlePacket (NetworkBufferDescriptor_t *pxNetworkBuffer );\r
+\r
+#endif /* ipconfigUSE_NBNS */\r
+\r
+#if( ipconfigUSE_DNS_CACHE != 0 )\r
+\r
+       uint32_t FreeRTOS_dnslookup( const char *pcHostName );\r
+\r
+#endif /* ipconfigUSE_DNS_CACHE != 0 */\r
+\r
+#if( ipconfigDNS_USE_CALLBACKS != 0 )\r
+\r
+       /*\r
+        * Users may define this type of function as a callback.\r
+        * It will be called when a DNS reply is received or when a timeout has been reached.\r
+        */\r
+       typedef void (* FOnDNSEvent ) ( const char * /* pcName */, void * /* pvSearchID */, uint32_t /* ulIPAddress */ );\r
+\r
+       /*\r
+        * Asynchronous version of gethostbyname()\r
+        * xTimeout is in units of ms.\r
+        */\r
+       uint32_t FreeRTOS_gethostbyname_a( const char *pcHostName, FOnDNSEvent pCallback, void *pvSearchID, TickType_t xTimeout );\r
+       void FreeRTOS_gethostbyname_cancel( void *pvSearchID );\r
+\r
+#endif\r
+\r
+/*\r
+ * FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE\r
+ * FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL:\r
+ * _TBD_ Add URL\r
+ */\r
+uint32_t FreeRTOS_gethostbyname( const char *pcHostName );\r
+\r
+\r
+#ifdef __cplusplus\r
+}      /* extern "C" */\r
+#endif\r
+\r
+#endif /* FREERTOS_DNS_H */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP.h
new file mode 100644 (file)
index 0000000..59311c4
--- /dev/null
@@ -0,0 +1,350 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef FREERTOS_IP_H\r
+#define FREERTOS_IP_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* Application level configuration options. */\r
+#include "FreeRTOSIPConfig.h"\r
+#include "FreeRTOSIPConfigDefaults.h"\r
+#include "IPTraceMacroDefaults.h"\r
+\r
+/* Some constants defining the sizes of several parts of a packet */\r
+#define ipSIZE_OF_ETH_HEADER                   14u\r
+#define ipSIZE_OF_IPv4_HEADER                  20u\r
+#define ipSIZE_OF_IGMP_HEADER                  8u\r
+#define ipSIZE_OF_ICMP_HEADER                  8u\r
+#define ipSIZE_OF_UDP_HEADER                   8u\r
+#define ipSIZE_OF_TCP_HEADER                   20u\r
+\r
+\r
+/* The number of octets in the MAC and IP addresses respectively. */\r
+#define ipMAC_ADDRESS_LENGTH_BYTES ( 6 )\r
+#define ipIP_ADDRESS_LENGTH_BYTES ( 4 )\r
+\r
+/* IP protocol definitions. */\r
+#define ipPROTOCOL_ICMP                        ( 1 )\r
+#define ipPROTOCOL_IGMP         ( 2 )\r
+#define ipPROTOCOL_TCP                 ( 6 )\r
+#define ipPROTOCOL_UDP                 ( 17 )\r
+\r
+/* Dimensions the buffers that are filled by received Ethernet frames. */\r
+#define ipSIZE_OF_ETH_CRC_BYTES                                        ( 4UL )\r
+#define ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES        ( 4UL )\r
+#define ipTOTAL_ETHERNET_FRAME_SIZE                            ( ( ( uint32_t ) ipconfigNETWORK_MTU ) + ( ( uint32_t ) ipSIZE_OF_ETH_HEADER ) + ipSIZE_OF_ETH_CRC_BYTES + ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES )\r
+\r
+/*_RB_ Comment may need updating. */\r
+/* Space left at the beginning of a network buffer storage area to store a\r
+pointer back to the network buffer.  Should be a multiple of 8 to ensure 8 byte\r
+alignment is maintained on architectures that require it.\r
+\r
+In order to get a 32-bit alignment of network packets, an offset of 2 bytes\r
+would be desirable, as defined by ipconfigPACKET_FILLER_SIZE.  So the malloc'd\r
+buffer will have the following contents:\r
+       uint32_t pointer;       // word-aligned\r
+       uchar_8 filler[6];\r
+       << ETH-header >>        // half-word-aligned\r
+       uchar_8 dest[6];    // start of pucEthernetBuffer\r
+       uchar_8 dest[6];\r
+       uchar16_t type;\r
+       << IP-header >>         // word-aligned\r
+       uint8_t ucVersionHeaderLength;\r
+       etc\r
+ */\r
+#if( ipconfigBUFFER_PADDING != 0 )\r
+    #define ipBUFFER_PADDING    ipconfigBUFFER_PADDING\r
+#else\r
+    #define ipBUFFER_PADDING    ( 8u + ipconfigPACKET_FILLER_SIZE )\r
+#endif\r
+\r
+/* The structure used to store buffers and pass them around the network stack.\r
+Buffers can be in use by the stack, in use by the network interface hardware\r
+driver, or free (not in use). */\r
+typedef struct xNETWORK_BUFFER\r
+{\r
+       ListItem_t xBufferListItem;     /* Used to reference the buffer form the free buffer list or a socket. */\r
+       uint32_t ulIPAddress;                   /* Source or destination IP address, depending on usage scenario. */\r
+       uint8_t *pucEthernetBuffer;     /* Pointer to the start of the Ethernet frame. */\r
+       size_t xDataLength;                     /* Starts by holding the total Ethernet frame length, then the UDP/TCP payload length. */\r
+       uint16_t usPort;                                /* Source or destination port, depending on usage scenario. */\r
+       uint16_t usBoundPort;                   /* The port to which a transmitting socket is bound. */\r
+       #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+               struct xNETWORK_BUFFER *pxNextBuffer; /* Possible optimisation for expert users - requires network driver support. */\r
+       #endif\r
+} NetworkBufferDescriptor_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xMAC_ADDRESS\r
+{\r
+       uint8_t ucBytes[ ipMAC_ADDRESS_LENGTH_BYTES ];\r
+}\r
+#include "pack_struct_end.h"\r
+\r
+typedef struct xMAC_ADDRESS MACAddress_t;\r
+\r
+typedef enum eNETWORK_EVENTS\r
+{\r
+       eNetworkUp,             /* The network is configured. */\r
+       eNetworkDown    /* The network connection has been lost. */\r
+} eIPCallbackEvent_t;\r
+\r
+typedef enum ePING_REPLY_STATUS\r
+{\r
+       eSuccess = 0,           /* A correct reply has been received for an outgoing ping. */\r
+       eInvalidChecksum,       /* A reply was received for an outgoing ping but the checksum of the reply was incorrect. */\r
+       eInvalidData            /* A reply was received to an outgoing ping but the payload of the reply was not correct. */\r
+} ePingReplyStatus_t;\r
+\r
+/* Endian related definitions. */\r
+#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )\r
+\r
+       /* FreeRTOS_htons / FreeRTOS_htonl: some platforms might have built-in versions\r
+       using a single instruction so allow these versions to be overridden. */\r
+       #ifndef FreeRTOS_htons\r
+               #define FreeRTOS_htons( usIn ) ( (uint16_t) ( ( ( usIn ) << 8U ) | ( ( usIn ) >> 8U ) ) )\r
+       #endif\r
+\r
+       #ifndef FreeRTOS_htonl\r
+               #define FreeRTOS_htonl( ulIn )                                                                                  \\r
+                       (                                                                                                                                       \\r
+                               ( uint32_t )                                                                                                    \\r
+                               (                                                                                                                               \\r
+                                       ( ( ( ( uint32_t ) ( ulIn ) )                ) << 24  ) |       \\r
+                                       ( ( ( ( uint32_t ) ( ulIn ) ) & 0x0000ff00UL ) <<  8  ) |       \\r
+                                       ( ( ( ( uint32_t ) ( ulIn ) ) & 0x00ff0000UL ) >>  8  ) |       \\r
+                                       ( ( ( ( uint32_t ) ( ulIn ) )                ) >> 24  )         \\r
+                               )                                                                                                                               \\r
+                       )\r
+       #endif\r
+\r
+#else /* ipconfigBYTE_ORDER */\r
+\r
+       #define FreeRTOS_htons( x ) ( ( uint16_t ) ( x ) )\r
+       #define FreeRTOS_htonl( x ) ( ( uint32_t ) ( x ) )\r
+\r
+#endif /* ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN */\r
+\r
+#define FreeRTOS_ntohs( x ) FreeRTOS_htons( x )\r
+#define FreeRTOS_ntohl( x ) FreeRTOS_htonl( x )\r
+\r
+#if( ipconfigHAS_INLINE_FUNCTIONS == 1 )\r
+\r
+       static portINLINE int32_t  FreeRTOS_max_int32  (int32_t  a, int32_t  b);\r
+       static portINLINE uint32_t FreeRTOS_max_uint32 (uint32_t a, uint32_t b);\r
+       static portINLINE int32_t  FreeRTOS_min_int32  (int32_t  a, int32_t  b);\r
+       static portINLINE uint32_t FreeRTOS_min_uint32 (uint32_t a, uint32_t b);\r
+       static portINLINE uint32_t FreeRTOS_round_up   (uint32_t a, uint32_t d);\r
+       static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d);\r
+       static portINLINE BaseType_t  FreeRTOS_min_BaseType  (BaseType_t  a, BaseType_t  b);\r
+       static portINLINE BaseType_t  FreeRTOS_max_BaseType  (BaseType_t  a, BaseType_t  b);\r
+       static portINLINE UBaseType_t FreeRTOS_max_UBaseType (UBaseType_t a, UBaseType_t b);\r
+       static portINLINE UBaseType_t FreeRTOS_min_UBaseType (UBaseType_t a, UBaseType_t  b);\r
+\r
+\r
+       static portINLINE int32_t  FreeRTOS_max_int32  (int32_t  a, int32_t  b) { return a >= b ? a : b; }\r
+       static portINLINE uint32_t FreeRTOS_max_uint32 (uint32_t a, uint32_t b) { return a >= b ? a : b; }\r
+       static portINLINE int32_t  FreeRTOS_min_int32  (int32_t  a, int32_t  b) { return a <= b ? a : b; }\r
+       static portINLINE uint32_t FreeRTOS_min_uint32 (uint32_t a, uint32_t b) { return a <= b ? a : b; }\r
+       static portINLINE uint32_t FreeRTOS_round_up   (uint32_t a, uint32_t d) { return d * ( ( a + d - 1u ) / d ); }\r
+       static portINLINE uint32_t FreeRTOS_round_down (uint32_t a, uint32_t d) { return d * ( a / d ); }\r
+\r
+       static portINLINE BaseType_t  FreeRTOS_max_BaseType  (BaseType_t  a, BaseType_t  b) { return a >= b ? a : b; }\r
+       static portINLINE UBaseType_t FreeRTOS_max_UBaseType (UBaseType_t a, UBaseType_t b) { return a >= b ? a : b; }\r
+       static portINLINE BaseType_t  FreeRTOS_min_BaseType  (BaseType_t  a, BaseType_t  b) { return a <= b ? a : b; }\r
+       static portINLINE UBaseType_t FreeRTOS_min_UBaseType (UBaseType_t  a, UBaseType_t  b) { return a <= b ? a : b; }\r
+\r
+#else\r
+\r
+       #define FreeRTOS_max_int32(a,b)  ( ( ( int32_t  ) ( a ) ) >= ( ( int32_t  ) ( b ) ) ? ( ( int32_t  ) ( a ) ) : ( ( int32_t  ) ( b ) ) )\r
+       #define FreeRTOS_max_uint32(a,b) ( ( ( uint32_t ) ( a ) ) >= ( ( uint32_t ) ( b ) ) ? ( ( uint32_t ) ( a ) ) : ( ( uint32_t ) ( b ) ) )\r
+\r
+       #define FreeRTOS_min_int32(a,b)  ( ( ( int32_t  ) a ) <= ( ( int32_t  ) b ) ? ( ( int32_t  ) a ) : ( ( int32_t  ) b ) )\r
+       #define FreeRTOS_min_uint32(a,b) ( ( ( uint32_t ) a ) <= ( ( uint32_t ) b ) ? ( ( uint32_t ) a ) : ( ( uint32_t ) b ) )\r
+\r
+       /*  Round-up: a = d * ( ( a + d - 1 ) / d ) */\r
+       #define FreeRTOS_round_up(a,d)   ( ( ( uint32_t ) ( d ) ) * ( ( ( ( uint32_t ) ( a ) ) + ( ( uint32_t ) ( d ) ) - 1UL ) / ( ( uint32_t ) ( d ) ) ) )\r
+       #define FreeRTOS_round_down(a,d) ( ( ( uint32_t ) ( d ) ) * ( ( ( uint32_t ) ( a ) ) / ( ( uint32_t ) ( d ) ) ) )\r
+\r
+       #define FreeRTOS_max_BaseType(a, b)  ( ( ( BaseType_t  ) ( a ) ) >= ( ( BaseType_t  ) ( b ) ) ? ( ( BaseType_t  ) ( a ) ) : ( ( BaseType_t  ) ( b ) ) )\r
+       #define FreeRTOS_max_UBaseType(a, b) ( ( ( UBaseType_t ) ( a ) ) >= ( ( UBaseType_t ) ( b ) ) ? ( ( UBaseType_t ) ( a ) ) : ( ( UBaseType_t ) ( b ) ) )\r
+       #define FreeRTOS_min_BaseType(a, b)  ( ( ( BaseType_t  ) ( a ) ) <= ( ( BaseType_t  ) ( b ) ) ? ( ( BaseType_t  ) ( a ) ) : ( ( BaseType_t  ) ( b ) ) )\r
+       #define FreeRTOS_min_UBaseType(a, b) ( ( ( UBaseType_t ) ( a ) ) <= ( ( UBaseType_t ) ( b ) ) ? ( ( UBaseType_t ) ( a ) ) : ( ( UBaseType_t ) ( b ) ) )\r
+\r
+#endif /* ipconfigHAS_INLINE_FUNCTIONS */\r
+\r
+#define pdMS_TO_MIN_TICKS( xTimeInMs ) ( pdMS_TO_TICKS( ( xTimeInMs ) ) < ( ( TickType_t ) 1 ) ? ( ( TickType_t ) 1 ) : pdMS_TO_TICKS( ( xTimeInMs ) ) )\r
+\r
+#ifndef pdTRUE_SIGNED\r
+       /* Temporary solution: eventually the defines below will appear in 'Source\include\projdefs.h' */\r
+       #define pdTRUE_SIGNED           pdTRUE\r
+       #define pdFALSE_SIGNED          pdFALSE\r
+       #define pdTRUE_UNSIGNED         ( ( UBaseType_t ) 1u )\r
+       #define pdFALSE_UNSIGNED        ( ( UBaseType_t ) 0u )\r
+#endif\r
+\r
+/*\r
+ * FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE\r
+ * FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/FreeRTOS_TCP_API_Functions.html\r
+ */\r
+BaseType_t FreeRTOS_IPInit( const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES ],\r
+       const uint8_t ucNetMask[ ipIP_ADDRESS_LENGTH_BYTES ],\r
+       const uint8_t ucGatewayAddress[ ipIP_ADDRESS_LENGTH_BYTES ],\r
+       const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ],\r
+       const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] );\r
+\r
+void * FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks );\r
+void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetMask, uint32_t *pulGatewayAddress, uint32_t *pulDNSServerAddress );\r
+void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint32_t *pulNetMask, const uint32_t *pulGatewayAddress, const uint32_t *pulDNSServerAddress );\r
+BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t xNumberOfBytesToSend, TickType_t xBlockTimeTicks );\r
+void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer );\r
+const uint8_t * FreeRTOS_GetMACAddress( void );\r
+void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent );\r
+void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier );\r
+uint32_t FreeRTOS_GetIPAddress( void );\r
+void FreeRTOS_SetIPAddress( uint32_t ulIPAddress );\r
+void FreeRTOS_SetNetmask( uint32_t ulNetmask );\r
+void FreeRTOS_SetGatewayAddress( uint32_t ulGatewayAddress );\r
+uint32_t FreeRTOS_GetGatewayAddress( void );\r
+uint32_t FreeRTOS_GetDNSServerAddress( void );\r
+uint32_t FreeRTOS_GetNetmask( void );\r
+void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress );\r
+BaseType_t FreeRTOS_IsNetworkUp( void );\r
+\r
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+       UBaseType_t uxGetMinimumIPQueueSpace( void );\r
+#endif\r
+\r
+/*\r
+ * Defined in FreeRTOS_Sockets.c\r
+ * //_RB_ Don't think this comment is correct.  If this is for internal use only it should appear after all the public API functions and not start with FreeRTOS_.\r
+ * Socket has had activity, reset the timer so it will not be closed\r
+ * because of inactivity\r
+ */\r
+const char *FreeRTOS_GetTCPStateName( UBaseType_t ulState);\r
+\r
+/* _HT_ Temporary: show all valid ARP entries\r
+ */\r
+void FreeRTOS_PrintARPCache( void );\r
+void FreeRTOS_ClearARP( void );\r
+\r
+#if( ipconfigDHCP_REGISTER_HOSTNAME == 1 )\r
+\r
+       /* DHCP has an option for clients to register their hostname.  It doesn't\r
+       have much use, except that a device can be found in a router along with its\r
+       name. If this option is used the callback below must be provided by the\r
+       application     writer to return a const string, denoting the device's name. */\r
+       const char *pcApplicationHostnameHook( void );\r
+\r
+#endif /* ipconfigDHCP_REGISTER_HOSTNAME */\r
+\r
+\r
+/* For backward compatibility define old structure names to the newer equivalent\r
+structure name. */\r
+#ifndef ipconfigENABLE_BACKWARD_COMPATIBILITY\r
+       #define ipconfigENABLE_BACKWARD_COMPATIBILITY   1\r
+#endif\r
+\r
+#if( ipconfigENABLE_BACKWARD_COMPATIBILITY == 1 )\r
+       #define xIPStackEvent_t                         IPStackEvent_t\r
+       #define xNetworkBufferDescriptor_t      NetworkBufferDescriptor_t\r
+       #define xMACAddress_t                           MACAddress_t\r
+       #define xWinProperties_t                        WinProperties_t\r
+       #define xSocket_t                                       Socket_t\r
+       #define xSocketSet_t                            SocketSet_t\r
+       #define ipSIZE_OF_IP_HEADER                     ipSIZE_OF_IPv4_HEADER\r
+\r
+       /* Since August 2016, the public types and fields below have changed name:\r
+       abbreviations TCP/UDP are now written in capitals, and type names now end with "_t". */\r
+       #define FOnConnected                            FOnConnected_t\r
+       #define FOnTcpReceive                           FOnTCPReceive_t\r
+       #define FOnTcpSent                                      FOnTCPSent_t\r
+       #define FOnUdpReceive                           FOnUDPReceive_t\r
+       #define FOnUdpSent                                      FOnUDPSent_t\r
+\r
+       #define pOnTcpConnected                         pxOnTCPConnected\r
+       #define pOnTcpReceive                           pxOnTCPReceive\r
+       #define pOnTcpSent                                      pxOnTCPSent\r
+       #define pOnUdpReceive                           pxOnUDPReceive\r
+       #define pOnUdpSent                                      pxOnUDPSent\r
+\r
+       #define FOnUdpSent                                      FOnUDPSent_t\r
+       #define FOnTcpSent                                      FOnTCPSent_t\r
+#endif /* ipconfigENABLE_BACKWARD_COMPATIBILITY */\r
+\r
+#ifdef __cplusplus\r
+} /* extern "C" */\r
+#endif\r
+\r
+#endif /* FREERTOS_IP_H */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_IP_Private.h
new file mode 100644 (file)
index 0000000..6af875a
--- /dev/null
@@ -0,0 +1,840 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef FREERTOS_IP_PRIVATE_H\r
+#define FREERTOS_IP_PRIVATE_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* Application level configuration options. */\r
+#include "FreeRTOSIPConfig.h"\r
+#include "FreeRTOSIPConfigDefaults.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "IPTraceMacroDefaults.h"\r
+#include "FreeRTOS_Stream_Buffer.h"\r
+#if( ipconfigUSE_TCP == 1 )\r
+       #include "FreeRTOS_TCP_WIN.h"\r
+       #include "FreeRTOS_TCP_IP.h"\r
+#endif\r
+\r
+#include "event_groups.h"\r
+\r
+typedef struct xNetworkAddressingParameters\r
+{\r
+       uint32_t ulDefaultIPAddress;\r
+       uint32_t ulNetMask;\r
+       uint32_t ulGatewayAddress;\r
+       uint32_t ulDNSServerAddress;\r
+       uint32_t ulBroadcastAddress;\r
+} NetworkAddressingParameters_t;\r
+\r
+extern BaseType_t xTCPWindowLoggingLevel;\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Protocol headers.                                         */\r
+/*-----------------------------------------------------------*/\r
+\r
+#include "pack_struct_start.h"\r
+struct xETH_HEADER\r
+{\r
+       MACAddress_t xDestinationAddress; /*  0 + 6 = 6  */\r
+       MACAddress_t xSourceAddress;      /*  6 + 6 = 12 */\r
+       uint16_t usFrameType;              /* 12 + 2 = 14 */\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xETH_HEADER EthernetHeader_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xARP_HEADER\r
+{\r
+       uint16_t usHardwareType;                                /*  0 +  2 =  2 */\r
+       uint16_t usProtocolType;                                /*  2 +  2 =  4 */\r
+       uint8_t ucHardwareAddressLength;                /*  4 +  1 =  5 */\r
+       uint8_t ucProtocolAddressLength;                /*  5 +  1 =  6 */\r
+       uint16_t usOperation;                                   /*  6 +  2 =  8 */\r
+       MACAddress_t xSenderHardwareAddress;    /*  8 +  6 = 14 */\r
+       uint8_t ucSenderProtocolAddress[ 4 ];   /* 14 +  4 = 18  */\r
+       MACAddress_t xTargetHardwareAddress;    /* 18 +  6 = 24  */\r
+       uint32_t ulTargetProtocolAddress;               /* 24 +  4 = 28  */\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xARP_HEADER ARPHeader_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xIP_HEADER\r
+{\r
+       uint8_t ucVersionHeaderLength;        /*  0 + 1 =  1 */\r
+       uint8_t ucDifferentiatedServicesCode; /*  1 + 1 =  2 */\r
+       uint16_t usLength;                    /*  2 + 2 =  4 */\r
+       uint16_t usIdentification;            /*  4 + 2 =  6 */\r
+       uint16_t usFragmentOffset;            /*  6 + 2 =  8 */\r
+       uint8_t ucTimeToLive;                 /*  8 + 1 =  9 */\r
+       uint8_t ucProtocol;                   /*  9 + 1 = 10 */\r
+       uint16_t usHeaderChecksum;            /* 10 + 2 = 12 */\r
+       uint32_t ulSourceIPAddress;           /* 12 + 4 = 16 */\r
+       uint32_t ulDestinationIPAddress;      /* 16 + 4 = 20 */\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xIP_HEADER IPHeader_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xIGMP_HEADER\r
+{\r
+       uint8_t ucVersionType;     /* 0 + 1 = 1 */\r
+       uint8_t ucMaxResponseTime; /* 1 + 1 = 2 */\r
+       uint16_t usChecksum;       /* 2 + 2 = 4 */\r
+       uint32_t usGroupAddress;   /* 4 + 4 = 8 */\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xIGMP_HEADER IGMPHeader_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xICMP_HEADER\r
+{\r
+       uint8_t ucTypeOfMessage;   /* 0 + 1 = 1 */\r
+       uint8_t ucTypeOfService;   /* 1 + 1 = 2 */\r
+       uint16_t usChecksum;       /* 2 + 2 = 4 */\r
+       uint16_t usIdentifier;     /* 4 + 2 = 6 */\r
+       uint16_t usSequenceNumber; /* 6 + 2 = 8 */\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xICMP_HEADER ICMPHeader_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xUDP_HEADER\r
+{\r
+       uint16_t usSourcePort;      /* 0 + 2 = 2 */\r
+       uint16_t usDestinationPort; /* 2 + 2 = 4 */\r
+       uint16_t usLength;          /* 4 + 2 = 6 */\r
+       uint16_t usChecksum;        /* 6 + 2 = 8 */\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xUDP_HEADER UDPHeader_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xTCP_HEADER\r
+{\r
+       uint16_t usSourcePort;          /* +  2 =  2 */\r
+       uint16_t usDestinationPort;     /* +  2 =  4 */\r
+       uint32_t ulSequenceNumber;      /* +  4 =  8 */\r
+       uint32_t ulAckNr;               /* +  4 = 12 */\r
+       uint8_t  ucTCPOffset;           /* +  1 = 13 */\r
+       uint8_t  ucTCPFlags;            /* +  1 = 14 */\r
+       uint16_t usWindow;                      /* +  2 = 15 */\r
+       uint16_t usChecksum;            /* +  2 = 18 */\r
+       uint16_t usUrgent;                      /* +  2 = 20 */\r
+#if ipconfigUSE_TCP == 1\r
+       /* the option data is not a part of the TCP header */\r
+       uint8_t  ucOptdata[ipSIZE_TCP_OPTIONS];         /* + 12 = 32 */\r
+#endif\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xTCP_HEADER TCPHeader_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xPSEUDO_HEADER\r
+{\r
+       uint32_t ulSourceAddress;\r
+       uint32_t ulDestinationAddress;\r
+       uint8_t ucZeros;\r
+       uint8_t ucProtocol;\r
+       uint16_t usUDPLength;\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xPSEUDO_HEADER PseudoHeader_t;\r
+\r
+/*-----------------------------------------------------------*/\r
+/* Nested protocol packets.                                  */\r
+/*-----------------------------------------------------------*/\r
+\r
+#include "pack_struct_start.h"\r
+struct xARP_PACKET\r
+{\r
+       EthernetHeader_t xEthernetHeader;       /*  0 + 14 = 14 */\r
+       ARPHeader_t xARPHeader;                 /* 14 + 28 = 42 */\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xARP_PACKET ARPPacket_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xIP_PACKET\r
+{\r
+       EthernetHeader_t xEthernetHeader;\r
+       IPHeader_t xIPHeader;\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xIP_PACKET IPPacket_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xICMP_PACKET\r
+{\r
+       EthernetHeader_t xEthernetHeader;\r
+       IPHeader_t xIPHeader;\r
+       ICMPHeader_t xICMPHeader;\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xICMP_PACKET ICMPPacket_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xUDP_PACKET\r
+{\r
+       EthernetHeader_t xEthernetHeader; /*  0 + 14 = 14 */\r
+       IPHeader_t xIPHeader;             /* 14 + 20 = 34 */\r
+       UDPHeader_t xUDPHeader;           /* 34 +  8 = 42 */\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xUDP_PACKET UDPPacket_t;\r
+\r
+#include "pack_struct_start.h"\r
+struct xTCP_PACKET\r
+{\r
+       EthernetHeader_t xEthernetHeader; /*  0 + 14 = 14 */\r
+       IPHeader_t xIPHeader;             /* 14 + 20 = 34 */\r
+       TCPHeader_t xTCPHeader;           /* 34 + 32 = 66 */\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xTCP_PACKET TCPPacket_t;\r
+\r
+typedef union XPROT_PACKET\r
+{\r
+       ARPPacket_t xARPPacket;\r
+       TCPPacket_t xTCPPacket;\r
+       UDPPacket_t xUDPPacket;\r
+       ICMPPacket_t xICMPPacket;\r
+} ProtocolPacket_t;\r
+\r
+\r
+/* The maximum UDP payload length. */\r
+#define ipMAX_UDP_PAYLOAD_LENGTH ( ( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER ) - ipSIZE_OF_UDP_HEADER )\r
+\r
+typedef enum\r
+{\r
+       eReleaseBuffer = 0,             /* Processing the frame did not find anything to do - just release the buffer. */\r
+       eProcessBuffer,                 /* An Ethernet frame has a valid address - continue process its contents. */\r
+       eReturnEthernetFrame,   /* The Ethernet frame contains an ARP or ICMP packet that can be returned to its source. */\r
+       eFrameConsumed                  /* Processing the Ethernet packet contents resulted in the payload being sent to the stack. */\r
+} eFrameProcessingResult_t;\r
+\r
+typedef enum\r
+{\r
+       eNoEvent = -1,\r
+       eNetworkDownEvent,              /* 0: The network interface has been lost and/or needs [re]connecting. */\r
+       eNetworkRxEvent,                /* 1: The network interface has queued a received Ethernet frame. */\r
+       eARPTimerEvent,                 /* 2: The ARP timer expired. */\r
+       eStackTxEvent,                  /* 3: The software stack has queued a packet to transmit. */\r
+       eDHCPEvent,                             /* 4: Process the DHCP state machine. */\r
+       eTCPTimerEvent,                 /* 5: See if any TCP socket needs attention. */\r
+       eTCPAcceptEvent,                /* 6: Client API FreeRTOS_accept() waiting for client connections. */\r
+       eTCPNetStat,                    /* 7: IP-task is asked to produce a netstat listing. */\r
+       eSocketBindEvent,               /* 8: Send a message to the IP-task to bind a socket to a port. */\r
+       eSocketCloseEvent,              /* 9: Send a message to the IP-task to close a socket. */\r
+       eSocketSelectEvent,             /*10: Send a message to the IP-task for select(). */\r
+       eSocketSignalEvent,             /*11: A socket must be signalled. */\r
+} eIPEvent_t;\r
+\r
+typedef struct IP_TASK_COMMANDS\r
+{\r
+       eIPEvent_t eEventType;\r
+       void *pvData;\r
+} IPStackEvent_t;\r
+\r
+#define ipBROADCAST_IP_ADDRESS 0xffffffffUL\r
+\r
+/* Offset into the Ethernet frame that is used to temporarily store information\r
+on the fragmentation status of the packet being sent.  The value is important,\r
+as it is past the location into which the destination address will get placed. */\r
+#define ipFRAGMENTATION_PARAMETERS_OFFSET              ( 6 )\r
+#define ipSOCKET_OPTIONS_OFFSET                                        ( 6 )\r
+\r
+/* Only used when outgoing fragmentation is being used (FreeRTOSIPConfig.h\r
+setting. */\r
+#define ipGET_UDP_PAYLOAD_OFFSET_FOR_FRAGMENT( usFragmentOffset ) ( ( ( usFragmentOffset ) == 0 ) ? ipUDP_PAYLOAD_OFFSET_IPv4 : ipIP_PAYLOAD_OFFSET )\r
+\r
+/* The offset into a UDP packet at which the UDP data (payload) starts. */\r
+#define ipUDP_PAYLOAD_OFFSET_IPv4      ( sizeof( UDPPacket_t ) )\r
+\r
+/* The offset into an IP packet into which the IP data (payload) starts. */\r
+#define ipIP_PAYLOAD_OFFSET            ( sizeof( IPPacket_t ) )\r
+\r
+#include "pack_struct_start.h"\r
+struct xUDP_IP_FRAGMENT_PARAMETERS\r
+{\r
+       uint8_t ucSocketOptions;\r
+       uint8_t ucPadFor16BitAlignment;\r
+       uint16_t usFragmentedPacketOffset;\r
+       uint16_t usFragmentLength;\r
+       uint16_t usPayloadChecksum;\r
+}\r
+#include "pack_struct_end.h"\r
+typedef struct xUDP_IP_FRAGMENT_PARAMETERS IPFragmentParameters_t;\r
+\r
+#if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )\r
+\r
+       /* Ethernet frame types. */\r
+       #define ipARP_FRAME_TYPE        ( 0x0608U )\r
+       #define ipIPv4_FRAME_TYPE       ( 0x0008U )\r
+\r
+       /* ARP related definitions. */\r
+       #define ipARP_PROTOCOL_TYPE                             ( 0x0008U )\r
+       #define ipARP_HARDWARE_TYPE_ETHERNET    ( 0x0100U )\r
+       #define ipARP_REQUEST                                   ( 0x0100U )\r
+       #define ipARP_REPLY                                             ( 0x0200U )\r
+\r
+#else\r
+\r
+       /* Ethernet frame types. */\r
+       #define ipARP_FRAME_TYPE        ( 0x0806U )\r
+       #define ipIPv4_FRAME_TYPE       ( 0x0800U )\r
+\r
+       /* ARP related definitions. */\r
+       #define ipARP_PROTOCOL_TYPE ( 0x0800U )\r
+       #define ipARP_HARDWARE_TYPE_ETHERNET ( 0x0001U )\r
+       #define ipARP_REQUEST ( 0x0001 )\r
+       #define ipARP_REPLY ( 0x0002 )\r
+\r
+#endif /* ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN */\r
+\r
+\r
+/* For convenience, a MAC address of all zeros and another of all 0xffs are\r
+defined const for quick reference. */\r
+extern const MACAddress_t xBroadcastMACAddress; /* all 0xff's */\r
+extern uint16_t usPacketIdentifier;\r
+\r
+/* Define a default UDP packet header (declared in FreeRTOS_UDP_IP.c) */\r
+typedef union xUDPPacketHeader\r
+{\r
+       uint8_t ucBytes[24];\r
+       uint32_t ulWords[6];\r
+} UDPPacketHeader_t;\r
+extern UDPPacketHeader_t xDefaultPartUDPPacketHeader;\r
+\r
+/* Structure that stores the netmask, gateway address and DNS server addresses. */\r
+extern NetworkAddressingParameters_t xNetworkAddressing;\r
+\r
+/* Structure that stores the defaults for netmask, gateway address and DNS.\r
+These values will be copied to 'xNetworkAddressing' in case DHCP is not used,\r
+and also in case DHCP does not lead to a confirmed request. */\r
+extern NetworkAddressingParameters_t xDefaultAddressing;\r
+\r
+/* True when BufferAllocation_1.c was included, false for BufferAllocation_2.c */\r
+extern const BaseType_t xBufferAllocFixedSize;\r
+\r
+/* Defined in FreeRTOS_Sockets.c */\r
+#if ( ipconfigUSE_TCP == 1 )\r
+       extern List_t xBoundTCPSocketsList;\r
+#endif\r
+\r
+/* The local IP address is accessed from within xDefaultPartUDPPacketHeader,\r
+rather than duplicated in its own variable. */\r
+#define ipLOCAL_IP_ADDRESS_POINTER ( ( uint32_t * ) &( xDefaultPartUDPPacketHeader.ulWords[ 20u / sizeof(uint32_t) ] ) )\r
+\r
+/* The local MAC address is accessed from within xDefaultPartUDPPacketHeader,\r
+rather than duplicated in its own variable. */\r
+#define ipLOCAL_MAC_ADDRESS ( &xDefaultPartUDPPacketHeader.ucBytes[0] )\r
+\r
+/* ICMP packets are sent using the same function as UDP packets.  The port\r
+number is used to distinguish between the two, as 0 is an invalid UDP port. */\r
+#define ipPACKET_CONTAINS_ICMP_DATA                                    ( 0 )\r
+\r
+/* For now, the lower 8 bits in 'xEventBits' will be reserved for the above\r
+socket events. */\r
+#define SOCKET_EVENT_BIT_COUNT   8\r
+\r
+#define vSetField16( pxBase, xType, xField, usValue ) \\r
+{ \\r
+       ( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t ) ( ( usValue ) >> 8 ); \\r
+       ( ( uint8_t* )( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( usValue ) & 0xff ); \\r
+}\r
+\r
+#define vSetField32( pxBase, xType, xField, ulValue ) \\r
+{ \\r
+       ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 0 ] = ( uint8_t )   ( ( ulValue ) >> 24 ); \\r
+       ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 1 ] = ( uint8_t ) ( ( ( ulValue ) >> 16 ) & 0xff ); \\r
+       ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 2 ] = ( uint8_t ) ( ( ( ulValue ) >> 8 ) & 0xff ); \\r
+       ( (uint8_t*)( pxBase ) ) [ offsetof( xType, xField ) + 3 ] = ( uint8_t )   ( ( ulValue ) & 0xff ); \\r
+}\r
+\r
+#define vFlip_16( left, right ) \\r
+       do { \\r
+               uint16_t tmp = (left); \\r
+               (left) = (right); \\r
+               (right) = tmp; \\r
+       } while (0)\r
+\r
+#define vFlip_32( left, right ) \\r
+       do { \\r
+               uint32_t tmp = (left); \\r
+               (left) = (right); \\r
+               (right) = tmp; \\r
+       } while (0)\r
+\r
+#ifndef ARRAY_SIZE\r
+       #define ARRAY_SIZE(x)   (BaseType_t)(sizeof(x)/sizeof(x)[0])\r
+#endif\r
+\r
+/*\r
+ * A version of FreeRTOS_GetReleaseNetworkBuffer() that can be called from an\r
+ * interrupt.  If a non zero value is returned, then the calling ISR should\r
+ * perform a context switch before exiting the ISR.\r
+ */\r
+BaseType_t FreeRTOS_ReleaseFreeNetworkBufferFromISR( void );\r
+\r
+/*\r
+ * Create a message that contains a command to initialise the network interface.\r
+ * This is used during initialisation, and at any time the network interface\r
+ * goes down thereafter.  The network interface hardware driver is responsible\r
+ * for sending the message that contains the network interface down command/\r
+ * event.\r
+ *\r
+ * Only use the FreeRTOS_NetworkDownFromISR() version if the function is to be\r
+ * called from an interrupt service routine.  If FreeRTOS_NetworkDownFromISR()\r
+ * returns a non-zero value then a context switch should be performed ebfore\r
+ * the interrupt is exited.\r
+ */\r
+void FreeRTOS_NetworkDown( void );\r
+BaseType_t FreeRTOS_NetworkDownFromISR( void );\r
+\r
+/*\r
+ * Processes incoming ARP packets.\r
+ */\r
+eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame );\r
+\r
+/*\r
+ * Inspect an Ethernet frame to see if it contains data that the stack needs to\r
+ * process.  eProcessBuffer is returned if the frame should be processed by the\r
+ * stack.  eReleaseBuffer is returned if the frame should be discarded.\r
+ */\r
+eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucEthernetBuffer );\r
+\r
+/*\r
+ * Return the checksum generated over xDataLengthBytes from pucNextData.\r
+ */\r
+uint16_t usGenerateChecksum( uint32_t ulSum, const uint8_t * pucNextData, size_t uxDataLengthBytes );\r
+\r
+/* Socket related private functions. */\r
+BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer, uint16_t usPort );\r
+void vNetworkSocketsInit( void );\r
+\r
+/*\r
+ * Returns pdTRUE if the IP task has been created and is initialised.  Otherwise\r
+ * returns pdFALSE.\r
+ */\r
+BaseType_t xIPIsNetworkTaskReady( void );\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+       /*\r
+        * Actually a user thing, but because xBoundTCPSocketsList, let it do by the\r
+        * IP-task\r
+        */\r
+       void vTCPNetStat( void );\r
+\r
+       /*\r
+        * At least one socket needs to check for timeouts\r
+        */\r
+       TickType_t xTCPTimerCheck( BaseType_t xWillSleep );\r
+\r
+       /* Every TCP socket has a buffer space just big enough to store\r
+       the last TCP header received.\r
+       As a reference of this field may be passed to DMA, force the\r
+       alignment to 8 bytes. */\r
+       typedef union\r
+       {\r
+               struct\r
+               {\r
+                       /* Increase the alignment of this union by adding a 64-bit variable. */\r
+                       uint64_t ullAlignmentWord;\r
+               } a;\r
+               struct\r
+               {\r
+                       /* The next field only serves to give 'ucLastPacket' a correct\r
+                       alignment of 8 + 2.  See comments in FreeRTOS_IP.h */\r
+                       uint8_t ucFillPacket[ ipconfigPACKET_FILLER_SIZE ];\r
+                       uint8_t ucLastPacket[ sizeof( TCPPacket_t ) ];\r
+               } u;\r
+       } LastTCPPacket_t;\r
+\r
+       /*\r
+        * Note that the values of all short and long integers in these structs\r
+        * are being stored in the native-endian way\r
+        * Translation should take place when accessing any structure which defines\r
+        * network packets, such as IPHeader_t and TCPHeader_t\r
+        */\r
+       typedef struct TCPSOCKET\r
+       {\r
+               uint32_t ulRemoteIP;            /* IP address of remote machine */\r
+               uint16_t usRemotePort;          /* Port on remote machine */\r
+               struct {\r
+                       /* Most compilers do like bit-flags */\r
+                       uint32_t\r
+                               bMssChange : 1,         /* This socket has seen a change in MSS */\r
+                               bPassAccept : 1,        /* when true, this socket may be returned in a call to accept() */\r
+                               bPassQueued : 1,        /* when true, this socket is an orphan until it gets connected\r
+                                                                        * Why an orphan? Because it may not be returned in a accept() call until it\r
+                                                                        * gets the state eESTABLISHED */\r
+                               bReuseSocket : 1,       /* When a listening socket gets a connection, do not create a new instance but keep on using it */\r
+                               bCloseAfterSend : 1,/* As soon as the last byte has been transmitted, finalise the connection\r
+                                                                        * Useful in e.g. FTP connections, where the last data bytes are sent along with the FIN flag */\r
+                               bUserShutdown : 1,      /* User requesting a graceful shutdown */\r
+                               bCloseRequested : 1,/* Request to finalise the connection */\r
+                               bLowWater : 1,          /* high-water level has been reached. Cleared as soon as 'rx-count < lo-water' */\r
+                               bWinChange : 1,         /* The value of bLowWater has changed, must send a window update */\r
+                               bSendKeepAlive : 1,     /* When this flag is true, a TCP keep-alive message must be send */\r
+                               bWaitKeepAlive : 1,     /* When this flag is true, a TCP keep-alive reply is expected */\r
+                               bConnPrepared : 1,      /* Connecting socket: Message has been prepared */\r
+                               #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+                                       bConnPassed : 1,        /* Connecting socket: Socket has been passed in a successful select()  */\r
+                               #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
+                               bFinAccepted : 1,       /* This socket has received (or sent) a FIN and accepted it */\r
+                               bFinSent : 1,           /* We've sent out a FIN */\r
+                               bFinRecv : 1,           /* We've received a FIN from our peer */\r
+                               bFinAcked : 1,          /* Our FIN packet has been acked */\r
+                               bFinLast : 1,           /* The last ACK (after FIN and FIN+ACK) has been sent or will be sent by the peer */\r
+                               bRxStopped : 1,         /* Application asked to temporarily stop reception */\r
+                               bMallocError : 1,       /* There was an error allocating a stream */\r
+                               bWinScaling : 1;        /* A TCP-Window Scaling option was offered and accepted in the SYN phase. */\r
+               } bits;\r
+               uint32_t ulHighestRxAllowed;\r
+                                                               /* The highest sequence number that we can receive at any moment */\r
+               uint16_t usTimeout;             /* Time (in ticks) after which this socket needs attention */\r
+               uint16_t usCurMSS;              /* Current Maximum Segment Size */\r
+               uint16_t usInitMSS;             /* Initial maximum segment Size */\r
+               uint16_t usChildCount;  /* In case of a listening socket: number of connections on this port number */\r
+               uint16_t usBacklog;             /* In case of a listening socket: maximum number of concurrent connections on this port number */\r
+               uint8_t ucRepCount;             /* Send repeat count, for retransmissions\r
+                                                                * This counter is separate from the xmitCount in the\r
+                                                                * TCP win segments */\r
+               uint8_t ucTCPState;             /* TCP state: see eTCP_STATE */\r
+               struct XSOCKET *pxPeerSocket;   /* for server socket: child, for child socket: parent */\r
+               #if( ipconfigTCP_KEEP_ALIVE == 1 )\r
+                       uint8_t ucKeepRepCount;\r
+                       TickType_t xLastAliveTime;\r
+               #endif /* ipconfigTCP_KEEP_ALIVE */\r
+               #if( ipconfigTCP_HANG_PROTECTION == 1 )\r
+                       TickType_t xLastActTime;\r
+               #endif /* ipconfigTCP_HANG_PROTECTION */\r
+               size_t uxLittleSpace;\r
+               size_t uxEnoughSpace;\r
+               size_t uxRxStreamSize;\r
+               size_t uxTxStreamSize;\r
+               StreamBuffer_t *rxStream;\r
+               StreamBuffer_t *txStream;\r
+               #if( ipconfigUSE_TCP_WIN == 1 )\r
+                       NetworkBufferDescriptor_t *pxAckMessage;\r
+               #endif /* ipconfigUSE_TCP_WIN */\r
+               /* Buffer space to store the last TCP header received. */\r
+               LastTCPPacket_t xPacket;\r
+               uint8_t tcpflags;               /* TCP flags */\r
+               #if( ipconfigUSE_TCP_WIN != 0 )\r
+                       uint8_t ucMyWinScaleFactor;\r
+                       uint8_t ucPeerWinScaleFactor;\r
+               #endif\r
+               #if( ipconfigUSE_CALLBACKS == 1 )\r
+                       FOnTCPReceive_t pxHandleReceive;        /*\r
+                                                                                                * In case of a TCP socket:\r
+                                                                                                * typedef void (* FOnTCPReceive_t) (Socket_t xSocket, void *pData, size_t xLength );\r
+                                                                                                */\r
+                       FOnTCPSent_t pxHandleSent;\r
+                       FOnConnected_t pxHandleConnected;       /* Actually type: typedef void (* FOnConnected_t) (Socket_t xSocket, BaseType_t ulConnected ); */\r
+               #endif /* ipconfigUSE_CALLBACKS */\r
+               uint32_t ulWindowSize;          /* Current Window size advertised by peer */\r
+               uint32_t ulRxCurWinSize;        /* Constantly changing: this is the current size available for data reception */\r
+               size_t uxRxWinSize;     /* Fixed value: size of the TCP reception window */\r
+               size_t uxTxWinSize;     /* Fixed value: size of the TCP transmit window */\r
+\r
+               TCPWindow_t xTCPWindow;\r
+       } IPTCPSocket_t;\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+\r
+typedef struct UDPSOCKET\r
+{\r
+       List_t xWaitingPacketsList;     /* Incoming packets */\r
+       #if( ipconfigUDP_MAX_RX_PACKETS > 0 )\r
+               UBaseType_t uxMaxPackets; /* Protection: limits the number of packets buffered per socket */\r
+       #endif /* ipconfigUDP_MAX_RX_PACKETS */\r
+       #if( ipconfigUSE_CALLBACKS == 1 )\r
+               FOnUDPReceive_t pxHandleReceive;        /*\r
+                                                                                        * In case of a UDP socket:\r
+                                                                                        * typedef void (* FOnUDPReceive_t) (Socket_t xSocket, void *pData, size_t xLength, struct freertos_sockaddr *pxAddr );\r
+                                                                                        */\r
+               FOnUDPSent_t pxHandleSent;\r
+       #endif /* ipconfigUSE_CALLBACKS */\r
+} IPUDPSocket_t;\r
+\r
+typedef enum eSOCKET_EVENT {\r
+       eSOCKET_RECEIVE = 0x0001,\r
+       eSOCKET_SEND    = 0x0002,\r
+       eSOCKET_ACCEPT  = 0x0004,\r
+       eSOCKET_CONNECT = 0x0008,\r
+       eSOCKET_BOUND   = 0x0010,\r
+       eSOCKET_CLOSED  = 0x0020,\r
+       eSOCKET_INTR    = 0x0040,\r
+       eSOCKET_ALL             = 0x007F,\r
+} eSocketEvent_t;\r
+\r
+typedef struct XSOCKET\r
+{\r
+       EventBits_t xEventBits;\r
+       EventGroupHandle_t xEventGroup;\r
+\r
+       ListItem_t xBoundSocketListItem; /* Used to reference the socket from a bound sockets list. */\r
+       TickType_t xReceiveBlockTime; /* if recv[to] is called while no data is available, wait this amount of time. Unit in clock-ticks */\r
+       TickType_t xSendBlockTime; /* if send[to] is called while there is not enough space to send, wait this amount of time. Unit in clock-ticks */\r
+\r
+       uint16_t usLocalPort;           /* Local port on this machine */\r
+       uint8_t ucSocketOptions;\r
+       uint8_t ucProtocol; /* choice of FREERTOS_IPPROTO_UDP/TCP */\r
+       #if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )\r
+               SemaphoreHandle_t pxUserSemaphore;\r
+       #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */\r
+       #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+               struct xSOCKET_SET *pxSocketSet;\r
+               /* User may indicate which bits are interesting for this socket. */\r
+               EventBits_t xSelectBits;\r
+               /* These bits indicate the events which have actually occurred.\r
+               They are maintained by the IP-task */\r
+               EventBits_t xSocketBits;\r
+       #endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
+       /* TCP/UDP specific fields: */\r
+       /* Before accessing any member of this structure, it should be confirmed */\r
+       /* that the protocol corresponds with the type of structure */\r
+\r
+       union\r
+       {\r
+               IPUDPSocket_t xUDP;\r
+               #if( ipconfigUSE_TCP == 1 )\r
+                       IPTCPSocket_t xTCP;\r
+                       /* Make sure that xTCP is 8-bytes aligned by\r
+                       declaring a 64-bit variable in the same union */\r
+                       uint64_t ullTCPAlignment;\r
+               #endif /* ipconfigUSE_TCP */\r
+       } u;\r
+} FreeRTOS_Socket_t;\r
+\r
+#if( ipconfigUSE_TCP == 1 )\r
+       /*\r
+        * Lookup a TCP socket, using a multiple matching: both port numbers and\r
+        * return IP address.\r
+        */\r
+       FreeRTOS_Socket_t *pxTCPSocketLookup( uint32_t ulLocalIP, UBaseType_t uxLocalPort, uint32_t ulRemoteIP, UBaseType_t uxRemotePort );\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+\r
+/*\r
+ * Look up a local socket by finding a match with the local port.\r
+ */\r
+FreeRTOS_Socket_t *pxUDPSocketLookup( UBaseType_t uxLocalPort );\r
+\r
+/*\r
+ * Called when the application has generated a UDP packet to send.\r
+ */\r
+void vProcessGeneratedUDPPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer );\r
+\r
+/*\r
+ * Calculate the upper-layer checksum\r
+ * Works both for UDP, ICMP and TCP packages\r
+ * bOut = true: checksum will be set in outgoing packets\r
+ * bOut = false: checksum will be calculated for incoming packets\r
+ *     returning 0xffff means: checksum was correct\r
+ */\r
+uint16_t usGenerateProtocolChecksum( const uint8_t * const pucEthernetBuffer, BaseType_t xOutgoingPacket );\r
+\r
+/*\r
+ * An Ethernet frame has been updated (maybe it was an ARP request or a PING\r
+ * request?) and is to be sent back to its source.\r
+ */\r
+void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType_t xReleaseAfterSend );\r
+\r
+/*\r
+ * The internal version of bind()\r
+ * If 'ulInternal' is true, it is called by the driver\r
+ * The TCP driver needs to bind a socket at the moment a listening socket\r
+ * creates a new connected socket\r
+ */\r
+BaseType_t vSocketBind( FreeRTOS_Socket_t *pxSocket, struct freertos_sockaddr * pxAddress, size_t uxAddressLength, BaseType_t xInternal );\r
+\r
+/*\r
+ * Internal function to add streaming data to a TCP socket. If ulIn == true,\r
+ * data will be added to the rxStream, otherwise to the tXStream.  Normally data\r
+ * will be written with ulOffset == 0, meaning: at the end of the FIFO.  When\r
+ * packet come in out-of-order, an offset will be used to put it in front and\r
+ * the head will not change yet.\r
+ */\r
+int32_t lTCPAddRxdata( FreeRTOS_Socket_t *pxSocket, size_t uxOffset, const uint8_t *pcData, uint32_t ulByteCount );\r
+\r
+/*\r
+ * Currently called for any important event.\r
+ */\r
+void vSocketWakeUpUser( FreeRTOS_Socket_t *pxSocket );\r
+\r
+/*\r
+ * Some helping function, their meaning should be clear\r
+ */\r
+static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr);\r
+static portINLINE uint32_t ulChar2u32 (const uint8_t *apChr)\r
+{\r
+       return  ( ( ( uint32_t )apChr[0] ) << 24) |\r
+                       ( ( ( uint32_t )apChr[1] ) << 16) |\r
+                       ( ( ( uint32_t )apChr[2] ) << 8) |\r
+                       ( ( ( uint32_t )apChr[3] ) );\r
+}\r
+\r
+static portINLINE uint16_t usChar2u16 (const uint8_t *apChr);\r
+static portINLINE uint16_t usChar2u16 (const uint8_t *apChr)\r
+{\r
+       return ( uint16_t )\r
+                       ( ( ( ( uint32_t )apChr[0] ) << 8) |\r
+                         ( ( ( uint32_t )apChr[1] ) ) );\r
+}\r
+\r
+/* Check a single socket for retransmissions and timeouts */\r
+BaseType_t xTCPSocketCheck( FreeRTOS_Socket_t *pxSocket );\r
+\r
+BaseType_t xTCPCheckNewClient( FreeRTOS_Socket_t *pxSocket );\r
+\r
+/* Defined in FreeRTOS_Sockets.c\r
+ * Close a socket\r
+ */\r
+void *vSocketClose( FreeRTOS_Socket_t *pxSocket );\r
+\r
+/*\r
+ * Send the event eEvent to the IP task event queue, using a block time of\r
+ * zero.  Return pdPASS if the message was sent successfully, otherwise return\r
+ * pdFALSE.\r
+*/\r
+BaseType_t xSendEventToIPTask( eIPEvent_t eEvent );\r
+\r
+/*\r
+ * The same as above, but a struct as a parameter, containing:\r
+ *             eIPEvent_t eEventType;\r
+ *             void *pvData;\r
+ */\r
+BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t xTimeout );\r
+\r
+/*\r
+ * Returns a pointer to the original NetworkBuffer from a pointer to a UDP\r
+ * payload buffer.\r
+ */\r
+NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( void *pvBuffer );\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       /*\r
+        * For the case where the network driver passes a buffer directly to a DMA\r
+        * descriptor, this function can be used to translate a 'network buffer' to\r
+        * a 'network buffer descriptor'.\r
+        */\r
+       NetworkBufferDescriptor_t *pxPacketBuffer_to_NetworkBuffer( const void *pvBuffer );\r
+#endif\r
+\r
+/*\r
+ * Internal: Sets a new state for a TCP socket and performs the necessary\r
+ * actions like calling a OnConnected handler to notify the socket owner.\r
+ */\r
+#if( ipconfigUSE_TCP == 1 )\r
+       void vTCPStateChange( FreeRTOS_Socket_t *pxSocket, enum eTCP_STATE eTCPState );\r
+#endif /* ipconfigUSE_TCP */\r
+\r
+/*_RB_ Should this be part of the public API? */\r
+void FreeRTOS_netstat( void );\r
+\r
+/* Returns pdTRUE is this function is called from the IP-task */\r
+BaseType_t xIsCallingFromIPTask( void );\r
+\r
+#if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )\r
+\r
+typedef struct xSOCKET_SET\r
+{\r
+       EventGroupHandle_t xSelectGroup;\r
+       BaseType_t bApiCalled;  /* True if the API was calling  the private vSocketSelect */\r
+       FreeRTOS_Socket_t *pxSocket;\r
+} SocketSelect_t;\r
+\r
+extern void vSocketSelect( SocketSelect_t *pxSocketSelect );\r
+\r
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
+\r
+void vIPSetDHCPTimerEnableState( BaseType_t xEnableState );\r
+void vIPReloadDHCPTimer( uint32_t ulLeaseTime );\r
+#if( ipconfigDNS_USE_CALLBACKS != 0 )\r
+       void vIPReloadDNSTimer( uint32_t ulCheckTime );\r
+       void vIPSetDnsTimerEnableState( BaseType_t xEnableState );\r
+#endif\r
+\r
+/* Send the network-up event and start the ARP timer. */\r
+void vIPNetworkUpCalls( void );\r
+\r
+#ifdef __cplusplus\r
+} /* extern "C" */\r
+#endif\r
+\r
+#endif /* FREERTOS_IP_PRIVATE_H */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Sockets.h
new file mode 100644 (file)
index 0000000..87fb7bb
--- /dev/null
@@ -0,0 +1,420 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef FREERTOS_SOCKETS_H\r
+#define FREERTOS_SOCKETS_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* Standard includes. */\r
+#include <string.h>\r
+\r
+/* Application level configuration options. */\r
+#include "FreeRTOSIPConfig.h"\r
+\r
+#ifndef FREERTOS_IP_CONFIG_H\r
+       #error FreeRTOSIPConfig.h has not been included yet\r
+#endif\r
+\r
+/* Event bit definitions are required by the select functions. */\r
+#include "event_groups.h"\r
+\r
+#ifndef INC_FREERTOS_H\r
+       #error FreeRTOS.h must be included before FreeRTOS_Sockets.h.\r
+#endif\r
+\r
+#ifndef INC_TASK_H\r
+       #ifndef TASK_H /* For compatibility with older FreeRTOS versions. */\r
+               #error The FreeRTOS header file task.h must be included before FreeRTOS_Sockets.h.\r
+       #endif\r
+#endif\r
+\r
+/* Assigned to an Socket_t variable when the socket is not valid, probably\r
+because it could not be created. */\r
+#define FREERTOS_INVALID_SOCKET        ( ( void * ) ~0U )\r
+\r
+/* API function error values.  As errno is supported, the FreeRTOS sockets\r
+functions return error codes rather than just a pass or fail indication. */\r
+/* HT: Extended the number of error codes, gave them positive values and if possible\r
+the corresponding found in errno.h\r
+In case of an error, API's will still return negative numbers, e.g.\r
+  return -pdFREERTOS_ERRNO_EWOULDBLOCK;\r
+in case an operation would block */\r
+\r
+/* The following defines are obsolete, please use -pdFREERTOS_ERRNO_Exxx */\r
+\r
+#define FREERTOS_SOCKET_ERROR  ( -1 )\r
+#define FREERTOS_EWOULDBLOCK   ( - pdFREERTOS_ERRNO_EWOULDBLOCK )\r
+#define FREERTOS_EINVAL                        ( - pdFREERTOS_ERRNO_EINVAL )\r
+#define FREERTOS_EADDRNOTAVAIL ( - pdFREERTOS_ERRNO_EADDRNOTAVAIL )\r
+#define FREERTOS_EADDRINUSE            ( - pdFREERTOS_ERRNO_EADDRINUSE )\r
+#define FREERTOS_ENOBUFS               ( - pdFREERTOS_ERRNO_ENOBUFS )\r
+#define FREERTOS_ENOPROTOOPT   ( - pdFREERTOS_ERRNO_ENOPROTOOPT )\r
+#define FREERTOS_ECLOSED               ( - pdFREERTOS_ERRNO_ENOTCONN )\r
+\r
+/* Values for the parameters to FreeRTOS_socket(), inline with the Berkeley\r
+standard.  See the documentation of FreeRTOS_socket() for more information. */\r
+#define FREERTOS_AF_INET               ( 2 )\r
+#define FREERTOS_AF_INET6              ( 10 )\r
+#define FREERTOS_SOCK_DGRAM            ( 2 )\r
+#define FREERTOS_IPPROTO_UDP   ( 17 )\r
+\r
+#define FREERTOS_SOCK_STREAM   ( 1 )\r
+#define FREERTOS_IPPROTO_TCP   ( 6 )\r
+/* IP packet of type "Any local network"\r
+ * can be used in stead of TCP for testing with sockets in raw mode\r
+ */\r
+#define FREERTOS_IPPROTO_USR_LAN  ( 63 )\r
+\r
+/* A bit value that can be passed into the FreeRTOS_sendto() function as part of\r
+the flags parameter.  Setting the FREERTOS_ZERO_COPY in the flags parameter\r
+indicates that the zero copy interface is being used.  See the documentation for\r
+FreeRTOS_sockets() for more information. */\r
+#define FREERTOS_ZERO_COPY             ( 1 )\r
+\r
+/* Values that can be passed in the option name parameter of calls to\r
+FreeRTOS_setsockopt(). */\r
+#define FREERTOS_SO_RCVTIMEO                   ( 0 )           /* Used to set the receive time out. */\r
+#define FREERTOS_SO_SNDTIMEO                   ( 1 )           /* Used to set the send time out. */\r
+#define FREERTOS_SO_UDPCKSUM_OUT               ( 2 )           /* Used to turn the use of the UDP checksum by a socket on or off.  This also doubles as part of an 8-bit bitwise socket option. */\r
+#if( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )\r
+       #define FREERTOS_SO_SET_SEMAPHORE       ( 3 )           /* Used to set a user's semaphore */\r
+#endif\r
+#define FREERTOS_SO_SNDBUF                             ( 4 )           /* Set the size of the send buffer (TCP only) */\r
+#define FREERTOS_SO_RCVBUF                             ( 5 )           /* Set the size of the receive buffer (TCP only) */\r
+\r
+#if ipconfigUSE_CALLBACKS == 1\r
+#define FREERTOS_SO_TCP_CONN_HANDLER   ( 6 )           /* Install a callback for (dis) connection events. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
+#define FREERTOS_SO_TCP_RECV_HANDLER   ( 7 )           /* Install a callback for receiving TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
+#define FREERTOS_SO_TCP_SENT_HANDLER   ( 8 )           /* Install a callback for sending TCP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
+#define FREERTOS_SO_UDP_RECV_HANDLER   ( 9 )           /* Install a callback for receiving UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
+#define FREERTOS_SO_UDP_SENT_HANDLER   ( 10 )          /* Install a callback for sending UDP data. Supply pointer to 'F_TCP_UDP_Handler_t' (see below) */\r
+#endif /* ipconfigUSE_CALLBACKS */\r
+\r
+#define FREERTOS_SO_REUSE_LISTEN_SOCKET        ( 11 )          /* When a listening socket gets connected, do not create a new one but re-use it */\r
+#define FREERTOS_SO_CLOSE_AFTER_SEND   ( 12 )          /* As soon as the last byte has been transmitted, finalise the connection */\r
+#define FREERTOS_SO_WIN_PROPERTIES             ( 13 )          /* Set all buffer and window properties in one call, parameter is pointer to WinProperties_t */\r
+#define FREERTOS_SO_SET_FULL_SIZE              ( 14 )          /* Refuse to send packets smaller than MSS  */\r
+\r
+#define FREERTOS_SO_STOP_RX                            ( 15 )          /* Tempoarily hold up reception, used by streaming client */\r
+\r
+#if( ipconfigUDP_MAX_RX_PACKETS > 0 )\r
+       #define FREERTOS_SO_UDP_MAX_RX_PACKETS  ( 16 )          /* This option helps to limit the maximum number of packets a UDP socket will buffer */\r
+#endif\r
+\r
+#define FREERTOS_NOT_LAST_IN_FRAGMENTED_PACKET         ( 0x80 )  /* For internal use only, but also part of an 8-bit bitwise value. */\r
+#define FREERTOS_FRAGMENTED_PACKET                             ( 0x40 )  /* For internal use only, but also part of an 8-bit bitwise value. */\r
+\r
+/* Values for flag for FreeRTOS_shutdown(). */\r
+#define FREERTOS_SHUT_RD                               ( 0 )           /* Not really at this moment, just for compatibility of the interface */\r
+#define FREERTOS_SHUT_WR                               ( 1 )\r
+#define FREERTOS_SHUT_RDWR                             ( 2 )\r
+\r
+/* Values for flag for FreeRTOS_recv(). */\r
+#define FREERTOS_MSG_OOB                               ( 2 )           /* process out-of-band data */\r
+#define FREERTOS_MSG_PEEK                              ( 4 )           /* peek at incoming message */\r
+#define FREERTOS_MSG_DONTROUTE                 ( 8 )           /* send without using routing tables */\r
+#define FREERTOS_MSG_DONTWAIT                  ( 16 )          /* Can be used with recvfrom(), sendto(), recv(), and send(). */\r
+\r
+typedef struct xWIN_PROPS {\r
+       /* Properties of the Tx buffer and Tx window */\r
+       int32_t lTxBufSize;     /* Unit: bytes */\r
+       int32_t lTxWinSize;     /* Unit: MSS */\r
+\r
+       /* Properties of the Rx buffer and Rx window */\r
+       int32_t lRxBufSize;     /* Unit: bytes */\r
+       int32_t lRxWinSize;     /* Unit: MSS */\r
+} WinProperties_t;\r
+\r
+/* For compatibility with the expected Berkeley sockets naming. */\r
+#define socklen_t uint32_t\r
+\r
+/* For this limited implementation, only two members are required in the\r
+Berkeley style sockaddr structure. */\r
+struct freertos_sockaddr\r
+{\r
+       /* _HT_ On 32- and 64-bit architectures, the addition of the two uint8_t\r
+       fields doesn't make the structure bigger, due to alignment.\r
+       The fields are inserted as a preparation for IPv6. */\r
+\r
+       /* sin_len and sin_family not used in the IPv4-only release. */\r
+       uint8_t sin_len;                /* length of this structure. */\r
+       uint8_t sin_family;             /* FREERTOS_AF_INET. */\r
+       uint16_t sin_port;\r
+       uint32_t sin_addr;\r
+};\r
+\r
+#if ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN\r
+\r
+       #define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 )                              \\r
+                                                                               ( ( ( ( uint32_t ) ( ucOctet3 ) ) << 24UL ) |           \\r
+                                                                               ( ( ( uint32_t ) ( ucOctet2 ) ) << 16UL ) |                     \\r
+                                                                               ( ( ( uint32_t ) ( ucOctet1 ) ) <<  8UL ) |                     \\r
+                                                                               ( ( uint32_t ) ( ucOctet0 ) ) )\r
+\r
+       #define FreeRTOS_inet_ntoa( ulIPAddress, pucBuffer )                                                                    \\r
+                                                               sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u",                       \\r
+                                                                       ( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ),                  \\r
+                                                                       ( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \\r
+                                                                       ( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ),\\r
+                                                                       ( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ) )\r
+\r
+#else /* ipconfigBYTE_ORDER */\r
+\r
+       #define FreeRTOS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 )                              \\r
+                                                                               ( ( ( ( uint32_t ) ( ucOctet0 ) ) << 24UL ) |           \\r
+                                                                               ( ( ( uint32_t ) ( ucOctet1 ) ) << 16UL ) |                     \\r
+                                                                               ( ( ( uint32_t ) ( ucOctet2 ) ) <<  8UL ) |                     \\r
+                                                                               ( ( uint32_t ) ( ucOctet3 ) ) )\r
+\r
+       #define FreeRTOS_inet_ntoa( ulIPAddress, pucBuffer )                                                                    \\r
+                                                               sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u",                       \\r
+                                                                       ( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ),                             \\r
+                                                                       ( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ),\\r
+                                                                       ( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \\r
+                                                                       ( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ) )\r
+\r
+#endif /* ipconfigBYTE_ORDER */\r
+\r
+/* The socket type itself. */\r
+typedef void *Socket_t;\r
+\r
+/* The SocketSet_t type is the equivalent to the fd_set type used by the\r
+Berkeley API. */\r
+typedef void *SocketSet_t;\r
+\r
+/**\r
+ * FULL, UP-TO-DATE AND MAINTAINED REFERENCE DOCUMENTATION FOR ALL THESE\r
+ * FUNCTIONS IS AVAILABLE ON THE FOLLOWING URL:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/FreeRTOS_TCP_API_Functions.html\r
+ */\r
+Socket_t FreeRTOS_socket( BaseType_t xDomain, BaseType_t xType, BaseType_t xProtocol );\r
+int32_t FreeRTOS_recvfrom( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags, struct freertos_sockaddr *pxSourceAddress, socklen_t *pxSourceAddressLength );\r
+int32_t FreeRTOS_sendto( Socket_t xSocket, const void *pvBuffer, size_t xTotalDataLength, BaseType_t xFlags, const struct freertos_sockaddr *pxDestinationAddress, socklen_t xDestinationAddressLength );\r
+BaseType_t FreeRTOS_bind( Socket_t xSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength );\r
+\r
+/* function to get the local address and IP port */\r
+size_t FreeRTOS_GetLocalAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress );\r
+\r
+/* Made available when ipconfigETHERNET_DRIVER_FILTERS_PACKETS is set to 1. */\r
+BaseType_t xPortHasUDPSocket( uint16_t usPortNr );\r
+\r
+#if ipconfigUSE_TCP == 1\r
+\r
+BaseType_t FreeRTOS_connect( Socket_t xClientSocket, struct freertos_sockaddr *pxAddress, socklen_t xAddressLength );\r
+BaseType_t FreeRTOS_listen( Socket_t xSocket, BaseType_t xBacklog );\r
+BaseType_t FreeRTOS_recv( Socket_t xSocket, void *pvBuffer, size_t xBufferLength, BaseType_t xFlags );\r
+BaseType_t FreeRTOS_send( Socket_t xSocket, const void *pvBuffer, size_t uxDataLength, BaseType_t xFlags );\r
+Socket_t FreeRTOS_accept( Socket_t xServerSocket, struct freertos_sockaddr *pxAddress, socklen_t *pxAddressLength );\r
+BaseType_t FreeRTOS_shutdown (Socket_t xSocket, BaseType_t xHow);\r
+\r
+#if( ipconfigSUPPORT_SIGNALS != 0 )\r
+       /* Send a signal to the task which is waiting for a given socket. */\r
+       BaseType_t FreeRTOS_SignalSocket( Socket_t xSocket );\r
+\r
+       /* Send a signal to the task which reads from this socket (FromISR\r
+       version). */\r
+       BaseType_t FreeRTOS_SignalSocketFromISR( Socket_t xSocket, BaseType_t *pxHigherPriorityTaskWoken );\r
+#endif /* ipconfigSUPPORT_SIGNALS */\r
+\r
+/* Return the remote address and IP port. */\r
+BaseType_t FreeRTOS_GetRemoteAddress( Socket_t xSocket, struct freertos_sockaddr *pxAddress );\r
+\r
+/* returns pdTRUE if TCP socket is connected */\r
+BaseType_t FreeRTOS_issocketconnected( Socket_t xSocket );\r
+\r
+/* returns the actual size of MSS being used */\r
+BaseType_t FreeRTOS_mss( Socket_t xSocket );\r
+\r
+/* for internal use only: return the connection status */\r
+BaseType_t FreeRTOS_connstatus( Socket_t xSocket );\r
+\r
+/* Returns the number of bytes that may be added to txStream */\r
+BaseType_t FreeRTOS_maywrite( Socket_t xSocket );\r
+\r
+/*\r
+ * Two helper functions, mostly for testing\r
+ * rx_size returns the number of bytes available in the Rx buffer\r
+ * tx_space returns the free space in the Tx buffer\r
+ */\r
+BaseType_t FreeRTOS_rx_size( Socket_t xSocket );\r
+BaseType_t FreeRTOS_tx_space( Socket_t xSocket );\r
+BaseType_t FreeRTOS_tx_size( Socket_t xSocket );\r
+\r
+/* Returns the number of outstanding bytes in txStream. */\r
+/* The function FreeRTOS_outstanding() was already implemented\r
+FreeRTOS_tx_size(). */\r
+#define FreeRTOS_outstanding( xSocket )        FreeRTOS_tx_size( xSocket )\r
+\r
+/* Returns the number of bytes in the socket's rxStream. */\r
+/* The function FreeRTOS_recvcount() was already implemented\r
+FreeRTOS_rx_size(). */\r
+#define FreeRTOS_recvcount( xSocket )  FreeRTOS_rx_size( xSocket )\r
+\r
+/*\r
+ * For advanced applications only:\r
+ * Get a direct pointer to the circular transmit buffer.\r
+ * '*pxLength' will contain the number of bytes that may be written.\r
+ */\r
+uint8_t *FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t *pxLength );\r
+\r
+#endif /* ipconfigUSE_TCP */\r
+\r
+/*\r
+ * Connect / disconnect handler for a TCP socket\r
+ * For example:\r
+ *             static void vMyConnectHandler (Socket_t xSocket, BaseType_t ulConnected)\r
+ *             {\r
+ *             }\r
+ *             F_TCP_UDP_Handler_t xHnd = { vMyConnectHandler };\r
+ *             FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_CONN_HANDLER, ( void * ) &xHnd, sizeof( xHnd ) );\r
+ */\r
+\r
+typedef void (* FOnConnected_t )( Socket_t /* xSocket */, BaseType_t /* ulConnected */ );\r
+\r
+/*\r
+ * Reception handler for a TCP socket\r
+ * A user-proved function will be called on reception of a message\r
+ * If the handler returns a positive number, the messages will not be stored\r
+ * For example:\r
+ *             static BaseType_t xOnTCPReceive( Socket_t xSocket, void * pData, size_t xLength )\r
+ *             {\r
+ *                     // handle the message\r
+ *                     return 1;\r
+ *             }\r
+ *             F_TCP_UDP_Handler_t xHand = { xOnTCPReceive };\r
+ *             FreeRTOS_setsockopt( sock, 0, FREERTOS_SO_TCP_RECV_HANDLER, ( void * ) &xHand, sizeof( xHand ) );\r
+ */\r
+typedef BaseType_t (* FOnTCPReceive_t )( Socket_t /* xSocket */, void * /* pData */, size_t /* xLength */ );\r
+typedef void (* FOnTCPSent_t )( Socket_t /* xSocket */, size_t /* xLength */ );\r
+\r
+/*\r
+ * Reception handler for a UDP socket\r
+ * A user-proved function will be called on reception of a message\r
+ * If the handler returns a positive number, the messages will not be stored\r
+ */\r
+typedef BaseType_t (* FOnUDPReceive_t ) (Socket_t /* xSocket */, void * /* pData */, size_t /* xLength */,\r
+       const struct freertos_sockaddr * /* pxFrom */, const struct freertos_sockaddr * /* pxDest */ );\r
+typedef void (* FOnUDPSent_t )( Socket_t /* xSocket */, size_t /* xLength */ );\r
+\r
+\r
+typedef union xTCP_UDP_HANDLER\r
+{\r
+       FOnConnected_t  pxOnTCPConnected;       /* FREERTOS_SO_TCP_CONN_HANDLER */\r
+       FOnTCPReceive_t pxOnTCPReceive;         /* FREERTOS_SO_TCP_RECV_HANDLER */\r
+       FOnTCPSent_t    pxOnTCPSent;            /* FREERTOS_SO_TCP_SENT_HANDLER */\r
+       FOnUDPReceive_t pxOnUDPReceive;         /* FREERTOS_SO_UDP_RECV_HANDLER */\r
+       FOnUDPSent_t    pxOnUDPSent;            /* FREERTOS_SO_UDP_SENT_HANDLER */\r
+} F_TCP_UDP_Handler_t;\r
+\r
+BaseType_t FreeRTOS_setsockopt( Socket_t xSocket, int32_t lLevel, int32_t lOptionName, const void *pvOptionValue, size_t xOptionLength );\r
+BaseType_t FreeRTOS_closesocket( Socket_t xSocket );\r
+uint32_t FreeRTOS_gethostbyname( const char *pcHostName );\r
+uint32_t FreeRTOS_inet_addr( const char * pcIPAddress );\r
+\r
+/*\r
+ * For the web server: borrow the circular Rx buffer for inspection\r
+ * HTML driver wants to see if a sequence of 13/10/13/10 is available\r
+ */\r
+const struct xSTREAM_BUFFER *FreeRTOS_get_rx_buf( Socket_t xSocket );\r
+\r
+void FreeRTOS_netstat( void );\r
+\r
+#if ipconfigSUPPORT_SELECT_FUNCTION == 1\r
+\r
+       /* For FD_SET and FD_CLR, a combination of the following bits can be used: */\r
+\r
+       typedef enum eSELECT_EVENT {\r
+               eSELECT_READ    = 0x0001,\r
+               eSELECT_WRITE   = 0x0002,\r
+               eSELECT_EXCEPT  = 0x0004,\r
+               eSELECT_INTR    = 0x0008,\r
+               eSELECT_ALL             = 0x000F,\r
+               /* Reserved for internal use: */\r
+               eSELECT_CALL_IP = 0x0010,\r
+               /* end */\r
+       } eSelectEvent_t;\r
+\r
+       SocketSet_t FreeRTOS_CreateSocketSet( void );\r
+       void FreeRTOS_DeleteSocketSet( SocketSet_t xSocketSet );\r
+       void FreeRTOS_FD_SET( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xBitsToSet );\r
+       void FreeRTOS_FD_CLR( Socket_t xSocket, SocketSet_t xSocketSet, EventBits_t xBitsToClear );\r
+       EventBits_t FreeRTOS_FD_ISSET( Socket_t xSocket, SocketSet_t xSocketSet );\r
+       BaseType_t FreeRTOS_select( SocketSet_t xSocketSet, TickType_t xBlockTimeTicks );\r
+\r
+#endif /* ipconfigSUPPORT_SELECT_FUNCTION */\r
+\r
+#ifdef __cplusplus\r
+} // extern "C"\r
+#endif\r
+\r
+#endif /* FREERTOS_SOCKETS_H */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_Stream_Buffer.h
new file mode 100644 (file)
index 0000000..9b84f97
--- /dev/null
@@ -0,0 +1,288 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*\r
+ *     FreeRTOS_Stream_Buffer.h\r
+ *\r
+ *     A cicular character buffer\r
+ *     An implementation of a circular buffer without a length field\r
+ *     If LENGTH defines the size of the buffer, a maximum of (LENGT-1) bytes can be stored\r
+ *     In order to add or read data from the buffer, memcpy() will be called at most 2 times\r
+ */\r
+\r
+#ifndef FREERTOS_STREAM_BUFFER_H\r
+#define        FREERTOS_STREAM_BUFFER_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+typedef struct xSTREAM_BUFFER {\r
+       volatile size_t uxTail;         /* next item to read */\r
+       volatile size_t uxMid;          /* iterator within the valid items */\r
+       volatile size_t uxHead;         /* next position store a new item */\r
+       volatile size_t uxFront;        /* iterator within the free space */\r
+       size_t LENGTH;                          /* const value: number of reserved elements */\r
+       uint8_t ucArray[ sizeof( size_t ) ];\r
+} StreamBuffer_t;\r
+\r
+static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer );\r
+static portINLINE void vStreamBufferClear( StreamBuffer_t *pxBuffer )\r
+{\r
+       /* Make the circular buffer empty */\r
+       pxBuffer->uxHead = 0u;\r
+       pxBuffer->uxTail = 0u;\r
+       pxBuffer->uxFront = 0u;\r
+       pxBuffer->uxMid = 0u;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper );\r
+static portINLINE size_t uxStreamBufferSpace( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper )\r
+{\r
+/* Returns the space between uxLower and uxUpper, which equals to the distance minus 1 */\r
+size_t uxCount;\r
+\r
+       uxCount = pxBuffer->LENGTH + uxUpper - uxLower - 1u;\r
+       if( uxCount >= pxBuffer->LENGTH )\r
+       {\r
+               uxCount -= pxBuffer->LENGTH;\r
+       }\r
+\r
+       return uxCount;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper );\r
+static portINLINE size_t uxStreamBufferDistance( const StreamBuffer_t *pxBuffer, const size_t uxLower, const size_t uxUpper )\r
+{\r
+/* Returns the distance between uxLower and uxUpper */\r
+size_t uxCount;\r
+\r
+       uxCount = pxBuffer->LENGTH + uxUpper - uxLower;\r
+       if ( uxCount >= pxBuffer->LENGTH )\r
+       {\r
+               uxCount -= pxBuffer->LENGTH;\r
+       }\r
+\r
+       return uxCount;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t *pxBuffer );\r
+static portINLINE size_t uxStreamBufferGetSpace( const StreamBuffer_t *pxBuffer )\r
+{\r
+/* Returns the number of items which can still be added to uxHead\r
+before hitting on uxTail */\r
+size_t uxHead = pxBuffer->uxHead;\r
+size_t uxTail = pxBuffer->uxTail;\r
+\r
+       return uxStreamBufferSpace( pxBuffer, uxHead, uxTail );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t *pxBuffer );\r
+static portINLINE size_t uxStreamBufferFrontSpace( const StreamBuffer_t *pxBuffer )\r
+{\r
+/* Distance between uxFront and uxTail\r
+or the number of items which can still be added to uxFront,\r
+before hitting on uxTail */\r
+\r
+size_t uxFront = pxBuffer->uxFront;\r
+size_t uxTail = pxBuffer->uxTail;\r
+\r
+       return uxStreamBufferSpace( pxBuffer, uxFront, uxTail );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t *pxBuffer );\r
+static portINLINE size_t uxStreamBufferGetSize( const StreamBuffer_t *pxBuffer )\r
+{\r
+/* Returns the number of items which can be read from uxTail\r
+before reaching uxHead */\r
+size_t uxHead = pxBuffer->uxHead;\r
+size_t uxTail = pxBuffer->uxTail;\r
+\r
+       return uxStreamBufferDistance( pxBuffer, uxTail, uxHead );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t *pxBuffer );\r
+static portINLINE size_t uxStreamBufferMidSpace( const StreamBuffer_t *pxBuffer )\r
+{\r
+/* Returns the distance between uxHead and uxMid */\r
+size_t uxHead = pxBuffer->uxHead;\r
+size_t uxMid = pxBuffer->uxMid;\r
+\r
+       return uxStreamBufferDistance( pxBuffer, uxMid, uxHead );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t uxCount );\r
+static portINLINE void vStreamBufferMoveMid( StreamBuffer_t *pxBuffer, size_t uxCount )\r
+{\r
+/* Increment uxMid, but no further than uxHead */\r
+size_t uxSize = uxStreamBufferMidSpace( pxBuffer );\r
+\r
+       if( uxCount > uxSize )\r
+       {\r
+               uxCount = uxSize;\r
+       }\r
+       pxBuffer->uxMid += uxCount;\r
+       if( pxBuffer->uxMid >= pxBuffer->LENGTH )\r
+       {\r
+               pxBuffer->uxMid -= pxBuffer->LENGTH;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+static portINLINE BaseType_t xStreamBufferIsEmpty( const StreamBuffer_t *pxBuffer );\r
+static portINLINE BaseType_t xStreamBufferIsEmpty( const StreamBuffer_t *pxBuffer )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       /* True if no item is available */\r
+       if( pxBuffer->uxHead == pxBuffer->uxTail )\r
+       {\r
+               xReturn = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdFALSE;\r
+       }\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE BaseType_t xStreamBufferIsFull( const StreamBuffer_t *pxBuffer );\r
+static portINLINE BaseType_t xStreamBufferIsFull( const StreamBuffer_t *pxBuffer )\r
+{\r
+       /* True if the available space equals zero. */\r
+       return ( BaseType_t ) ( uxStreamBufferGetSpace( pxBuffer ) == 0u );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight );\r
+static portINLINE BaseType_t xStreamBufferLessThenEqual( const StreamBuffer_t *pxBuffer, const size_t uxLeft, const size_t uxRight )\r
+{\r
+BaseType_t xReturn;\r
+size_t uxTail = pxBuffer->uxTail;\r
+\r
+       /* Returns true if ( uxLeft < uxRight ) */\r
+       if( ( uxLeft < uxTail ) ^ ( uxRight < uxTail ) )\r
+       {\r
+               if( uxRight < uxTail )\r
+               {\r
+                       xReturn = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       xReturn = pdFALSE;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if( uxLeft <= uxRight )\r
+               {\r
+                       xReturn = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       xReturn = pdFALSE;\r
+               }\r
+       }\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t *pxBuffer, uint8_t **ppucData );\r
+static portINLINE size_t uxStreamBufferGetPtr( StreamBuffer_t *pxBuffer, uint8_t **ppucData )\r
+{\r
+size_t uxNextTail = pxBuffer->uxTail;\r
+size_t uxSize = uxStreamBufferGetSize( pxBuffer );\r
+\r
+       *ppucData = pxBuffer->ucArray + uxNextTail;\r
+\r
+       return FreeRTOS_min_uint32( uxSize, pxBuffer->LENGTH - uxNextTail );\r
+}\r
+\r
+/*\r
+ * Add bytes to a stream buffer.\r
+ *\r
+ * pxBuffer -  The buffer to which the bytes will be added.\r
+ * uxOffset -  If uxOffset > 0, data will be written at an offset from uxHead\r
+ *                             while uxHead will not be moved yet.\r
+ * pucData -   A pointer to the data to be added.\r
+ * uxCount -   The number of bytes to add.\r
+ */\r
+size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount );\r
+\r
+/*\r
+ * Read bytes from a stream buffer.\r
+ *\r
+ * pxBuffer -  The buffer from which the bytes will be read.\r
+ * uxOffset -  Can be used to read data located at a certain offset from 'uxTail'.\r
+ * pucData -   A pointer to the buffer into which data will be read.\r
+ * uxMaxCount -        The number of bytes to read.\r
+ * xPeek -             If set to pdTRUE the data will remain in the buffer.\r
+ */\r
+size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek );\r
+\r
+#ifdef __cplusplus\r
+} /* extern "C" */\r
+#endif\r
+\r
+#endif /* !defined( FREERTOS_STREAM_BUFFER_H ) */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_IP.h
new file mode 100644 (file)
index 0000000..3d51640
--- /dev/null
@@ -0,0 +1,112 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef FREERTOS_TCP_IP_H\r
+#define FREERTOS_TCP_IP_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t *pxNetworkBuffer );\r
+\r
+typedef enum eTCP_STATE {\r
+       /* Comments about the TCP states are borrowed from the very useful\r
+        * Wiki page:\r
+        * http://en.wikipedia.org/wiki/Transmission_Control_Protocol */\r
+       eCLOSED = 0u,   /* 0 (server + client) no connection state at all. */\r
+       eTCP_LISTEN,    /* 1 (server) waiting for a connection request\r
+                                                from any remote TCP and port. */\r
+       eCONNECT_SYN,   /* 2 (client) internal state: socket wants to send\r
+                                                a connect */\r
+       eSYN_FIRST,             /* 3 (server) Just created, must ACK the SYN request. */\r
+       eSYN_RECEIVED,  /* 4 (server) waiting for a confirming connection request\r
+                                                acknowledgement after having both received and sent a connection request. */\r
+       eESTABLISHED,   /* 5 (server + client) an open connection, data received can be\r
+                                                delivered to the user. The normal state for the data transfer phase of the connection. */\r
+       eFIN_WAIT_1,    /* 6 (server + client) waiting for a connection termination request from the remote TCP,\r
+                                                or an acknowledgement of the connection termination request previously sent. */\r
+       eFIN_WAIT_2,    /* 7 (server + client) waiting for a connection termination request from the remote TCP. */\r
+       eCLOSE_WAIT,    /* 8 (server + client) waiting for a connection termination request from the local user. */\r
+       eCLOSING,               /*   (server + client) waiting for a connection termination request acknowledgement from the remote TCP. */\r
+       eLAST_ACK,              /* 9 (server + client) waiting for an acknowledgement of the connection termination request\r
+                                                previously sent to the remote TCP\r
+                                                (which includes an acknowledgement of its connection termination request). */\r
+       eTIME_WAIT,             /* 10 (either server or client) waiting for enough time to pass to be sure the remote TCP received the\r
+                                                acknowledgement of its connection termination request. [According to RFC 793 a connection can\r
+                                                stay in TIME-WAIT for a maximum of four minutes known as a MSL (maximum segment lifetime).] */\r
+} eIPTCPState_t;\r
+\r
+\r
+#ifdef __cplusplus\r
+} // extern "C"\r
+#endif\r
+\r
+#endif /* FREERTOS_TCP_IP_H */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_TCP_WIN.h
new file mode 100644 (file)
index 0000000..b55c697
--- /dev/null
@@ -0,0 +1,253 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*\r
+ *     FreeRTOS_TCP_WIN.c\r
+ *  Module which handles the TCP windowing schemes for FreeRTOS-PLUS-TCP\r
+ */\r
+\r
+#ifndef        FREERTOS_TCP_WIN_H\r
+#define        FREERTOS_TCP_WIN_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+extern BaseType_t xTCPWindowLoggingLevel;\r
+\r
+typedef struct xTCPTimer\r
+{\r
+       uint32_t ulBorn;\r
+} TCPTimer_t;\r
+\r
+typedef struct xTCP_SEGMENT\r
+{\r
+       uint32_t ulSequenceNumber;              /* The sequence number of the first byte in this packet */\r
+       int32_t lMaxLength;                             /* Maximum space, number of bytes which can be stored in this segment */\r
+       int32_t lDataLength;                    /* Actual number of bytes */\r
+       int32_t lStreamPos;                             /* reference to the [t|r]xStream of the socket */\r
+       TCPTimer_t xTransmitTimer;              /* saves a timestamp at the moment this segment gets transmitted (TX only) */\r
+       union\r
+       {\r
+               struct\r
+               {\r
+                       uint32_t\r
+                               ucTransmitCount : 8,/* Number of times the segment has been transmitted, used to calculate the RTT */\r
+                               ucDupAckCount : 8,      /* Counts the number of times that a higher segment was ACK'd. After 3 times a Fast Retransmission takes place */\r
+                               bOutstanding : 1,       /* It the peer's turn, we're just waiting for an ACK */\r
+                               bAcked : 1,                     /* This segment has been acknowledged */\r
+                               bIsForRx : 1;           /* pdTRUE if segment is used for reception */\r
+               } bits;\r
+               uint32_t ulFlags;\r
+       } u;\r
+#if( ipconfigUSE_TCP_WIN != 0 )\r
+       struct xLIST_ITEM xQueueItem;   /* TX only: segments can be linked in one of three queues: xPriorityQueue, xTxQueue, and xWaitQueue */\r
+       struct xLIST_ITEM xListItem;    /* With this item the segment can be connected to a list, depending on who is owning it */\r
+#endif\r
+} TCPSegment_t;\r
+\r
+typedef struct xTCP_WINSIZE\r
+{\r
+       uint32_t ulRxWindowLength;\r
+       uint32_t ulTxWindowLength;\r
+} TCPWinSize_t;\r
+\r
+/*\r
+ * If TCP time-stamps are being used, they will occupy 12 bytes in\r
+ * each packet, and thus the message space will become smaller\r
+ */\r
+/* Keep this as a multiple of 4 */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       #if( ipconfigUSE_TCP_TIMESTAMPS == 1 )\r
+               #define ipSIZE_TCP_OPTIONS      ( 16u + 12u )\r
+       #else\r
+               #define ipSIZE_TCP_OPTIONS      16u\r
+       #endif\r
+#else\r
+       #if     ipconfigUSE_TCP_TIMESTAMPS == 1\r
+               #define ipSIZE_TCP_OPTIONS   ( 12u + 12u )\r
+       #else\r
+               #define ipSIZE_TCP_OPTIONS   12u\r
+       #endif\r
+#endif\r
+\r
+/*\r
+ *     Every TCP connection owns a TCP window for the administration of all packets\r
+ *     It owns two sets of segment descriptors, incoming and outgoing\r
+ */\r
+typedef struct xTCP_WINDOW\r
+{\r
+       union\r
+       {\r
+               struct\r
+               {\r
+                       uint32_t\r
+                               bHasInit : 1,           /* The window structure has been initialised */\r
+                               bSendFullSize : 1,      /* May only send packets with a size equal to MSS (for optimisation) */\r
+                               bTimeStamps : 1;        /* Socket is supposed to use TCP time-stamps. This depends on the */\r
+               } bits;                                         /* party which opens the connection */\r
+               uint32_t ulFlags;\r
+       } u;\r
+       TCPWinSize_t xSize;\r
+       struct\r
+       {\r
+               uint32_t ulFirstSequenceNumber;  /* Logging & debug: the first segment received/sent in this connection\r
+                                                                                 * for Tx: initial send sequence number (ISS)\r
+                                                                                 * for Rx: initial receive sequence number (IRS) */\r
+               uint32_t ulCurrentSequenceNumber;/* Tx/Rx: the oldest sequence number not yet confirmed, also SND.UNA / RCV.NXT\r
+                                                                                 * In other words: the sequence number of the left side of the sliding window */\r
+               uint32_t ulFINSequenceNumber;    /* The sequence number which carried the FIN flag */\r
+               uint32_t ulHighestSequenceNumber;/* Sequence number of the right-most byte + 1 */\r
+#if( ipconfigUSE_TCP_TIMESTAMPS == 1 )\r
+               uint32_t ulTimeStamp;                    /* The value of the TCP timestamp, transmitted or received */\r
+#endif\r
+       } rx, tx;\r
+       uint32_t ulOurSequenceNumber;           /* The SEQ number we're sending out */\r
+       uint32_t ulUserDataLength;                      /* Number of bytes in Rx buffer which may be passed to the user, after having received a 'missing packet' */\r
+       uint32_t ulNextTxSequenceNumber;        /* The sequence number given to the next byte to be added for transmission */\r
+       int32_t lSRTT;                                          /* Smoothed Round Trip Time, it may increment quickly and it decrements slower */\r
+       uint8_t ucOptionLength;                         /* Number of valid bytes in ulOptionsData[] */\r
+#if( ipconfigUSE_TCP_WIN == 1 )\r
+       List_t xPriorityQueue;                          /* Priority queue: segments which must be sent immediately */\r
+       List_t xTxQueue;                                        /* Transmit queue: segments queued for transmission */\r
+       List_t xWaitQueue;                                      /* Waiting queue:  outstanding segments */\r
+       TCPSegment_t *pxHeadSegment;            /* points to a segment which has not been transmitted and it's size is still growing (user data being added) */\r
+       uint32_t ulOptionsData[ipSIZE_TCP_OPTIONS/sizeof(uint32_t)];    /* Contains the options we send out */\r
+       List_t xTxSegments;                                     /* A linked list of all transmission segments, sorted on sequence number */\r
+       List_t xRxSegments;                                     /* A linked list of reception segments, order depends on sequence of arrival */\r
+#else\r
+       /* For tiny TCP, there is only 1 outstanding TX segment */\r
+       TCPSegment_t xTxSegment;                        /* Priority queue */\r
+#endif\r
+       uint16_t usOurPortNumber;                       /* Mostly for debugging/logging: our TCP port number */\r
+       uint16_t usPeerPortNumber;                      /* debugging/logging: the peer's TCP port number */\r
+       uint16_t usMSS;                                         /* Current accepted MSS */\r
+       uint16_t usMSSInit;                                     /* MSS as configured by the socket owner */\r
+} TCPWindow_t;\r
+\r
+\r
+/*=============================================================================\r
+ *\r
+ * Creation and destruction\r
+ *\r
+ *=============================================================================*/\r
+\r
+/* Create and initialize a window */\r
+void vTCPWindowCreate( TCPWindow_t *pxWindow, uint32_t ulRxWindowLength,\r
+       uint32_t ulTxWindowLength, uint32_t ulAckNumber, uint32_t ulSequenceNumber, uint32_t ulMSS );\r
+\r
+/* Destroy a window (always returns NULL)\r
+ * It will free some resources: a collection of segments */\r
+void vTCPWindowDestroy( TCPWindow_t *pxWindow );\r
+\r
+/* Initialize a window */\r
+void vTCPWindowInit( TCPWindow_t *pxWindow, uint32_t ulAckNumber, uint32_t ulSequenceNumber, uint32_t ulMSS );\r
+\r
+/*=============================================================================\r
+ *\r
+ * Rx functions\r
+ *\r
+ *=============================================================================*/\r
+\r
+/* if true may be passed directly to user (segment expected and window is empty)\r
+ * But pxWindow->ackno should always be used to set "BUF->ackno" */\r
+int32_t lTCPWindowRxCheck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength, uint32_t ulSpace );\r
+\r
+/* When lTCPWindowRxCheck returned false, please call store for this unexpected data */\r
+BaseType_t xTCPWindowRxStore( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber, uint32_t ulLength );\r
+\r
+/* This function will be called as soon as a FIN is received. It will return true\r
+ * if there are no 'open' reception segments */\r
+BaseType_t xTCPWindowRxEmpty( TCPWindow_t *pxWindow );\r
+\r
+/* _HT_ Temporary function for testing/debugging\r
+ * Not used at this moment */\r
+void vTCPWinShowSegments( TCPWindow_t *pxWindow, BaseType_t bForRx );\r
+\r
+/*=============================================================================\r
+ *\r
+ * Tx functions\r
+ *\r
+ *=============================================================================*/\r
+\r
+/* Adds data to the Tx-window */\r
+int32_t lTCPWindowTxAdd( TCPWindow_t *pxWindow, uint32_t ulLength, int32_t lPosition, int32_t lMax );\r
+\r
+/* Check data to be sent and calculate the time period we may sleep */\r
+BaseType_t xTCPWindowTxHasData( TCPWindow_t *pxWindow, uint32_t ulWindowSize, TickType_t *pulDelay );\r
+\r
+/* See if anything is left to be sent\r
+ * Function will be called when a FIN has been received. Only when the TX window is clean,\r
+ * it will return pdTRUE */\r
+BaseType_t xTCPWindowTxDone( TCPWindow_t *pxWindow );\r
+\r
+/* Fetches data to be sent.\r
+ * apPos will point to a location with the circular data buffer: txStream */\r
+uint32_t ulTCPWindowTxGet( TCPWindow_t *pxWindow, uint32_t ulWindowSize, int32_t *plPosition );\r
+\r
+/* Receive a normal ACK */\r
+uint32_t ulTCPWindowTxAck( TCPWindow_t *pxWindow, uint32_t ulSequenceNumber );\r
+\r
+/* Receive a SACK option */\r
+uint32_t ulTCPWindowTxSack( TCPWindow_t *pxWindow, uint32_t ulFirst, uint32_t ulLast );\r
+\r
+\r
+#ifdef __cplusplus\r
+}      /* extern "C" */\r
+#endif\r
+\r
+#endif /* FREERTOS_TCP_WIN_H */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_UDP_IP.h
new file mode 100644 (file)
index 0000000..5f704af
--- /dev/null
@@ -0,0 +1,88 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef FREERTOS_UDP_IP_H\r
+#define FREERTOS_UDP_IP_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* Application level configuration options. */\r
+#include "FreeRTOSIPConfig.h"\r
+#include "FreeRTOSIPConfigDefaults.h"\r
+#include "IPTraceMacroDefaults.h"\r
+\r
+\r
+#ifdef __cplusplus\r
+} // extern "C"\r
+#endif\r
+\r
+#endif /* FREERTOS_UDP_IP_H */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/FreeRTOS_errno_TCP.h
new file mode 100644 (file)
index 0000000..a8b0bc0
--- /dev/null
@@ -0,0 +1,122 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special \r
+ * License Arrangements heading of the FreeRTOS+TCP license information web \r
+ * page, then it can be used under the terms of the FreeRTOS Open Source \r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ * \r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license \r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef FREERTOS_ERRNO_TCP\r
+#define FREERTOS_ERRNO_TCP\r
+\r
+/* The following definitions will be included in the core FreeRTOS code in\r
+future versions of FreeRTOS - hence the 'pd' (ProjDefs) prefix - at which time\r
+this file will be removed. */\r
+\r
+/* The following errno values are used by FreeRTOS+ components, not FreeRTOS\r
+itself. */\r
+\r
+/* For future compatibility (see comment above), check the definitions have not\r
+already been made. */\r
+#ifndef pdFREERTOS_ERRNO_NONE\r
+       #define pdFREERTOS_ERRNO_NONE                   0       /* No errors */\r
+       #define pdFREERTOS_ERRNO_ENOENT                 2       /* No such file or directory */\r
+       #define pdFREERTOS_ERRNO_EINTR                  4       /* Interrupted system call */\r
+       #define pdFREERTOS_ERRNO_EIO                    5       /* I/O error */\r
+       #define pdFREERTOS_ERRNO_ENXIO                  6       /* No such device or address */\r
+       #define pdFREERTOS_ERRNO_EBADF                  9       /* Bad file number */\r
+       #define pdFREERTOS_ERRNO_EAGAIN                 11      /* No more processes */\r
+       #define pdFREERTOS_ERRNO_EWOULDBLOCK    11      /* Operation would block */\r
+       #define pdFREERTOS_ERRNO_ENOMEM                 12      /* Not enough memory */\r
+       #define pdFREERTOS_ERRNO_EACCES                 13      /* Permission denied */\r
+       #define pdFREERTOS_ERRNO_EFAULT                 14      /* Bad address */\r
+       #define pdFREERTOS_ERRNO_EBUSY                  16      /* Mount device busy */\r
+       #define pdFREERTOS_ERRNO_EEXIST                 17      /* File exists */\r
+       #define pdFREERTOS_ERRNO_EXDEV                  18      /* Cross-device link */\r
+       #define pdFREERTOS_ERRNO_ENODEV                 19      /* No such device */\r
+       #define pdFREERTOS_ERRNO_ENOTDIR                20      /* Not a directory */\r
+       #define pdFREERTOS_ERRNO_EISDIR                 21      /* Is a directory */\r
+       #define pdFREERTOS_ERRNO_EINVAL                 22      /* Invalid argument */\r
+       #define pdFREERTOS_ERRNO_ENOSPC                 28      /* No space left on device */\r
+       #define pdFREERTOS_ERRNO_ESPIPE                 29      /* Illegal seek */\r
+       #define pdFREERTOS_ERRNO_EROFS                  30      /* Read only file system */\r
+       #define pdFREERTOS_ERRNO_EUNATCH                42      /* Protocol driver not attached */\r
+       #define pdFREERTOS_ERRNO_EBADE                  50      /* Invalid exchange */\r
+       #define pdFREERTOS_ERRNO_EFTYPE                 79      /* Inappropriate file type or format */\r
+       #define pdFREERTOS_ERRNO_ENMFILE                89      /* No more files */\r
+       #define pdFREERTOS_ERRNO_ENOTEMPTY              90      /* Directory not empty */\r
+       #define pdFREERTOS_ERRNO_ENAMETOOLONG   91      /* File or path name too long */\r
+       #define pdFREERTOS_ERRNO_EOPNOTSUPP             95      /* Operation not supported on transport endpoint */\r
+       #define pdFREERTOS_ERRNO_ENOBUFS                105     /* No buffer space available */\r
+       #define pdFREERTOS_ERRNO_ENOPROTOOPT    109     /* Protocol not available */\r
+       #define pdFREERTOS_ERRNO_EADDRINUSE             112     /* Address already in use */\r
+       #define pdFREERTOS_ERRNO_ETIMEDOUT              116     /* Connection timed out */\r
+       #define pdFREERTOS_ERRNO_EINPROGRESS    119     /* Connection already in progress */\r
+       #define pdFREERTOS_ERRNO_EALREADY               120     /* Socket already connected */\r
+       #define pdFREERTOS_ERRNO_EADDRNOTAVAIL  125     /* Address not available */\r
+       #define pdFREERTOS_ERRNO_EISCONN                127     /* Socket is already connected */\r
+       #define pdFREERTOS_ERRNO_ENOTCONN               128     /* Socket is not connected */\r
+       #define pdFREERTOS_ERRNO_ENOMEDIUM              135     /* No medium inserted */\r
+       #define pdFREERTOS_ERRNO_EILSEQ                 138     /* An invalid UTF-16 sequence was encountered. */\r
+       #define pdFREERTOS_ERRNO_ECANCELED              140     /* Operation canceled. */\r
+\r
+       /* The following endian values are used by FreeRTOS+ components, not FreeRTOS\r
+       itself. */\r
+       #define pdFREERTOS_LITTLE_ENDIAN        0\r
+       #define pdFREERTOS_BIG_ENDIAN           1\r
+\r
+#endif /* pdFREERTOS_ERRNO_NONE */\r
+\r
+#endif /* FREERTOS_ERRNO_TCP */\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/IPTraceMacroDefaults.h
new file mode 100644 (file)
index 0000000..3e30722
--- /dev/null
@@ -0,0 +1,225 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* This file provides default (empty) implementations for any IP trace macros\r
+that are not defined by the user.  See\r
+http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_IP_Trace.html */\r
+\r
+#ifndef UDP_TRACE_MACRO_DEFAULTS_H\r
+#define UDP_TRACE_MACRO_DEFAULTS_H\r
+\r
+#ifndef iptraceNETWORK_DOWN\r
+       #define iptraceNETWORK_DOWN()\r
+#endif\r
+\r
+#ifndef iptraceNETWORK_BUFFER_RELEASED\r
+       #define iptraceNETWORK_BUFFER_RELEASED( pxBufferAddress )\r
+#endif\r
+\r
+#ifndef iptraceNETWORK_BUFFER_OBTAINED\r
+       #define iptraceNETWORK_BUFFER_OBTAINED( pxBufferAddress )\r
+#endif\r
+\r
+#ifndef iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR\r
+       #define iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxBufferAddress )\r
+#endif\r
+\r
+#ifndef iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER\r
+       #define iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER()\r
+#endif\r
+\r
+#ifndef iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR\r
+       #define iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR()\r
+#endif\r
+\r
+#ifndef iptraceCREATING_ARP_REQUEST\r
+       #define iptraceCREATING_ARP_REQUEST( ulIPAddress )\r
+#endif\r
+\r
+#ifndef iptraceARP_TABLE_ENTRY_WILL_EXPIRE\r
+       #define iptraceARP_TABLE_ENTRY_WILL_EXPIRE( ulIPAddress )\r
+#endif\r
+\r
+#ifndef iptraceARP_TABLE_ENTRY_EXPIRED\r
+       #define iptraceARP_TABLE_ENTRY_EXPIRED( ulIPAddress )\r
+#endif\r
+\r
+#ifndef iptraceARP_TABLE_ENTRY_CREATED\r
+       #define iptraceARP_TABLE_ENTRY_CREATED( ulIPAddress, ucMACAddress )\r
+#endif\r
+\r
+#ifndef iptraceSENDING_UDP_PACKET\r
+       #define iptraceSENDING_UDP_PACKET( ulIPAddress )\r
+#endif\r
+\r
+#ifndef iptracePACKET_DROPPED_TO_GENERATE_ARP\r
+       #define iptracePACKET_DROPPED_TO_GENERATE_ARP( ulIPAddress )\r
+#endif\r
+\r
+#ifndef iptraceICMP_PACKET_RECEIVED\r
+       #define iptraceICMP_PACKET_RECEIVED()\r
+#endif\r
+\r
+#ifndef iptraceSENDING_PING_REPLY\r
+       #define iptraceSENDING_PING_REPLY( ulIPAddress )\r
+#endif\r
+\r
+#ifndef traceARP_PACKET_RECEIVED\r
+       #define traceARP_PACKET_RECEIVED()\r
+#endif\r
+\r
+#ifndef iptracePROCESSING_RECEIVED_ARP_REPLY\r
+       #define iptracePROCESSING_RECEIVED_ARP_REPLY( ulIPAddress )\r
+#endif\r
+\r
+#ifndef iptraceSENDING_ARP_REPLY\r
+       #define iptraceSENDING_ARP_REPLY( ulIPAddress )\r
+#endif\r
+\r
+#ifndef iptraceFAILED_TO_CREATE_SOCKET\r
+       #define iptraceFAILED_TO_CREATE_SOCKET()\r
+#endif\r
+\r
+#ifndef iptraceFAILED_TO_CREATE_EVENT_GROUP\r
+       #define iptraceFAILED_TO_CREATE_EVENT_GROUP()\r
+#endif\r
+\r
+#ifndef iptraceRECVFROM_DISCARDING_BYTES\r
+       #define iptraceRECVFROM_DISCARDING_BYTES( xNumberOfBytesDiscarded )\r
+#endif\r
+\r
+#ifndef iptraceETHERNET_RX_EVENT_LOST\r
+       #define iptraceETHERNET_RX_EVENT_LOST()\r
+#endif\r
+\r
+#ifndef iptraceSTACK_TX_EVENT_LOST\r
+       #define iptraceSTACK_TX_EVENT_LOST( xEvent )\r
+#endif\r
+\r
+#ifndef iptraceNETWORK_EVENT_RECEIVED\r
+       #define iptraceNETWORK_EVENT_RECEIVED( eEvent )\r
+#endif\r
+\r
+#ifndef iptraceBIND_FAILED\r
+       #define iptraceBIND_FAILED( xSocket, usPort )\r
+#endif\r
+\r
+#ifndef iptraceDHCP_REQUESTS_FAILED_USING_DEFAULT_IP_ADDRESS\r
+       #define iptraceDHCP_REQUESTS_FAILED_USING_DEFAULT_IP_ADDRESS( ulIPAddress )\r
+#endif\r
+\r
+#ifndef iptraceSENDING_DHCP_DISCOVER\r
+       #define iptraceSENDING_DHCP_DISCOVER()\r
+#endif\r
+\r
+#ifndef iptraceSENDING_DHCP_REQUEST\r
+       #define iptraceSENDING_DHCP_REQUEST()\r
+#endif\r
+\r
+#ifndef iptraceDHCP_SUCCEDEED\r
+       #define iptraceDHCP_SUCCEDEED( address )\r
+#endif\r
+\r
+#ifndef iptraceNETWORK_INTERFACE_TRANSMIT\r
+       #define iptraceNETWORK_INTERFACE_TRANSMIT()\r
+#endif\r
+\r
+#ifndef iptraceNETWORK_INTERFACE_RECEIVE\r
+       #define iptraceNETWORK_INTERFACE_RECEIVE()\r
+#endif\r
+\r
+#ifndef iptraceSENDING_DNS_REQUEST\r
+       #define iptraceSENDING_DNS_REQUEST()\r
+#endif\r
+\r
+#ifndef        iptraceWAITING_FOR_TX_DMA_DESCRIPTOR\r
+       #define iptraceWAITING_FOR_TX_DMA_DESCRIPTOR()\r
+#endif\r
+\r
+#ifndef ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS\r
+       #define ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS 0\r
+#endif\r
+\r
+#ifndef iptraceFAILED_TO_NOTIFY_SELECT_GROUP\r
+       #define iptraceFAILED_TO_NOTIFY_SELECT_GROUP( xSocket )\r
+#endif\r
+\r
+#ifndef pvPortMallocSocket\r
+       #define pvPortMallocSocket(xSize) pvPortMalloc( ( xSize ) )\r
+#endif\r
+\r
+#ifndef iptraceRECVFROM_TIMEOUT\r
+       #define iptraceRECVFROM_TIMEOUT()\r
+#endif\r
+\r
+#ifndef iptraceRECVFROM_INTERRUPTED\r
+       #define iptraceRECVFROM_INTERRUPTED()\r
+#endif\r
+\r
+#ifndef iptraceNO_BUFFER_FOR_SENDTO\r
+       #define iptraceNO_BUFFER_FOR_SENDTO()\r
+#endif\r
+\r
+#ifndef iptraceSENDTO_SOCKET_NOT_BOUND\r
+       #define iptraceSENDTO_SOCKET_NOT_BOUND()\r
+#endif\r
+\r
+#ifndef iptraceSENDTO_DATA_TOO_LONG\r
+       #define iptraceSENDTO_DATA_TOO_LONG()\r
+#endif\r
+\r
+#endif /* UDP_TRACE_MACRO_DEFAULTS_H */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkBufferManagement.h
new file mode 100644 (file)
index 0000000..6eeddc8
--- /dev/null
@@ -0,0 +1,102 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef NETWORK_BUFFER_MANAGEMENT_H\r
+#define NETWORK_BUFFER_MANAGEMENT_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* NOTE PUBLIC API FUNCTIONS. */\r
+BaseType_t xNetworkBuffersInitialise( void );\r
+NetworkBufferDescriptor_t *pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks );\r
+NetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes );\r
+void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer );\r
+BaseType_t vNetworkBufferReleaseFromISR( NetworkBufferDescriptor_t * const pxNetworkBuffer );\r
+uint8_t *pucGetNetworkBuffer( size_t *pxRequestedSizeBytes );\r
+void vReleaseNetworkBuffer( uint8_t *pucEthernetBuffer );\r
+\r
+/* Get the current number of free network buffers. */\r
+UBaseType_t uxGetNumberOfFreeNetworkBuffers( void );\r
+\r
+/* Get the lowest number of free network buffers. */\r
+UBaseType_t uxGetMinimumFreeNetworkBuffers( void );\r
+\r
+/* Copy a network buffer into a bigger buffer. */\r
+NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer,\r
+       BaseType_t xNewLength);\r
+\r
+/* Increase the size of a Network Buffer.\r
+In case BufferAllocation_2.c is used, the new space must be allocated. */\r
+NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer,\r
+       size_t xNewSizeBytes );\r
+\r
+#if ipconfigTCP_IP_SANITY\r
+       /*\r
+        * Check if an address is a valid pointer to a network descriptor\r
+        * by looking it up in the array of network descriptors\r
+        */\r
+       UBaseType_t bIsValidNetworkDescriptor (const NetworkBufferDescriptor_t * pxDesc);\r
+       BaseType_t prvIsFreeBuffer( const NetworkBufferDescriptor_t *pxDescr );\r
+#endif\r
+\r
+#ifdef __cplusplus\r
+} // extern "C"\r
+#endif\r
+\r
+#endif /* NETWORK_BUFFER_MANAGEMENT_H */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/include/NetworkInterface.h
new file mode 100644 (file)
index 0000000..65e235d
--- /dev/null
@@ -0,0 +1,76 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef NETWORK_INTERFACE_H\r
+#define NETWORK_INTERFACE_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* NOTE PUBLIC API FUNCTIONS. */\r
+BaseType_t xNetworkInterfaceInitialise( void );\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend );\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] );\r
+BaseType_t xGetPhyLinkStatus( void );\r
+\r
+#ifdef __cplusplus\r
+} // extern "C"\r
+#endif\r
+\r
+#endif /* NETWORK_INTERFACE_H */\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_1.c
new file mode 100644 (file)
index 0000000..fb86089
--- /dev/null
@@ -0,0 +1,455 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/******************************************************************************\r
+ *\r
+ * See the following web page for essential buffer allocation scheme usage and\r
+ * configuration details:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html\r
+ *\r
+ ******************************************************************************/\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* For an Ethernet interrupt to be able to obtain a network buffer there must\r
+be at least this number of buffers available. */\r
+#define baINTERRUPT_BUFFER_GET_THRESHOLD       ( 3 )\r
+\r
+/* A list of free (available) NetworkBufferDescriptor_t structures. */\r
+static List_t xFreeBuffersList;\r
+\r
+/* Some statistics about the use of buffers. */\r
+static UBaseType_t uxMinimumFreeNetworkBuffers = 0u;\r
+\r
+/* Declares the pool of NetworkBufferDescriptor_t structures that are available\r
+to the system.  All the network buffers referenced from xFreeBuffersList exist\r
+in this array.  The array is not accessed directly except during initialisation,\r
+when the xFreeBuffersList is filled (as all the buffers are free when the system\r
+is booted). */\r
+static NetworkBufferDescriptor_t xNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];\r
+\r
+/* This constant is defined as true to let FreeRTOS_TCP_IP.c know that the\r
+network buffers have constant size, large enough to hold the biggest Ethernet\r
+packet. No resizing will be done. */\r
+const BaseType_t xBufferAllocFixedSize = pdTRUE;\r
+\r
+/* The semaphore used to obtain network buffers. */\r
+static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;\r
+\r
+#if( ipconfigTCP_IP_SANITY != 0 )\r
+       static char cIsLow = pdFALSE;\r
+       UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc );\r
+#else\r
+       static UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc );\r
+#endif /* ipconfigTCP_IP_SANITY */\r
+\r
+static void prvShowWarnings( void );\r
+\r
+/* The user can define their own ipconfigBUFFER_ALLOC_LOCK() and\r
+ipconfigBUFFER_ALLOC_UNLOCK() macros, especially for use form an ISR.  If these\r
+are not defined then default them to call the normal enter/exit critical\r
+section macros. */\r
+#if !defined( ipconfigBUFFER_ALLOC_LOCK )\r
+\r
+       #define ipconfigBUFFER_ALLOC_INIT( ) do {} while (0)\r
+       #define ipconfigBUFFER_ALLOC_LOCK_FROM_ISR()            \\r
+               UBaseType_t uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \\r
+               {\r
+\r
+       #define ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR()          \\r
+                       portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \\r
+               }\r
+\r
+       #define ipconfigBUFFER_ALLOC_LOCK()                                     taskENTER_CRITICAL()\r
+       #define ipconfigBUFFER_ALLOC_UNLOCK()                           taskEXIT_CRITICAL()\r
+\r
+#endif /* ipconfigBUFFER_ALLOC_LOCK */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigTCP_IP_SANITY != 0 )\r
+\r
+       /* HT: SANITY code will be removed as soon as the library is stable\r
+        * and and ready to become public\r
+        * Function below gives information about the use of buffers */\r
+       #define WARN_LOW                ( 2 )\r
+       #define WARN_HIGH               ( ( 5 * ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) / 10 )\r
+\r
+#endif /* ipconfigTCP_IP_SANITY */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigTCP_IP_SANITY != 0 )\r
+\r
+       BaseType_t prvIsFreeBuffer( const NetworkBufferDescriptor_t *pxDescr )\r
+       {\r
+               return ( bIsValidNetworkDescriptor( pxDescr ) != 0 ) &&\r
+                       ( listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxDescr->xBufferListItem ) ) != 0 );\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+       static void prvShowWarnings( void )\r
+       {\r
+               UBaseType_t uxCount = uxGetNumberOfFreeNetworkBuffers( );\r
+               if( ( ( cIsLow == 0 ) && ( uxCount <= WARN_LOW ) ) || ( ( cIsLow != 0 ) && ( uxCount >= WARN_HIGH ) ) )\r
+               {\r
+                       cIsLow = !cIsLow;\r
+                       FreeRTOS_debug_printf( ( "*** Warning *** %s %lu buffers left\n", cIsLow ? "only" : "now", uxCount ) );\r
+               }\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+       UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc )\r
+       {\r
+               uint32_t offset = ( uint32_t ) ( ((const char *)pxDesc) - ((const char *)xNetworkBuffers) );\r
+               if( ( offset >= sizeof( xNetworkBuffers ) ) ||\r
+                       ( ( offset % sizeof( xNetworkBuffers[0] ) ) != 0 ) )\r
+                       return pdFALSE;\r
+               return (UBaseType_t) (pxDesc - xNetworkBuffers) + 1;\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+#else\r
+       static UBaseType_t bIsValidNetworkDescriptor (const NetworkBufferDescriptor_t * pxDesc)\r
+       {\r
+               ( void ) pxDesc;\r
+               return ( UBaseType_t ) pdTRUE;\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+       static void prvShowWarnings( void )\r
+       {\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+#endif /* ipconfigTCP_IP_SANITY */\r
+\r
+BaseType_t xNetworkBuffersInitialise( void )\r
+{\r
+BaseType_t xReturn, x;\r
+\r
+       /* Only initialise the buffers and their associated kernel objects if they\r
+       have not been initialised before. */\r
+       if( xNetworkBufferSemaphore == NULL )\r
+       {\r
+               /* In case alternative locking is used, the mutexes can be initialised\r
+               here */\r
+               ipconfigBUFFER_ALLOC_INIT();\r
+\r
+               xNetworkBufferSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );\r
+               configASSERT( xNetworkBufferSemaphore );\r
+\r
+               if( xNetworkBufferSemaphore != NULL )\r
+               {\r
+                       vListInitialise( &xFreeBuffersList );\r
+\r
+                       /* Initialise all the network buffers.  The buffer storage comes\r
+                       from the network interface, and different hardware has different\r
+                       requirements. */\r
+                       vNetworkInterfaceAllocateRAMToBuffers( xNetworkBuffers );\r
+                       for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )\r
+                       {\r
+                               /* Initialise and set the owner of the buffer list items. */\r
+                               vListInitialiseItem( &( xNetworkBuffers[ x ].xBufferListItem ) );\r
+                               listSET_LIST_ITEM_OWNER( &( xNetworkBuffers[ x ].xBufferListItem ), &xNetworkBuffers[ x ] );\r
+\r
+                               /* Currently, all buffers are available for use. */\r
+                               vListInsert( &xFreeBuffersList, &( xNetworkBuffers[ x ].xBufferListItem ) );\r
+                       }\r
+\r
+                       uxMinimumFreeNetworkBuffers = ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;\r
+               }\r
+       }\r
+\r
+       if( xNetworkBufferSemaphore == NULL )\r
+       {\r
+               xReturn = pdFAIL;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdPASS;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+NetworkBufferDescriptor_t *pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )\r
+{\r
+NetworkBufferDescriptor_t *pxReturn = NULL;\r
+BaseType_t xInvalid = pdFALSE;\r
+UBaseType_t uxCount;\r
+\r
+       /* The current implementation only has a single size memory block, so\r
+       the requested size parameter is not used (yet). */\r
+       ( void ) xRequestedSizeBytes;\r
+\r
+       if( xNetworkBufferSemaphore != NULL )\r
+       {\r
+               /* If there is a semaphore available, there is a network buffer\r
+               available. */\r
+               if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )\r
+               {\r
+                       /* Protect the structure as it is accessed from tasks and\r
+                       interrupts. */\r
+                       ipconfigBUFFER_ALLOC_LOCK();\r
+                       {\r
+                               pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );\r
+\r
+                               if( ( bIsValidNetworkDescriptor( pxReturn ) != pdFALSE_UNSIGNED ) &&\r
+                                       listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxReturn->xBufferListItem ) ) )\r
+                               {\r
+                                       uxListRemove( &( pxReturn->xBufferListItem ) );\r
+                               }\r
+                               else\r
+                               {\r
+                                       xInvalid = pdTRUE;\r
+                               }\r
+                       }\r
+                       ipconfigBUFFER_ALLOC_UNLOCK();\r
+\r
+                       if( xInvalid == pdTRUE )\r
+                       {\r
+                               /* _RB_ Can printf() be called from an interrupt?  (comment\r
+                               above says this can be called from an interrupt too) */\r
+                               /* _HT_ The function shall not be called from an ISR. Comment\r
+                               was indeed misleading. Hopefully clear now?\r
+                               So the printf()is OK here. */\r
+                               FreeRTOS_debug_printf( ( "pxGetNetworkBufferWithDescriptor: INVALID BUFFER: %p (valid %lu)\n",\r
+                                       pxReturn, bIsValidNetworkDescriptor( pxReturn ) ) );\r
+                               pxReturn = NULL;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Reading UBaseType_t, no critical section needed. */\r
+                               uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );\r
+\r
+                               /* For stats, latch the lowest number of network buffers since\r
+                               booting. */\r
+                               if( uxMinimumFreeNetworkBuffers > uxCount )\r
+                               {\r
+                                       uxMinimumFreeNetworkBuffers = uxCount;\r
+                               }\r
+\r
+                               pxReturn->xDataLength = xRequestedSizeBytes;\r
+\r
+                               #if( ipconfigTCP_IP_SANITY != 0 )\r
+                               {\r
+                                       prvShowWarnings();\r
+                               }\r
+                               #endif /* ipconfigTCP_IP_SANITY */\r
+\r
+                               #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+                               {\r
+                                       /* make sure the buffer is not linked */\r
+                                       pxReturn->pxNextBuffer = NULL;\r
+                               }\r
+                               #endif /* ipconfigUSE_LINKED_RX_MESSAGES */\r
+\r
+                               if( xTCPWindowLoggingLevel > 3 )\r
+                               {\r
+                                       FreeRTOS_debug_printf( ( "BUF_GET[%ld]: %p (%p)\n",\r
+                                               bIsValidNetworkDescriptor( pxReturn ),\r
+                                               pxReturn, pxReturn->pucEthernetBuffer ) );\r
+                               }\r
+                       }\r
+                       iptraceNETWORK_BUFFER_OBTAINED( pxReturn );\r
+               }\r
+               else\r
+               {\r
+                       iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();\r
+               }\r
+       }\r
+\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+NetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes )\r
+{\r
+NetworkBufferDescriptor_t *pxReturn = NULL;\r
+\r
+       /* The current implementation only has a single size memory block, so\r
+       the requested size parameter is not used (yet). */\r
+       ( void ) xRequestedSizeBytes;\r
+\r
+       /* If there is a semaphore available then there is a buffer available, but,\r
+       as this is called from an interrupt, only take a buffer if there are at\r
+       least baINTERRUPT_BUFFER_GET_THRESHOLD buffers remaining.  This prevents,\r
+       to a certain degree at least, a rapidly executing interrupt exhausting\r
+       buffer and in so doing preventing tasks from continuing. */\r
+       if( uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) xNetworkBufferSemaphore ) > ( UBaseType_t ) baINTERRUPT_BUFFER_GET_THRESHOLD )\r
+       {\r
+               if( xSemaphoreTakeFromISR( xNetworkBufferSemaphore, NULL ) == pdPASS )\r
+               {\r
+                       /* Protect the structure as it is accessed from tasks and interrupts. */\r
+                       ipconfigBUFFER_ALLOC_LOCK_FROM_ISR();\r
+                       {\r
+                               pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );\r
+                               uxListRemove( &( pxReturn->xBufferListItem ) );\r
+                       }\r
+                       ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR();\r
+\r
+                       iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxReturn );\r
+               }\r
+       }\r
+\r
+       if( pxReturn == NULL )\r
+       {\r
+               iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR();\r
+       }\r
+\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t vNetworkBufferReleaseFromISR( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       /* Ensure the buffer is returned to the list of free buffers before the\r
+       counting semaphore is 'given' to say a buffer is available. */\r
+       ipconfigBUFFER_ALLOC_LOCK_FROM_ISR();\r
+       {\r
+               vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
+       }\r
+       ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR();\r
+\r
+       xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken );\r
+       iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );\r
+\r
+       return xHigherPriorityTaskWoken;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+BaseType_t xListItemAlreadyInFreeList;\r
+\r
+       if( bIsValidNetworkDescriptor( pxNetworkBuffer ) == pdFALSE_UNSIGNED )\r
+       {\r
+               FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: Invalid buffer %p\n", pxNetworkBuffer ) );\r
+               return ;\r
+       }\r
+       /* Ensure the buffer is returned to the list of free buffers before the\r
+       counting semaphore is 'given' to say a buffer is available. */\r
+       ipconfigBUFFER_ALLOC_LOCK();\r
+       {\r
+               {\r
+                       xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
+\r
+                       if( xListItemAlreadyInFreeList == pdFALSE )\r
+                       {\r
+                               vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
+                       }\r
+               }\r
+       }\r
+       ipconfigBUFFER_ALLOC_UNLOCK();\r
+\r
+       if( xListItemAlreadyInFreeList )\r
+       {\r
+               FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n",\r
+                       pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) );\r
+       }\r
+       if( xListItemAlreadyInFreeList == pdFALSE )\r
+       {\r
+               xSemaphoreGive( xNetworkBufferSemaphore );\r
+               prvShowWarnings();\r
+               if( xTCPWindowLoggingLevel > 3 )\r
+                       FreeRTOS_debug_printf( ( "BUF_PUT[%ld]: %p (%p) (now %lu)\n",\r
+                               bIsValidNetworkDescriptor( pxNetworkBuffer ),\r
+                               pxNetworkBuffer, pxNetworkBuffer->pucEthernetBuffer,\r
+                               uxGetNumberOfFreeNetworkBuffers( ) ) );\r
+       }\r
+       iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+UBaseType_t uxGetMinimumFreeNetworkBuffers( void )\r
+{\r
+       return uxMinimumFreeNetworkBuffers;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )\r
+{\r
+       return listCURRENT_LIST_LENGTH( &xFreeBuffersList );\r
+}\r
+\r
+NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer, size_t xNewSizeBytes )\r
+{\r
+       /* In BufferAllocation_1.c all network buffer are allocated with a\r
+       maximum size of 'ipTOTAL_ETHERNET_FRAME_SIZE'.No need to resize the\r
+       network buffer. */\r
+       ( void ) xNewSizeBytes;\r
+       return pxNetworkBuffer;\r
+}\r
+\r
+/*#endif */ /* ipconfigINCLUDE_TEST_CODE */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/BufferManagement/BufferAllocation_2.c
new file mode 100644 (file)
index 0000000..dd43818
--- /dev/null
@@ -0,0 +1,410 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/******************************************************************************\r
+ *\r
+ * See the following web page for essential buffer allocation scheme usage and\r
+ * configuration details:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html\r
+ *\r
+ ******************************************************************************/\r
+\r
+/* THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR\r
+THAT WILL FRAGMENT THE HEAP MEMORY.  For example, heap_2 must not be used,\r
+heap_4 can be used. */\r
+\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkInterface.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* The obtained network buffer must be large enough to hold a packet that might\r
+replace the packet that was requested to be sent. */\r
+#if ipconfigUSE_TCP == 1\r
+       #define baMINIMAL_BUFFER_SIZE           sizeof( TCPPacket_t )\r
+#else\r
+       #define baMINIMAL_BUFFER_SIZE           sizeof( ARPPacket_t )\r
+#endif /* ipconfigUSE_TCP == 1 */\r
+\r
+/*_RB_ This is too complex not to have an explanation. */\r
+#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )\r
+       #define ASSERT_CONCAT_(a, b) a##b\r
+       #define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)\r
+       #define STATIC_ASSERT(e) \\r
+               ;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }\r
+\r
+       STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE );\r
+#endif\r
+\r
+/* A list of free (available) NetworkBufferDescriptor_t structures. */\r
+static List_t xFreeBuffersList;\r
+\r
+/* Some statistics about the use of buffers. */\r
+static size_t uxMinimumFreeNetworkBuffers;\r
+\r
+/* Declares the pool of NetworkBufferDescriptor_t structures that are available\r
+to the system.  All the network buffers referenced from xFreeBuffersList exist\r
+in this array.  The array is not accessed directly except during initialisation,\r
+when the xFreeBuffersList is filled (as all the buffers are free when the system\r
+is booted). */\r
+static NetworkBufferDescriptor_t xNetworkBufferDescriptors[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];\r
+\r
+/* This constant is defined as false to let FreeRTOS_TCP_IP.c know that the\r
+network buffers have a variable size: resizing may be necessary */\r
+const BaseType_t xBufferAllocFixedSize = pdFALSE;\r
+\r
+/* The semaphore used to obtain network buffers. */\r
+static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkBuffersInitialise( void )\r
+{\r
+BaseType_t xReturn, x;\r
+\r
+       /* Only initialise the buffers and their associated kernel objects if they\r
+       have not been initialised before. */\r
+       if( xNetworkBufferSemaphore == NULL )\r
+       {\r
+               xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );\r
+               configASSERT( xNetworkBufferSemaphore );\r
+               #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
+               {\r
+                       vQueueAddToRegistry( xNetworkBufferSemaphore, "NetBufSem" );\r
+               }\r
+               #endif /* configQUEUE_REGISTRY_SIZE */\r
+\r
+               /* If the trace recorder code is included name the semaphore for viewing\r
+               in FreeRTOS+Trace.  */\r
+               #if( ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 )\r
+               {\r
+                       extern QueueHandle_t xNetworkEventQueue;\r
+                       vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" );\r
+                       vTraceSetQueueName( xNetworkBufferSemaphore, "NetworkBufferCount" );\r
+               }\r
+               #endif /*  ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */\r
+\r
+               if( xNetworkBufferSemaphore != NULL )\r
+               {\r
+                       vListInitialise( &xFreeBuffersList );\r
+\r
+                       /* Initialise all the network buffers.  No storage is allocated to\r
+                       the buffers yet. */\r
+                       for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )\r
+                       {\r
+                               /* Initialise and set the owner of the buffer list items. */\r
+                               xNetworkBufferDescriptors[ x ].pucEthernetBuffer = NULL;\r
+                               vListInitialiseItem( &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );\r
+                               listSET_LIST_ITEM_OWNER( &( xNetworkBufferDescriptors[ x ].xBufferListItem ), &xNetworkBufferDescriptors[ x ] );\r
+\r
+                               /* Currently, all buffers are available for use. */\r
+                               vListInsert( &xFreeBuffersList, &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );\r
+                       }\r
+\r
+                       uxMinimumFreeNetworkBuffers = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;\r
+               }\r
+       }\r
+\r
+       if( xNetworkBufferSemaphore == NULL )\r
+       {\r
+               xReturn = pdFAIL;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdPASS;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+uint8_t *pucGetNetworkBuffer( size_t *pxRequestedSizeBytes )\r
+{\r
+uint8_t *pucEthernetBuffer;\r
+size_t xSize = *pxRequestedSizeBytes;\r
+\r
+       if( xSize < baMINIMAL_BUFFER_SIZE )\r
+       {\r
+               /* Buffers must be at least large enough to hold a TCP-packet with\r
+               headers, or an ARP packet, in case TCP is not included. */\r
+               xSize = baMINIMAL_BUFFER_SIZE;\r
+       }\r
+\r
+       /* Round up xSize to the nearest multiple of N bytes,\r
+       where N equals 'sizeof( size_t )'. */\r
+       if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u )\r
+       {\r
+               xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u;\r
+       }\r
+       *pxRequestedSizeBytes = xSize;\r
+\r
+       /* Allocate a buffer large enough to store the requested Ethernet frame size\r
+       and a pointer to a network buffer structure (hence the addition of\r
+       ipBUFFER_PADDING bytes). */\r
+       pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING );\r
+       configASSERT( pucEthernetBuffer );\r
+\r
+       if( pucEthernetBuffer != NULL )\r
+       {\r
+               /* Enough space is left at the start of the buffer to place a pointer to\r
+               the network buffer structure that references this Ethernet buffer.\r
+               Return a pointer to the start of the Ethernet buffer itself. */\r
+               pucEthernetBuffer += ipBUFFER_PADDING;\r
+       }\r
+\r
+       return pucEthernetBuffer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vReleaseNetworkBuffer( uint8_t *pucEthernetBuffer )\r
+{\r
+       /* There is space before the Ethernet buffer in which a pointer to the\r
+       network buffer that references this Ethernet buffer is stored.  Remove the\r
+       space before freeing the buffer. */\r
+       if( pucEthernetBuffer != NULL )\r
+       {\r
+               pucEthernetBuffer -= ipBUFFER_PADDING;\r
+               vPortFree( ( void * ) pucEthernetBuffer );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+NetworkBufferDescriptor_t *pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )\r
+{\r
+NetworkBufferDescriptor_t *pxReturn = NULL;\r
+size_t uxCount;\r
+\r
+       if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )\r
+       {\r
+               /* ARP packets can replace application packets, so the storage must be\r
+               at least large enough to hold an ARP. */\r
+               xRequestedSizeBytes = baMINIMAL_BUFFER_SIZE;\r
+       }\r
+\r
+       /* Add 2 bytes to xRequestedSizeBytes and round up xRequestedSizeBytes\r
+       to the nearest multiple of N bytes, where N equals 'sizeof( size_t )'. */\r
+       xRequestedSizeBytes += 2u;\r
+       if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u )\r
+       {\r
+               xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u;\r
+       }\r
+\r
+       /* If there is a semaphore available, there is a network buffer available. */\r
+       if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )\r
+       {\r
+               /* Protect the structure as it is accessed from tasks and interrupts. */\r
+               taskENTER_CRITICAL();\r
+               {\r
+                       pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );\r
+                       uxListRemove( &( pxReturn->xBufferListItem ) );\r
+               }\r
+               taskEXIT_CRITICAL();\r
+\r
+               /* Reading UBaseType_t, no critical section needed. */\r
+               uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );\r
+\r
+               if( uxMinimumFreeNetworkBuffers > uxCount )\r
+               {\r
+                       uxMinimumFreeNetworkBuffers = uxCount;\r
+               }\r
+\r
+               /* Allocate storage of exactly the requested size to the buffer. */\r
+               configASSERT( pxReturn->pucEthernetBuffer == NULL );\r
+               if( xRequestedSizeBytes > 0 )\r
+               {\r
+                       /* Extra space is obtained so a pointer to the network buffer can\r
+                       be stored at the beginning of the buffer. */\r
+                       pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING );\r
+\r
+                       if( pxReturn->pucEthernetBuffer == NULL )\r
+                       {\r
+                               /* The attempt to allocate storage for the buffer payload failed,\r
+                               so the network buffer structure cannot be used and must be\r
+                               released. */\r
+                               vReleaseNetworkBufferAndDescriptor( pxReturn );\r
+                               pxReturn = NULL;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Store a pointer to the network buffer structure in the\r
+                               buffer storage area, then move the buffer pointer on past the\r
+                               stored pointer so the pointer value is not overwritten by the\r
+                               application when the buffer is used. */\r
+                               *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn;\r
+                               pxReturn->pucEthernetBuffer += ipBUFFER_PADDING;\r
+\r
+                               /* Store the actual size of the allocated buffer, which may be\r
+                               greater than the original requested size. */\r
+                               pxReturn->xDataLength = xRequestedSizeBytes;\r
+\r
+                               #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )\r
+                               {\r
+                                       /* make sure the buffer is not linked */\r
+                                       pxReturn->pxNextBuffer = NULL;\r
+                               }\r
+                               #endif /* ipconfigUSE_LINKED_RX_MESSAGES */\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* A descriptor is being returned without an associated buffer being\r
+                       allocated. */\r
+               }\r
+       }\r
+\r
+       if( pxReturn == NULL )\r
+       {\r
+               iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();\r
+       }\r
+       else\r
+       {\r
+               iptraceNETWORK_BUFFER_OBTAINED( pxReturn );\r
+       }\r
+\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+BaseType_t xListItemAlreadyInFreeList;\r
+\r
+       /* Ensure the buffer is returned to the list of free buffers before the\r
+       counting semaphore is 'given' to say a buffer is available.  Release the\r
+       storage allocated to the buffer payload.  THIS FILE SHOULD NOT BE USED\r
+       IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP\r
+       MEMORY.  For example, heap_2 must not be used, heap_4 can be used. */\r
+       vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );\r
+       pxNetworkBuffer->pucEthernetBuffer = NULL;\r
+\r
+       taskENTER_CRITICAL();\r
+       {\r
+               xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
+\r
+               if( xListItemAlreadyInFreeList == pdFALSE )\r
+               {\r
+                       vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
+               }\r
+       }\r
+       taskEXIT_CRITICAL();\r
+\r
+       if( xListItemAlreadyInFreeList == pdFALSE )\r
+       {\r
+               xSemaphoreGive( xNetworkBufferSemaphore );\r
+       }\r
+\r
+       iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Returns the number of free network buffers\r
+ */\r
+UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )\r
+{\r
+       return listCURRENT_LIST_LENGTH( &xFreeBuffersList );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+UBaseType_t uxGetMinimumFreeNetworkBuffers( void )\r
+{\r
+       return uxMinimumFreeNetworkBuffers;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer, size_t xNewSizeBytes )\r
+{\r
+size_t xOriginalLength;\r
+uint8_t *pucBuffer;\r
+\r
+       xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING;\r
+       xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING;\r
+\r
+       pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) );\r
+\r
+       if( pucBuffer == NULL )\r
+       {\r
+               /* In case the allocation fails, return NULL. */\r
+               pxNetworkBuffer = NULL;\r
+       }\r
+       else\r
+       {\r
+               pxNetworkBuffer->xDataLength = xNewSizeBytes;\r
+               if( xNewSizeBytes > xOriginalLength )\r
+               {\r
+                       xNewSizeBytes = xOriginalLength;\r
+               }\r
+\r
+               memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes );\r
+               vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );\r
+               pxNetworkBuffer->pucEthernetBuffer = pucBuffer;\r
+       }\r
+       \r
+       return pxNetworkBuffer;\r
+}\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_end.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_end.h
new file mode 100644 (file)
index 0000000..9ce33f4
--- /dev/null
@@ -0,0 +1,78 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*****************************************************************************\r
+ *\r
+ * See the following URL for an explanation of this file:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html\r
+ *\r
+ *****************************************************************************/\r
+__attribute__( (packed) );\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_start.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/GCC/pack_struct_start.h
new file mode 100644 (file)
index 0000000..f9335cb
--- /dev/null
@@ -0,0 +1,80 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*****************************************************************************\r
+ *\r
+ * See the following URL for an explanation of this file:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html\r
+ *\r
+ *****************************************************************************/\r
+\r
+/* Nothing to do here. */\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_end.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_end.h
new file mode 100644 (file)
index 0000000..4a4a4ef
--- /dev/null
@@ -0,0 +1,79 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*****************************************************************************\r
+ *\r
+ * See the following URL for an explanation of this file:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html\r
+ *\r
+ *****************************************************************************/\r
+\r
+;\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_start.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/IAR/pack_struct_start.h
new file mode 100644 (file)
index 0000000..af79f52
--- /dev/null
@@ -0,0 +1,81 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*****************************************************************************\r
+ *\r
+ * See the following URL for an explanation of this file:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html\r
+ *\r
+ *****************************************************************************/\r
+\r
+__packed\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_end.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_end.h
new file mode 100644 (file)
index 0000000..5c30920
--- /dev/null
@@ -0,0 +1,80 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*****************************************************************************\r
+ *\r
+ * See the following URL for an explanation of this file:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html\r
+ *\r
+ *****************************************************************************/\r
+\r
+;\r
+#pragma pack( pop )\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_start.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/MSVC/pack_struct_start.h
new file mode 100644 (file)
index 0000000..bca26e7
--- /dev/null
@@ -0,0 +1,79 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*****************************************************************************\r
+ *\r
+ * See the following URL for an explanation of this file:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html\r
+ *\r
+ *****************************************************************************/\r
+\r
+#pragma pack( push, 1 )\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_end.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_end.h
new file mode 100644 (file)
index 0000000..da67ba7
--- /dev/null
@@ -0,0 +1,86 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*****************************************************************************\r
+ *\r
+ * See the following URL for an explanation of this file:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html\r
+ *\r
+ *****************************************************************************/\r
+\r
+\r
+#ifdef _SH\r
+       #ifdef __RENESAS__\r
+               ;\r
+               #pragma unpack\r
+       #endif\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_start.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/Compiler/Renesas/pack_struct_start.h
new file mode 100644 (file)
index 0000000..31675a8
--- /dev/null
@@ -0,0 +1,85 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*****************************************************************************\r
+ *\r
+ * See the following URL for an explanation of this file:\r
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html\r
+ *\r
+ *****************************************************************************/\r
+\r
+\r
+#ifdef _SH\r
+       #ifdef __RENESAS__\r
+               #pragma pack 1\r
+       #endif\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/NetworkInterface.c
new file mode 100644 (file)
index 0000000..7a0da57
--- /dev/null
@@ -0,0 +1,680 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+/* Some files from the Atmel Software Framework */\r
+/*_RB_ The SAM4E portable layer has three different header files called gmac.h! */\r
+#include "instance/gmac.h"\r
+#include <sysclk.h>\r
+#include <ethernet_phy.h>\r
+\r
+#ifndef        BMSR_LINK_STATUS\r
+       #define BMSR_LINK_STATUS            0x0004  //!< Link status\r
+#endif\r
+\r
+#ifndef        PHY_LS_HIGH_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+       receiving packets. */\r
+       #define PHY_LS_HIGH_CHECK_TIME_MS       15000\r
+#endif\r
+\r
+#ifndef        PHY_LS_LOW_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still low every second. */\r
+       #define PHY_LS_LOW_CHECK_TIME_MS        1000\r
+#endif\r
+\r
+/* Interrupt events to process.  Currently only the Rx event is processed\r
+although code for other events is included to allow for possible future\r
+expansion. */\r
+#define EMAC_IF_RX_EVENT        1UL\r
+#define EMAC_IF_TX_EVENT        2UL\r
+#define EMAC_IF_ERR_EVENT       4UL\r
+#define EMAC_IF_ALL_EVENT       ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )\r
+\r
+#define ETHERNET_CONF_PHY_ADDR  BOARD_GMAC_PHY_ADDR\r
+\r
+#define HZ_PER_MHZ                             ( 1000000UL )\r
+\r
+#ifndef        EMAC_MAX_BLOCK_TIME_MS\r
+       #define EMAC_MAX_BLOCK_TIME_MS  100ul\r
+#endif\r
+\r
+#if !defined( GMAC_USES_TX_CALLBACK ) || ( GMAC_USES_TX_CALLBACK != 1 )\r
+       #error Please define GMAC_USES_TX_CALLBACK as 1\r
+#endif\r
+\r
+#if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+       #warning The EMAC of SAM4E has fixed-size RX buffers so ZERO_COPY_RX is not possible\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to 4x\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+       #define configEMAC_TASK_STACK_SIZE ( 4 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Wait a fixed time for the link status to indicate the network is up.\r
+ */\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime );\r
+\r
+#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )\r
+       void vGMACGenerateChecksum( uint8_t *apBuffer );\r
+#endif\r
+\r
+/*\r
+ * Called from the ASF GMAC driver.\r
+ */\r
+static void prvRxCallback( uint32_t ulStatus );\r
+static void prvTxCallback( uint32_t ulStatus, uint8_t *puc_buffer );\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes GMAC interrupts.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*\r
+ * Initialise the ASF GMAC driver.\r
+ */\r
+static BaseType_t prvGMACInit( void );\r
+\r
+/*\r
+ * Try to obtain an Rx packet from the hardware.\r
+ */\r
+static uint32_t prvEMACRxPoll( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Bit map of outstanding ETH interrupt events for processing.  Currently only\r
+the Rx interrupt is handled, although code is included for other events to\r
+enable future expansion. */\r
+static volatile uint32_t ulISREvents;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+static volatile BaseType_t xGMACSwitchRequired;\r
+\r
+/* ethernet_phy_addr: the address of the PHY in use.\r
+Atmel was a bit ambiguous about it so the address will be stored\r
+in this variable, see ethernet_phy.c */\r
+extern int ethernet_phy_addr;\r
+\r
+/* LLMNR multicast address. */\r
+static const uint8_t llmnr_mac_address[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };\r
+\r
+/* The GMAC object as defined by the ASF drivers. */\r
+static gmac_device_t gs_gmac_dev;\r
+\r
+/* MAC address to use. */\r
+extern const uint8_t ucMACAddress[ 6 ];\r
+\r
+/* Holds the handle of the task used as a deferred interrupt processor.  The\r
+handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
+related interrupts. */\r
+TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+static QueueHandle_t xTxBufferQueue;\r
+int tx_release_count[ 4 ];\r
+\r
+/* xTXDescriptorSemaphore is a counting semaphore with\r
+a maximum count of GMAC_TX_BUFFERS, which is the number of\r
+DMA TX descriptors. */\r
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * GMAC interrupt handler.\r
+ */\r
+void GMAC_Handler(void)\r
+{\r
+       xGMACSwitchRequired = pdFALSE;\r
+\r
+       /* gmac_handler() may call prvRxCallback() which may change\r
+       the value of xGMACSwitchRequired. */\r
+       gmac_handler( &gs_gmac_dev );\r
+\r
+       if( xGMACSwitchRequired != pdFALSE )\r
+       {\r
+               portEND_SWITCHING_ISR( xGMACSwitchRequired );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRxCallback( uint32_t ulStatus )\r
+{\r
+       if( ( ( ulStatus & GMAC_RSR_REC ) != 0 ) && ( xEMACTaskHandle != NULL ) )\r
+       {\r
+               /* let the prvEMACHandlerTask know that there was an RX event. */\r
+               ulISREvents |= EMAC_IF_RX_EVENT;\r
+               /* Only an RX interrupt can wakeup prvEMACHandlerTask. */\r
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTxCallback( uint32_t ulStatus, uint8_t *puc_buffer )\r
+{\r
+       if( ( xTxBufferQueue != NULL ) && ( xEMACTaskHandle != NULL ) )\r
+       {\r
+               /* let the prvEMACHandlerTask know that there was an RX event. */\r
+               ulISREvents |= EMAC_IF_TX_EVENT;\r
+\r
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xGMACSwitchRequired );\r
+               xQueueSendFromISR( xTxBufferQueue, &puc_buffer, ( BaseType_t * ) &xGMACSwitchRequired );\r
+               tx_release_count[ 2 ]++;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+const TickType_t x5_Seconds = 5000UL;\r
+\r
+       if( xEMACTaskHandle == NULL )\r
+       {\r
+               prvGMACInit();\r
+\r
+               /* Wait at most 5 seconds for a Link Status in the PHY. */\r
+               xGMACWaitLS( pdMS_TO_TICKS( x5_Seconds ) );\r
+\r
+               /* The handler task is created at the highest possible priority to\r
+               ensure the interrupt handler can return directly to it. */\r
+               xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+               configASSERT( xEMACTaskHandle );\r
+       }\r
+\r
+       if( xTxBufferQueue == NULL )\r
+       {\r
+               xTxBufferQueue = xQueueCreate( GMAC_TX_BUFFERS, sizeof( void * ) );\r
+               configASSERT( xTxBufferQueue );\r
+       }\r
+\r
+       if( xTXDescriptorSemaphore == NULL )\r
+       {\r
+               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) GMAC_TX_BUFFERS, ( UBaseType_t ) GMAC_TX_BUFFERS );\r
+               configASSERT( xTXDescriptorSemaphore );\r
+       }\r
+       /* When returning non-zero, the stack will become active and\r
+    start DHCP (in configured) */\r
+       return ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xResult;\r
+\r
+       /* This function returns true if the Link Status in the PHY is high. */\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+       {\r
+               xResult = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xResult = pdFALSE;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )\r
+{\r
+/* Do not wait too long for a free TX DMA buffer. */\r
+const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );\r
+\r
+       do {\r
+               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )\r
+               {\r
+                       /* Do not attempt to send packets as long as the Link Status is low. */\r
+                       break;\r
+               }\r
+               if( xTXDescriptorSemaphore == NULL )\r
+               {\r
+                       /* Semaphore has not been created yet? */\r
+                       break;\r
+               }\r
+               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
+               {\r
+                       /* Time-out waiting for a free TX descriptor. */\r
+                       tx_release_count[ 3 ]++;\r
+                       break;\r
+               }\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       /* Confirm that the pxDescriptor may be kept by the driver. */\r
+                       configASSERT( bReleaseAfterSend != pdFALSE );\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+               gmac_dev_write( &gs_gmac_dev, (void *)pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength, prvTxCallback );\r
+\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       /* Confirm that the pxDescriptor may be kept by the driver. */\r
+                       bReleaseAfterSend = pdFALSE;\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+               /* Not interested in a call-back after TX. */\r
+               iptraceNETWORK_INTERFACE_TRANSMIT();\r
+       } while( 0 );\r
+\r
+       if( bReleaseAfterSend != pdFALSE )\r
+       {\r
+               vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+       }\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvGMACInit( void )\r
+{\r
+uint32_t ncfgr;\r
+\r
+       gmac_options_t gmac_option;\r
+\r
+       memset( &gmac_option, '\0', sizeof( gmac_option ) );\r
+       gmac_option.uc_copy_all_frame = 0;\r
+       gmac_option.uc_no_boardcast = 0;\r
+       memcpy( gmac_option.uc_mac_addr, ucMACAddress, sizeof( gmac_option.uc_mac_addr ) );\r
+\r
+       gs_gmac_dev.p_hw = GMAC;\r
+       gmac_dev_init( GMAC, &gs_gmac_dev, &gmac_option );\r
+\r
+       NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+       NVIC_EnableIRQ( GMAC_IRQn );\r
+\r
+       /* Contact the Ethernet PHY and store it's address in 'ethernet_phy_addr' */\r
+       ethernet_phy_init( GMAC, ETHERNET_CONF_PHY_ADDR, sysclk_get_cpu_hz() );\r
+\r
+       ethernet_phy_auto_negotiate( GMAC, ethernet_phy_addr );\r
+       ethernet_phy_set_link( GMAC, ethernet_phy_addr, 1 );\r
+\r
+       /* The GMAC driver will call a hook prvRxCallback(), which\r
+       in turn will wake-up the task by calling vTaskNotifyGiveFromISR() */\r
+       gmac_dev_set_rx_callback( &gs_gmac_dev, prvRxCallback );\r
+       gmac_set_address( GMAC, 1, (uint8_t*)llmnr_mac_address );\r
+\r
+       ncfgr = GMAC_NCFGR_SPD | GMAC_NCFGR_FD;\r
+\r
+       GMAC->GMAC_NCFGR = ( GMAC->GMAC_NCFGR & ~( GMAC_NCFGR_SPD | GMAC_NCFGR_FD ) ) | ncfgr;\r
+\r
+       return 1;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static inline unsigned long ulReadMDIO( unsigned /*short*/ usAddress )\r
+{\r
+uint32_t ulValue, ulReturn;\r
+int rc;\r
+\r
+       gmac_enable_management( GMAC, 1 );\r
+       rc = gmac_phy_read( GMAC, ethernet_phy_addr, usAddress, &ulValue );\r
+       gmac_enable_management( GMAC, 0 );\r
+       if( rc == GMAC_OK )\r
+       {\r
+               ulReturn = ulValue;\r
+       }\r
+       else\r
+       {\r
+               ulReturn = 0UL;\r
+       }\r
+\r
+       return ulReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime )\r
+{\r
+TickType_t xStartTime = xTaskGetTickCount();\r
+TickType_t xEndTime;\r
+BaseType_t xReturn;\r
+const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );\r
+\r
+       for( ;; )\r
+       {\r
+               xEndTime = xTaskGetTickCount();\r
+\r
+               if( ( xEndTime - xStartTime ) > xMaxTime )\r
+               {\r
+                       /* Wated more than xMaxTime, return. */\r
+                       xReturn = pdFALSE;\r
+                       break;\r
+               }\r
+\r
+               /* Check the link status again. */\r
+               ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+               {\r
+                       /* Link is up - return. */\r
+                       xReturn = pdTRUE;\r
+                       break;\r
+               }\r
+\r
+               /* Link is down - wait in the Blocked state for a short while (to allow\r
+               other tasks to execute) before checking again. */\r
+               vTaskDelay( xShortTime );\r
+       }\r
+\r
+       FreeRTOS_printf( ( "xGMACWaitLS: %ld (PHY %d) freq %lu Mz\n",\r
+               xReturn,\r
+               ethernet_phy_addr,\r
+               sysclk_get_cpu_hz() / HZ_PER_MHZ ) );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+//#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1 ) && ( ipconfigHAS_TX_CRC_OFFLOADING == 0 )\r
+\r
+       void vGMACGenerateChecksum( uint8_t *apBuffer )\r
+       {\r
+       ProtocolPacket_t *xProtPacket = (ProtocolPacket_t *)apBuffer;\r
+\r
+               if ( xProtPacket->xTCPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE )\r
+               {\r
+                       IPHeader_t *pxIPHeader = &( xProtPacket->xTCPPacket.xIPHeader );\r
+\r
+                       /* Calculate the IP header checksum. */\r
+                       pxIPHeader->usHeaderChecksum = 0x00;\r
+                       pxIPHeader->usHeaderChecksum = usGenerateChecksum( 0u, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ipSIZE_OF_IPv4_HEADER );\r
+                       pxIPHeader->usHeaderChecksum = ~FreeRTOS_htons( pxIPHeader->usHeaderChecksum );\r
+\r
+                       /* Calculate the TCP checksum for an outgoing packet. */\r
+                       usGenerateProtocolChecksum( ( uint8_t * ) apBuffer, pdTRUE );\r
+               }\r
+       }\r
+\r
+//#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvEMACRxPoll( void )\r
+{\r
+unsigned char *pucUseBuffer;\r
+uint32_t ulReceiveCount, ulResult, ulReturnValue = 0;\r
+static NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor = NULL;\r
+const UBaseType_t xMinDescriptorsToLeave = 2UL;\r
+const TickType_t xBlockTime = pdMS_TO_TICKS( 100UL );\r
+static IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+\r
+       for( ;; )\r
+       {\r
+               /* If pxNextNetworkBufferDescriptor was not left pointing at a valid\r
+               descriptor then allocate one now. */\r
+               if( ( pxNextNetworkBufferDescriptor == NULL ) && ( uxGetNumberOfFreeNetworkBuffers() > xMinDescriptorsToLeave ) )\r
+               {\r
+                       pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xBlockTime );\r
+               }\r
+\r
+               if( pxNextNetworkBufferDescriptor != NULL )\r
+               {\r
+                       /* Point pucUseBuffer to the buffer pointed to by the descriptor. */\r
+                       pucUseBuffer = ( unsigned char* ) ( pxNextNetworkBufferDescriptor->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE );\r
+               }\r
+               else\r
+               {\r
+                       /* As long as pxNextNetworkBufferDescriptor is NULL, the incoming\r
+                       messages will be flushed and ignored. */\r
+                       pucUseBuffer = NULL;\r
+               }\r
+\r
+               /* Read the next packet from the hardware into pucUseBuffer. */\r
+               ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, &ulReceiveCount );\r
+\r
+               if( ( ulResult != GMAC_OK ) || ( ulReceiveCount == 0 ) )\r
+               {\r
+                       /* No data from the hardware. */\r
+                       break;\r
+               }\r
+\r
+               if( pxNextNetworkBufferDescriptor == NULL )\r
+               {\r
+                       /* Data was read from the hardware, but no descriptor was available\r
+                       for it, so it will be dropped. */\r
+                       iptraceETHERNET_RX_EVENT_LOST();\r
+                       continue;\r
+               }\r
+\r
+               iptraceNETWORK_INTERFACE_RECEIVE();\r
+               pxNextNetworkBufferDescriptor->xDataLength = ( size_t ) ulReceiveCount;\r
+               xRxEvent.pvData = ( void * ) pxNextNetworkBufferDescriptor;\r
+\r
+               /* Send the descriptor to the IP task for processing. */\r
+               if( xSendEventStructToIPTask( &xRxEvent, xBlockTime ) != pdTRUE )\r
+               {\r
+                       /* The buffer could not be sent to the stack so must be released\r
+                       again. */\r
+                       vReleaseNetworkBufferAndDescriptor( pxNextNetworkBufferDescriptor );\r
+                       iptraceETHERNET_RX_EVENT_LOST();\r
+                       FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );\r
+               }\r
+\r
+               /* Now the buffer has either been passed to the IP-task,\r
+               or it has been released in the code above. */\r
+               pxNextNetworkBufferDescriptor = NULL;\r
+               ulReturnValue++;\r
+       }\r
+\r
+       return ulReturnValue;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vCheckBuffersAndQueue( void )\r
+{\r
+static UBaseType_t uxLastMinBufferCount = 0;\r
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+       static UBaseType_t uxLastMinQueueSpace;\r
+#endif\r
+static UBaseType_t uxCurrentCount;\r
+\r
+       #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+       {\r
+               uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+               if( uxLastMinQueueSpace != uxCurrentCount )\r
+               {\r
+                       /* The logging produced below may be helpful\r
+                       while tuning +TCP: see how many buffers are in use. */\r
+                       uxLastMinQueueSpace = uxCurrentCount;\r
+                       FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+               }\r
+       }\r
+       #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+       uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+       if( uxLastMinBufferCount != uxCurrentCount )\r
+       {\r
+               /* The logging produced below may be helpful\r
+               while tuning +TCP: see how many buffers are in use. */\r
+               uxLastMinBufferCount = uxCurrentCount;\r
+               FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                       uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+       }\r
+\r
+}\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+UBaseType_t uxCount;\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       NetworkBufferDescriptor_t *pxBuffer;\r
+#endif\r
+uint8_t *pucBuffer;\r
+BaseType_t xResult = 0;\r
+uint32_t xStatus;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       configASSERT( xEMACTaskHandle );\r
+\r
+       vTaskSetTimeOutState( &xPhyTime );\r
+       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+       for( ;; )\r
+       {\r
+               vCheckBuffersAndQueue();\r
+\r
+               if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )\r
+               {\r
+                       /* No events to process now, wait for the next. */\r
+                       ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
+               {\r
+                       ulISREvents &= ~EMAC_IF_RX_EVENT;\r
+\r
+                       /* Wait for the EMAC interrupt to indicate that another packet has been\r
+                       received. */\r
+                       xResult = prvEMACRxPoll();\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
+               {\r
+                       /* Future extension: code to release TX buffers if zero-copy is used. */\r
+                       ulISREvents &= ~EMAC_IF_TX_EVENT;\r
+                       while( xQueueReceive( xTxBufferQueue, &pucBuffer, 0 ) != pdFALSE )\r
+                       {\r
+                               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+                               {\r
+                                       pxBuffer = pxPacketBuffer_to_NetworkBuffer( pucBuffer );\r
+                                       if( pxBuffer != NULL )\r
+                                       {\r
+                                               vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+                                               tx_release_count[ 0 ]++;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               tx_release_count[ 1 ]++;\r
+                                       }\r
+                               }\r
+                               #else\r
+                               {\r
+                                       tx_release_count[ 0 ]++;\r
+                               }\r
+                               #endif\r
+                               uxCount = uxQueueMessagesWaiting( ( QueueHandle_t ) xTXDescriptorSemaphore );\r
+                               if( uxCount < GMAC_TX_BUFFERS )\r
+                               {\r
+                                       /* Tell the counting semaphore that one more TX descriptor is available. */\r
+                                       xSemaphoreGive( xTXDescriptorSemaphore );\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )\r
+               {\r
+                       /* Future extension: logging about errors that occurred. */\r
+                       ulISREvents &= ~EMAC_IF_ERR_EVENT;\r
+               }\r
+\r
+               if( xResult > 0 )\r
+               {\r
+                       /* A packet was received. No need to check for the PHY status now,\r
+                       but set a timer to check it later on. */\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       xResult = 0;\r
+               }\r
+               else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )\r
+               {\r
+                       /* Check the link status again. */\r
+                       xStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )\r
+                       {\r
+                               ulPHYLinkStatus = xStatus;\r
+                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );\r
+                       }\r
+\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/component/gmac.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/component/gmac.h
new file mode 100644 (file)
index 0000000..6eb069f
--- /dev/null
@@ -0,0 +1,746 @@
+/**\r
+ * \file\r
+ *\r
+ * Copyright (c) 2012 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef _SAM4E_GMAC_COMPONENT_\r
+#define _SAM4E_GMAC_COMPONENT_\r
+\r
+/* ============================================================================= */\r
+/**  SOFTWARE API DEFINITION FOR Gigabit Ethernet MAC */\r
+/* ============================================================================= */\r
+/** \addtogroup SAM4E_GMAC Gigabit Ethernet MAC */\r
+/*@{*/\r
+\r
+#if !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__))\r
+/** \brief GmacSa hardware registers */\r
+typedef struct {\r
+  RwReg   GMAC_SAB;        /**< \brief (GmacSa Offset: 0x0) Specific Address 1 Bottom [31:0] Register */\r
+  RwReg   GMAC_SAT;        /**< \brief (GmacSa Offset: 0x4) Specific Address 1 Top [47:32] Register */\r
+} GmacSa;\r
+/** \brief Gmac hardware registers */\r
+#define GMACSA_NUMBER 4\r
+typedef struct {\r
+  RwReg   GMAC_NCR;        /**< \brief (Gmac Offset: 0x000) Network Control Register */\r
+  RwReg   GMAC_NCFGR;      /**< \brief (Gmac Offset: 0x004) Network Configuration Register */\r
+  RoReg   GMAC_NSR;        /**< \brief (Gmac Offset: 0x008) Network Status Register */\r
+  RwReg   GMAC_UR;         /**< \brief (Gmac Offset: 0x00C) User Register */\r
+  RwReg   GMAC_DCFGR;      /**< \brief (Gmac Offset: 0x010) DMA Configuration Register */\r
+  RwReg   GMAC_TSR;        /**< \brief (Gmac Offset: 0x014) Transmit Status Register */\r
+  RwReg   GMAC_RBQB;       /**< \brief (Gmac Offset: 0x018) Receive Buffer Queue Base Address */\r
+  RwReg   GMAC_TBQB;       /**< \brief (Gmac Offset: 0x01C) Transmit Buffer Queue Base Address */\r
+  RwReg   GMAC_RSR;        /**< \brief (Gmac Offset: 0x020) Receive Status Register */\r
+  RoReg   GMAC_ISR;        /**< \brief (Gmac Offset: 0x024) Interrupt Status Register */\r
+  WoReg   GMAC_IER;        /**< \brief (Gmac Offset: 0x028) Interrupt Enable Register */\r
+  WoReg   GMAC_IDR;        /**< \brief (Gmac Offset: 0x02C) Interrupt Disable Register */\r
+  RoReg   GMAC_IMR;        /**< \brief (Gmac Offset: 0x030) Interrupt Mask Register */\r
+  RwReg   GMAC_MAN;        /**< \brief (Gmac Offset: 0x034) PHY Maintenance Register */\r
+  RoReg   GMAC_RPQ;        /**< \brief (Gmac Offset: 0x038) Received Pause Quantum Register */\r
+  RwReg   GMAC_TPQ;        /**< \brief (Gmac Offset: 0x03C) Transmit Pause Quantum Register */\r
+  RwReg   GMAC_TPSF;       /**< \brief (Gmac Offset: 0x040) TX Partial Store and Forward Register */\r
+  RwReg   GMAC_RPSF;       /**< \brief (Gmac Offset: 0x044) RX Partial Store and Forward Register */\r
+  RoReg   Reserved1[14];\r
+  RwReg   GMAC_HRB;        /**< \brief (Gmac Offset: 0x080) Hash Register Bottom [31:0] */\r
+  RwReg   GMAC_HRT;        /**< \brief (Gmac Offset: 0x084) Hash Register Top [63:32] */\r
+  GmacSa  GMAC_SA[GMACSA_NUMBER]; /**< \brief (Gmac Offset: 0x088) 1 .. 4 */\r
+  RwReg   GMAC_TIDM[4];    /**< \brief (Gmac Offset: 0x0A8) Type ID Match 1 Register */\r
+  RwReg   GMAC_WOL;        /**< \brief (Gmac Offset: 0x0B8) Wake on LAN Register */\r
+  RwReg   GMAC_IPGS;       /**< \brief (Gmac Offset: 0x0BC) IPG Stretch Register */\r
+  RwReg   GMAC_SVLAN;      /**< \brief (Gmac Offset: 0x0C0) Stacked VLAN Register */\r
+  RwReg   GMAC_TPFCP;      /**< \brief (Gmac Offset: 0x0C4) Transmit PFC Pause Register */\r
+  RwReg   GMAC_SAMB1;      /**< \brief (Gmac Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register */\r
+  RwReg   GMAC_SAMT1;      /**< \brief (Gmac Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register */\r
+  RoReg   Reserved2[12];\r
+  RoReg   GMAC_OTLO;       /**< \brief (Gmac Offset: 0x100) Octets Transmitted [31:0] Register */\r
+  RoReg   GMAC_OTHI;       /**< \brief (Gmac Offset: 0x104) Octets Transmitted [47:32] Register */\r
+  RoReg   GMAC_FT;         /**< \brief (Gmac Offset: 0x108) Frames Transmitted Register */\r
+  RoReg   GMAC_BCFT;       /**< \brief (Gmac Offset: 0x10C) Broadcast Frames Transmitted Register */\r
+  RoReg   GMAC_MFT;        /**< \brief (Gmac Offset: 0x110) Multicast Frames Transmitted Register */\r
+  RoReg   GMAC_PFT;        /**< \brief (Gmac Offset: 0x114) Pause Frames Transmitted Register */\r
+  RoReg   GMAC_BFT64;      /**< \brief (Gmac Offset: 0x118) 64 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TBFT127;    /**< \brief (Gmac Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TBFT255;    /**< \brief (Gmac Offset: 0x120) 128 to 255 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TBFT511;    /**< \brief (Gmac Offset: 0x124) 256 to 511 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TBFT1023;   /**< \brief (Gmac Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TBFT1518;   /**< \brief (Gmac Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_GTBFT1518;  /**< \brief (Gmac Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register */\r
+  RoReg   GMAC_TUR;        /**< \brief (Gmac Offset: 0x134) Transmit Under Runs Register */\r
+  RoReg   GMAC_SCF;        /**< \brief (Gmac Offset: 0x138) Single Collision Frames Register */\r
+  RoReg   GMAC_MCF;        /**< \brief (Gmac Offset: 0x13C) Multiple Collision Frames Register */\r
+  RoReg   GMAC_EC;         /**< \brief (Gmac Offset: 0x140) Excessive Collisions Register */\r
+  RoReg   GMAC_LC;         /**< \brief (Gmac Offset: 0x144) Late Collisions Register */\r
+  RoReg   GMAC_DTF;        /**< \brief (Gmac Offset: 0x148) Deferred Transmission Frames Register */\r
+  RoReg   GMAC_CSE;        /**< \brief (Gmac Offset: 0x14C) Carrier Sense Errors Register */\r
+  RoReg   GMAC_ORLO;       /**< \brief (Gmac Offset: 0x150) Octets Received [31:0] Received */\r
+  RoReg   GMAC_ORHI;       /**< \brief (Gmac Offset: 0x154) Octets Received [47:32] Received */\r
+  RoReg   GMAC_FR;         /**< \brief (Gmac Offset: 0x158) Frames Received Register */\r
+  RoReg   GMAC_BCFR;       /**< \brief (Gmac Offset: 0x15C) Broadcast Frames Received Register */\r
+  RoReg   GMAC_MFR;        /**< \brief (Gmac Offset: 0x160) Multicast Frames Received Register */\r
+  RoReg   GMAC_PFR;        /**< \brief (Gmac Offset: 0x164) Pause Frames Received Register */\r
+  RoReg   GMAC_BFR64;      /**< \brief (Gmac Offset: 0x168) 64 Byte Frames Received Register */\r
+  RoReg   GMAC_TBFR127;    /**< \brief (Gmac Offset: 0x16C) 65 to 127 Byte Frames Received Register */\r
+  RoReg   GMAC_TBFR255;    /**< \brief (Gmac Offset: 0x170) 128 to 255 Byte Frames Received Register */\r
+  RoReg   GMAC_TBFR511;    /**< \brief (Gmac Offset: 0x174) 256 to 511Byte Frames Received Register */\r
+  RoReg   GMAC_TBFR1023;   /**< \brief (Gmac Offset: 0x178) 512 to 1023 Byte Frames Received Register */\r
+  RoReg   GMAC_TBFR1518;   /**< \brief (Gmac Offset: 0x17C) 1024 to 1518 Byte Frames Received Register */\r
+  RoReg   GMAC_TMXBFR;     /**< \brief (Gmac Offset: 0x180) 1519 to Maximum Byte Frames Received Register */\r
+  RoReg   GMAC_UFR;        /**< \brief (Gmac Offset: 0x184) Undersize Frames Received Register */\r
+  RoReg   GMAC_OFR;        /**< \brief (Gmac Offset: 0x188) Oversize Frames Received Register */\r
+  RoReg   GMAC_JR;         /**< \brief (Gmac Offset: 0x18C) Jabbers Received Register */\r
+  RoReg   GMAC_FCSE;       /**< \brief (Gmac Offset: 0x190) Frame Check Sequence Errors Register */\r
+  RoReg   GMAC_LFFE;       /**< \brief (Gmac Offset: 0x194) Length Field Frame Errors Register */\r
+  RoReg   GMAC_RSE;        /**< \brief (Gmac Offset: 0x198) Receive Symbol Errors Register */\r
+  RoReg   GMAC_AE;         /**< \brief (Gmac Offset: 0x19C) Alignment Errors Register */\r
+  RoReg   GMAC_RRE;        /**< \brief (Gmac Offset: 0x1A0) Receive Resource Errors Register */\r
+  RoReg   GMAC_ROE;        /**< \brief (Gmac Offset: 0x1A4) Receive Overrun Register */\r
+  RoReg   GMAC_IHCE;       /**< \brief (Gmac Offset: 0x1A8) IP Header Checksum Errors Register */\r
+  RoReg   GMAC_TCE;        /**< \brief (Gmac Offset: 0x1AC) TCP Checksum Errors Register */\r
+  RoReg   GMAC_UCE;        /**< \brief (Gmac Offset: 0x1B0) UDP Checksum Errors Register */\r
+  RoReg   Reserved3[5];\r
+  RwReg   GMAC_TSSS;       /**< \brief (Gmac Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register */\r
+  RwReg   GMAC_TSSN;       /**< \brief (Gmac Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register */\r
+  RwReg   GMAC_TS;         /**< \brief (Gmac Offset: 0x1D0) 1588 Timer Seconds Register */\r
+  RwReg   GMAC_TN;         /**< \brief (Gmac Offset: 0x1D4) 1588 Timer Nanoseconds Register */\r
+  WoReg   GMAC_TA;         /**< \brief (Gmac Offset: 0x1D8) 1588 Timer Adjust Register */\r
+  RwReg   GMAC_TI;         /**< \brief (Gmac Offset: 0x1DC) 1588 Timer Increment Register */\r
+  RoReg   GMAC_EFTS;       /**< \brief (Gmac Offset: 0x1E0) PTP Event Frame Transmitted Seconds */\r
+  RoReg   GMAC_EFTN;       /**< \brief (Gmac Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds */\r
+  RoReg   GMAC_EFRS;       /**< \brief (Gmac Offset: 0x1E8) PTP Event Frame Received Seconds */\r
+  RoReg   GMAC_EFRN;       /**< \brief (Gmac Offset: 0x1EC) PTP Event Frame Received Nanoseconds */\r
+  RoReg   GMAC_PEFTS;      /**< \brief (Gmac Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds */\r
+  RoReg   GMAC_PEFTN;      /**< \brief (Gmac Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds */\r
+  RoReg   GMAC_PEFRS;      /**< \brief (Gmac Offset: 0x1F8) PTP Peer Event Frame Received Seconds */\r
+  RoReg   GMAC_PEFRN;      /**< \brief (Gmac Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds */\r
+  RoReg   Reserved4[128];\r
+  RoReg   GMAC_ISRPQ[7];   /**< \brief (Gmac Offset: 0x400) Interrupt Status Register Priority Queue */\r
+  RoReg   Reserved5[9];\r
+  RwReg   GMAC_TBQBAPQ[7]; /**< \brief (Gmac Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue */\r
+  RoReg   Reserved6[9];\r
+  RwReg   GMAC_RBQBAPQ[7]; /**< \brief (Gmac Offset: 0x480) Receive Buffer Queue Base Address Priority Queue */\r
+  RoReg   Reserved7[1];\r
+  RwReg   GMAC_RBSRPQ[7];  /**< \brief (Gmac Offset: 0x4A0) Receive Buffer Size Register Priority Queue */\r
+  RoReg   Reserved8[17];\r
+  RwReg   GMAC_ST1RPQ[16]; /**< \brief (Gmac Offset: 0x500) Screening Type1 Register Priority Queue */\r
+  RwReg   GMAC_ST2RPQ[16]; /**< \brief (Gmac Offset: 0x540) Screening Type2 Register Priority Queue */\r
+  RoReg   Reserved9[32];\r
+  WoReg   GMAC_IERPQ[7];   /**< \brief (Gmac Offset: 0x600) Interrupt Enable Register Priority Queue */\r
+  RoReg   Reserved10[1];\r
+  WoReg   GMAC_IDRPQ[7];   /**< \brief (Gmac Offset: 0x620) Interrupt Disable Register Priority Queue */\r
+  RoReg   Reserved11[1];\r
+  RwReg   GMAC_IMRPQ[7];   /**< \brief (Gmac Offset: 0x640) Interrupt Mask Register Priority Queue */\r
+} Gmac;\r
+#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */\r
+/* -------- GMAC_NCR : (GMAC Offset: 0x000) Network Control Register -------- */\r
+#define GMAC_NCR_LB (0x1u << 0) /**< \brief (GMAC_NCR) Loop Back */\r
+#define GMAC_NCR_LBL (0x1u << 1) /**< \brief (GMAC_NCR) Loop Back Local */\r
+#define GMAC_NCR_RXEN (0x1u << 2) /**< \brief (GMAC_NCR) Receive Enable */\r
+#define GMAC_NCR_TXEN (0x1u << 3) /**< \brief (GMAC_NCR) Transmit Enable */\r
+#define GMAC_NCR_MPE (0x1u << 4) /**< \brief (GMAC_NCR) Management Port Enable */\r
+#define GMAC_NCR_CLRSTAT (0x1u << 5) /**< \brief (GMAC_NCR) Clear Statistics Registers */\r
+#define GMAC_NCR_INCSTAT (0x1u << 6) /**< \brief (GMAC_NCR) Increment Statistics Registers */\r
+#define GMAC_NCR_WESTAT (0x1u << 7) /**< \brief (GMAC_NCR) Write Enable for Statistics Registers */\r
+#define GMAC_NCR_BP (0x1u << 8) /**< \brief (GMAC_NCR) Back pressure */\r
+#define GMAC_NCR_TSTART (0x1u << 9) /**< \brief (GMAC_NCR) Start Transmission */\r
+#define GMAC_NCR_THALT (0x1u << 10) /**< \brief (GMAC_NCR) Transmit Halt */\r
+#define GMAC_NCR_TXPF (0x1u << 11) /**< \brief (GMAC_NCR) Transmit Pause Frame */\r
+#define GMAC_NCR_TXZQPF (0x1u << 12) /**< \brief (GMAC_NCR) Transmit Zero Quantum Pause Frame */\r
+#define GMAC_NCR_RDS (0x1u << 14) /**< \brief (GMAC_NCR) Read Snapshot */\r
+#define GMAC_NCR_SRTSM (0x1u << 15) /**< \brief (GMAC_NCR) Store Receive Time Stamp to Memory */\r
+#define GMAC_NCR_ENPBPR (0x1u << 16) /**< \brief (GMAC_NCR) Enable PFC Priority-based Pause Reception */\r
+#define GMAC_NCR_TXPBPF (0x1u << 17) /**< \brief (GMAC_NCR) Transmit PFC Priority-based Pause Frame */\r
+#define GMAC_NCR_FNP (0x1u << 18) /**< \brief (GMAC_NCR) Flush Next Packet */\r
+/* -------- GMAC_NCFGR : (GMAC Offset: 0x004) Network Configuration Register -------- */\r
+#define GMAC_NCFGR_SPD (0x1u << 0) /**< \brief (GMAC_NCFGR) Speed */\r
+#define GMAC_NCFGR_FD (0x1u << 1) /**< \brief (GMAC_NCFGR) Full Duplex */\r
+#define GMAC_NCFGR_DNVLAN (0x1u << 2) /**< \brief (GMAC_NCFGR) Discard Non-VLAN FRAMES */\r
+#define GMAC_NCFGR_JFRAME (0x1u << 3) /**< \brief (GMAC_NCFGR) Jumbo Frame Size */\r
+#define GMAC_NCFGR_CAF (0x1u << 4) /**< \brief (GMAC_NCFGR) Copy All Frames */\r
+#define GMAC_NCFGR_NBC (0x1u << 5) /**< \brief (GMAC_NCFGR) No Broadcast */\r
+#define GMAC_NCFGR_MTIHEN (0x1u << 6) /**< \brief (GMAC_NCFGR) Multicast Hash Enable */\r
+#define GMAC_NCFGR_UNIHEN (0x1u << 7) /**< \brief (GMAC_NCFGR) Unicast Hash Enable */\r
+#define GMAC_NCFGR_MAXFS (0x1u << 8) /**< \brief (GMAC_NCFGR) 1536 Maximum Frame Size */\r
+#define GMAC_NCFGR_GBE (0x1u << 10) /**< \brief (GMAC_NCFGR) Gigabit Mode Enable */\r
+#define GMAC_NCFGR_PIS (0x1u << 11) /**< \brief (GMAC_NCFGR) Physical Interface Select */\r
+#define GMAC_NCFGR_RTY (0x1u << 12) /**< \brief (GMAC_NCFGR) Retry Test */\r
+#define GMAC_NCFGR_PEN (0x1u << 13) /**< \brief (GMAC_NCFGR) Pause Enable */\r
+#define GMAC_NCFGR_RXBUFO_Pos 14\r
+#define GMAC_NCFGR_RXBUFO_Msk (0x3u << GMAC_NCFGR_RXBUFO_Pos) /**< \brief (GMAC_NCFGR) Receive Buffer Offset */\r
+#define GMAC_NCFGR_RXBUFO(value) ((GMAC_NCFGR_RXBUFO_Msk & ((value) << GMAC_NCFGR_RXBUFO_Pos)))\r
+#define GMAC_NCFGR_LFERD (0x1u << 16) /**< \brief (GMAC_NCFGR) Length Field Error Frame Discard */\r
+#define GMAC_NCFGR_RFCS (0x1u << 17) /**< \brief (GMAC_NCFGR) Remove FCS */\r
+#define GMAC_NCFGR_CLK_Pos 18\r
+#define GMAC_NCFGR_CLK_Msk (0x7u << GMAC_NCFGR_CLK_Pos) /**< \brief (GMAC_NCFGR) MDC CLock Division */\r
+#define   GMAC_NCFGR_CLK_MCK_8 (0x0u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 8 (MCK up to 20 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_16 (0x1u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 16 (MCK up to 40 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_32 (0x2u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 32 (MCK up to 80 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_48 (0x3u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 48 (MCK up to 120MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_64 (0x4u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 64 (MCK up to 160 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_96 (0x5u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 96 (MCK up to 240 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_128 (0x6u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 128 (MCK up to 320 MHz) */\r
+#define   GMAC_NCFGR_CLK_MCK_224 (0x7u << 18) /**< \brief (GMAC_NCFGR) MCK divided by 224 (MCK up to 540 MHz) */\r
+#define GMAC_NCFGR_DBW_Pos 21\r
+#define GMAC_NCFGR_DBW_Msk (0x3u << GMAC_NCFGR_DBW_Pos) /**< \brief (GMAC_NCFGR) Data Bus Width */\r
+#define   GMAC_NCFGR_DBW_DBW32 (0x0u << 21) /**< \brief (GMAC_NCFGR) 32-bit data bus width */\r
+#define   GMAC_NCFGR_DBW_DBW64 (0x1u << 21) /**< \brief (GMAC_NCFGR) 64-bit data bus width */\r
+#define GMAC_NCFGR_DCPF (0x1u << 23) /**< \brief (GMAC_NCFGR) Disable Copy of Pause Frames */\r
+#define GMAC_NCFGR_RXCOEN (0x1u << 24) /**< \brief (GMAC_NCFGR) Receive Checksum Offload Enable */\r
+#define GMAC_NCFGR_EFRHD (0x1u << 25) /**< \brief (GMAC_NCFGR) Enable Frames Received in Half Duplex */\r
+#define GMAC_NCFGR_IRXFCS (0x1u << 26) /**< \brief (GMAC_NCFGR) Ignore RX FCS */\r
+#define GMAC_NCFGR_IPGSEN (0x1u << 28) /**< \brief (GMAC_NCFGR) IP Stretch Enable */\r
+#define GMAC_NCFGR_RXBP (0x1u << 29) /**< \brief (GMAC_NCFGR) Receive Bad Preamble */\r
+#define GMAC_NCFGR_IRXER (0x1u << 30) /**< \brief (GMAC_NCFGR) Ignore IPG rx_er */\r
+/* -------- GMAC_NSR : (GMAC Offset: 0x008) Network Status Register -------- */\r
+#define GMAC_NSR_MDIO (0x1u << 1) /**< \brief (GMAC_NSR) MDIO Input Status */\r
+#define GMAC_NSR_IDLE (0x1u << 2) /**< \brief (GMAC_NSR) PHY Management Logic Idle */\r
+/* -------- GMAC_UR : (GMAC Offset: 0x00C) User Register -------- */\r
+#define GMAC_UR_RGMII (0x1u << 0) /**< \brief (GMAC_UR) RGMII Mode */\r
+#define GMAC_UR_HDFC (0x1u << 6) /**< \brief (GMAC_UR) Half Duplex Flow Control */\r
+#define GMAC_UR_BPDG (0x1u << 7) /**< \brief (GMAC_UR) BPDG Bypass Deglitchers */\r
+/* -------- GMAC_DCFGR : (GMAC Offset: 0x010) DMA Configuration Register -------- */\r
+#define GMAC_DCFGR_FBLDO_Pos 0\r
+#define GMAC_DCFGR_FBLDO_Msk (0x1fu << GMAC_DCFGR_FBLDO_Pos) /**< \brief (GMAC_DCFGR) Fixed Burst Length for DMA Data Operations: */\r
+#define   GMAC_DCFGR_FBLDO_SINGLE (0x1u << 0) /**< \brief (GMAC_DCFGR) 00001: Always use SINGLE AHB bursts */\r
+#define   GMAC_DCFGR_FBLDO_INCR4 (0x4u << 0) /**< \brief (GMAC_DCFGR) 001xx: Attempt to use INCR4 AHB bursts (Default) */\r
+#define   GMAC_DCFGR_FBLDO_INCR8 (0x8u << 0) /**< \brief (GMAC_DCFGR) 01xxx: Attempt to use INCR8 AHB bursts */\r
+#define   GMAC_DCFGR_FBLDO_INCR16 (0x10u << 0) /**< \brief (GMAC_DCFGR) 1xxxx: Attempt to use INCR16 AHB bursts */\r
+#define GMAC_DCFGR_ESMA (0x1u << 6) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Management Descriptor Accesses */\r
+#define GMAC_DCFGR_ESPA (0x1u << 7) /**< \brief (GMAC_DCFGR) Endian Swap Mode Enable for Packet Data Accesses */\r
+#define GMAC_DCFGR_RXBMS_Pos 8\r
+#define GMAC_DCFGR_RXBMS_Msk (0x3u << GMAC_DCFGR_RXBMS_Pos) /**< \brief (GMAC_DCFGR) Receiver Packet Buffer Memory Size Select */\r
+#define   GMAC_DCFGR_RXBMS_EIGHTH (0x0u << 8) /**< \brief (GMAC_DCFGR) 1 Kbyte Memory Size */\r
+#define   GMAC_DCFGR_RXBMS_QUARTER (0x1u << 8) /**< \brief (GMAC_DCFGR) 2 Kbytes Memory Size */\r
+#define   GMAC_DCFGR_RXBMS_HALF (0x2u << 8) /**< \brief (GMAC_DCFGR) 4 Kbytes Memory Size */\r
+#define   GMAC_DCFGR_RXBMS_FULL (0x3u << 8) /**< \brief (GMAC_DCFGR) 8 Kbytes Memory Size */\r
+#define GMAC_DCFGR_TXPBMS (0x1u << 10) /**< \brief (GMAC_DCFGR) Transmitter Packet Buffer Memory Size Select */\r
+#define GMAC_DCFGR_TXCOEN (0x1u << 11) /**< \brief (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable */\r
+#define GMAC_DCFGR_DRBS_Pos 16\r
+#define GMAC_DCFGR_DRBS_Msk (0xffu << GMAC_DCFGR_DRBS_Pos) /**< \brief (GMAC_DCFGR) DMA Receive Buffer Size */\r
+#define GMAC_DCFGR_DRBS(value) ((GMAC_DCFGR_DRBS_Msk & ((value) << GMAC_DCFGR_DRBS_Pos)))\r
+#define GMAC_DCFGR_DDRP (0x1u << 24) /**< \brief (GMAC_DCFGR) DMA Discard Receive Packets */\r
+/* -------- GMAC_TSR : (GMAC Offset: 0x014) Transmit Status Register -------- */\r
+#define GMAC_TSR_UBR (0x1u << 0) /**< \brief (GMAC_TSR) Used Bit Read */\r
+#define GMAC_TSR_COL (0x1u << 1) /**< \brief (GMAC_TSR) Collision Occurred */\r
+#define GMAC_TSR_RLE (0x1u << 2) /**< \brief (GMAC_TSR) Retry Limit Exceeded */\r
+#define GMAC_TSR_TXGO (0x1u << 3) /**< \brief (GMAC_TSR) Transmit Go */\r
+#define GMAC_TSR_TFC (0x1u << 4) /**< \brief (GMAC_TSR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_TSR_TXCOMP (0x1u << 5) /**< \brief (GMAC_TSR) Transmit Complete */\r
+#define GMAC_TSR_UND (0x1u << 6) /**< \brief (GMAC_TSR) Transmit Under Run */\r
+#define GMAC_TSR_LCO (0x1u << 7) /**< \brief (GMAC_TSR) Late Collision Occurred */\r
+#define GMAC_TSR_HRESP (0x1u << 8) /**< \brief (GMAC_TSR) HRESP Not OK */\r
+/* -------- GMAC_RBQB : (GMAC Offset: 0x018) Receive Buffer Queue Base Address -------- */\r
+#define GMAC_RBQB_ADDR_Pos 2\r
+#define GMAC_RBQB_ADDR_Msk (0x3fffffffu << GMAC_RBQB_ADDR_Pos) /**< \brief (GMAC_RBQB) Receive buffer queue base address */\r
+#define GMAC_RBQB_ADDR(value) ((GMAC_RBQB_ADDR_Msk & ((value) << GMAC_RBQB_ADDR_Pos)))\r
+/* -------- GMAC_TBQB : (GMAC Offset: 0x01C) Transmit Buffer Queue Base Address -------- */\r
+#define GMAC_TBQB_ADDR_Pos 2\r
+#define GMAC_TBQB_ADDR_Msk (0x3fffffffu << GMAC_TBQB_ADDR_Pos) /**< \brief (GMAC_TBQB) Transmit Buffer Queue Base Address */\r
+#define GMAC_TBQB_ADDR(value) ((GMAC_TBQB_ADDR_Msk & ((value) << GMAC_TBQB_ADDR_Pos)))\r
+/* -------- GMAC_RSR : (GMAC Offset: 0x020) Receive Status Register -------- */\r
+#define GMAC_RSR_BNA (0x1u << 0) /**< \brief (GMAC_RSR) Buffer Not Available */\r
+#define GMAC_RSR_REC (0x1u << 1) /**< \brief (GMAC_RSR) Frame Received */\r
+#define GMAC_RSR_RXOVR (0x1u << 2) /**< \brief (GMAC_RSR) Receive Overrun */\r
+#define GMAC_RSR_HNO (0x1u << 3) /**< \brief (GMAC_RSR) HRESP Not OK */\r
+/* -------- GMAC_ISR : (GMAC Offset: 0x024) Interrupt Status Register -------- */\r
+#define GMAC_ISR_MFS (0x1u << 0) /**< \brief (GMAC_ISR) Management Frame Sent */\r
+#define GMAC_ISR_RCOMP (0x1u << 1) /**< \brief (GMAC_ISR) Receive Complete */\r
+#define GMAC_ISR_RXUBR (0x1u << 2) /**< \brief (GMAC_ISR) RX Used Bit Read */\r
+#define GMAC_ISR_TXUBR (0x1u << 3) /**< \brief (GMAC_ISR) TX Used Bit Read */\r
+#define GMAC_ISR_TUR (0x1u << 4) /**< \brief (GMAC_ISR) Transmit Under Run */\r
+#define GMAC_ISR_RLEX (0x1u << 5) /**< \brief (GMAC_ISR) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_ISR_TFC (0x1u << 6) /**< \brief (GMAC_ISR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_ISR_TCOMP (0x1u << 7) /**< \brief (GMAC_ISR) Transmit Complete */\r
+#define GMAC_ISR_ROVR (0x1u << 10) /**< \brief (GMAC_ISR) Receive Overrun */\r
+#define GMAC_ISR_HRESP (0x1u << 11) /**< \brief (GMAC_ISR) HRESP Not OK */\r
+#define GMAC_ISR_PFNZ (0x1u << 12) /**< \brief (GMAC_ISR) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_ISR_PTZ (0x1u << 13) /**< \brief (GMAC_ISR) Pause Time Zero */\r
+#define GMAC_ISR_PFTR (0x1u << 14) /**< \brief (GMAC_ISR) Pause Frame Transmitted */\r
+#define GMAC_ISR_EXINT (0x1u << 15) /**< \brief (GMAC_ISR) External Interrupt */\r
+#define GMAC_ISR_DRQFR (0x1u << 18) /**< \brief (GMAC_ISR) PTP Delay Request Frame Received */\r
+#define GMAC_ISR_SFR (0x1u << 19) /**< \brief (GMAC_ISR) PTP Sync Frame Received */\r
+#define GMAC_ISR_DRQFT (0x1u << 20) /**< \brief (GMAC_ISR) PTP Delay Request Frame Transmitted */\r
+#define GMAC_ISR_SFT (0x1u << 21) /**< \brief (GMAC_ISR) PTP Sync Frame Transmitted */\r
+#define GMAC_ISR_PDRQFR (0x1u << 22) /**< \brief (GMAC_ISR) PDelay Request Frame Received */\r
+#define GMAC_ISR_PDRSFR (0x1u << 23) /**< \brief (GMAC_ISR) PDelay Response Frame Received */\r
+#define GMAC_ISR_PDRQFT (0x1u << 24) /**< \brief (GMAC_ISR) PDelay Request Frame Transmitted */\r
+#define GMAC_ISR_PDRSFT (0x1u << 25) /**< \brief (GMAC_ISR) PDelay Response Frame Transmitted */\r
+#define GMAC_ISR_SRI (0x1u << 26) /**< \brief (GMAC_ISR) TSU Seconds Register Increment */\r
+#define GMAC_ISR_WOL (0x1u << 28) /**< \brief (GMAC_ISR) Wake On LAN */\r
+/* -------- GMAC_IER : (GMAC Offset: 0x028) Interrupt Enable Register -------- */\r
+#define GMAC_IER_MFS (0x1u << 0) /**< \brief (GMAC_IER) Management Frame Sent */\r
+#define GMAC_IER_RCOMP (0x1u << 1) /**< \brief (GMAC_IER) Receive Complete */\r
+#define GMAC_IER_RXUBR (0x1u << 2) /**< \brief (GMAC_IER) RX Used Bit Read */\r
+#define GMAC_IER_TXUBR (0x1u << 3) /**< \brief (GMAC_IER) TX Used Bit Read */\r
+#define GMAC_IER_TUR (0x1u << 4) /**< \brief (GMAC_IER) Transmit Under Run */\r
+#define GMAC_IER_RLEX (0x1u << 5) /**< \brief (GMAC_IER) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IER_TFC (0x1u << 6) /**< \brief (GMAC_IER) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IER_TCOMP (0x1u << 7) /**< \brief (GMAC_IER) Transmit Complete */\r
+#define GMAC_IER_ROVR (0x1u << 10) /**< \brief (GMAC_IER) Receive Overrun */\r
+#define GMAC_IER_HRESP (0x1u << 11) /**< \brief (GMAC_IER) HRESP Not OK */\r
+#define GMAC_IER_PFNZ (0x1u << 12) /**< \brief (GMAC_IER) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_IER_PTZ (0x1u << 13) /**< \brief (GMAC_IER) Pause Time Zero */\r
+#define GMAC_IER_PFTR (0x1u << 14) /**< \brief (GMAC_IER) Pause Frame Transmitted */\r
+#define GMAC_IER_EXINT (0x1u << 15) /**< \brief (GMAC_IER) External Interrupt */\r
+#define GMAC_IER_DRQFR (0x1u << 18) /**< \brief (GMAC_IER) PTP Delay Request Frame Received */\r
+#define GMAC_IER_SFR (0x1u << 19) /**< \brief (GMAC_IER) PTP Sync Frame Received */\r
+#define GMAC_IER_DRQFT (0x1u << 20) /**< \brief (GMAC_IER) PTP Delay Request Frame Transmitted */\r
+#define GMAC_IER_SFT (0x1u << 21) /**< \brief (GMAC_IER) PTP Sync Frame Transmitted */\r
+#define GMAC_IER_PDRQFR (0x1u << 22) /**< \brief (GMAC_IER) PDelay Request Frame Received */\r
+#define GMAC_IER_PDRSFR (0x1u << 23) /**< \brief (GMAC_IER) PDelay Response Frame Received */\r
+#define GMAC_IER_PDRQFT (0x1u << 24) /**< \brief (GMAC_IER) PDelay Request Frame Transmitted */\r
+#define GMAC_IER_PDRSFT (0x1u << 25) /**< \brief (GMAC_IER) PDelay Response Frame Transmitted */\r
+#define GMAC_IER_SRI (0x1u << 26) /**< \brief (GMAC_IER) TSU Seconds Register Increment */\r
+#define GMAC_IER_WOL (0x1u << 28) /**< \brief (GMAC_IER) Wake On LAN */\r
+/* -------- GMAC_IDR : (GMAC Offset: 0x02C) Interrupt Disable Register -------- */\r
+#define GMAC_IDR_MFS (0x1u << 0) /**< \brief (GMAC_IDR) Management Frame Sent */\r
+#define GMAC_IDR_RCOMP (0x1u << 1) /**< \brief (GMAC_IDR) Receive Complete */\r
+#define GMAC_IDR_RXUBR (0x1u << 2) /**< \brief (GMAC_IDR) RX Used Bit Read */\r
+#define GMAC_IDR_TXUBR (0x1u << 3) /**< \brief (GMAC_IDR) TX Used Bit Read */\r
+#define GMAC_IDR_TUR (0x1u << 4) /**< \brief (GMAC_IDR) Transmit Under Run */\r
+#define GMAC_IDR_RLEX (0x1u << 5) /**< \brief (GMAC_IDR) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IDR_TFC (0x1u << 6) /**< \brief (GMAC_IDR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IDR_TCOMP (0x1u << 7) /**< \brief (GMAC_IDR) Transmit Complete */\r
+#define GMAC_IDR_ROVR (0x1u << 10) /**< \brief (GMAC_IDR) Receive Overrun */\r
+#define GMAC_IDR_HRESP (0x1u << 11) /**< \brief (GMAC_IDR) HRESP Not OK */\r
+#define GMAC_IDR_PFNZ (0x1u << 12) /**< \brief (GMAC_IDR) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_IDR_PTZ (0x1u << 13) /**< \brief (GMAC_IDR) Pause Time Zero */\r
+#define GMAC_IDR_PFTR (0x1u << 14) /**< \brief (GMAC_IDR) Pause Frame Transmitted */\r
+#define GMAC_IDR_EXINT (0x1u << 15) /**< \brief (GMAC_IDR) External Interrupt */\r
+#define GMAC_IDR_DRQFR (0x1u << 18) /**< \brief (GMAC_IDR) PTP Delay Request Frame Received */\r
+#define GMAC_IDR_SFR (0x1u << 19) /**< \brief (GMAC_IDR) PTP Sync Frame Received */\r
+#define GMAC_IDR_DRQFT (0x1u << 20) /**< \brief (GMAC_IDR) PTP Delay Request Frame Transmitted */\r
+#define GMAC_IDR_SFT (0x1u << 21) /**< \brief (GMAC_IDR) PTP Sync Frame Transmitted */\r
+#define GMAC_IDR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IDR) PDelay Request Frame Received */\r
+#define GMAC_IDR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IDR) PDelay Response Frame Received */\r
+#define GMAC_IDR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IDR) PDelay Request Frame Transmitted */\r
+#define GMAC_IDR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IDR) PDelay Response Frame Transmitted */\r
+#define GMAC_IDR_SRI (0x1u << 26) /**< \brief (GMAC_IDR) TSU Seconds Register Increment */\r
+#define GMAC_IDR_WOL (0x1u << 28) /**< \brief (GMAC_IDR) Wake On LAN */\r
+/* -------- GMAC_IMR : (GMAC Offset: 0x030) Interrupt Mask Register -------- */\r
+#define GMAC_IMR_MFS (0x1u << 0) /**< \brief (GMAC_IMR) Management Frame Sent */\r
+#define GMAC_IMR_RCOMP (0x1u << 1) /**< \brief (GMAC_IMR) Receive Complete */\r
+#define GMAC_IMR_RXUBR (0x1u << 2) /**< \brief (GMAC_IMR) RX Used Bit Read */\r
+#define GMAC_IMR_TXUBR (0x1u << 3) /**< \brief (GMAC_IMR) TX Used Bit Read */\r
+#define GMAC_IMR_TUR (0x1u << 4) /**< \brief (GMAC_IMR) Transmit Under Run */\r
+#define GMAC_IMR_RLEX (0x1u << 5) /**< \brief (GMAC_IMR) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IMR_TFC (0x1u << 6) /**< \brief (GMAC_IMR) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IMR_TCOMP (0x1u << 7) /**< \brief (GMAC_IMR) Transmit Complete */\r
+#define GMAC_IMR_ROVR (0x1u << 10) /**< \brief (GMAC_IMR) Receive Overrun */\r
+#define GMAC_IMR_HRESP (0x1u << 11) /**< \brief (GMAC_IMR) HRESP Not OK */\r
+#define GMAC_IMR_PFNZ (0x1u << 12) /**< \brief (GMAC_IMR) Pause Frame with Non-zero Pause Quantum Received */\r
+#define GMAC_IMR_PTZ (0x1u << 13) /**< \brief (GMAC_IMR) Pause Time Zero */\r
+#define GMAC_IMR_PFTR (0x1u << 14) /**< \brief (GMAC_IMR) Pause Frame Transmitted */\r
+#define GMAC_IMR_EXINT (0x1u << 15) /**< \brief (GMAC_IMR) External Interrupt */\r
+#define GMAC_IMR_DRQFR (0x1u << 18) /**< \brief (GMAC_IMR) PTP Delay Request Frame Received */\r
+#define GMAC_IMR_SFR (0x1u << 19) /**< \brief (GMAC_IMR) PTP Sync Frame Received */\r
+#define GMAC_IMR_DRQFT (0x1u << 20) /**< \brief (GMAC_IMR) PTP Delay Request Frame Transmitted */\r
+#define GMAC_IMR_SFT (0x1u << 21) /**< \brief (GMAC_IMR) PTP Sync Frame Transmitted */\r
+#define GMAC_IMR_PDRQFR (0x1u << 22) /**< \brief (GMAC_IMR) PDelay Request Frame Received */\r
+#define GMAC_IMR_PDRSFR (0x1u << 23) /**< \brief (GMAC_IMR) PDelay Response Frame Received */\r
+#define GMAC_IMR_PDRQFT (0x1u << 24) /**< \brief (GMAC_IMR) PDelay Request Frame Transmitted */\r
+#define GMAC_IMR_PDRSFT (0x1u << 25) /**< \brief (GMAC_IMR) PDelay Response Frame Transmitted */\r
+/* -------- GMAC_MAN : (GMAC Offset: 0x034) PHY Maintenance Register -------- */\r
+#define GMAC_MAN_DATA_Pos 0\r
+#define GMAC_MAN_DATA_Msk (0xffffu << GMAC_MAN_DATA_Pos) /**< \brief (GMAC_MAN) PHY Data */\r
+#define GMAC_MAN_DATA(value) ((GMAC_MAN_DATA_Msk & ((value) << GMAC_MAN_DATA_Pos)))\r
+#define GMAC_MAN_WTN_Pos 16\r
+#define GMAC_MAN_WTN_Msk (0x3u << GMAC_MAN_WTN_Pos) /**< \brief (GMAC_MAN) Write Ten */\r
+#define GMAC_MAN_WTN(value) ((GMAC_MAN_WTN_Msk & ((value) << GMAC_MAN_WTN_Pos)))\r
+#define GMAC_MAN_REGA_Pos 18\r
+#define GMAC_MAN_REGA_Msk (0x1fu << GMAC_MAN_REGA_Pos) /**< \brief (GMAC_MAN) Register Address */\r
+#define GMAC_MAN_REGA(value) ((GMAC_MAN_REGA_Msk & ((value) << GMAC_MAN_REGA_Pos)))\r
+#define GMAC_MAN_PHYA_Pos 23\r
+#define GMAC_MAN_PHYA_Msk (0x1fu << GMAC_MAN_PHYA_Pos) /**< \brief (GMAC_MAN) PHY Address */\r
+#define GMAC_MAN_PHYA(value) ((GMAC_MAN_PHYA_Msk & ((value) << GMAC_MAN_PHYA_Pos)))\r
+#define GMAC_MAN_OP_Pos 28\r
+#define GMAC_MAN_OP_Msk (0x3u << GMAC_MAN_OP_Pos) /**< \brief (GMAC_MAN) Operation */\r
+#define GMAC_MAN_OP(value) ((GMAC_MAN_OP_Msk & ((value) << GMAC_MAN_OP_Pos)))\r
+#define GMAC_MAN_CLTTO (0x1u << 30) /**< \brief (GMAC_MAN) Clause 22 Operation */\r
+#define GMAC_MAN_WZO (0x1u << 31) /**< \brief (GMAC_MAN) Write ZERO */\r
+/* -------- GMAC_RPQ : (GMAC Offset: 0x038) Received Pause Quantum Register -------- */\r
+#define GMAC_RPQ_RPQ_Pos 0\r
+#define GMAC_RPQ_RPQ_Msk (0xffffu << GMAC_RPQ_RPQ_Pos) /**< \brief (GMAC_RPQ) Received Pause Quantum */\r
+/* -------- GMAC_TPQ : (GMAC Offset: 0x03C) Transmit Pause Quantum Register -------- */\r
+#define GMAC_TPQ_TPQ_Pos 0\r
+#define GMAC_TPQ_TPQ_Msk (0xffffu << GMAC_TPQ_TPQ_Pos) /**< \brief (GMAC_TPQ) Transmit Pause Quantum */\r
+#define GMAC_TPQ_TPQ(value) ((GMAC_TPQ_TPQ_Msk & ((value) << GMAC_TPQ_TPQ_Pos)))\r
+/* -------- GMAC_TPSF : (GMAC Offset: 0x040) TX Partial Store and Forward Register -------- */\r
+#define GMAC_TPSF_TPB1ADR_Pos 0\r
+#define GMAC_TPSF_TPB1ADR_Msk (0xfffu << GMAC_TPSF_TPB1ADR_Pos) /**< \brief (GMAC_TPSF) tx_pbuf_addr-1:0 */\r
+#define GMAC_TPSF_TPB1ADR(value) ((GMAC_TPSF_TPB1ADR_Msk & ((value) << GMAC_TPSF_TPB1ADR_Pos)))\r
+#define GMAC_TPSF_ENTXP (0x1u << 31) /**< \brief (GMAC_TPSF) Enable TX Partial Store and Forward Operation */\r
+/* -------- GMAC_RPSF : (GMAC Offset: 0x044) RX Partial Store and Forward Register -------- */\r
+#define GMAC_RPSF_RPB1ADR_Pos 0\r
+#define GMAC_RPSF_RPB1ADR_Msk (0xfffu << GMAC_RPSF_RPB1ADR_Pos) /**< \brief (GMAC_RPSF) rx_pbuf_addr-1:0 */\r
+#define GMAC_RPSF_RPB1ADR(value) ((GMAC_RPSF_RPB1ADR_Msk & ((value) << GMAC_RPSF_RPB1ADR_Pos)))\r
+#define GMAC_RPSF_ENRXP (0x1u << 31) /**< \brief (GMAC_RPSF) Enable RX Partial Store and Forward Operation */\r
+/* -------- GMAC_HRB : (GMAC Offset: 0x080) Hash Register Bottom [31:0] -------- */\r
+#define GMAC_HRB_ADDR_Pos 0\r
+#define GMAC_HRB_ADDR_Msk (0xffffffffu << GMAC_HRB_ADDR_Pos) /**< \brief (GMAC_HRB) Hash Address */\r
+#define GMAC_HRB_ADDR(value) ((GMAC_HRB_ADDR_Msk & ((value) << GMAC_HRB_ADDR_Pos)))\r
+/* -------- GMAC_HRT : (GMAC Offset: 0x084) Hash Register Top [63:32] -------- */\r
+#define GMAC_HRT_ADDR_Pos 0\r
+#define GMAC_HRT_ADDR_Msk (0xffffffffu << GMAC_HRT_ADDR_Pos) /**< \brief (GMAC_HRT) Hash Address */\r
+#define GMAC_HRT_ADDR(value) ((GMAC_HRT_ADDR_Msk & ((value) << GMAC_HRT_ADDR_Pos)))\r
+/* -------- GMAC_SAB1 : (GMAC Offset: 0x088) Specific Address 1 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB1_ADDR_Pos 0\r
+#define GMAC_SAB1_ADDR_Msk (0xffffffffu << GMAC_SAB1_ADDR_Pos) /**< \brief (GMAC_SAB1) Specific Address 1 */\r
+#define GMAC_SAB1_ADDR(value) ((GMAC_SAB1_ADDR_Msk & ((value) << GMAC_SAB1_ADDR_Pos)))\r
+/* -------- GMAC_SAT1 : (GMAC Offset: 0x08C) Specific Address 1 Top [47:32] Register -------- */\r
+#define GMAC_SAT1_ADDR_Pos 0\r
+#define GMAC_SAT1_ADDR_Msk (0xffffu << GMAC_SAT1_ADDR_Pos) /**< \brief (GMAC_SAT1) Specific Address 1 */\r
+#define GMAC_SAT1_ADDR(value) ((GMAC_SAT1_ADDR_Msk & ((value) << GMAC_SAT1_ADDR_Pos)))\r
+/* -------- GMAC_SAB2 : (GMAC Offset: 0x090) Specific Address 2 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB2_ADDR_Pos 0\r
+#define GMAC_SAB2_ADDR_Msk (0xffffffffu << GMAC_SAB2_ADDR_Pos) /**< \brief (GMAC_SAB2) Specific Address 2 */\r
+#define GMAC_SAB2_ADDR(value) ((GMAC_SAB2_ADDR_Msk & ((value) << GMAC_SAB2_ADDR_Pos)))\r
+/* -------- GMAC_SAT2 : (GMAC Offset: 0x094) Specific Address 2 Top [47:32] Register -------- */\r
+#define GMAC_SAT2_ADDR_Pos 0\r
+#define GMAC_SAT2_ADDR_Msk (0xffffu << GMAC_SAT2_ADDR_Pos) /**< \brief (GMAC_SAT2) Specific Address 2 */\r
+#define GMAC_SAT2_ADDR(value) ((GMAC_SAT2_ADDR_Msk & ((value) << GMAC_SAT2_ADDR_Pos)))\r
+/* -------- GMAC_SAB3 : (GMAC Offset: 0x098) Specific Address 3 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB3_ADDR_Pos 0\r
+#define GMAC_SAB3_ADDR_Msk (0xffffffffu << GMAC_SAB3_ADDR_Pos) /**< \brief (GMAC_SAB3) Specific Address 3 */\r
+#define GMAC_SAB3_ADDR(value) ((GMAC_SAB3_ADDR_Msk & ((value) << GMAC_SAB3_ADDR_Pos)))\r
+/* -------- GMAC_SAT3 : (GMAC Offset: 0x09C) Specific Address 3 Top [47:32] Register -------- */\r
+#define GMAC_SAT3_ADDR_Pos 0\r
+#define GMAC_SAT3_ADDR_Msk (0xffffu << GMAC_SAT3_ADDR_Pos) /**< \brief (GMAC_SAT3) Specific Address 3 */\r
+#define GMAC_SAT3_ADDR(value) ((GMAC_SAT3_ADDR_Msk & ((value) << GMAC_SAT3_ADDR_Pos)))\r
+/* -------- GMAC_SAB4 : (GMAC Offset: 0x0A0) Specific Address 4 Bottom [31:0] Register -------- */\r
+#define GMAC_SAB4_ADDR_Pos 0\r
+#define GMAC_SAB4_ADDR_Msk (0xffffffffu << GMAC_SAB4_ADDR_Pos) /**< \brief (GMAC_SAB4) Specific Address 4 */\r
+#define GMAC_SAB4_ADDR(value) ((GMAC_SAB4_ADDR_Msk & ((value) << GMAC_SAB4_ADDR_Pos)))\r
+/* -------- GMAC_SAT4 : (GMAC Offset: 0x0A4) Specific Address 4 Top [47:32] Register -------- */\r
+#define GMAC_SAT4_ADDR_Pos 0\r
+#define GMAC_SAT4_ADDR_Msk (0xffffu << GMAC_SAT4_ADDR_Pos) /**< \brief (GMAC_SAT4) Specific Address 4 */\r
+#define GMAC_SAT4_ADDR(value) ((GMAC_SAT4_ADDR_Msk & ((value) << GMAC_SAT4_ADDR_Pos)))\r
+/* -------- GMAC_TIDM[4] : (GMAC Offset: 0x0A8) Type ID Match 1 Register -------- */\r
+#define GMAC_TIDM_TID_Pos 0\r
+#define GMAC_TIDM_TID_Msk (0xffffu << GMAC_TIDM_TID_Pos) /**< \brief (GMAC_TIDM[4]) Type ID Match 1 */\r
+#define GMAC_TIDM_TID(value) ((GMAC_TIDM_TID_Msk & ((value) << GMAC_TIDM_TID_Pos)))\r
+/* -------- GMAC_WOL : (GMAC Offset: 0x0B8) Wake on LAN Register -------- */\r
+#define GMAC_WOL_IP_Pos 0\r
+#define GMAC_WOL_IP_Msk (0xffffu << GMAC_WOL_IP_Pos) /**< \brief (GMAC_WOL) ARP Request IP Address */\r
+#define GMAC_WOL_IP(value) ((GMAC_WOL_IP_Msk & ((value) << GMAC_WOL_IP_Pos)))\r
+#define GMAC_WOL_MAG (0x1u << 16) /**< \brief (GMAC_WOL) Magic Packet Event Enable */\r
+#define GMAC_WOL_ARP (0x1u << 17) /**< \brief (GMAC_WOL) ARP Request IP Address */\r
+#define GMAC_WOL_SA1 (0x1u << 18) /**< \brief (GMAC_WOL) Specific Address Register 1 Event Enable */\r
+#define GMAC_WOL_MTI (0x1u << 19) /**< \brief (GMAC_WOL) Multicast Hash Event Enable */\r
+/* -------- GMAC_IPGS : (GMAC Offset: 0x0BC) IPG Stretch Register -------- */\r
+#define GMAC_IPGS_FL_Pos 0\r
+#define GMAC_IPGS_FL_Msk (0xffffu << GMAC_IPGS_FL_Pos) /**< \brief (GMAC_IPGS) Frame Length */\r
+#define GMAC_IPGS_FL(value) ((GMAC_IPGS_FL_Msk & ((value) << GMAC_IPGS_FL_Pos)))\r
+/* -------- GMAC_SVLAN : (GMAC Offset: 0x0C0) Stacked VLAN Register -------- */\r
+#define GMAC_SVLAN_VLAN_TYPE_Pos 0\r
+#define GMAC_SVLAN_VLAN_TYPE_Msk (0xffffu << GMAC_SVLAN_VLAN_TYPE_Pos) /**< \brief (GMAC_SVLAN) User Defined VLAN_TYPE Field */\r
+#define GMAC_SVLAN_VLAN_TYPE(value) ((GMAC_SVLAN_VLAN_TYPE_Msk & ((value) << GMAC_SVLAN_VLAN_TYPE_Pos)))\r
+#define GMAC_SVLAN_ESVLAN (0x1u << 31) /**< \brief (GMAC_SVLAN) Enable Stacked VLAN Processing Mode */\r
+/* -------- GMAC_TPFCP : (GMAC Offset: 0x0C4) Transmit PFC Pause Register -------- */\r
+#define GMAC_TPFCP_PEV_Pos 0\r
+#define GMAC_TPFCP_PEV_Msk (0xffu << GMAC_TPFCP_PEV_Pos) /**< \brief (GMAC_TPFCP) Priority Enable Vector */\r
+#define GMAC_TPFCP_PEV(value) ((GMAC_TPFCP_PEV_Msk & ((value) << GMAC_TPFCP_PEV_Pos)))\r
+#define GMAC_TPFCP_PQ_Pos 8\r
+#define GMAC_TPFCP_PQ_Msk (0xffu << GMAC_TPFCP_PQ_Pos) /**< \brief (GMAC_TPFCP) Pause Quantum */\r
+#define GMAC_TPFCP_PQ(value) ((GMAC_TPFCP_PQ_Msk & ((value) << GMAC_TPFCP_PQ_Pos)))\r
+/* -------- GMAC_SAMB1 : (GMAC Offset: 0x0C8) Specific Address 1 Mask Bottom [31:0] Register -------- */\r
+#define GMAC_SAMB1_ADDR_Pos 0\r
+#define GMAC_SAMB1_ADDR_Msk (0xffffffffu << GMAC_SAMB1_ADDR_Pos) /**< \brief (GMAC_SAMB1) Specific Address 1 Mask */\r
+#define GMAC_SAMB1_ADDR(value) ((GMAC_SAMB1_ADDR_Msk & ((value) << GMAC_SAMB1_ADDR_Pos)))\r
+/* -------- GMAC_SAMT1 : (GMAC Offset: 0x0CC) Specific Address 1 Mask Top [47:32] Register -------- */\r
+#define GMAC_SAMT1_ADDR_Pos 0\r
+#define GMAC_SAMT1_ADDR_Msk (0xffffu << GMAC_SAMT1_ADDR_Pos) /**< \brief (GMAC_SAMT1) Specific Address 1 Mask */\r
+#define GMAC_SAMT1_ADDR(value) ((GMAC_SAMT1_ADDR_Msk & ((value) << GMAC_SAMT1_ADDR_Pos)))\r
+/* -------- GMAC_OTLO : (GMAC Offset: 0x100) Octets Transmitted [31:0] Register -------- */\r
+#define GMAC_OTLO_TXO_Pos 0\r
+#define GMAC_OTLO_TXO_Msk (0xffffffffu << GMAC_OTLO_TXO_Pos) /**< \brief (GMAC_OTLO) Transmitted Octets */\r
+/* -------- GMAC_OTHI : (GMAC Offset: 0x104) Octets Transmitted [47:32] Register -------- */\r
+#define GMAC_OTHI_TXO_Pos 0\r
+#define GMAC_OTHI_TXO_Msk (0xffffu << GMAC_OTHI_TXO_Pos) /**< \brief (GMAC_OTHI) Transmitted Octets */\r
+/* -------- GMAC_FT : (GMAC Offset: 0x108) Frames Transmitted Register -------- */\r
+#define GMAC_FT_FTX_Pos 0\r
+#define GMAC_FT_FTX_Msk (0xffffffffu << GMAC_FT_FTX_Pos) /**< \brief (GMAC_FT) Frames Transmitted without Error */\r
+/* -------- GMAC_BCFT : (GMAC Offset: 0x10C) Broadcast Frames Transmitted Register -------- */\r
+#define GMAC_BCFT_BFTX_Pos 0\r
+#define GMAC_BCFT_BFTX_Msk (0xffffffffu << GMAC_BCFT_BFTX_Pos) /**< \brief (GMAC_BCFT) Broadcast Frames Transmitted without Error */\r
+/* -------- GMAC_MFT : (GMAC Offset: 0x110) Multicast Frames Transmitted Register -------- */\r
+#define GMAC_MFT_MFTX_Pos 0\r
+#define GMAC_MFT_MFTX_Msk (0xffffffffu << GMAC_MFT_MFTX_Pos) /**< \brief (GMAC_MFT) Multicast Frames Transmitted without Error */\r
+/* -------- GMAC_PFT : (GMAC Offset: 0x114) Pause Frames Transmitted Register -------- */\r
+#define GMAC_PFT_PFTX_Pos 0\r
+#define GMAC_PFT_PFTX_Msk (0xffffu << GMAC_PFT_PFTX_Pos) /**< \brief (GMAC_PFT) Pause Frames Transmitted Register */\r
+/* -------- GMAC_BFT64 : (GMAC Offset: 0x118) 64 Byte Frames Transmitted Register -------- */\r
+#define GMAC_BFT64_NFTX_Pos 0\r
+#define GMAC_BFT64_NFTX_Msk (0xffffffffu << GMAC_BFT64_NFTX_Pos) /**< \brief (GMAC_BFT64) 64 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT127 : (GMAC Offset: 0x11C) 65 to 127 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT127_NFTX_Pos 0\r
+#define GMAC_TBFT127_NFTX_Msk (0xffffffffu << GMAC_TBFT127_NFTX_Pos) /**< \brief (GMAC_TBFT127) 65 to 127 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT255 : (GMAC Offset: 0x120) 128 to 255 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT255_NFTX_Pos 0\r
+#define GMAC_TBFT255_NFTX_Msk (0xffffffffu << GMAC_TBFT255_NFTX_Pos) /**< \brief (GMAC_TBFT255) 128 to 255 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT511 : (GMAC Offset: 0x124) 256 to 511 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT511_NFTX_Pos 0\r
+#define GMAC_TBFT511_NFTX_Msk (0xffffffffu << GMAC_TBFT511_NFTX_Pos) /**< \brief (GMAC_TBFT511) 256 to 511 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT1023 : (GMAC Offset: 0x128) 512 to 1023 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT1023_NFTX_Pos 0\r
+#define GMAC_TBFT1023_NFTX_Msk (0xffffffffu << GMAC_TBFT1023_NFTX_Pos) /**< \brief (GMAC_TBFT1023) 512 to 1023 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TBFT1518 : (GMAC Offset: 0x12C) 1024 to 1518 Byte Frames Transmitted Register -------- */\r
+#define GMAC_TBFT1518_NFTX_Pos 0\r
+#define GMAC_TBFT1518_NFTX_Msk (0xffffffffu << GMAC_TBFT1518_NFTX_Pos) /**< \brief (GMAC_TBFT1518) 1024 to 1518 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_GTBFT1518 : (GMAC Offset: 0x130) Greater Than 1518 Byte Frames Transmitted Register -------- */\r
+#define GMAC_GTBFT1518_NFTX_Pos 0\r
+#define GMAC_GTBFT1518_NFTX_Msk (0xffffffffu << GMAC_GTBFT1518_NFTX_Pos) /**< \brief (GMAC_GTBFT1518) Greater than 1518 Byte Frames Transmitted without Error */\r
+/* -------- GMAC_TUR : (GMAC Offset: 0x134) Transmit Under Runs Register -------- */\r
+#define GMAC_TUR_TXUNR_Pos 0\r
+#define GMAC_TUR_TXUNR_Msk (0x3ffu << GMAC_TUR_TXUNR_Pos) /**< \brief (GMAC_TUR) Transmit Under Runs */\r
+/* -------- GMAC_SCF : (GMAC Offset: 0x138) Single Collision Frames Register -------- */\r
+#define GMAC_SCF_SCOL_Pos 0\r
+#define GMAC_SCF_SCOL_Msk (0x3ffffu << GMAC_SCF_SCOL_Pos) /**< \brief (GMAC_SCF) Single Collision */\r
+/* -------- GMAC_MCF : (GMAC Offset: 0x13C) Multiple Collision Frames Register -------- */\r
+#define GMAC_MCF_MCOL_Pos 0\r
+#define GMAC_MCF_MCOL_Msk (0x3ffffu << GMAC_MCF_MCOL_Pos) /**< \brief (GMAC_MCF) Multiple Collision */\r
+/* -------- GMAC_EC : (GMAC Offset: 0x140) Excessive Collisions Register -------- */\r
+#define GMAC_EC_XCOL_Pos 0\r
+#define GMAC_EC_XCOL_Msk (0x3ffu << GMAC_EC_XCOL_Pos) /**< \brief (GMAC_EC) Excessive Collisions */\r
+/* -------- GMAC_LC : (GMAC Offset: 0x144) Late Collisions Register -------- */\r
+#define GMAC_LC_LCOL_Pos 0\r
+#define GMAC_LC_LCOL_Msk (0x3ffu << GMAC_LC_LCOL_Pos) /**< \brief (GMAC_LC) Late Collisions */\r
+/* -------- GMAC_DTF : (GMAC Offset: 0x148) Deferred Transmission Frames Register -------- */\r
+#define GMAC_DTF_DEFT_Pos 0\r
+#define GMAC_DTF_DEFT_Msk (0x3ffffu << GMAC_DTF_DEFT_Pos) /**< \brief (GMAC_DTF) Deferred Transmission */\r
+/* -------- GMAC_CSE : (GMAC Offset: 0x14C) Carrier Sense Errors Register -------- */\r
+#define GMAC_CSE_CSR_Pos 0\r
+#define GMAC_CSE_CSR_Msk (0x3ffu << GMAC_CSE_CSR_Pos) /**< \brief (GMAC_CSE) Carrier Sense Error */\r
+/* -------- GMAC_ORLO : (GMAC Offset: 0x150) Octets Received [31:0] Received -------- */\r
+#define GMAC_ORLO_RXO_Pos 0\r
+#define GMAC_ORLO_RXO_Msk (0xffffffffu << GMAC_ORLO_RXO_Pos) /**< \brief (GMAC_ORLO) Received Octets */\r
+/* -------- GMAC_ORHI : (GMAC Offset: 0x154) Octets Received [47:32] Received -------- */\r
+#define GMAC_ORHI_RXO_Pos 0\r
+#define GMAC_ORHI_RXO_Msk (0xffffu << GMAC_ORHI_RXO_Pos) /**< \brief (GMAC_ORHI) Received Octets */\r
+/* -------- GMAC_FR : (GMAC Offset: 0x158) Frames Received Register -------- */\r
+#define GMAC_FR_FRX_Pos 0\r
+#define GMAC_FR_FRX_Msk (0xffffffffu << GMAC_FR_FRX_Pos) /**< \brief (GMAC_FR) Frames Received without Error */\r
+/* -------- GMAC_BCFR : (GMAC Offset: 0x15C) Broadcast Frames Received Register -------- */\r
+#define GMAC_BCFR_BFRX_Pos 0\r
+#define GMAC_BCFR_BFRX_Msk (0xffffffffu << GMAC_BCFR_BFRX_Pos) /**< \brief (GMAC_BCFR) Broadcast Frames Received without Error */\r
+/* -------- GMAC_MFR : (GMAC Offset: 0x160) Multicast Frames Received Register -------- */\r
+#define GMAC_MFR_MFRX_Pos 0\r
+#define GMAC_MFR_MFRX_Msk (0xffffffffu << GMAC_MFR_MFRX_Pos) /**< \brief (GMAC_MFR) Multicast Frames Received without Error */\r
+/* -------- GMAC_PFR : (GMAC Offset: 0x164) Pause Frames Received Register -------- */\r
+#define GMAC_PFR_PFRX_Pos 0\r
+#define GMAC_PFR_PFRX_Msk (0xffffu << GMAC_PFR_PFRX_Pos) /**< \brief (GMAC_PFR) Pause Frames Received Register */\r
+/* -------- GMAC_BFR64 : (GMAC Offset: 0x168) 64 Byte Frames Received Register -------- */\r
+#define GMAC_BFR64_NFRX_Pos 0\r
+#define GMAC_BFR64_NFRX_Msk (0xffffffffu << GMAC_BFR64_NFRX_Pos) /**< \brief (GMAC_BFR64) 64 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR127 : (GMAC Offset: 0x16C) 65 to 127 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR127_NFRX_Pos 0\r
+#define GMAC_TBFR127_NFRX_Msk (0xffffffffu << GMAC_TBFR127_NFRX_Pos) /**< \brief (GMAC_TBFR127) 65 to 127 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR255 : (GMAC Offset: 0x170) 128 to 255 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR255_NFRX_Pos 0\r
+#define GMAC_TBFR255_NFRX_Msk (0xffffffffu << GMAC_TBFR255_NFRX_Pos) /**< \brief (GMAC_TBFR255) 128 to 255 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR511 : (GMAC Offset: 0x174) 256 to 511Byte Frames Received Register -------- */\r
+#define GMAC_TBFR511_NFRX_Pos 0\r
+#define GMAC_TBFR511_NFRX_Msk (0xffffffffu << GMAC_TBFR511_NFRX_Pos) /**< \brief (GMAC_TBFR511) 256 to 511 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR1023 : (GMAC Offset: 0x178) 512 to 1023 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR1023_NFRX_Pos 0\r
+#define GMAC_TBFR1023_NFRX_Msk (0xffffffffu << GMAC_TBFR1023_NFRX_Pos) /**< \brief (GMAC_TBFR1023) 512 to 1023 Byte Frames Received without Error */\r
+/* -------- GMAC_TBFR1518 : (GMAC Offset: 0x17C) 1024 to 1518 Byte Frames Received Register -------- */\r
+#define GMAC_TBFR1518_NFRX_Pos 0\r
+#define GMAC_TBFR1518_NFRX_Msk (0xffffffffu << GMAC_TBFR1518_NFRX_Pos) /**< \brief (GMAC_TBFR1518) 1024 to 1518 Byte Frames Received without Error */\r
+/* -------- GMAC_TMXBFR : (GMAC Offset: 0x180) 1519 to Maximum Byte Frames Received Register -------- */\r
+#define GMAC_TMXBFR_NFRX_Pos 0\r
+#define GMAC_TMXBFR_NFRX_Msk (0xffffffffu << GMAC_TMXBFR_NFRX_Pos) /**< \brief (GMAC_TMXBFR) 1519 to Maximum Byte Frames Received without Error */\r
+/* -------- GMAC_UFR : (GMAC Offset: 0x184) Undersize Frames Received Register -------- */\r
+#define GMAC_UFR_UFRX_Pos 0\r
+#define GMAC_UFR_UFRX_Msk (0x3ffu << GMAC_UFR_UFRX_Pos) /**< \brief (GMAC_UFR) Undersize Frames Received */\r
+/* -------- GMAC_OFR : (GMAC Offset: 0x188) Oversize Frames Received Register -------- */\r
+#define GMAC_OFR_OFRX_Pos 0\r
+#define GMAC_OFR_OFRX_Msk (0x3ffu << GMAC_OFR_OFRX_Pos) /**< \brief (GMAC_OFR) Oversized Frames Received */\r
+/* -------- GMAC_JR : (GMAC Offset: 0x18C) Jabbers Received Register -------- */\r
+#define GMAC_JR_JRX_Pos 0\r
+#define GMAC_JR_JRX_Msk (0x3ffu << GMAC_JR_JRX_Pos) /**< \brief (GMAC_JR) Jabbers Received */\r
+/* -------- GMAC_FCSE : (GMAC Offset: 0x190) Frame Check Sequence Errors Register -------- */\r
+#define GMAC_FCSE_FCKR_Pos 0\r
+#define GMAC_FCSE_FCKR_Msk (0x3ffu << GMAC_FCSE_FCKR_Pos) /**< \brief (GMAC_FCSE) Frame Check Sequence Errors */\r
+/* -------- GMAC_LFFE : (GMAC Offset: 0x194) Length Field Frame Errors Register -------- */\r
+#define GMAC_LFFE_LFER_Pos 0\r
+#define GMAC_LFFE_LFER_Msk (0x3ffu << GMAC_LFFE_LFER_Pos) /**< \brief (GMAC_LFFE) Length Field Frame Errors */\r
+/* -------- GMAC_RSE : (GMAC Offset: 0x198) Receive Symbol Errors Register -------- */\r
+#define GMAC_RSE_RXSE_Pos 0\r
+#define GMAC_RSE_RXSE_Msk (0x3ffu << GMAC_RSE_RXSE_Pos) /**< \brief (GMAC_RSE) Receive Symbol Errors */\r
+/* -------- GMAC_AE : (GMAC Offset: 0x19C) Alignment Errors Register -------- */\r
+#define GMAC_AE_AER_Pos 0\r
+#define GMAC_AE_AER_Msk (0x3ffu << GMAC_AE_AER_Pos) /**< \brief (GMAC_AE) Alignment Errors */\r
+/* -------- GMAC_RRE : (GMAC Offset: 0x1A0) Receive Resource Errors Register -------- */\r
+#define GMAC_RRE_RXRER_Pos 0\r
+#define GMAC_RRE_RXRER_Msk (0x3ffffu << GMAC_RRE_RXRER_Pos) /**< \brief (GMAC_RRE) Receive Resource Errors */\r
+/* -------- GMAC_ROE : (GMAC Offset: 0x1A4) Receive Overrun Register -------- */\r
+#define GMAC_ROE_RXOVR_Pos 0\r
+#define GMAC_ROE_RXOVR_Msk (0x3ffu << GMAC_ROE_RXOVR_Pos) /**< \brief (GMAC_ROE) Receive Overruns */\r
+/* -------- GMAC_IHCE : (GMAC Offset: 0x1A8) IP Header Checksum Errors Register -------- */\r
+#define GMAC_IHCE_HCKER_Pos 0\r
+#define GMAC_IHCE_HCKER_Msk (0xffu << GMAC_IHCE_HCKER_Pos) /**< \brief (GMAC_IHCE) IP Header Checksum Errors */\r
+/* -------- GMAC_TCE : (GMAC Offset: 0x1AC) TCP Checksum Errors Register -------- */\r
+#define GMAC_TCE_TCKER_Pos 0\r
+#define GMAC_TCE_TCKER_Msk (0xffu << GMAC_TCE_TCKER_Pos) /**< \brief (GMAC_TCE) TCP Checksum Errors */\r
+/* -------- GMAC_UCE : (GMAC Offset: 0x1B0) UDP Checksum Errors Register -------- */\r
+#define GMAC_UCE_UCKER_Pos 0\r
+#define GMAC_UCE_UCKER_Msk (0xffu << GMAC_UCE_UCKER_Pos) /**< \brief (GMAC_UCE) UDP Checksum Errors */\r
+/* -------- GMAC_TSSS : (GMAC Offset: 0x1C8) 1588 Timer Sync Strobe Seconds Register -------- */\r
+#define GMAC_TSSS_VTS_Pos 0\r
+#define GMAC_TSSS_VTS_Msk (0xffffffffu << GMAC_TSSS_VTS_Pos) /**< \brief (GMAC_TSSS) Value of Timer Seconds Register Capture */\r
+#define GMAC_TSSS_VTS(value) ((GMAC_TSSS_VTS_Msk & ((value) << GMAC_TSSS_VTS_Pos)))\r
+/* -------- GMAC_TSSN : (GMAC Offset: 0x1CC) 1588 Timer Sync Strobe Nanoseconds Register -------- */\r
+#define GMAC_TSSN_VTN_Pos 0\r
+#define GMAC_TSSN_VTN_Msk (0x3fffffffu << GMAC_TSSN_VTN_Pos) /**< \brief (GMAC_TSSN) Value Timer Nanoseconds Register Capture */\r
+#define GMAC_TSSN_VTN(value) ((GMAC_TSSN_VTN_Msk & ((value) << GMAC_TSSN_VTN_Pos)))\r
+/* -------- GMAC_TS : (GMAC Offset: 0x1D0) 1588 Timer Seconds Register -------- */\r
+#define GMAC_TS_TCS_Pos 0\r
+#define GMAC_TS_TCS_Msk (0xffffffffu << GMAC_TS_TCS_Pos) /**< \brief (GMAC_TS) Timer Count in Seconds */\r
+#define GMAC_TS_TCS(value) ((GMAC_TS_TCS_Msk & ((value) << GMAC_TS_TCS_Pos)))\r
+/* -------- GMAC_TN : (GMAC Offset: 0x1D4) 1588 Timer Nanoseconds Register -------- */\r
+#define GMAC_TN_TNS_Pos 0\r
+#define GMAC_TN_TNS_Msk (0x3fffffffu << GMAC_TN_TNS_Pos) /**< \brief (GMAC_TN) Timer Count in Nanoseconds */\r
+#define GMAC_TN_TNS(value) ((GMAC_TN_TNS_Msk & ((value) << GMAC_TN_TNS_Pos)))\r
+/* -------- GMAC_TA : (GMAC Offset: 0x1D8) 1588 Timer Adjust Register -------- */\r
+#define GMAC_TA_ITDT_Pos 0\r
+#define GMAC_TA_ITDT_Msk (0x3fffffffu << GMAC_TA_ITDT_Pos) /**< \brief (GMAC_TA) Increment/Decrement */\r
+#define GMAC_TA_ITDT(value) ((GMAC_TA_ITDT_Msk & ((value) << GMAC_TA_ITDT_Pos)))\r
+#define GMAC_TA_ADJ (0x1u << 31) /**< \brief (GMAC_TA) Adjust 1588 Timer */\r
+/* -------- GMAC_TI : (GMAC Offset: 0x1DC) 1588 Timer Increment Register -------- */\r
+#define GMAC_TI_CNS_Pos 0\r
+#define GMAC_TI_CNS_Msk (0xffu << GMAC_TI_CNS_Pos) /**< \brief (GMAC_TI) Count Nanoseconds */\r
+#define GMAC_TI_CNS(value) ((GMAC_TI_CNS_Msk & ((value) << GMAC_TI_CNS_Pos)))\r
+#define GMAC_TI_ACNS_Pos 8\r
+#define GMAC_TI_ACNS_Msk (0xffu << GMAC_TI_ACNS_Pos) /**< \brief (GMAC_TI) Alternative Count Nanoseconds */\r
+#define GMAC_TI_ACNS(value) ((GMAC_TI_ACNS_Msk & ((value) << GMAC_TI_ACNS_Pos)))\r
+#define GMAC_TI_NIT_Pos 16\r
+#define GMAC_TI_NIT_Msk (0xffu << GMAC_TI_NIT_Pos) /**< \brief (GMAC_TI) Number of Increments */\r
+#define GMAC_TI_NIT(value) ((GMAC_TI_NIT_Msk & ((value) << GMAC_TI_NIT_Pos)))\r
+/* -------- GMAC_EFTS : (GMAC Offset: 0x1E0) PTP Event Frame Transmitted Seconds -------- */\r
+#define GMAC_EFTS_RUD_Pos 0\r
+#define GMAC_EFTS_RUD_Msk (0xffffffffu << GMAC_EFTS_RUD_Pos) /**< \brief (GMAC_EFTS) Register Update */\r
+/* -------- GMAC_EFTN : (GMAC Offset: 0x1E4) PTP Event Frame Transmitted Nanoseconds -------- */\r
+#define GMAC_EFTN_RUD_Pos 0\r
+#define GMAC_EFTN_RUD_Msk (0x3fffffffu << GMAC_EFTN_RUD_Pos) /**< \brief (GMAC_EFTN) Register Update */\r
+/* -------- GMAC_EFRS : (GMAC Offset: 0x1E8) PTP Event Frame Received Seconds -------- */\r
+#define GMAC_EFRS_RUD_Pos 0\r
+#define GMAC_EFRS_RUD_Msk (0xffffffffu << GMAC_EFRS_RUD_Pos) /**< \brief (GMAC_EFRS) Register Update */\r
+/* -------- GMAC_EFRN : (GMAC Offset: 0x1EC) PTP Event Frame Received Nanoseconds -------- */\r
+#define GMAC_EFRN_RUD_Pos 0\r
+#define GMAC_EFRN_RUD_Msk (0x3fffffffu << GMAC_EFRN_RUD_Pos) /**< \brief (GMAC_EFRN) Register Update */\r
+/* -------- GMAC_PEFTS : (GMAC Offset: 0x1F0) PTP Peer Event Frame Transmitted Seconds -------- */\r
+#define GMAC_PEFTS_RUD_Pos 0\r
+#define GMAC_PEFTS_RUD_Msk (0xffffffffu << GMAC_PEFTS_RUD_Pos) /**< \brief (GMAC_PEFTS) Register Update */\r
+/* -------- GMAC_PEFTN : (GMAC Offset: 0x1F4) PTP Peer Event Frame Transmitted Nanoseconds -------- */\r
+#define GMAC_PEFTN_RUD_Pos 0\r
+#define GMAC_PEFTN_RUD_Msk (0x3fffffffu << GMAC_PEFTN_RUD_Pos) /**< \brief (GMAC_PEFTN) Register Update */\r
+/* -------- GMAC_PEFRS : (GMAC Offset: 0x1F8) PTP Peer Event Frame Received Seconds -------- */\r
+#define GMAC_PEFRS_RUD_Pos 0\r
+#define GMAC_PEFRS_RUD_Msk (0xffffffffu << GMAC_PEFRS_RUD_Pos) /**< \brief (GMAC_PEFRS) Register Update */\r
+/* -------- GMAC_PEFRN : (GMAC Offset: 0x1FC) PTP Peer Event Frame Received Nanoseconds -------- */\r
+#define GMAC_PEFRN_RUD_Pos 0\r
+#define GMAC_PEFRN_RUD_Msk (0x3fffffffu << GMAC_PEFRN_RUD_Pos) /**< \brief (GMAC_PEFRN) Register Update */\r
+/* -------- GMAC_ISRPQ[7] : (GMAC Offset: 0x400) Interrupt Status Register Priority Queue -------- */\r
+#define GMAC_ISRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_ISRPQ[7]) Receive Complete */\r
+#define GMAC_ISRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_ISRPQ[7]) RX Used Bit Read */\r
+#define GMAC_ISRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_ISRPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_ISRPQ_TFC (0x1u << 6) /**< \brief (GMAC_ISRPQ[7]) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_ISRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_ISRPQ[7]) Transmit Complete */\r
+#define GMAC_ISRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_ISRPQ[7]) Receive Overrun */\r
+#define GMAC_ISRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_ISRPQ[7]) HRESP Not OK */\r
+/* -------- GMAC_TBQBAPQ[7] : (GMAC Offset: 0x440) Transmit Buffer Queue Base Address Priority Queue -------- */\r
+#define GMAC_TBQBAPQ_TXBQBA_Pos 2\r
+#define GMAC_TBQBAPQ_TXBQBA_Msk (0x3fu << GMAC_TBQBAPQ_TXBQBA_Pos) /**< \brief (GMAC_TBQBAPQ[7]) Transmit Buffer Queue Base Address */\r
+#define GMAC_TBQBAPQ_TXBQBA(value) ((GMAC_TBQBAPQ_TXBQBA_Msk & ((value) << GMAC_TBQBAPQ_TXBQBA_Pos)))\r
+/* -------- GMAC_RBQBAPQ[7] : (GMAC Offset: 0x480) Receive Buffer Queue Base Address Priority Queue -------- */\r
+#define GMAC_RBQBAPQ_RXBQBA_Pos 2\r
+#define GMAC_RBQBAPQ_RXBQBA_Msk (0x3fu << GMAC_RBQBAPQ_RXBQBA_Pos) /**< \brief (GMAC_RBQBAPQ[7]) Receive Buffer Queue Base Address */\r
+#define GMAC_RBQBAPQ_RXBQBA(value) ((GMAC_RBQBAPQ_RXBQBA_Msk & ((value) << GMAC_RBQBAPQ_RXBQBA_Pos)))\r
+/* -------- GMAC_RBSRPQ[7] : (GMAC Offset: 0x4A0) Receive Buffer Size Register Priority Queue -------- */\r
+#define GMAC_RBSRPQ_RBS_Pos 0\r
+#define GMAC_RBSRPQ_RBS_Msk (0xffffu << GMAC_RBSRPQ_RBS_Pos) /**< \brief (GMAC_RBSRPQ[7]) Receive Buffer Size */\r
+#define GMAC_RBSRPQ_RBS(value) ((GMAC_RBSRPQ_RBS_Msk & ((value) << GMAC_RBSRPQ_RBS_Pos)))\r
+/* -------- GMAC_ST1RPQ[16] : (GMAC Offset: 0x500) Screening Type1 Register Priority Queue -------- */\r
+#define GMAC_ST1RPQ_QNB_Pos 0\r
+#define GMAC_ST1RPQ_QNB_Msk (0xfu << GMAC_ST1RPQ_QNB_Pos) /**< \brief (GMAC_ST1RPQ[16]) Que Number (0->7) */\r
+#define GMAC_ST1RPQ_QNB(value) ((GMAC_ST1RPQ_QNB_Msk & ((value) << GMAC_ST1RPQ_QNB_Pos)))\r
+#define GMAC_ST1RPQ_DSTCM_Pos 4\r
+#define GMAC_ST1RPQ_DSTCM_Msk (0xffu << GMAC_ST1RPQ_DSTCM_Pos) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match */\r
+#define GMAC_ST1RPQ_DSTCM(value) ((GMAC_ST1RPQ_DSTCM_Msk & ((value) << GMAC_ST1RPQ_DSTCM_Pos)))\r
+#define GMAC_ST1RPQ_UDPM_Pos 12\r
+#define GMAC_ST1RPQ_UDPM_Msk (0xffffu << GMAC_ST1RPQ_UDPM_Pos) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match */\r
+#define GMAC_ST1RPQ_UDPM(value) ((GMAC_ST1RPQ_UDPM_Msk & ((value) << GMAC_ST1RPQ_UDPM_Pos)))\r
+#define GMAC_ST1RPQ_DSTCE (0x1u << 28) /**< \brief (GMAC_ST1RPQ[16]) Differentiated Services or Traffic Class Match Enable */\r
+#define GMAC_ST1RPQ_UDPE (0x1u << 29) /**< \brief (GMAC_ST1RPQ[16]) UDP Port Match Enable */\r
+/* -------- GMAC_ST2RPQ[16] : (GMAC Offset: 0x540) Screening Type2 Register Priority Queue -------- */\r
+#define GMAC_ST2RPQ_QNB_Pos 0\r
+#define GMAC_ST2RPQ_QNB_Msk (0xfu << GMAC_ST2RPQ_QNB_Pos) /**< \brief (GMAC_ST2RPQ[16]) Que Number (0->7) */\r
+#define GMAC_ST2RPQ_QNB(value) ((GMAC_ST2RPQ_QNB_Msk & ((value) << GMAC_ST2RPQ_QNB_Pos)))\r
+#define GMAC_ST2RPQ_VLANP_Pos 4\r
+#define GMAC_ST2RPQ_VLANP_Msk (0xfu << GMAC_ST2RPQ_VLANP_Pos) /**< \brief (GMAC_ST2RPQ[16]) VLAN Priority */\r
+#define GMAC_ST2RPQ_VLANP(value) ((GMAC_ST2RPQ_VLANP_Msk & ((value) << GMAC_ST2RPQ_VLANP_Pos)))\r
+#define GMAC_ST2RPQ_VLANE (0x1u << 8) /**< \brief (GMAC_ST2RPQ[16]) VLAN Enable */\r
+/* -------- GMAC_IERPQ[7] : (GMAC Offset: 0x600) Interrupt Enable Register Priority Queue -------- */\r
+#define GMAC_IERPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IERPQ[7]) Receive Complete */\r
+#define GMAC_IERPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IERPQ[7]) RX Used Bit Read */\r
+#define GMAC_IERPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IERPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IERPQ_TFC (0x1u << 6) /**< \brief (GMAC_IERPQ[7]) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IERPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IERPQ[7]) Transmit Complete */\r
+#define GMAC_IERPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IERPQ[7]) Receive Overrun */\r
+#define GMAC_IERPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IERPQ[7]) HRESP Not OK */\r
+/* -------- GMAC_IDRPQ[7] : (GMAC Offset: 0x620) Interrupt Disable Register Priority Queue -------- */\r
+#define GMAC_IDRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IDRPQ[7]) Receive Complete */\r
+#define GMAC_IDRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IDRPQ[7]) RX Used Bit Read */\r
+#define GMAC_IDRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IDRPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IDRPQ_TFC (0x1u << 6) /**< \brief (GMAC_IDRPQ[7]) Transmit Frame Corruption due to AHB error */\r
+#define GMAC_IDRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IDRPQ[7]) Transmit Complete */\r
+#define GMAC_IDRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IDRPQ[7]) Receive Overrun */\r
+#define GMAC_IDRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IDRPQ[7]) HRESP Not OK */\r
+/* -------- GMAC_IMRPQ[7] : (GMAC Offset: 0x640) Interrupt Mask Register Priority Queue -------- */\r
+#define GMAC_IMRPQ_RCOMP (0x1u << 1) /**< \brief (GMAC_IMRPQ[7]) Receive Complete */\r
+#define GMAC_IMRPQ_RXUBR (0x1u << 2) /**< \brief (GMAC_IMRPQ[7]) RX Used Bit Read */\r
+#define GMAC_IMRPQ_RLEX (0x1u << 5) /**< \brief (GMAC_IMRPQ[7]) Retry Limit Exceeded or Late Collision */\r
+#define GMAC_IMRPQ_AHB (0x1u << 6) /**< \brief (GMAC_IMRPQ[7]) AHB Error */\r
+#define GMAC_IMRPQ_TCOMP (0x1u << 7) /**< \brief (GMAC_IMRPQ[7]) Transmit Complete */\r
+#define GMAC_IMRPQ_ROVR (0x1u << 10) /**< \brief (GMAC_IMRPQ[7]) Receive Overrun */\r
+#define GMAC_IMRPQ_HRESP (0x1u << 11) /**< \brief (GMAC_IMRPQ[7]) HRESP Not OK */\r
+\r
+/*@}*/\r
+\r
+\r
+#endif /* _SAM4E_GMAC_COMPONENT_ */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/ethernet_phy.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/ethernet_phy.c
new file mode 100644 (file)
index 0000000..fe9e296
--- /dev/null
@@ -0,0 +1,454 @@
+ /**\r
+ * \file\r
+ *\r
+ * \brief API driver for KSZ8051MNL PHY component.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "FreeRTOSIPConfig.h"\r
+\r
+#include "ethernet_phy.h"\r
+#include "instance/gmac.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL)\r
+ *\r
+ * Driver for the ksz8051mnl component. This driver provides access to the main\r
+ * features of the PHY.\r
+ *\r
+ * \section dependencies Dependencies\r
+ * This driver depends on the following modules:\r
+ * - \ref gmac_group Ethernet Media Access Controller (GMAC) module.\r
+ *\r
+ * @{\r
+ */\r
+\r
+SPhyProps phyProps;\r
+\r
+/* Max PHY number */\r
+#define ETH_PHY_MAX_ADDR   31\r
+\r
+/* Ethernet PHY operation max retry count */\r
+#define ETH_PHY_RETRY_MAX 1000000\r
+\r
+/* Ethernet PHY operation timeout */\r
+#define ETH_PHY_TIMEOUT 10\r
+\r
+/**\r
+ * \brief Find a valid PHY Address ( from addrStart to 31 ).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_start_addr Start address of the PHY to be searched.\r
+ *\r
+ * \return 0xFF when no valid PHY address is found.\r
+ */\r
+int ethernet_phy_addr = 0;\r
+static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr,\r
+               uint8_t uc_start_addr)\r
+{\r
+       uint32_t ul_value = 0;\r
+       uint8_t uc_cnt;\r
+       uint8_t uc_phy_address = uc_phy_addr;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+/*\r
+#define GMII_OUI_MSB            0x0022\r
+#define GMII_OUI_LSB            0x05\r
+\r
+PHYID1 = 0x0022\r
+PHYID2 = 0x1550\r
+0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0\r
+*/\r
+       /* Check the current PHY address */\r
+       gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value);\r
+\r
+       /* Find another one */\r
+       if (ul_value != GMII_OUI_MSB) {\r
+               ethernet_phy_addr = 0xFF;\r
+               for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) {\r
+                       uc_phy_address = (uc_phy_address + 1) & 0x1F;\r
+                       ul_value = 0;\r
+                       gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value);\r
+                       if (ul_value == GMII_OUI_MSB) {\r
+                               ethernet_phy_addr = uc_phy_address;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       gmac_enable_management(p_gmac, false);\r
+\r
+       if (ethernet_phy_addr != 0xFF) {\r
+               gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value);\r
+       }\r
+       return ethernet_phy_addr;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Perform a HW initialization to the PHY and set up clocks.\r
+ *\r
+ * This should be called only once to initialize the PHY pre-settings.\r
+ * The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups).\r
+ * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).\r
+ * The RXDV pin is used to select test mode on reset (pulled up for test mode).\r
+ * The above pins should be predefined for corresponding settings in resetPins.\r
+ * The GMAC peripheral pins are configured after the reset is done.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param ul_mck GMAC MCK.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck)\r
+{\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+       uint8_t uc_phy;\r
+\r
+       ethernet_phy_reset(GMAC,uc_phy_addr);\r
+\r
+       /* Configure GMAC runtime clock */\r
+       uc_rc = gmac_set_mdc_clock(p_gmac, mck);\r
+       if (uc_rc != GMAC_OK) {\r
+               return 0;\r
+       }\r
+\r
+       /* Check PHY Address */\r
+       uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0);\r
+       if (uc_phy == 0xFF) {\r
+               return 0;\r
+       }\r
+       if (uc_phy != uc_phy_addr) {\r
+               ethernet_phy_reset(p_gmac, uc_phy_addr);\r
+       }\r
+       phy_props.phy_chn = uc_phy;\r
+       return uc_phy;\r
+}\r
+\r
+\r
+/**\r
+ * \brief Get the Link & speed settings, and automatically set up the GMAC with the\r
+ * settings.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,\r
+               uint8_t uc_apply_setting_flag)\r
+{\r
+       uint32_t ul_stat1;\r
+       uint32_t ul_stat2;\r
+       uint8_t uc_phy_address, uc_speed = true, uc_fd = true;\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+\r
+       uc_phy_address = uc_phy_addr;\r
+\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);\r
+       if (uc_rc != GMAC_OK) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return uc_rc;\r
+       }\r
+       if ((ul_stat1 & GMII_LINK_STATUS) == 0) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return GMAC_INVALID;\r
+       }\r
+\r
+       if (uc_apply_setting_flag == 0) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Read advertisement */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);\r
+phy_props.phy_stat1 = ul_stat1;\r
+phy_props.phy_stat2 = ul_stat2;\r
+       if (uc_rc != GMAC_OK) {\r
+               /* Disable PHY management and start the GMAC transfer */\r
+               gmac_enable_management(p_gmac, false);\r
+\r
+               return uc_rc;\r
+       }\r
+\r
+       if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {\r
+               /* Set GMAC for 100BaseTX and Full Duplex */\r
+               uc_speed = true;\r
+               uc_fd = true;\r
+       } else\r
+       if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {\r
+               /* Set MII for 100BaseTX and Half Duplex */\r
+               uc_speed = true;\r
+               uc_fd = false;\r
+       } else\r
+       if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {\r
+               /* Set MII for 10BaseT and Full Duplex */\r
+               uc_speed = false;\r
+               uc_fd = true;\r
+       } else\r
+       if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {\r
+               /* Set MII for 10BaseT and Half Duplex */\r
+               uc_speed = false;\r
+               uc_fd = false;\r
+       }\r
+\r
+       gmac_set_speed(p_gmac, uc_speed);\r
+       gmac_enable_full_duplex(p_gmac, uc_fd);\r
+\r
+       /* Start the GMAC transfers */\r
+       gmac_enable_management(p_gmac, false);\r
+       return uc_rc;\r
+}\r
+\r
+PhyProps_t phy_props;\r
+\r
+/**\r
+ * \brief Issue an auto negotiation of the PHY.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)\r
+{\r
+       uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;\r
+       uint32_t ul_value;\r
+       uint32_t ul_phy_anar;\r
+       uint32_t ul_retry_count = 0;\r
+       uint8_t uc_speed = 0;\r
+       uint8_t uc_fd=0;\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+\r
+       /* Set up control register */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -1;\r
+               return uc_rc;\r
+       }\r
+\r
+       ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */\r
+       ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);\r
+       ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -2;\r
+               return uc_rc;\r
+       }\r
+\r
+       /*\r
+        * Set the Auto_negotiation Advertisement Register.\r
+        * MII advertising for Next page.\r
+        * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.\r
+        */\r
+       ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |\r
+                       GMII_AN_IEEE_802_3;\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -3;\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Read & modify control register */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -4;\r
+               return uc_rc;\r
+       }\r
+\r
+       ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -5;\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Restart auto negotiation */\r
+       ul_value |= (uint32_t)GMII_RESTART_AUTONEG;\r
+       ul_value &= ~(uint32_t)GMII_ISOLATE;\r
+       uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -6;\r
+               return uc_rc;\r
+       }\r
+\r
+       /* Check if auto negotiation is completed */\r
+       while (1) {\r
+               uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);\r
+               if (uc_rc != GMAC_OK) {\r
+                       gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -7;\r
+                       return uc_rc;\r
+               }\r
+               /* Done successfully */\r
+               if (ul_value & GMII_AUTONEG_COMP) {\r
+                       break;\r
+               }\r
+\r
+               /* Timeout check */\r
+               if (ul_retry_max) {\r
+                       if (++ul_retry_count >= ul_retry_max) {\r
+                               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -8;\r
+                               return GMAC_TIMEOUT;\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* Get the auto negotiate link partner base page */\r
+       uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);\r
+       if (uc_rc != GMAC_OK) {\r
+               gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = -9;\r
+               return uc_rc;\r
+       }\r
+\r
+\r
+       /* Set up the GMAC link speed */\r
+       if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {\r
+               /* Set MII for 100BaseTX and Full Duplex */\r
+               uc_speed = true;\r
+               uc_fd = true;\r
+       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {\r
+               /* Set MII for 10BaseT and Full Duplex */\r
+               uc_speed = false;\r
+               uc_fd = true;\r
+       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {\r
+               /* Set MII for 100BaseTX and half Duplex */\r
+               uc_speed = true;\r
+               uc_fd = false;\r
+       } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {\r
+               /* Set MII for 10BaseT and half Duplex */\r
+               uc_speed = false;\r
+               uc_fd = false;\r
+       }\r
+\r
+       gmac_set_speed(p_gmac, uc_speed);\r
+       gmac_enable_full_duplex(p_gmac, uc_fd);\r
+\r
+       /* Select Media Independent Interface type */\r
+       gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);\r
+\r
+       gmac_enable_transmit(GMAC, true);\r
+       gmac_enable_receive(GMAC, true);\r
+\r
+       gmac_enable_management(p_gmac, false);\r
+phy_props.phy_result = 1;\r
+       return uc_rc;\r
+}\r
+\r
+/**\r
+ * \brief Issue a SW reset to reset all registers of the PHY.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr)\r
+{\r
+       uint32_t ul_bmcr = GMII_RESET;\r
+       uint8_t uc_phy_address = uc_phy_addr;\r
+       uint32_t ul_timeout = ETH_PHY_TIMEOUT;\r
+       uint8_t uc_rc = GMAC_TIMEOUT;\r
+\r
+       gmac_enable_management(p_gmac, true);\r
+\r
+       ul_bmcr = GMII_RESET;\r
+       gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr);\r
+\r
+       do {\r
+               gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr);\r
+               ul_timeout--;\r
+       } while ((ul_bmcr & GMII_RESET) && ul_timeout);\r
+\r
+       gmac_enable_management(p_gmac, false);\r
+\r
+       if (!ul_timeout) {\r
+               uc_rc = GMAC_OK;\r
+       }\r
+\r
+       return (uc_rc);\r
+}\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \}\r
+ */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/ethernet_phy.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/ethernet_phy.h
new file mode 100644 (file)
index 0000000..8ea5fa0
--- /dev/null
@@ -0,0 +1,281 @@
+/**\r
+ * \file\r
+ *\r
+ * \brief KSZ8051MNL (Ethernet PHY) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef ETHERNET_PHY_H_INCLUDED\r
+#define ETHERNET_PHY_H_INCLUDED\r
+\r
+#include "compiler.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+// IEEE defined Registers\r
+#define GMII_BMCR        0x00   // Basic Control\r
+#define GMII_BMSR        0x01   // Basic Status\r
+#define GMII_PHYID1      0x02   // PHY Idendifier 1\r
+#define GMII_PHYID2      0x03   // PHY Idendifier 2\r
+#define GMII_ANAR        0x04   // Auto_Negotiation Advertisement\r
+#define GMII_ANLPAR      0x05   // Auto_negotiation Link Partner Ability\r
+#define GMII_ANER        0x06   // Auto-negotiation Expansion\r
+#define GMII_ANNPR       0x07   // Auto-negotiation Next Page\r
+#define GMII_ANLPNPAR    0x08   // Link Partner Next Page Ability\r
+//#define GMII_1000BTCR    9   // 1000Base-T Control  // Reserved\r
+//#define GMII_1000BTSR   10   // 1000Base-T Status   // Reserved\r
+#define GMII_AFECR1        0x11   // AFE Control 1\r
+//#define GMII_ERDWR      12   // Extend Register - Data Write Register\r
+//#define GMII_ERDRR      13   // Extend Register - Data Read Register\r
+//14    reserved\r
+#define GMII_RXERCR        0x15   // RXER Counter\r
+\r
+       #define PHY_REG_01_BMSR            0x01 // Basic mode status register\r
+       #define PHY_REG_02_PHYSID1         0x02 // PHYS ID 1\r
+       #define PHY_REG_03_PHYSID2         0x03 // PHYS ID 2\r
+       #define PHY_REG_04_ADVERTISE       0x04 // Advertisement control reg\r
+       #define PHY_REG_05_LPA             0x05 // Link partner ability reg\r
+       #define PHY_REG_06_ANER            0x06 //      6       RW              Auto-Negotiation Expansion Register\r
+       #define PHY_REG_07_ANNPTR          0x07 //      7       RW              Auto-Negotiation Next Page TX\r
+       #define PHY_REG_08_RESERVED0       0x08 // 0x08..0x0Fh  8-15    RW              RESERVED\r
+\r
+       #define PHY_REG_10_PHYSTS     0x10      // 16   RO              PHY Status Register\r
+       #define PHY_REG_11_MICR       0x11      // 17   RW              MII Interrupt Control Register\r
+       #define PHY_REG_12_MISR       0x12      // 18   RO              MII Interrupt Status Register\r
+       #define PHY_REG_13_RESERVED1  0x13      // 19   RW              RESERVED\r
+       #define PHY_REG_14_FCSCR      0x14      // 20   RO              False Carrier Sense Counter Register\r
+       #define PHY_REG_15_RECR       0x15      // 21   RO              Receive Error Counter Register\r
+       #define PHY_REG_16_PCSR       0x16      // 22   RW              PCS Sub-Layer Configuration and Status Register\r
+       #define PHY_REG_17_RBR        0x17      // 23   RW              RMII and Bypass Register\r
+       #define PHY_REG_18_LEDCR      0x18      // 24   RW              LED Direct Control Register\r
+       #define PHY_REG_19_PHYCR      0x19      // 25   RW              PHY Control Register\r
+       #define PHY_REG_1A_10BTSCR    0x1A      // 26   RW              10Base-T Status/Control Register\r
+       #define PHY_REG_1B_CDCTRL1    0x1B      // 27   RW              CD Test Control Register and BIST Extensions Register\r
+       #define PHY_REG_1B_INT_CTRL   0x1B      // 27   RW              KSZ8041NL interrupt control\r
+       #define PHY_REG_1C_RESERVED2  0x1C      // 28   RW              RESERVED\r
+       #define PHY_REG_1D_EDCR       0x1D      // 29   RW              Energy Detect Control Register\r
+       #define PHY_REG_1E_RESERVED3  0x1E      //\r
+       #define PHY_REG_1F_RESERVED4  0x1F      // 30-31        RW              RESERVED\r
+\r
+       #define PHY_REG_1E_PHYCR_1    0x1E      //\r
+       #define PHY_REG_1F_PHYCR_2    0x1F      //\r
+\r
+       #define PHY_SPEED_10       1\r
+       #define PHY_SPEED_100      2\r
+       #define PHY_SPEED_AUTO     (PHY_SPEED_10|PHY_SPEED_100)\r
+\r
+       #define PHY_MDIX_DIRECT    1\r
+       #define PHY_MDIX_CROSSED   2\r
+       #define PHY_MDIX_AUTO      (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT)\r
+\r
+       #define PHY_DUPLEX_HALF    1\r
+       #define PHY_DUPLEX_FULL    2\r
+       #define PHY_DUPLEX_AUTO    (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF)\r
+\r
+       typedef struct _SPhyProps {\r
+               unsigned char speed;\r
+               unsigned char mdix;\r
+               unsigned char duplex;\r
+               unsigned char spare;\r
+       } SPhyProps;\r
+\r
+       const char *phyPrintable (const SPhyProps *apProps);\r
+\r
+       extern SPhyProps phyProps;\r
+\r
+#define GMII_OMSOR        0x16   // Operation Mode Strap Override\r
+#define GMII_OMSSR       0x17   // Operation Mode Strap Status\r
+#define GMII_ECR      0x18   // Expanded Control\r
+//#define GMII_DPPSR      19   // Digital PMA/PCS Status\r
+//20    reserved\r
+//#define GMII_RXERCR     21   // RXER Counter Register\r
+//22-26 reserved\r
+#define GMII_ICSR        0x1B   // Interrupt Control/Status\r
+//#define GMII_DDC1R       28   // Digital Debug Control 1 Register\r
+#define GMII_LCSR        0x1D   // LinkMD Control/Status\r
+\r
+//29-30 reserved\r
+#define GMII_PCR1       0x1E   // PHY Control 1\r
+#define GMII_PCR2       0x1F   // PHY Control 2\r
+\r
+/*\r
+//Extend Registers\r
+#define GMII_CCR        256  // Common Control Register\r
+#define GMII_SSR        257  // Strap Status Register\r
+#define GMII_OMSOR      258  // Operation Mode Strap Override Register\r
+#define GMII_OMSSR      259  // Operation Mode Strap Status Register\r
+#define GMII_RCCPSR     260  // RGMII Clock and Control Pad Skew Register\r
+#define GMII_RRDPSR     261  // RGMII RX Data Pad Skew Register\r
+#define GMII_ATR        263  // Analog Test Register\r
+*/\r
+\r
+\r
+// Bit definitions: GMII_BMCR 0x00 Basic Control\r
+#define GMII_RESET             (1 << 15) // 1= Software Reset; 0=Normal Operation\r
+#define GMII_LOOPBACK          (1 << 14) // 1=loopback Enabled; 0=Normal Operation\r
+#define GMII_SPEED_SELECT      (1 << 13) // 1=100Mbps; 0=10Mbps\r
+#define GMII_AUTONEG           (1 << 12) // Auto-negotiation Enable\r
+#define GMII_POWER_DOWN        (1 << 11) // 1=Power down 0=Normal operation\r
+#define GMII_ISOLATE           (1 << 10) // 1 = Isolates 0 = Normal operation\r
+#define GMII_RESTART_AUTONEG   (1 << 9)  // 1 = Restart auto-negotiation 0 = Normal operation\r
+#define GMII_DUPLEX_MODE       (1 << 8)  // 1 = Full duplex operation 0 = Normal operation\r
+#define GMII_COLLISION_TEST    (1 << 7)  // 1 = Enable COL test; 0 = Disable COL test\r
+//#define GMII_SPEED_SELECT_MSB  (1 << 6)  // Reserved\r
+//      Reserved                6 to 0   // Read as 0, ignore on write\r
+\r
+// Bit definitions: GMII_BMSR 0x01 Basic Status\r
+#define GMII_100BASE_T4        (1 << 15) // 100BASE-T4 Capable\r
+#define GMII_100BASE_TX_FD     (1 << 14) // 100BASE-TX Full Duplex Capable\r
+#define GMII_100BASE_T4_HD     (1 << 13) // 100BASE-TX Half Duplex Capable\r
+#define GMII_10BASE_T_FD       (1 << 12) // 10BASE-T Full Duplex Capable\r
+#define GMII_10BASE_T_HD       (1 << 11) // 10BASE-T Half Duplex Capable\r
+//      Reserved                10 to79  // Read as 0, ignore on write\r
+//#define GMII_EXTEND_STATUS     (1 << 8)  // 1 = Extend Status Information In Reg 15\r
+//      Reserved                7\r
+#define GMII_MF_PREAMB_SUPPR   (1 << 6)  // MII Frame Preamble Suppression\r
+#define GMII_AUTONEG_COMP      (1 << 5)  // Auto-negotiation Complete\r
+#define GMII_REMOTE_FAULT      (1 << 4)  // Remote Fault\r
+#define GMII_AUTONEG_ABILITY   (1 << 3)  // Auto Configuration Ability\r
+#define GMII_LINK_STATUS       (1 << 2)  // Link Status\r
+#define GMII_JABBER_DETECT     (1 << 1)  // Jabber Detect\r
+#define GMII_EXTEND_CAPAB      (1 << 0)  // Extended Capability\r
+\r
+\r
+// Bit definitions: GMII_PHYID1 0x02 PHY Idendifier 1\r
+// Bit definitions: GMII_PHYID2 0x03 PHY Idendifier 2\r
+#define GMII_LSB_MASK           0x3F\r
+#define GMII_OUI_MSB            0x0022\r
+#define GMII_OUI_LSB            0x05\r
+\r
+\r
+// Bit definitions: GMII_ANAR   0x04 Auto_Negotiation Advertisement\r
+// Bit definitions: GMII_ANLPAR 0x05 Auto_negotiation Link Partner Ability\r
+#define GMII_NP               (1 << 15) // Next page Indication\r
+//      Reserved               7\r
+#define GMII_RF               (1 << 13) // Remote Fault\r
+//      Reserved               12       // Write as 0, ignore on read\r
+#define GMII_PAUSE_MASK       (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner)\r
+                                        // 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device)\r
+#define GMII_100T4               (1 << 9)  // 100BASE-T4 Support\r
+#define GMII_100TX_FDX           (1 << 8)  // 100BASE-TX Full Duplex Support\r
+#define GMII_100TX_HDX           (1 << 7)  // 100BASE-TX Support\r
+#define GMII_10_FDX           (1 << 6)  // 10BASE-T Full Duplex Support\r
+#define GMII_10_HDX           (1 << 5)  // 10BASE-T Support\r
+//      Selector                 4 to 0   // Protocol Selection Bits\r
+#define GMII_AN_IEEE_802_3      0x0001    // [00001] = IEEE 802.3\r
+\r
+\r
+// Bit definitions: GMII_ANER 0x06 Auto-negotiation Expansion\r
+//      Reserved                15 to 5  // Read as 0, ignore on write\r
+#define GMII_PDF              (1 << 4) // Local Device Parallel Detection Fault\r
+#define GMII_LP_NP_ABLE       (1 << 3) // Link Partner Next Page Able\r
+#define GMII_NP_ABLE          (1 << 2) // Local Device Next Page Able\r
+#define GMII_PAGE_RX          (1 << 1) // New Page Received\r
+#define GMII_LP_AN_ABLE       (1 << 0) // Link Partner Auto-negotiation Able\r
+\r
+/**\r
+ * \brief Perform a HW initialization to the PHY and set up clocks.\r
+ *\r
+ * This should be called only once to initialize the PHY pre-settings.\r
+ * The PHY address is the reset status of CRS, RXD[3:0] (the GmacPins' pullups).\r
+ * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).\r
+ * The RXDV pin is used to select test mode on reset (pulled up for test mode).\r
+ * The above pins should be predefined for corresponding settings in resetPins.\r
+ * The GMAC peripheral pins are configured after the reset is done.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param ul_mck GMAC MCK.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t ul_mck);\r
+\r
+\r
+/**\r
+ * \brief Get the Link & speed settings, and automatically set up the GMAC with the\r
+ * settings.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,\r
+               uint8_t uc_apply_setting_flag);\r
+\r
+\r
+/**\r
+ * \brief Issue an auto negotiation of the PHY.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr);\r
+\r
+/**\r
+ * \brief Issue a SW reset to reset all registers of the PHY.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr PHY address.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr);\r
+\r
+typedef struct xPHY_PROPS {\r
+       signed char phy_result;\r
+       uint32_t phy_params;\r
+       uint32_t phy_stat1;\r
+       uint32_t phy_stat2;\r
+       unsigned char phy_chn;\r
+} PhyProps_t;\r
+extern PhyProps_t phy_props;\r
+\r
+#ifdef __cplusplus\r
+} /* extern "C" */\r
+#endif\r
+\r
+#endif /* #ifndef ETHERNET_PHY_H_INCLUDED */\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.c
new file mode 100644 (file)
index 0000000..fe73a73
--- /dev/null
@@ -0,0 +1,945 @@
+ /**\r
+ * \file\r
+ *\r
+ * \brief GMAC (Ethernet MAC) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+#include "FreeRTOSIPConfig.h"\r
+\r
+#include "compiler.h"\r
+#include "instance/gmac.h"\r
+#include "ethernet_phy.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+#ifndef ARRAY_SIZE\r
+#define ARRAY_SIZE(x)  (int)( sizeof(x) / sizeof(x)[0] )\r
+#endif\r
+/**\r
+ * \defgroup gmac_group Ethernet Media Access Controller\r
+ *\r
+ * See \ref gmac_quickstart.\r
+ *\r
+ * Driver for the GMAC (Ethernet Media Access Controller).\r
+ * This file contains basic functions for the GMAC, with support for all modes, settings\r
+ * and clock speeds.\r
+ *\r
+ * \section dependencies Dependencies\r
+ * This driver does not depend on other modules.\r
+ *\r
+ * @{\r
+ */\r
+\r
+/** TX descriptor lists */\r
+COMPILER_ALIGNED(8)\r
+static gmac_tx_descriptor_t gs_tx_desc[ GMAC_TX_BUFFERS ];\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+/** TX callback lists */\r
+static gmac_dev_tx_cb_t gs_tx_callback[ GMAC_TX_BUFFERS ];\r
+#endif\r
+/** RX descriptors lists */\r
+COMPILER_ALIGNED(8)\r
+static gmac_rx_descriptor_t gs_rx_desc[ GMAC_RX_BUFFERS ];\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+       /** Send Buffer. Section 3.6 of AMBA 2.0 spec states that burst should not cross the\r
+        * 1K Boundaries. Receive buffer manager write operations are burst of 2 words => 3 lsb bits\r
+        * of the address shall be set to 0.\r
+        */\r
+       COMPILER_ALIGNED(8)\r
+       static uint8_t gs_uc_tx_buffer[ GMAC_TX_BUFFERS * GMAC_TX_UNITSIZE ];\r
+#endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+/** Receive Buffer */\r
+COMPILER_ALIGNED(8)\r
+static uint8_t gs_uc_rx_buffer[ GMAC_RX_BUFFERS * GMAC_RX_UNITSIZE ];\r
+\r
+/**\r
+ * GMAC device memory management struct.\r
+ */\r
+typedef struct gmac_dev_mem {\r
+       /* Pointer to allocated buffer for RX. The address should be 8-byte aligned\r
+       and the size should be GMAC_RX_UNITSIZE * wRxSize. */\r
+       uint8_t *p_rx_buffer;\r
+       /* Pointer to allocated RX descriptor list. */\r
+       gmac_rx_descriptor_t *p_rx_dscr;\r
+       /* RX size, in number of registered units (RX descriptors). */\r
+       /* Increased size from 16- to 32-bits, because it's more efficient */\r
+       uint32_t us_rx_size;\r
+       /* Pointer to allocated buffer for TX. The address should be 8-byte aligned\r
+       and the size should be GMAC_TX_UNITSIZE * wTxSize. */\r
+       uint8_t *p_tx_buffer;\r
+       /* Pointer to allocated TX descriptor list. */\r
+       gmac_tx_descriptor_t *p_tx_dscr;\r
+       /* TX size, in number of registered units (TX descriptors). */\r
+       uint32_t us_tx_size;\r
+} gmac_dev_mem_t;\r
+\r
+/** Return count in buffer */\r
+#define CIRC_CNT( head, tail, size )           ( ( ( head ) - ( tail ) ) % ( size ) )\r
+\r
+/*\r
+ * Return space available, from 0 to size-1.\r
+ * Always leave one free char as a completely full buffer that has (head == tail),\r
+ * which is the same as empty.\r
+ */\r
+#define CIRC_SPACE( head, tail, size )         CIRC_CNT( ( tail ), ( ( head ) + 1 ), ( size ) )\r
+\r
+/** Circular buffer is empty ? */\r
+#define CIRC_EMPTY( head, tail )                       ( head == tail )\r
+/** Clear circular buffer */\r
+#define CIRC_CLEAR( head, tail )                       do { ( head ) = 0; ( tail ) = 0; } while( 0 )\r
+\r
+/** Increment head or tail */\r
+static __inline void circ_inc32( int32_t *lHeadOrTail, uint32_t ulSize )\r
+{\r
+       ( *lHeadOrTail ) ++;\r
+    if( ( *lHeadOrTail ) >= ( int32_t )ulSize )\r
+       {\r
+               ( *lHeadOrTail ) = 0;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Wait PHY operation to be completed.\r
+ *\r
+ * \param p_gmac HW controller address.\r
+ * \param ul_retry The retry times, 0 to wait forever until completeness.\r
+ *\r
+ * Return GMAC_OK if the operation is completed successfully.\r
+ */\r
+static uint8_t gmac_wait_phy(Gmac* p_gmac, const uint32_t ul_retry)\r
+{\r
+       volatile uint32_t ul_retry_count = 0;\r
+       const uint32_t xPHYPollDelay = pdMS_TO_TICKS( 1ul );\r
+\r
+       while (!gmac_is_phy_idle(p_gmac)) {\r
+               if (ul_retry == 0) {\r
+                       continue;\r
+               }\r
+\r
+               ul_retry_count++;\r
+\r
+               if (ul_retry_count >= ul_retry) {\r
+                       return GMAC_TIMEOUT;\r
+               }\r
+\r
+               /* Block the task to allow other tasks to execute while the PHY\r
+               is not connected. */\r
+               vTaskDelay( xPHYPollDelay );\r
+       }\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Disable transfer, reset registers and descriptor lists.\r
+ *\r
+ * \param p_dev Pointer to GMAC driver instance.\r
+ *\r
+ */\r
+static void gmac_reset_tx_mem(gmac_device_t* p_dev)\r
+{\r
+       Gmac *p_hw = p_dev->p_hw;\r
+       uint8_t *p_tx_buff = p_dev->p_tx_buffer;\r
+       gmac_tx_descriptor_t *p_td = p_dev->p_tx_dscr;\r
+\r
+       uint32_t ul_index;\r
+       uint32_t ul_address;\r
+\r
+       /* Disable TX */\r
+       gmac_enable_transmit(p_hw, 0);\r
+\r
+       /* Set up the TX descriptors */\r
+       CIRC_CLEAR(p_dev->l_tx_head, p_dev->l_tx_tail);\r
+       for( ul_index = 0; ul_index < p_dev->ul_tx_list_size; ul_index++ )\r
+       {\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       ul_address = (uint32_t) 0u;\r
+               }\r
+               #else\r
+               {\r
+                       ul_address = (uint32_t) (&(p_tx_buff[ul_index * GMAC_TX_UNITSIZE]));\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+               p_td[ul_index].addr = ul_address;\r
+               p_td[ul_index].status.val = GMAC_TXD_USED;\r
+       }\r
+       p_td[p_dev->ul_tx_list_size - 1].status.val =\r
+                       GMAC_TXD_USED | GMAC_TXD_WRAP;\r
+\r
+       /* Set transmit buffer queue */\r
+       gmac_set_tx_queue(p_hw, (uint32_t) p_td);\r
+}\r
+\r
+/**\r
+ * \brief Disable receiver, reset registers and descriptor list.\r
+ *\r
+ * \param p_drv Pointer to GMAC Driver instance.\r
+ */\r
+static void gmac_reset_rx_mem(gmac_device_t* p_dev)\r
+{\r
+       Gmac *p_hw = p_dev->p_hw;\r
+       uint8_t *p_rx_buff = p_dev->p_rx_buffer;\r
+       gmac_rx_descriptor_t *pRd = p_dev->p_rx_dscr;\r
+\r
+       uint32_t ul_index;\r
+       uint32_t ul_address;\r
+\r
+       /* Disable RX */\r
+       gmac_enable_receive(p_hw, 0);\r
+\r
+       /* Set up the RX descriptors */\r
+       p_dev->ul_rx_idx = 0;\r
+       for( ul_index = 0; ul_index < p_dev->ul_rx_list_size; ul_index++ )\r
+       {\r
+               ul_address = (uint32_t) (&(p_rx_buff[ul_index * GMAC_RX_UNITSIZE]));\r
+               pRd[ul_index].addr.val = ul_address & GMAC_RXD_ADDR_MASK;\r
+               pRd[ul_index].status.val = 0;\r
+       }\r
+       pRd[p_dev->ul_rx_list_size - 1].addr.val |= GMAC_RXD_WRAP;\r
+\r
+       /* Set receive buffer queue */\r
+       gmac_set_rx_queue(p_hw, (uint32_t) pRd);\r
+}\r
+\r
+\r
+/**\r
+ * \brief Initialize the allocated buffer lists for GMAC driver to transfer data.\r
+ * Must be invoked after gmac_dev_init() but before RX/TX starts.\r
+ *\r
+ * \note If input address is not 8-byte aligned, the address is automatically\r
+ *       adjusted and the list size is reduced by one.\r
+ *\r
+ * \param p_gmac Pointer to GMAC instance.\r
+ * \param p_gmac_dev Pointer to GMAC device instance.\r
+ * \param p_dev_mm Pointer to the GMAC memory management control block.\r
+ * \param p_tx_cb Pointer to allocated TX callback list.\r
+ *\r
+ * \return GMAC_OK or GMAC_PARAM.\r
+ */\r
+static uint8_t gmac_init_mem(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+               gmac_dev_mem_t* p_dev_mm\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+               , gmac_dev_tx_cb_t* p_tx_cb\r
+#endif\r
+               )\r
+{\r
+       if (p_dev_mm->us_rx_size <= 1 || p_dev_mm->us_tx_size <= 1\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+               || p_tx_cb == NULL\r
+#endif\r
+               ) {\r
+               return GMAC_PARAM;\r
+       }\r
+\r
+       /* Assign RX buffers */\r
+       if (((uint32_t) p_dev_mm->p_rx_buffer & 0x7)\r
+                       || ((uint32_t) p_dev_mm->p_rx_dscr & 0x7)) {\r
+               p_dev_mm->us_rx_size--;\r
+       }\r
+       p_gmac_dev->p_rx_buffer =\r
+                       (uint8_t *) ((uint32_t) p_dev_mm->p_rx_buffer & 0xFFFFFFF8);\r
+       p_gmac_dev->p_rx_dscr =\r
+                       (gmac_rx_descriptor_t *) ((uint32_t) p_dev_mm->p_rx_dscr\r
+                       & 0xFFFFFFF8);\r
+       p_gmac_dev->ul_rx_list_size = p_dev_mm->us_rx_size;\r
+\r
+       /* Assign TX buffers */\r
+       if (((uint32_t) p_dev_mm->p_tx_buffer & 0x7)\r
+                       || ((uint32_t) p_dev_mm->p_tx_dscr & 0x7)) {\r
+               p_dev_mm->us_tx_size--;\r
+       }\r
+       p_gmac_dev->p_tx_buffer =\r
+                       (uint8_t *) ((uint32_t) p_dev_mm->p_tx_buffer & 0xFFFFFFF8);\r
+       p_gmac_dev->p_tx_dscr =\r
+                       (gmac_tx_descriptor_t *) ((uint32_t) p_dev_mm->p_tx_dscr\r
+                       & 0xFFFFFFF8);\r
+       p_gmac_dev->ul_tx_list_size = p_dev_mm->us_tx_size;\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       p_gmac_dev->func_tx_cb_list = p_tx_cb;\r
+#endif\r
+       /* Reset TX & RX */\r
+       gmac_reset_rx_mem(p_gmac_dev);\r
+       gmac_reset_tx_mem(p_gmac_dev);\r
+\r
+       /* Enable Rx and Tx, plus the statistics register */\r
+       gmac_enable_transmit(p_gmac, true);\r
+       gmac_enable_receive(p_gmac, true);\r
+       gmac_enable_statistics_write(p_gmac, true);\r
+\r
+       /* Set up the interrupts for transmission and errors */\r
+       gmac_enable_interrupt(p_gmac,\r
+                       GMAC_IER_RXUBR | /* Enable receive used bit read interrupt. */\r
+                       GMAC_IER_TUR   | /* Enable transmit underrun interrupt. */\r
+                       GMAC_IER_RLEX  | /* Enable retry limit  exceeded interrupt. */\r
+                       GMAC_IER_TFC   | /* Enable transmit buffers exhausted in mid-frame interrupt. */\r
+                       GMAC_IER_TCOMP | /* Enable transmit complete interrupt. */\r
+                       GMAC_IER_ROVR  | /* Enable receive overrun interrupt. */\r
+                       GMAC_IER_HRESP | /* Enable Hresp not OK interrupt. */\r
+                       GMAC_IER_PFNZ  | /* Enable pause frame received interrupt. */\r
+                       GMAC_IER_PTZ);   /* Enable pause time zero interrupt. */\r
+\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Read the PHY register.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_address PHY address.\r
+ * \param uc_address Register address.\r
+ * \param p_value Pointer to a 32-bit location to store read data.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,\r
+               uint32_t* p_value)\r
+{\r
+       gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 1, 0);\r
+\r
+       if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {\r
+               return GMAC_TIMEOUT;\r
+       }\r
+       *p_value = gmac_get_phy_data(p_gmac);\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Write the PHY register.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_address PHY Address.\r
+ * \param uc_address Register Address.\r
+ * \param ul_value Data to write, actually 16-bit data.\r
+ *\r
+ * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.\r
+ */\r
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,\r
+               uint8_t uc_address, uint32_t ul_value)\r
+{\r
+       gmac_maintain_phy(p_gmac, uc_phy_address, uc_address, 0, ul_value);\r
+\r
+       if (gmac_wait_phy(p_gmac, MAC_PHY_RETRY_MAX) == GMAC_TIMEOUT) {\r
+               return GMAC_TIMEOUT;\r
+       }\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Initialize the GMAC driver.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param p_opt GMAC configure options.\r
+ */\r
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+               gmac_options_t* p_opt)\r
+{\r
+       gmac_dev_mem_t gmac_dev_mm;\r
+\r
+       /* Disable TX & RX and more */\r
+       gmac_network_control(p_gmac, 0);\r
+       gmac_disable_interrupt(p_gmac, ~0u);\r
+\r
+\r
+       gmac_clear_statistics(p_gmac);\r
+\r
+       /* Clear all status bits in the receive status register. */\r
+       gmac_clear_rx_status(p_gmac, GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA);\r
+\r
+       /* Clear all status bits in the transmit status register */\r
+       gmac_clear_tx_status(p_gmac, GMAC_TSR_UBR | GMAC_TSR_COL | GMAC_TSR_RLE\r
+                       | GMAC_TSR_TFC | GMAC_TSR_TXCOMP | GMAC_TSR_UND);\r
+\r
+       /* Clear interrupts */\r
+       gmac_get_interrupt_status(p_gmac);\r
+#if !defined(ETHERNET_CONF_DATA_OFFSET)\r
+       /*  Receive Buffer Offset\r
+        * Indicates the number of bytes by which the received data\r
+        * is offset from the start of the receive buffer\r
+        * which can be handy for alignment reasons */\r
+       /* Note: FreeRTOS+TCP wants to have this offset set to 2 bytes */\r
+       #error ETHERNET_CONF_DATA_OFFSET not defined, assuming 0\r
+#endif\r
+       /* Enable the copy of data into the buffers\r
+          ignore broadcasts, and not copy FCS. */\r
+\r
+       gmac_set_configure(p_gmac,\r
+                       ( gmac_get_configure(p_gmac) & ~GMAC_NCFGR_RXBUFO_Msk ) |\r
+                       GMAC_NCFGR_RFCS |   /*  Remove FCS, frame check sequence (last 4 bytes) */\r
+                       GMAC_NCFGR_PEN |    /* Pause Enable */\r
+                       GMAC_NCFGR_RXBUFO( ETHERNET_CONF_DATA_OFFSET ) |\r
+                       GMAC_RXD_RXCOEN );\r
+\r
+       /*\r
+        * GMAC_DCFGR_TXCOEN: (GMAC_DCFGR) Transmitter Checksum Generation Offload Enable.\r
+        * Note: tha SAM4E does have RX checksum offloading\r
+        * but TX checksum offloading has NOT been implemented.\r
+        * http://community.atmel.com/forum/sam4e-gmac-transmit-checksum-offload-enablesolved\r
+        */\r
+\r
+       gmac_set_dma(p_gmac,\r
+                       gmac_get_dma(p_gmac) | GMAC_DCFGR_TXCOEN );\r
+\r
+       gmac_enable_copy_all(p_gmac, p_opt->uc_copy_all_frame);\r
+       gmac_disable_broadcast(p_gmac, p_opt->uc_no_boardcast);\r
+\r
+       /* Fill in GMAC device memory management */\r
+       gmac_dev_mm.p_rx_buffer = gs_uc_rx_buffer;\r
+       gmac_dev_mm.p_rx_dscr = gs_rx_desc;\r
+       gmac_dev_mm.us_rx_size = GMAC_RX_BUFFERS;\r
+\r
+       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       {\r
+               gmac_dev_mm.p_tx_buffer = NULL;\r
+       }\r
+       #else\r
+       {\r
+               gmac_dev_mm.p_tx_buffer = gs_uc_tx_buffer;\r
+       }\r
+       #endif\r
+       gmac_dev_mm.p_tx_dscr = gs_tx_desc;\r
+       gmac_dev_mm.us_tx_size = GMAC_TX_BUFFERS;\r
+\r
+       gmac_init_mem(p_gmac, p_gmac_dev, &gmac_dev_mm\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+               , gs_tx_callback\r
+#endif\r
+               );\r
+\r
+       gmac_set_address(p_gmac, 0, p_opt->uc_mac_addr);\r
+}\r
+\r
+/**\r
+ * \brief Frames can be read from the GMAC in multiple sections.\r
+ *\r
+ * Returns > 0 if a complete frame is available\r
+ * It also it cleans up incomplete older frames\r
+ */\r
+\r
+static uint32_t gmac_dev_poll(gmac_device_t* p_gmac_dev)\r
+{\r
+       uint32_t ulReturn = 0;\r
+       int32_t ulIndex = p_gmac_dev->ul_rx_idx;\r
+       gmac_rx_descriptor_t *pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];\r
+\r
+       /* Discard any incomplete frames */\r
+       while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) &&\r
+                       (pxHead->status.val & GMAC_RXD_SOF) == 0) {\r
+               pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);\r
+               circ_inc32 (&ulIndex, p_gmac_dev->ul_rx_list_size);\r
+               pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];\r
+               p_gmac_dev->ul_rx_idx = ulIndex;\r
+               #if( GMAC_STATS != 0 )\r
+               {\r
+                       gmacStats.incompCount++;\r
+               }\r
+               #endif\r
+       }\r
+\r
+       while ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) != 0) {\r
+               if ((pxHead->status.val & GMAC_RXD_EOF) != 0) {\r
+                       /* Here a complete frame has been seen with SOF and EOF */\r
+                       ulReturn = pxHead->status.bm.len;\r
+                       break;\r
+               }\r
+               circ_inc32 (&ulIndex, p_gmac_dev->ul_rx_list_size);\r
+               pxHead = &p_gmac_dev->p_rx_dscr[ulIndex];\r
+               if ((pxHead->addr.val & GMAC_RXD_OWNERSHIP) == 0) {\r
+                       /* CPU is not the owner (yet) */\r
+                       break;\r
+               }\r
+               if ((pxHead->status.val & GMAC_RXD_SOF) != 0) {\r
+                       /* Strange, we found a new Start Of Frame\r
+                        * discard previous segments */\r
+                       int32_t ulPrev = p_gmac_dev->ul_rx_idx;\r
+                       pxHead = &p_gmac_dev->p_rx_dscr[ulPrev];\r
+                       do {\r
+                               pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);\r
+                               circ_inc32 (&ulPrev, p_gmac_dev->ul_rx_list_size);\r
+                               pxHead = &p_gmac_dev->p_rx_dscr[ulPrev];\r
+                               #if( GMAC_STATS != 0 )\r
+                               {\r
+                                       gmacStats.truncCount++;\r
+                               }\r
+                               #endif\r
+                       } while (ulPrev != ulIndex);\r
+                       p_gmac_dev->ul_rx_idx = ulIndex;\r
+               }\r
+       }\r
+       return ulReturn;\r
+}\r
+\r
+/**\r
+ * \brief Frames can be read from the GMAC in multiple sections.\r
+ * Read ul_frame_size bytes from the GMAC receive buffers to pcTo.\r
+ * p_rcv_size is the size of the entire frame.  Generally gmac_read\r
+ * will be repeatedly called until the sum of all the ul_frame_size equals\r
+ * the value of p_rcv_size.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param p_frame Address of the frame buffer.\r
+ * \param ul_frame_size  Length of the frame.\r
+ * \param p_rcv_size   Received frame size.\r
+ *\r
+ * \return GMAC_OK if receiving frame successfully, otherwise failed.\r
+ */\r
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,\r
+               uint32_t ul_frame_size, uint32_t* p_rcv_size)\r
+{\r
+       int32_t nextIdx;        /* A copy of the Rx-index 'ul_rx_idx' */\r
+       int32_t bytesLeft = gmac_dev_poll (p_gmac_dev);\r
+       gmac_rx_descriptor_t *pxHead;\r
+\r
+       if (bytesLeft == 0 )\r
+       {\r
+               return GMAC_RX_NULL;\r
+       }\r
+\r
+       /* gmac_dev_poll has confirmed that there is a complete frame at\r
+        * the current position 'ul_rx_idx'\r
+        */\r
+       nextIdx = p_gmac_dev->ul_rx_idx;\r
+\r
+       /* Read +2 bytes because buffers are aligned at -2 bytes */\r
+       bytesLeft = min( bytesLeft + 2, ( int32_t )ul_frame_size );\r
+\r
+       /* The frame will be copied in 1 or 2 memcpy's */\r
+       if( ( p_frame != NULL ) && ( bytesLeft != 0 ) )\r
+       {\r
+       const uint8_t *source;\r
+       int32_t left;\r
+       int32_t toCopy;\r
+\r
+               source = p_gmac_dev->p_rx_buffer + nextIdx * GMAC_RX_UNITSIZE;\r
+               left = bytesLeft;\r
+               toCopy = ( p_gmac_dev->ul_rx_list_size - nextIdx ) * GMAC_RX_UNITSIZE;\r
+               if(toCopy > left )\r
+               {\r
+                       toCopy = left;\r
+               }\r
+               memcpy (p_frame, source, toCopy);\r
+               left -= toCopy;\r
+\r
+               if( left != 0ul )\r
+               {\r
+                       memcpy (p_frame + toCopy, (void*)p_gmac_dev->p_rx_buffer, left);\r
+               }\r
+       }\r
+\r
+       do\r
+       {\r
+               pxHead = &p_gmac_dev->p_rx_dscr[nextIdx];\r
+               pxHead->addr.val &= ~(GMAC_RXD_OWNERSHIP);\r
+               circ_inc32 (&nextIdx, p_gmac_dev->ul_rx_list_size);\r
+       } while ((pxHead->status.val & GMAC_RXD_EOF) == 0);\r
+\r
+       p_gmac_dev->ul_rx_idx = nextIdx;\r
+\r
+       *p_rcv_size = bytesLeft;\r
+\r
+       return GMAC_OK;\r
+}\r
+\r
+\r
+extern void vGMACGenerateChecksum( uint8_t *apBuffer );\r
+\r
+/**\r
+ * \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the\r
+ * GMAC Tx buffers, and then indicates to the GMAC that the buffer is ready.\r
+ * If lEndOfFrame is true then the data being copied is the end of the frame\r
+ * and the frame can be transmitted.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param p_buffer       Pointer to the data buffer.\r
+ * \param ul_size    Length of the frame.\r
+ * \param func_tx_cb  Transmit callback function.\r
+ *\r
+ * \return Length sent.\r
+ */\r
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,\r
+               uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb)\r
+{\r
+\r
+       volatile gmac_tx_descriptor_t *p_tx_td;\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       volatile gmac_dev_tx_cb_t *p_func_tx_cb;\r
+#endif\r
+\r
+       Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+#if( GMAC_USES_TX_CALLBACK == 0 )\r
+       ( void )func_tx_cb;\r
+#endif\r
+\r
+       /* Check parameter */\r
+       if (ul_size > GMAC_TX_UNITSIZE) {\r
+               return GMAC_PARAM;\r
+       }\r
+\r
+       /* Pointers to the current transmit descriptor */\r
+       p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_head];\r
+\r
+       /* If no free TxTd, buffer can't be sent, schedule the wakeup callback */\r
+//     if (CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,\r
+//                                     p_gmac_dev->ul_tx_list_size) == 0)\r
+       {\r
+               if ((p_tx_td->status.val & GMAC_TXD_USED) == 0)\r
+                       return GMAC_TX_BUSY;\r
+       }\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       /* Pointers to the current Tx callback */\r
+       p_func_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_head];\r
+#endif\r
+\r
+       /* Set up/copy data to transmission buffer */\r
+       if (p_buffer && ul_size) {\r
+               /* Driver manages the ring buffer */\r
+               /* Calculating the checksum here is faster than calculating it from the GMAC buffer\r
+                * because withing p_buffer, it is well aligned */\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       /* Zero-copy... */\r
+                       p_tx_td->addr = ( uint32_t ) p_buffer;\r
+               }\r
+               #else\r
+               {\r
+                       /* Or memcopy... */\r
+                       memcpy((void *)p_tx_td->addr, p_buffer, ul_size);\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+               vGMACGenerateChecksum( ( uint8_t * ) p_tx_td->addr );\r
+       }\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       /* Tx callback */\r
+       *p_func_tx_cb = func_tx_cb;\r
+#endif\r
+\r
+       /* Update transmit descriptor status */\r
+\r
+       /* The buffer size defined is the length of ethernet frame,\r
+          so it's always the last buffer of the frame. */\r
+       if( p_gmac_dev->l_tx_head == ( int32_t )( p_gmac_dev->ul_tx_list_size - 1 ) )\r
+       {\r
+               /* No need to 'and' with GMAC_TXD_LEN_MASK because ul_size has been checked */\r
+               p_tx_td->status.val =\r
+                       ul_size | GMAC_TXD_LAST | GMAC_TXD_WRAP;\r
+       } else {\r
+               p_tx_td->status.val =\r
+                       ul_size | GMAC_TXD_LAST;\r
+       }\r
+\r
+       circ_inc32( &p_gmac_dev->l_tx_head, p_gmac_dev->ul_tx_list_size );\r
+\r
+       /* Now start to transmit if it is still not done */\r
+       gmac_start_transmission(p_hw);\r
+\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Get current load of transmit.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ *\r
+ * \return Current load of transmit.\r
+ */\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+/* Without defining GMAC_USES_TX_CALLBACK, l_tx_tail won't be updated */\r
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev)\r
+{\r
+       uint16_t us_head = p_gmac_dev->l_tx_head;\r
+       uint16_t us_tail = p_gmac_dev->l_tx_tail;\r
+       return CIRC_CNT(us_head, us_tail, p_gmac_dev->ul_tx_list_size);\r
+}\r
+#endif\r
+\r
+/**\r
+ * \brief Register/Clear RX callback. Callback will be invoked after the next received\r
+ * frame.\r
+ *\r
+ * When gmac_dev_read() returns GMAC_RX_NULL, the application task calls\r
+ * gmac_dev_set_rx_callback() to register func_rx_cb() callback and enters suspend state.\r
+ * The callback is in charge to resume the task once a new frame has been\r
+ * received. The next time gmac_dev_read() is called, it will be successful.\r
+ *\r
+ * This function is usually invoked from the RX callback itself with NULL\r
+ * callback, to unregister. Once the callback has resumed the application task,\r
+ * there is no need to invoke the callback again.\r
+ *\r
+ * \param p_gmac_dev Pointer to the GMAC device instance.\r
+ * \param func_tx_cb  Receive callback function.\r
+ */\r
+void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_rx_cb_t func_rx_cb)\r
+{\r
+       Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+       if (func_rx_cb == NULL) {\r
+               gmac_disable_interrupt(p_hw, GMAC_IDR_RCOMP);\r
+               p_gmac_dev->func_rx_cb = NULL;\r
+       } else {\r
+               p_gmac_dev->func_rx_cb = func_rx_cb;\r
+               gmac_enable_interrupt(p_hw, GMAC_IER_RCOMP);\r
+       }\r
+}\r
+\r
+/**\r
+ *  \brief Register/Clear TX wakeup callback.\r
+ *\r
+ * When gmac_dev_write() returns GMAC_TX_BUSY (all transmit descriptor busy), the application\r
+ * task calls gmac_dev_set_tx_wakeup_callback() to register func_wakeup() callback and\r
+ * enters suspend state. The callback is in charge to resume the task once\r
+ * several transmit descriptors have been released. The next time gmac_dev_write() will be called,\r
+ * it shall be successful.\r
+ *\r
+ * This function is usually invoked with NULL callback from the TX wakeup\r
+ * callback itself, to unregister. Once the callback has resumed the\r
+ * application task, there is no need to invoke the callback again.\r
+ *\r
+ * \param p_gmac_dev   Pointer to GMAC device instance.\r
+ * \param func_wakeup    Pointer to wakeup callback function.\r
+ * \param uc_threshold Number of free transmit descriptor before wakeup callback invoked.\r
+ *\r
+ * \return GMAC_OK, GMAC_PARAM on parameter error.\r
+ */\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_wakeup_cb_t func_wakeup_cb, uint8_t uc_threshold)\r
+{\r
+       if (func_wakeup_cb == NULL) {\r
+               p_gmac_dev->func_wakeup_cb = NULL;\r
+       } else {\r
+               if (uc_threshold <= p_gmac_dev->ul_tx_list_size) {\r
+                       p_gmac_dev->func_wakeup_cb = func_wakeup_cb;\r
+                       p_gmac_dev->uc_wakeup_threshold = uc_threshold;\r
+               } else {\r
+                       return GMAC_PARAM;\r
+               }\r
+       }\r
+\r
+       return GMAC_OK;\r
+}\r
+#endif /* GMAC_USES_WAKEUP_CALLBACK */\r
+\r
+/**\r
+ * \brief Reset TX & RX queue & statistics.\r
+ *\r
+ * \param p_gmac_dev   Pointer to GMAC device instance.\r
+ */\r
+void gmac_dev_reset(gmac_device_t* p_gmac_dev)\r
+{\r
+       Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+       gmac_reset_rx_mem(p_gmac_dev);\r
+       gmac_reset_tx_mem(p_gmac_dev);\r
+       gmac_network_control(p_hw, GMAC_NCR_TXEN | GMAC_NCR_RXEN\r
+                       | GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);\r
+}\r
+\r
+void gmac_dev_halt(Gmac* p_gmac);\r
+\r
+void gmac_dev_halt(Gmac* p_gmac)\r
+{\r
+       gmac_network_control(p_gmac, GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);\r
+       gmac_disable_interrupt(p_gmac, ~0u);\r
+}\r
+\r
+\r
+/**\r
+ * \brief GMAC Interrupt handler.\r
+ *\r
+ * \param p_gmac_dev   Pointer to GMAC device instance.\r
+ */\r
+\r
+#if( GMAC_STATS != 0 )\r
+       extern int logPrintf( const char *pcFormat, ... );\r
+\r
+       void gmac_show_irq_counts ()\r
+       {\r
+               int index;\r
+               for (index = 0; index < ARRAY_SIZE(intPairs); index++) {\r
+                       if (gmacStats.intStatus[intPairs[index].index]) {\r
+                               logPrintf("%s : %6u\n", intPairs[index].name, gmacStats.intStatus[intPairs[index].index]);\r
+                       }\r
+               }\r
+       }\r
+#endif\r
+\r
+void gmac_handler(gmac_device_t* p_gmac_dev)\r
+{\r
+       Gmac *p_hw = p_gmac_dev->p_hw;\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       gmac_tx_descriptor_t *p_tx_td;\r
+       gmac_dev_tx_cb_t *p_tx_cb = NULL;\r
+       uint32_t ul_tx_status_flag;\r
+#endif\r
+#if( GMAC_STATS != 0 )\r
+       int index;\r
+#endif\r
+\r
+       /* volatile */ uint32_t ul_isr;\r
+       /* volatile */ uint32_t ul_rsr;\r
+       /* volatile */ uint32_t ul_tsr;\r
+\r
+       ul_isr = gmac_get_interrupt_status(p_hw);\r
+       ul_rsr = gmac_get_rx_status(p_hw);\r
+       ul_tsr = gmac_get_tx_status(p_hw);\r
+\r
+/*     Why clear bits that are ignored anyway ? */\r
+/*     ul_isr &= ~(gmac_get_interrupt_mask(p_hw) | 0xF8030300); */\r
+       #if( GMAC_STATS != 0 )\r
+       {\r
+               for (index = 0; index < ARRAY_SIZE(intPairs); index++) {\r
+                       if (ul_isr & intPairs[index].mask)\r
+                               gmacStats.intStatus[intPairs[index].index]++;\r
+               }\r
+       }\r
+       #endif /* GMAC_STATS != 0 */\r
+\r
+       /* RX packet */\r
+       if ((ul_isr & GMAC_ISR_RCOMP) || (ul_rsr & (GMAC_RSR_REC|GMAC_RSR_RXOVR|GMAC_RSR_BNA))) {\r
+               /* Clear status */\r
+               gmac_clear_rx_status(p_hw, ul_rsr);\r
+\r
+               if (ul_isr & GMAC_ISR_RCOMP)\r
+                       ul_rsr |= GMAC_RSR_REC;\r
+               /* Invoke callbacks which can be useful to wake op a task */\r
+               if (p_gmac_dev->func_rx_cb) {\r
+                       p_gmac_dev->func_rx_cb(ul_rsr);\r
+               }\r
+       }\r
+\r
+       /* TX packet */\r
+       if ((ul_isr & GMAC_ISR_TCOMP) || (ul_tsr & (GMAC_TSR_TXCOMP|GMAC_TSR_COL|GMAC_TSR_RLE|GMAC_TSR_UND))) {\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+               ul_tx_status_flag = GMAC_TSR_TXCOMP;\r
+#endif\r
+               /* A frame transmitted */\r
+\r
+               /* Check RLE */\r
+               if (ul_tsr & GMAC_TSR_RLE) {\r
+                       /* Status RLE & Number of discarded buffers */\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+                       ul_tx_status_flag = GMAC_TSR_RLE | CIRC_CNT(p_gmac_dev->l_tx_head,\r
+                                       p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);\r
+                       p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_tail];\r
+#endif\r
+                       gmac_reset_tx_mem(p_gmac_dev);\r
+                       gmac_enable_transmit(p_hw, 1);\r
+               }\r
+               /* Clear status */\r
+               gmac_clear_tx_status(p_hw, ul_tsr);\r
+\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+               if (!CIRC_EMPTY(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail)) {\r
+                       /* Check the buffers */\r
+                       do {\r
+                               p_tx_td = &p_gmac_dev->p_tx_dscr[p_gmac_dev->l_tx_tail];\r
+                               p_tx_cb = &p_gmac_dev->func_tx_cb_list[p_gmac_dev->l_tx_tail];\r
+                               /* Any error? Exit if buffer has not been sent yet */\r
+                               if ((p_tx_td->status.val & GMAC_TXD_USED) == 0) {\r
+                                       break;\r
+                               }\r
+\r
+                               /* Notify upper layer that a packet has been sent */\r
+                               if (*p_tx_cb) {\r
+                                       (*p_tx_cb) (ul_tx_status_flag, (void*)p_tx_td->addr);\r
+                                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+                                       {\r
+                                               p_tx_td->addr = 0ul;\r
+                                       }\r
+                                       #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+                               }\r
+\r
+                               circ_inc32(&p_gmac_dev->l_tx_tail, p_gmac_dev->ul_tx_list_size);\r
+                       } while (CIRC_CNT(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,\r
+                                                       p_gmac_dev->ul_tx_list_size));\r
+               }\r
+\r
+               if (ul_tsr & GMAC_TSR_RLE) {\r
+                       /* Notify upper layer RLE */\r
+                       if (*p_tx_cb) {\r
+                               (*p_tx_cb) (ul_tx_status_flag, NULL);\r
+                       }\r
+               }\r
+#endif /* GMAC_USES_TX_CALLBACK */\r
+\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+               /* If a wakeup has been scheduled, notify upper layer that it can\r
+                  send other packets, and the sending will be successful. */\r
+               if ((CIRC_SPACE(p_gmac_dev->l_tx_head, p_gmac_dev->l_tx_tail,\r
+                               p_gmac_dev->ul_tx_list_size) >= p_gmac_dev->uc_wakeup_threshold)\r
+                               && p_gmac_dev->func_wakeup_cb) {\r
+                       p_gmac_dev->func_wakeup_cb();\r
+               }\r
+#endif\r
+       }\r
+}\r
+\r
+//@}\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/gmac.h
new file mode 100644 (file)
index 0000000..fca3ece
--- /dev/null
@@ -0,0 +1,1346 @@
+ /**\r
+ * \file\r
+ *\r
+ * \brief GMAC (Ethernet MAC) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef GMAC_H_INCLUDED\r
+#define GMAC_H_INCLUDED\r
+\r
+#include "compiler.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/** The buffer addresses written into the descriptors must be aligned, so the\r
+    last few bits are zero.  These bits have special meaning for the GMAC\r
+    peripheral and cannot be used as part of the address. */\r
+#define GMAC_RXD_ADDR_MASK      0xFFFFFFFC\r
+#define GMAC_RXD_WRAP         (1ul << 1)  /**< Wrap bit */\r
+#define GMAC_RXD_OWNERSHIP    (1ul << 0)  /**< Ownership bit */\r
+\r
+#define GMAC_RXD_BROADCAST    (1ul << 31) /**< Broadcast detected */\r
+#define GMAC_RXD_MULTIHASH    (1ul << 30) /**< Multicast hash match */\r
+#define GMAC_RXD_UNIHASH      (1ul << 29) /**< Unicast hash match */\r
+#define GMAC_RXD_ADDR_FOUND      (1ul << 27) /**< Specific address match found */\r
+#define GMAC_RXD_ADDR        (3ul << 25) /**< Address match */\r
+#define GMAC_RXD_RXCOEN        (1ul << 24) /**< RXCOEN related function */\r
+#define GMAC_RXD_TYPE         (3ul << 22) /**< Type ID match */\r
+#define GMAC_RXD_VLAN         (1ul << 21) /**< VLAN tag detected */\r
+#define GMAC_RXD_PRIORITY     (1ul << 20) /**< Priority tag detected */\r
+#define GMAC_RXD_PRIORITY_MASK  (3ul << 17) /**< VLAN priority */\r
+#define GMAC_RXD_CFI          (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */\r
+#define GMAC_RXD_EOF          (1ul << 15) /**< End of frame */\r
+#define GMAC_RXD_SOF          (1ul << 14) /**< Start of frame */\r
+#define GMAC_RXD_FCS          (1ul << 13) /**< Frame check sequence */\r
+#define GMAC_RXD_OFFSET_MASK                /**< Receive buffer offset */\r
+#define GMAC_RXD_LEN_MASK       (0xFFF)     /**< Length of frame including FCS (if selected) */\r
+#define GMAC_RXD_LENJUMBO_MASK  (0x3FFF)    /**< Jumbo frame length */\r
+\r
+#define GMAC_TXD_USED         (1ul << 31) /**< Frame is transmitted */\r
+#define GMAC_TXD_WRAP         (1ul << 30) /**< Last descriptor */\r
+#define GMAC_TXD_ERROR        (1ul << 29) /**< Retry limit exceeded, error */\r
+#define GMAC_TXD_UNDERRUN     (1ul << 28) /**< Transmit underrun */\r
+#define GMAC_TXD_EXHAUSTED    (1ul << 27) /**< Buffer exhausted */\r
+#define GMAC_TXD_LATE    (1ul << 26) /**< Late collision,transmit  error  */\r
+#define GMAC_TXD_CHECKSUM_ERROR   (7ul << 20) /**< Checksum error */\r
+#define GMAC_TXD_NOCRC        (1ul << 16) /**< No CRC */\r
+#define GMAC_TXD_LAST         (1ul << 15) /**< Last buffer in frame */\r
+#define GMAC_TXD_LEN_MASK       (0x1FFF)     /**< Length of buffer */\r
+\r
+/** The MAC can support frame lengths up to 1536 bytes */\r
+#define GMAC_FRAME_LENTGH_MAX       1536\r
+\r
+#define GMAC_RX_UNITSIZE            128     /**< Fixed size for RX buffer  */\r
+#define GMAC_TX_UNITSIZE            1518    /**< Size for ETH frame length */\r
+\r
+/** GMAC clock speed */\r
+#define GMAC_MCK_SPEED_240MHZ        (240*1000*1000)\r
+#define GMAC_MCK_SPEED_160MHZ        (160*1000*1000)\r
+#define GMAC_MCK_SPEED_120MHZ        (120*1000*1000)\r
+#define GMAC_MCK_SPEED_80MHZ          (80*1000*1000)\r
+#define GMAC_MCK_SPEED_40MHZ          (40*1000*1000)\r
+#define GMAC_MCK_SPEED_20MHZ          (20*1000*1000)\r
+\r
+/** GMAC maintain code default value*/\r
+#define GMAC_MAN_CODE_VALUE    (10)\r
+\r
+/** GMAC maintain start of frame default value*/\r
+#define GMAC_MAN_SOF_VALUE     (1)\r
+\r
+/** GMAC maintain read/write*/\r
+#define GMAC_MAN_RW_TYPE       (2)\r
+\r
+/** GMAC maintain read only*/\r
+#define GMAC_MAN_READ_ONLY     (1)\r
+\r
+/** GMAC address length */\r
+#define GMAC_ADDR_LENGTH       (6)\r
+\r
+\r
+#define GMAC_DUPLEX_HALF 0\r
+#define GMAC_DUPLEX_FULL 1\r
+\r
+#define GMAC_SPEED_10M      0\r
+#define GMAC_SPEED_100M     1\r
+\r
+/**\r
+ * \brief Return codes for GMAC APIs.\r
+ */\r
+typedef enum {\r
+       GMAC_OK = 0,         /** 0  Operation OK */\r
+       GMAC_TIMEOUT = 1,    /** 1  GMAC operation timeout */\r
+       GMAC_TX_BUSY,        /** 2  TX in progress */\r
+       GMAC_RX_NULL,        /** 3  No data received */\r
+       GMAC_SIZE_TOO_SMALL, /** 4  Buffer size not enough */\r
+       GMAC_PARAM,          /** 5  Parameter error, TX packet invalid or RX size too small */\r
+       GMAC_INVALID = 0xFF, /* Invalid */\r
+} gmac_status_t;\r
+\r
+/**\r
+ * \brief Media Independent Interface (MII) type.\r
+ */\r
+typedef enum {\r
+       GMAC_PHY_MII = 0,         /** MII mode */\r
+       GMAC_PHY_RMII = 1,    /** Reduced MII mode */\r
+       GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/\r
+} gmac_mii_mode_t;\r
+\r
+/** Receive buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_rx_descriptor {\r
+       union gmac_rx_addr {\r
+               uint32_t val;\r
+               struct gmac_rx_addr_bm {\r
+                       uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */\r
+                       b_wrap:1,   /**< Marks last descriptor in receive buffer */\r
+                       addr_dw:30; /**< Address in number of DW */\r
+               } bm;\r
+       } addr; /**< Address, Wrap & Ownership */\r
+       union gmac_rx_status {\r
+               uint32_t val;\r
+               struct gmac_rx_status_bm {\r
+                       uint32_t len:13,       /**  0..12  Length of frame including FCS */\r
+                       b_fcs:1,               /**  13     Receive buffer offset,  bits 13:12 of frame length for jumbo frame */\r
+                       b_sof:1,               /**  14     Start of frame */\r
+                       b_eof:1,               /**  15     End of frame */\r
+                       b_cfi:1,               /**  16     Concatenation Format Indicator */\r
+                       vlan_priority:3,       /**  17..19 VLAN priority (if VLAN detected) */\r
+                       b_priority_detected:1, /**  20     Priority tag detected */\r
+                       b_vlan_detected:1,     /**  21     VLAN tag detected */\r
+                       b_type_id_match:2,     /**  22..23 Type ID match */\r
+                       b_checksumoffload:1,   /**  24     Checksum offload specific function */\r
+                       b_addrmatch:2,         /**  25..26 Address register match */\r
+                       b_ext_addr_match:1,    /**  27     External address match found */\r
+                       reserved:1,            /**  28     */\r
+                       b_uni_hash_match:1,    /**  29     Unicast hash match */\r
+                       b_multi_hash_match:1,  /**  30     Multicast hash match */\r
+                       b_boardcast_detect:1;  /**  31     Global broadcast address detected */\r
+               } bm;\r
+       } status;\r
+} gmac_rx_descriptor_t;\r
+\r
+/** Transmit buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_tx_descriptor {\r
+       uint32_t addr;\r
+       union gmac_tx_status {\r
+               uint32_t val;\r
+               struct gmac_tx_status_bm {\r
+                       uint32_t len:14,     /**  0..13 Length of buffer */\r
+                       reserved:1,          /** 14            */\r
+                       b_last_buffer:1,     /** 15     Last buffer (in the current frame) */\r
+                       b_no_crc:1,          /** 16     No CRC */\r
+                       reserved1:3,         /** 17..19        */\r
+                       b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */\r
+                       reserved2:3,         /** 23..25        */\r
+                       b_lco:1,             /** 26     Late collision, transmit error detected */\r
+                       b_exhausted:1,       /** 27     Buffer exhausted in mid frame */\r
+                       b_underrun:1,        /** 28     Transmit underrun */\r
+                       b_error:1,           /** 29     Retry limit exceeded, error detected */\r
+                       b_wrap:1,            /** 30     Marks last descriptor in TD list */\r
+                       b_used:1;            /** 31     User clear, GMAC sets this to 1 once a frame has been successfully transmitted */\r
+               } bm;\r
+       } status;\r
+} gmac_tx_descriptor_t;\r
+\r
+COMPILER_PACK_RESET()\r
+\r
+/**\r
+ * \brief Input parameters when initializing the gmac module mode.\r
+ */\r
+typedef struct gmac_options {\r
+       /*  Enable/Disable CopyAllFrame */\r
+       uint8_t uc_copy_all_frame;\r
+       /* Enable/Disable NoBroadCast */\r
+       uint8_t uc_no_boardcast;\r
+       /* MAC address */\r
+       uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];\r
+} gmac_options_t;\r
+\r
+/** RX callback */\r
+typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status);\r
+/** Wakeup callback */\r
+typedef void (*gmac_dev_wakeup_cb_t) (void);\r
+\r
+/**\r
+ * GMAC driver structure.\r
+ */\r
+typedef struct gmac_device {\r
+\r
+       /** Pointer to HW register base */\r
+       Gmac *p_hw;\r
+       /**\r
+        * Pointer to allocated TX buffer.\r
+        * Section 3.6 of AMBA 2.0 spec states that burst should not cross\r
+        * 1K Boundaries.\r
+        * Receive buffer manager writes are burst of 2 words => 3 lsb bits\r
+        * of the address shall be set to 0.\r
+        */\r
+       uint8_t *p_tx_buffer;\r
+       /** Pointer to allocated RX buffer */\r
+       uint8_t *p_rx_buffer;\r
+       /** Pointer to Rx TDs (must be 8-byte aligned) */\r
+       gmac_rx_descriptor_t *p_rx_dscr;\r
+       /** Pointer to Tx TDs (must be 8-byte aligned) */\r
+       gmac_tx_descriptor_t *p_tx_dscr;\r
+       /** Optional callback to be invoked once a frame has been received */\r
+       gmac_dev_tx_cb_t func_rx_cb;\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+       /** Optional callback to be invoked once several TDs have been released */\r
+       gmac_dev_wakeup_cb_t func_wakeup_cb;\r
+#endif\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       /** Optional callback list to be invoked once TD has been processed */\r
+       gmac_dev_tx_cb_t *func_tx_cb_list;\r
+#endif\r
+       /** RX TD list size */\r
+       uint32_t ul_rx_list_size;\r
+       /** RX index for current processing TD */\r
+       uint32_t ul_rx_idx;\r
+       /** TX TD list size */\r
+       uint32_t ul_tx_list_size;\r
+       /** Circular buffer head pointer by upper layer (buffer to be sent) */\r
+       int32_t l_tx_head;\r
+       /** Circular buffer tail pointer incremented by handlers (buffer sent) */\r
+       int32_t l_tx_tail;\r
+\r
+       /** Number of free TD before wakeup callback is invoked */\r
+       uint32_t uc_wakeup_threshold;\r
+} gmac_device_t;\r
+\r
+/**\r
+ * \brief Write network control value.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_ncr   Network control value.\r
+ */\r
+static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)\r
+{\r
+       p_gmac->GMAC_NCR = ul_ncr;\r
+}\r
+\r
+/**\r
+ * \brief Get network control value.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+\r
+static inline uint32_t gmac_get_network_control(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NCR;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC receive.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC transmit.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC transmit, else to enable it.\r
+ */\r
+static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC management.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC management, else to enable it.\r
+ */\r
+static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_MPE;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Clear all statistics registers.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_clear_statistics(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Increase all statistics registers.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_increase_statistics(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable statistics registers writing.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the statistics registers writing, else to enable it.\r
+ */\r
+static inline void gmac_enable_statistics_write(Gmac* p_gmac,\r
+               uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief In half-duplex mode, forces collisions on all received frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the back pressure, else to enable it.\r
+ */\r
+static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_BP;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Start transmission.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_start_transmission(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;\r
+}\r
+\r
+/**\r
+ * \brief Halt transmission.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_halt_transmission(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_THALT;\r
+}\r
+\r
+/**\r
+ * \brief Transmit pause frame.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_frame(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;\r
+}\r
+\r
+/**\r
+ * \brief Transmit zero quantum pause frame.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;\r
+}\r
+\r
+/**\r
+ * \brief Read snapshot.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_read_snapshot(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_RDS;\r
+}\r
+\r
+/**\r
+ * \brief Store receivetime stamp to memory.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to normal operation, else to enable the store.\r
+ */\r
+static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   1 to set the reception, 0 to disable.\r
+ */\r
+static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Transmit PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)\r
+{\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;\r
+}\r
+\r
+/**\r
+ * \brief Flush next packet.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_flush_next_packet(Gmac* p_gmac)\r
+{\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_FNP;\r
+}\r
+\r
+/**\r
+ * \brief Set up network configuration register.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+  * \param ul_cfg   Network configuration value.\r
+ */\r
+static inline void gmac_set_configure(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+       p_gmac->GMAC_NCFGR = ul_cfg;\r
+}\r
+\r
+/**\r
+ * \brief Get network configuration.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Network configuration.\r
+ */\r
+static inline uint32_t gmac_get_configure(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NCFGR;\r
+}\r
+\r
+\r
+/* Get and set DMA Configuration Register */\r
+static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+       p_gmac->GMAC_DCFGR = ul_cfg;\r
+}\r
+\r
+static inline uint32_t gmac_get_dma(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_DCFGR;\r
+}\r
+\r
+/**\r
+ * \brief Set speed.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.\r
+ */\r
+static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)\r
+{\r
+       if (uc_speed) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Full-Duplex mode.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the Full-Duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Copy(Receive) All Valid Frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable copying all valid frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable jumbo frames (up to 10240 bytes).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the jumbo frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Disable/Enable broadcast receiving.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   1 to disable the broadcast, else to enable it.\r
+ */\r
+static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable multicast hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the multicast hash, else to enable it.\r
+ */\r
+static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable big frames (over 1518, up to 1536).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable big frames else to enable it.\r
+ */\r
+static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Set MDC clock divider.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_mck   GMAC MCK.\r
+ *\r
+ * \return GMAC_OK if successfully.\r
+ */\r
+static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)\r
+{\r
+       uint32_t ul_clk;\r
+       \r
+       if (ul_mck > GMAC_MCK_SPEED_240MHZ) {\r
+               return GMAC_INVALID;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_96;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_64;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_48;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_32;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_16;\r
+       } else {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_8;\r
+       }\r
+       ;\r
+       p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable retry test.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable pause (when a valid pause frame is received).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable pause frame, else to enable it.\r
+ */\r
+static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Set receive buffer offset to 0 ~ 3.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)\r
+{\r
+       p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;\r
+       p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable receive length field checking.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable receive length field checking, else to enable it.\r
+ */\r
+static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable discarding FCS field of received frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable discarding FCS field of received frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * \brief Enable/Disable frames to be received in half-duplex mode\r
+ * while transmitting.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the received in half-duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable ignore RX FCS.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable ignore RX FCS, else to enable it.\r
+ */\r
+static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Get Network Status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Network status.\r
+ */\r
+static inline uint32_t gmac_get_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NSR;\r
+}\r
+\r
+/**\r
+ * \brief Get MDIO IN pin status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return MDIO IN pin status.\r
+ */\r
+static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)\r
+{\r
+       return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Check if PHY is idle.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  1 if PHY is idle.\r
+ */\r
+static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)\r
+{\r
+       return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Return transmit status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Transmit status.\r
+ */\r
+static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_TSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear transmit status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_status   Transmit status.\r
+ */\r
+static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+       p_gmac->GMAC_TSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Return receive status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_RSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear receive status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_status   Receive status.\r
+ */\r
+static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+       p_gmac->GMAC_RSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Set Rx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_addr   Rx queue address.\r
+ */\r
+static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+       p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Rx Queue Address.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_RBQB;\r
+}\r
+\r
+/**\r
+ * \brief Set Tx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_addr  Tx queue address.\r
+ */\r
+static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+       p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Tx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_TBQB;\r
+}\r
+\r
+/**\r
+ * \brief Enable interrupt(s).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_source   Interrupt source(s) to be enabled.\r
+ */\r
+static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+       p_gmac->GMAC_IER = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Disable interrupt(s).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_source   Interrupt source(s) to be disabled.\r
+ */\r
+static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+       p_gmac->GMAC_IDR = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt status.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_ISR;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt mask.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt mask.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_IMR;\r
+}\r
+\r
+/**\r
+ * \brief Execute PHY maintenance command.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr   PHY address.\r
+ * \param uc_reg_addr   Register address.\r
+ * \param uc_rw   1 to Read, 0 to write.\r
+ * \param us_data   Data to be performed, write only.\r
+ */\r
+static inline void gmac_maintain_phy(Gmac* p_gmac,\r
+               uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,\r
+               uint16_t us_data)\r
+{\r
+       /* Wait until bus idle */\r
+       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+       /* Write maintain register */\r
+       p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)\r
+                       | GMAC_MAN_CLTTO \r
+                       | GMAC_MAN_PHYA(uc_phy_addr)\r
+                       | GMAC_MAN_REGA(uc_reg_addr)\r
+                       | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))\r
+                       | GMAC_MAN_DATA(us_data);\r
+}\r
+\r
+/**\r
+ * \brief Get PHY maintenance data returned.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Get PHY data.\r
+ */\r
+static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)\r
+{\r
+       /* Wait until bus idle */\r
+       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+       /* Return data */\r
+       return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);\r
+}\r
+\r
+/**\r
+ * \brief Set Hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_hash_top   Hash top.\r
+ * \param ul_hash_bottom   Hash bottom.\r
+ */\r
+static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,\r
+               uint32_t ul_hash_bottom)\r
+{\r
+       p_gmac->GMAC_HRB = ul_hash_bottom;\r
+       p_gmac->GMAC_HRT = ul_hash_top;\r
+}\r
+\r
+/**\r
+ * \brief Set 64 bits Hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ull_hash   64 bits hash value.\r
+ */\r
+static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)\r
+{\r
+       p_gmac->GMAC_HRB = (uint32_t) ull_hash;\r
+       p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param p_mac_addr  GMAC address.\r
+ */\r
+static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,\r
+               uint8_t* p_mac_addr)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)\r
+                       | (p_mac_addr[2] << 16)\r
+                       | (p_mac_addr[1] << 8)\r
+                       | (p_mac_addr[0]);\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)\r
+                       | (p_mac_addr[4]);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via 2 dword.\r
+  *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param ul_mac_top  GMAC top address.\r
+ * \param ul_mac_bottom  GMAC bottom address.\r
+ */\r
+static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,\r
+               uint32_t ul_mac_top, uint32_t ul_mac_bottom)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via int64.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param ull_mac  64-bit GMAC address.\r
+ */\r
+static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,\r
+               uint64_t ull_mac)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Select media independent interface mode.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param mode   Media independent interface mode.\r
+ */\r
+static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)\r
+{\r
+       switch (mode) {\r
+               case GMAC_PHY_MII:\r
+               case GMAC_PHY_RMII:\r
+                       p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;\r
+               break;\r
+\r
+               default:\r
+                       p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;\r
+               break;\r
+       }\r
+}\r
+\r
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,\r
+               uint32_t* p_value);\r
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,\r
+               uint8_t uc_address, uint32_t ul_value);\r
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+               gmac_options_t* p_opt);\r
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,\r
+               uint32_t ul_frame_size, uint32_t* p_rcv_size);\r
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,\r
+               uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);\r
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);\r
+void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_tx_cb_t func_rx_cb);\r
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);\r
+void gmac_dev_reset(gmac_device_t* p_gmac_dev);\r
+void gmac_handler(gmac_device_t* p_gmac_dev);\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \page gmac_quickstart Quickstart guide for GMAC driver.\r
+ *\r
+ * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",\r
+ * with step-by-step instructions on how to configure and use the driver in a\r
+ * selection of use cases.\r
+ *\r
+ * The use cases contain several code fragments. The code fragments in the\r
+ * steps for setup can be copied into a custom initialization function, while\r
+ * the steps for usage can be copied into, e.g., the main application function.\r
+ *\r
+ * \section gmac_basic_use_case Basic use case\r
+ * In the basic use case, the GMAC driver are configured for:\r
+ * - PHY component KSZ8051MNL is used\r
+ * - GMAC uses MII mode\r
+ * - The number of receive buffer is 16\r
+ * - The number of transfer buffer is 8\r
+ * - MAC address is set to 00-04-25-1c-a0-02\r
+ * - IP address is set to 192.168.0.2\r
+ * - IP address is set to 192.168.0.2\r
+ * - Gateway is set to 192.168.0.1\r
+ * - Network mask is 255.255.255.0\r
+ * - PHY operation max retry count is 1000000\r
+ * - GMAC is configured to not support copy all frame and support broadcast\r
+ * - The data will be read from the ethernet\r
+ *\r
+ * \section gmac_basic_use_case_setup Setup steps\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_prereq Prerequisites\r
+ * -# \ref sysclk_group "System Clock Management (sysclock)"\r
+ * -# \ref pmc_group "Power Management Controller (pmc)"\r
+ * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_code Example code\r
+ * Content of conf_eth.h\r
+ * \code\r
+ * #define GMAC_RX_BUFFERS                               16\r
+ * #define GMAC_TX_BUFFERS                               8\r
+ * #define MAC_PHY_RETRY_MAX                             1000000\r
+ * #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ * #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ * #define ETHERNET_CONF_ETHADDR1                        0x04\r
+ * #define ETHERNET_CONF_ETHADDR2                        0x25\r
+ * #define ETHERNET_CONF_ETHADDR3                        0x1C\r
+ * #define ETHERNET_CONF_ETHADDR4                        0xA0\r
+ * #define ETHERNET_CONF_ETHADDR5                        0x02\r
+ * #define ETHERNET_CONF_IPADDR0                         192\r
+ * #define ETHERNET_CONF_IPADDR1                         168\r
+ * #define ETHERNET_CONF_IPADDR2                         0\r
+ * #define ETHERNET_CONF_IPADDR3                         2\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR0                   192\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR1                   168\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR2                   0\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR3                   1\r
+ * #define ETHERNET_CONF_NET_MASK0                       255\r
+ * #define ETHERNET_CONF_NET_MASK1                       255\r
+ * #define ETHERNET_CONF_NET_MASK2                       255\r
+ * #define ETHERNET_CONF_NET_MASK3                       0\r
+ * #define ETH_PHY_MODE                                  ETH_PHY_MODE\r
+ * \endcode\r
+ *\r
+ * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined\r
+ * to trace the actual size of the data received.\r
+ * \code\r
+ * static gmac_device_t gs_gmac_dev;\r
+ * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];\r
+ *\r
+ * uint32_t ul_frm_size;\r
+ * \endcode\r
+ *\r
+ * Add to application C-file:\r
+ * \code\r
+ *   void gmac_init(void)\r
+ *   {\r
+ *       sysclk_init();\r
+ *\r
+ *       board_init();\r
+ *\r
+ *       pmc_enable_periph_clk(ID_GMAC);\r
+ *\r
+ *       gmac_option.uc_copy_all_frame = 0;\r
+ *       gmac_option.uc_no_boardcast = 0;\r
+ *       memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ *       gs_gmac_dev.p_hw = GMAC;\r
+ *\r
+ *       gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ *\r
+ *       NVIC_EnableIRQ(GMAC_IRQn);\r
+ *\r
+ *       ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ * \r
+ *       ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ *\r
+ *       ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_flow Workflow\r
+ * - Ensure that conf_eth.h is present and contains the\r
+ * following configuration symbol. This configuration file is used\r
+ * by the driver and should not be included by the application.\r
+ * -# Define the receiving buffer size used in the internal GMAC driver.\r
+ * The buffer size used for RX is GMAC_RX_BUFFERS * 128.\r
+ * If it was supposed receiving a large number of frame, the\r
+ * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept\r
+ * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least \r
+ * (2048/128)=16, and as there are additional frames coming, a preferred\r
+ * number is 24 depending on a normal Ethernet throughput.\r
+ *   - \code\r
+ *        #define GMAC_RX_BUFFERS                               16\r
+ *   \endcode\r
+ * -# Define the transmitting buffer size used in the internal GMAC driver.\r
+ * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.\r
+ *   - \code\r
+ *        #define GMAC_TX_BUFFERS                               8\r
+ *   \endcode\r
+ * -# Define maximum retry time for a PHY read/write operation.\r
+ *   - \code\r
+ *        #define MAC_PHY_RETRY_MAX                             1000000\r
+ *   \endcode\r
+ * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved\r
+ * for ATMEL, application should always change this address to its' own.\r
+ *   - \code\r
+ *        #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ *        #define ETHERNET_CONF_ETHADDR1                        0x04\r
+ *        #define ETHERNET_CONF_ETHADDR2                        0x25\r
+ *        #define ETHERNET_CONF_ETHADDR3                        0x1C\r
+ *        #define ETHERNET_CONF_ETHADDR4                        0xA0\r
+ *        #define ETHERNET_CONF_ETHADDR5                        0x02\r
+ *   \endcode\r
+ * -# Define the IP address configration used in the application. When DHCP\r
+ *  is enabled, this configuration is not effected.\r
+ *   - \code\r
+ *        #define ETHERNET_CONF_IPADDR0                         192\r
+ *        #define ETHERNET_CONF_IPADDR1                         168\r
+ *        #define ETHERNET_CONF_IPADDR2                         0\r
+ *        #define ETHERNET_CONF_IPADDR3                         2\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR0                   192\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR1                   168\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR2                   0\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR3                   1\r
+ *        #define ETHERNET_CONF_NET_MASK0                       255\r
+ *        #define ETHERNET_CONF_NET_MASK1                       255\r
+ *        #define ETHERNET_CONF_NET_MASK2                       255\r
+ *        #define ETHERNET_CONF_NET_MASK3                       0\r
+ *   \endcode\r
+ * -# Configure the PHY maintainance interface.\r
+ *   - \code\r
+ *        #define ETH_PHY_MODE                                  GMAC_PHY_MII\r
+ *   \endcode\r
+ * -# Enable the system clock:\r
+ *   - \code sysclk_init(); \endcode\r
+ * -# Enable PIO configurations for GMAC:\r
+ *   - \code board_init(); \endcode\r
+ * -# Enable PMC clock for GMAC:\r
+ *   - \code pmc_enable_periph_clk(ID_GMAC); \endcode\r
+ * -# Set the GMAC options; it's set to copy all frame and support broadcast:\r
+ *   - \code\r
+ *         gmac_option.uc_copy_all_frame = 0;\r
+ *         gmac_option.uc_no_boardcast = 0;\r
+ *         memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ *         gs_gmac_dev.p_hw = GMAC;\r
+ * \endcode\r
+ * -# Initialize GMAC device with the filled option:\r
+ *   - \code\r
+ *         gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ * \endcode\r
+ * -# Enable the interrupt service for GMAC:\r
+ *   - \code\r
+ *         NVIC_EnableIRQ(GMAC_IRQn);\r
+ * \endcode\r
+ * -# Initialize the PHY component:\r
+ *   - \code\r
+ *         ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ * \endcode\r
+  * -# The link will be established based on auto negotiation.\r
+ *   - \code\r
+ *         ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ * \endcode\r
+ * -# Establish the ethernet link; the network can be worked from now on:\r
+ *   - \code\r
+ *         ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \section gmac_basic_use_case_usage Usage steps\r
+ * \subsection gmac_basic_use_case_usage_code Example code\r
+ * Add to, e.g., main loop in application C-file:\r
+ * \code\r
+ *    gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_usage_flow Workflow\r
+ * -# Start reading the data from the ethernet:\r
+ *   - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode\r
+ */\r
+\r
+#      define GMAC_STATS 0\r
+\r
+#if( GMAC_STATS != 0 )\r
+\r
+       /* Here below some code to study the types and\r
+       frequencies of  GMAC interrupts. */\r
+       #define GMAC_IDX_RXUBR 0\r
+       #define GMAC_IDX_TUR   1\r
+       #define GMAC_IDX_RLEX  2\r
+       #define GMAC_IDX_TFC   3\r
+       #define GMAC_IDX_RCOMP 4\r
+       #define GMAC_IDX_TCOMP 5\r
+       #define GMAC_IDX_ROVR  6\r
+       #define GMAC_IDX_HRESP 7\r
+       #define GMAC_IDX_PFNZ  8\r
+       #define GMAC_IDX_PTZ   9\r
+\r
+       struct SGmacStats {\r
+               unsigned recvCount;\r
+               unsigned rovrCount;\r
+               unsigned bnaCount;\r
+               unsigned sendCount;\r
+               unsigned sovrCount;\r
+               unsigned incompCount;\r
+               unsigned truncCount;\r
+\r
+               unsigned intStatus[10];\r
+       };\r
+       extern struct SGmacStats gmacStats;\r
+\r
+       struct SIntPair {\r
+               const char *name;\r
+               unsigned mask;\r
+               int index;\r
+       };\r
+\r
+       #define MK_PAIR( NAME )   #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME\r
+       static const struct SIntPair intPairs[] = {\r
+               { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */\r
+               { MK_PAIR( TUR   ) }, /* Enable transmit underrun interrupt. */\r
+               { MK_PAIR( RLEX  ) }, /* Enable retry limit  exceeded interrupt. */\r
+               { MK_PAIR( TFC   ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */\r
+               { MK_PAIR( RCOMP ) }, /* Receive complete */\r
+               { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */\r
+               { MK_PAIR( ROVR  ) }, /* Enable receive overrun interrupt. */\r
+               { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */\r
+               { MK_PAIR( PFNZ  ) }, /* Enable pause frame received interrupt. */\r
+               { MK_PAIR( PTZ   ) }  /* Enable pause time zero interrupt. */\r
+       };\r
+\r
+       void gmac_show_irq_counts ();\r
+\r
+#endif\r
+\r
+#endif /* GMAC_H_INCLUDED */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/instance/gmac.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ATSAM4E/instance/gmac.h
new file mode 100644 (file)
index 0000000..24d806d
--- /dev/null
@@ -0,0 +1,1349 @@
+ /**\r
+ * \file\r
+ *\r
+ * \brief GMAC (Ethernet MAC) driver for SAM.\r
+ *\r
+ * Copyright (c) 2013 Atmel Corporation. All rights reserved.\r
+ *\r
+ * \asf_license_start\r
+ *\r
+ * \page License\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ *    this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ *    this list of conditions and the following disclaimer in the documentation\r
+ *    and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of Atmel may not be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * 4. This software may only be redistributed and used in connection with an\r
+ *    Atmel microcontroller product.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * \asf_license_stop\r
+ *\r
+ */\r
+\r
+#ifndef GMAC_H_INCLUDED\r
+#define GMAC_H_INCLUDED\r
+\r
+#include "compiler.h"\r
+#include "component/gmac.h"\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/** The buffer addresses written into the descriptors must be aligned, so the\r
+    last few bits are zero.  These bits have special meaning for the GMAC\r
+    peripheral and cannot be used as part of the address. */\r
+#define GMAC_RXD_ADDR_MASK      0xFFFFFFFC\r
+#define GMAC_RXD_WRAP         (1ul << 1)  /**< Wrap bit */\r
+#define GMAC_RXD_OWNERSHIP    (1ul << 0)  /**< Ownership bit */\r
+\r
+#define GMAC_RXD_BROADCAST    (1ul << 31) /**< Broadcast detected */\r
+#define GMAC_RXD_MULTIHASH    (1ul << 30) /**< Multicast hash match */\r
+#define GMAC_RXD_UNIHASH      (1ul << 29) /**< Unicast hash match */\r
+#define GMAC_RXD_ADDR_FOUND      (1ul << 27) /**< Specific address match found */\r
+#define GMAC_RXD_ADDR        (3ul << 25) /**< Address match */\r
+#define GMAC_RXD_RXCOEN        (1ul << 24) /**< RXCOEN related function */\r
+#define GMAC_RXD_TYPE         (3ul << 22) /**< Type ID match */\r
+#define GMAC_RXD_VLAN         (1ul << 21) /**< VLAN tag detected */\r
+#define GMAC_RXD_PRIORITY     (1ul << 20) /**< Priority tag detected */\r
+#define GMAC_RXD_PRIORITY_MASK  (3ul << 17) /**< VLAN priority */\r
+#define GMAC_RXD_CFI          (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */\r
+#define GMAC_RXD_EOF          (1ul << 15) /**< End of frame */\r
+#define GMAC_RXD_SOF          (1ul << 14) /**< Start of frame */\r
+#define GMAC_RXD_FCS          (1ul << 13) /**< Frame check sequence */\r
+#define GMAC_RXD_OFFSET_MASK                /**< Receive buffer offset */\r
+#define GMAC_RXD_LEN_MASK       (0xFFF)     /**< Length of frame including FCS (if selected) */\r
+#define GMAC_RXD_LENJUMBO_MASK  (0x3FFF)    /**< Jumbo frame length */\r
+\r
+#define GMAC_TXD_USED         (1ul << 31) /**< Frame is transmitted */\r
+#define GMAC_TXD_WRAP         (1ul << 30) /**< Last descriptor */\r
+#define GMAC_TXD_ERROR        (1ul << 29) /**< Retry limit exceeded, error */\r
+#define GMAC_TXD_UNDERRUN     (1ul << 28) /**< Transmit underrun */\r
+#define GMAC_TXD_EXHAUSTED    (1ul << 27) /**< Buffer exhausted */\r
+#define GMAC_TXD_LATE    (1ul << 26) /**< Late collision,transmit  error  */\r
+#define GMAC_TXD_CHECKSUM_ERROR   (7ul << 20) /**< Checksum error */\r
+#define GMAC_TXD_NOCRC        (1ul << 16) /**< No CRC */\r
+#define GMAC_TXD_LAST         (1ul << 15) /**< Last buffer in frame */\r
+#define GMAC_TXD_LEN_MASK       (0x1FFF)     /**< Length of buffer */\r
+\r
+/** The MAC can support frame lengths up to 1536 bytes */\r
+#define GMAC_FRAME_LENTGH_MAX       1536\r
+\r
+#define GMAC_RX_UNITSIZE            128     /**< Fixed size for RX buffer  */\r
+#define GMAC_TX_UNITSIZE            1518    /**< Size for ETH frame length */\r
+\r
+/** GMAC clock speed */\r
+#define GMAC_MCK_SPEED_240MHZ        (240*1000*1000)\r
+#define GMAC_MCK_SPEED_160MHZ        (160*1000*1000)\r
+#define GMAC_MCK_SPEED_120MHZ        (120*1000*1000)\r
+#define GMAC_MCK_SPEED_80MHZ          (80*1000*1000)\r
+#define GMAC_MCK_SPEED_40MHZ          (40*1000*1000)\r
+#define GMAC_MCK_SPEED_20MHZ          (20*1000*1000)\r
+\r
+/** GMAC maintain code default value*/\r
+#define GMAC_MAN_CODE_VALUE    (10)\r
+\r
+/** GMAC maintain start of frame default value*/\r
+#define GMAC_MAN_SOF_VALUE     (1)\r
+\r
+/** GMAC maintain read/write*/\r
+#define GMAC_MAN_RW_TYPE       (2)\r
+\r
+/** GMAC maintain read only*/\r
+#define GMAC_MAN_READ_ONLY     (1)\r
+\r
+/** GMAC address length */\r
+#define GMAC_ADDR_LENGTH       (6)\r
+\r
+\r
+#define GMAC_DUPLEX_HALF 0\r
+#define GMAC_DUPLEX_FULL 1\r
+\r
+#define GMAC_SPEED_10M      0\r
+#define GMAC_SPEED_100M     1\r
+\r
+/**\r
+ * \brief Return codes for GMAC APIs.\r
+ */\r
+typedef enum {\r
+       GMAC_OK = 0,         /** 0  Operation OK */\r
+       GMAC_TIMEOUT = 1,    /** 1  GMAC operation timeout */\r
+       GMAC_TX_BUSY,        /** 2  TX in progress */\r
+       GMAC_RX_NULL,        /** 3  No data received */\r
+       GMAC_SIZE_TOO_SMALL, /** 4  Buffer size not enough */\r
+       GMAC_PARAM,          /** 5  Parameter error, TX packet invalid or RX size too small */\r
+       GMAC_INVALID = 0xFF, /* Invalid */\r
+} gmac_status_t;\r
+\r
+/**\r
+ * \brief Media Independent Interface (MII) type.\r
+ */\r
+typedef enum {\r
+       GMAC_PHY_MII = 0,         /** MII mode */\r
+       GMAC_PHY_RMII = 1,    /** Reduced MII mode */\r
+       GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/\r
+} gmac_mii_mode_t;\r
+\r
+/** Receive buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_rx_descriptor {\r
+       union gmac_rx_addr {\r
+               uint32_t val;\r
+               struct gmac_rx_addr_bm {\r
+                       uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */\r
+                       b_wrap:1,   /**< Marks last descriptor in receive buffer */\r
+                       addr_dw:30; /**< Address in number of DW */\r
+               } bm;\r
+       } addr; /**< Address, Wrap & Ownership */\r
+       union gmac_rx_status {\r
+               uint32_t val;\r
+               struct gmac_rx_status_bm {\r
+                       uint32_t len:13,       /**  0..12  Length of frame including FCS */\r
+                       b_fcs:1,               /**  13     Receive buffer offset,  bits 13:12 of frame length for jumbo frame */\r
+                       b_sof:1,               /**  14     Start of frame */\r
+                       b_eof:1,               /**  15     End of frame */\r
+                       b_cfi:1,               /**  16     Concatenation Format Indicator */\r
+                       vlan_priority:3,       /**  17..19 VLAN priority (if VLAN detected) */\r
+                       b_priority_detected:1, /**  20     Priority tag detected */\r
+                       b_vlan_detected:1,     /**  21     VLAN tag detected */\r
+                       b_type_id_match:2,     /**  22..23 Type ID match */\r
+                       b_checksumoffload:1,   /**  24     Checksum offload specific function */\r
+                       b_addrmatch:2,         /**  25..26 Address register match */\r
+                       b_ext_addr_match:1,    /**  27     External address match found */\r
+                       reserved:1,            /**  28     */\r
+                       b_uni_hash_match:1,    /**  29     Unicast hash match */\r
+                       b_multi_hash_match:1,  /**  30     Multicast hash match */\r
+                       b_boardcast_detect:1;  /**  31     Global broadcast address detected */\r
+               } bm;\r
+       } status;\r
+} gmac_rx_descriptor_t;\r
+\r
+/** Transmit buffer descriptor struct */\r
+COMPILER_PACK_SET(8)\r
+typedef struct gmac_tx_descriptor {\r
+       uint32_t addr;\r
+       union gmac_tx_status {\r
+               uint32_t val;\r
+               struct gmac_tx_status_bm {\r
+                       uint32_t len:14,     /**  0..13 Length of buffer */\r
+                       reserved:1,          /** 14            */\r
+                       b_last_buffer:1,     /** 15     Last buffer (in the current frame) */\r
+                       b_no_crc:1,          /** 16     No CRC */\r
+                       reserved1:3,         /** 17..19        */\r
+                       b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */\r
+                       reserved2:3,         /** 23..25        */\r
+                       b_lco:1,             /** 26     Late collision, transmit error detected */\r
+                       b_exhausted:1,       /** 27     Buffer exhausted in mid frame */\r
+                       b_underrun:1,        /** 28     Transmit underrun */\r
+                       b_error:1,           /** 29     Retry limit exceeded, error detected */\r
+                       b_wrap:1,            /** 30     Marks last descriptor in TD list */\r
+                       b_used:1;            /** 31     User clear, GMAC sets this to 1 once a frame has been successfully transmitted */\r
+               } bm;\r
+       } status;\r
+} gmac_tx_descriptor_t;\r
+\r
+COMPILER_PACK_RESET()\r
+\r
+/**\r
+ * \brief Input parameters when initializing the gmac module mode.\r
+ */\r
+typedef struct gmac_options {\r
+       /*  Enable/Disable CopyAllFrame */\r
+       uint8_t uc_copy_all_frame;\r
+       /* Enable/Disable NoBroadCast */\r
+       uint8_t uc_no_boardcast;\r
+       /* MAC address */\r
+       uint8_t uc_mac_addr[GMAC_ADDR_LENGTH];\r
+} gmac_options_t;\r
+\r
+/** TX callback */\r
+typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status, uint8_t *puc_buffer);\r
+/** RX callback */\r
+typedef void (*gmac_dev_rx_cb_t) (uint32_t ul_status);\r
+/** Wakeup callback */\r
+typedef void (*gmac_dev_wakeup_cb_t) (void);\r
+\r
+/**\r
+ * GMAC driver structure.\r
+ */\r
+typedef struct gmac_device {\r
+\r
+       /** Pointer to HW register base */\r
+       Gmac *p_hw;\r
+       /**\r
+        * Pointer to allocated TX buffer.\r
+        * Section 3.6 of AMBA 2.0 spec states that burst should not cross\r
+        * 1K Boundaries.\r
+        * Receive buffer manager writes are burst of 2 words => 3 lsb bits\r
+        * of the address shall be set to 0.\r
+        */\r
+       uint8_t *p_tx_buffer;\r
+       /** Pointer to allocated RX buffer */\r
+       uint8_t *p_rx_buffer;\r
+       /** Pointer to Rx TDs (must be 8-byte aligned) */\r
+       gmac_rx_descriptor_t *p_rx_dscr;\r
+       /** Pointer to Tx TDs (must be 8-byte aligned) */\r
+       gmac_tx_descriptor_t *p_tx_dscr;\r
+       /** Optional callback to be invoked once a frame has been received */\r
+       gmac_dev_rx_cb_t func_rx_cb;\r
+#if( GMAC_USES_WAKEUP_CALLBACK )\r
+       /** Optional callback to be invoked once several TDs have been released */\r
+       gmac_dev_wakeup_cb_t func_wakeup_cb;\r
+#endif\r
+#if( GMAC_USES_TX_CALLBACK != 0 )\r
+       /** Optional callback list to be invoked once TD has been processed */\r
+       gmac_dev_tx_cb_t *func_tx_cb_list;\r
+#endif\r
+       /** RX TD list size */\r
+       uint32_t ul_rx_list_size;\r
+       /** RX index for current processing TD */\r
+       uint32_t ul_rx_idx;\r
+       /** TX TD list size */\r
+       uint32_t ul_tx_list_size;\r
+       /** Circular buffer head pointer by upper layer (buffer to be sent) */\r
+       int32_t l_tx_head;\r
+       /** Circular buffer tail pointer incremented by handlers (buffer sent) */\r
+       int32_t l_tx_tail;\r
+\r
+       /** Number of free TD before wakeup callback is invoked */\r
+       uint32_t uc_wakeup_threshold;\r
+} gmac_device_t;\r
+\r
+/**\r
+ * \brief Write network control value.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_ncr   Network control value.\r
+ */\r
+static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr)\r
+{\r
+       p_gmac->GMAC_NCR = ul_ncr;\r
+}\r
+\r
+/**\r
+ * \brief Get network control value.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+\r
+static inline uint32_t gmac_get_network_control(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NCR;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC receive.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_RXEN;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC transmit.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC transmit, else to enable it.\r
+ */\r
+static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_TXEN;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable GMAC management.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable GMAC management, else to enable it.\r
+ */\r
+static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_MPE;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Clear all statistics registers.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_clear_statistics(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Increase all statistics registers.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_increase_statistics(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable statistics registers writing.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the statistics registers writing, else to enable it.\r
+ */\r
+static inline void gmac_enable_statistics_write(Gmac* p_gmac,\r
+               uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief In half-duplex mode, forces collisions on all received frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the back pressure, else to enable it.\r
+ */\r
+static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_BP;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_BP;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Start transmission.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_start_transmission(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TSTART;\r
+}\r
+\r
+/**\r
+ * \brief Halt transmission.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_halt_transmission(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_THALT;\r
+}\r
+\r
+/**\r
+ * \brief Transmit pause frame.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_frame(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TXPF;\r
+}\r
+\r
+/**\r
+ * \brief Transmit zero quantum pause frame.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF;\r
+}\r
+\r
+/**\r
+ * \brief Read snapshot.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_read_snapshot(Gmac* p_gmac)\r
+{\r
+       p_gmac->GMAC_NCR |= GMAC_NCR_RDS;\r
+}\r
+\r
+/**\r
+ * \brief Store receivetime stamp to memory.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to normal operation, else to enable the store.\r
+ */\r
+static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   1 to set the reception, 0 to disable.\r
+ */\r
+static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR;\r
+       } else {\r
+               p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Transmit PFC priority-based pause reception.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac)\r
+{\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF;\r
+}\r
+\r
+/**\r
+ * \brief Flush next packet.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_flush_next_packet(Gmac* p_gmac)\r
+{\r
+               p_gmac->GMAC_NCR |= GMAC_NCR_FNP;\r
+}\r
+\r
+/**\r
+ * \brief Set up network configuration register.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+  * \param ul_cfg   Network configuration value.\r
+ */\r
+static inline void gmac_set_configure(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+       p_gmac->GMAC_NCFGR = ul_cfg;\r
+}\r
+\r
+/**\r
+ * \brief Get network configuration.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Network configuration.\r
+ */\r
+static inline uint32_t gmac_get_configure(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NCFGR;\r
+}\r
+\r
+\r
+/* Get and set DMA Configuration Register */\r
+static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg)\r
+{\r
+       p_gmac->GMAC_DCFGR = ul_cfg;\r
+}\r
+\r
+static inline uint32_t gmac_get_dma(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_DCFGR;\r
+}\r
+\r
+/**\r
+ * \brief Set speed.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.\r
+ */\r
+static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed)\r
+{\r
+       if (uc_speed) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Full-Duplex mode.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the Full-Duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable Copy(Receive) All Valid Frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable copying all valid frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable jumbo frames (up to 10240 bytes).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the jumbo frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Disable/Enable broadcast receiving.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   1 to disable the broadcast, else to enable it.\r
+ */\r
+static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable multicast hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the multicast hash, else to enable it.\r
+ */\r
+static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable big frames (over 1518, up to 1536).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable big frames else to enable it.\r
+ */\r
+static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Set MDC clock divider.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_mck   GMAC MCK.\r
+ *\r
+ * \return GMAC_OK if successfully.\r
+ */\r
+static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck)\r
+{\r
+       uint32_t ul_clk;\r
+\r
+       if (ul_mck > GMAC_MCK_SPEED_240MHZ) {\r
+               return GMAC_INVALID;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_96;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_64;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_48;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_32;\r
+       } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_16;\r
+       } else {\r
+               ul_clk = GMAC_NCFGR_CLK_MCK_8;\r
+       }\r
+       ;\r
+       p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk;\r
+       return GMAC_OK;\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable retry test.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the GMAC receiver, else to enable it.\r
+ */\r
+static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable pause (when a valid pause frame is received).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable pause frame, else to enable it.\r
+ */\r
+static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Set receive buffer offset to 0 ~ 3.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset)\r
+{\r
+       p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk;\r
+       p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset);\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable receive length field checking.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable receive length field checking, else to enable it.\r
+ */\r
+static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable discarding FCS field of received frames.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable discarding FCS field of received frames, else to enable it.\r
+ */\r
+static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS;\r
+       }\r
+}\r
+\r
+\r
+/**\r
+ * \brief Enable/Disable frames to be received in half-duplex mode\r
+ * while transmitting.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable the received in half-duplex mode, else to enable it.\r
+ */\r
+static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Enable/Disable ignore RX FCS.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_enable   0 to disable ignore RX FCS, else to enable it.\r
+ */\r
+static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable)\r
+{\r
+       if (uc_enable) {\r
+               p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS;\r
+       } else {\r
+               p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS;\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Get Network Status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Network status.\r
+ */\r
+static inline uint32_t gmac_get_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_NSR;\r
+}\r
+\r
+/**\r
+ * \brief Get MDIO IN pin status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return MDIO IN pin status.\r
+ */\r
+static inline uint8_t gmac_get_MDIO(Gmac* p_gmac)\r
+{\r
+       return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Check if PHY is idle.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  1 if PHY is idle.\r
+ */\r
+static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac)\r
+{\r
+       return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0);\r
+}\r
+\r
+/**\r
+ * \brief Return transmit status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Transmit status.\r
+ */\r
+static inline uint32_t gmac_get_tx_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_TSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear transmit status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_status   Transmit status.\r
+ */\r
+static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+       p_gmac->GMAC_TSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Return receive status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ */\r
+static inline uint32_t gmac_get_rx_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_RSR;\r
+}\r
+\r
+/**\r
+ * \brief Clear receive status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_status   Receive status.\r
+ */\r
+static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status)\r
+{\r
+       p_gmac->GMAC_RSR = ul_status;\r
+}\r
+\r
+/**\r
+ * \brief Set Rx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_addr   Rx queue address.\r
+ */\r
+static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+       p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Rx Queue Address.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_RBQB;\r
+}\r
+\r
+/**\r
+ * \brief Set Tx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_addr  Tx queue address.\r
+ */\r
+static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr)\r
+{\r
+       p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr;\r
+}\r
+\r
+/**\r
+ * \brief Get Tx Queue.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return  Rx queue address.\r
+ */\r
+static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_TBQB;\r
+}\r
+\r
+/**\r
+ * \brief Enable interrupt(s).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_source   Interrupt source(s) to be enabled.\r
+ */\r
+static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+       p_gmac->GMAC_IER = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Disable interrupt(s).\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_source   Interrupt source(s) to be disabled.\r
+ */\r
+static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source)\r
+{\r
+       p_gmac->GMAC_IDR = ul_source;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt status.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt status.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_ISR;\r
+}\r
+\r
+/**\r
+ * \brief Return interrupt mask.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Interrupt mask.\r
+ */\r
+static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac)\r
+{\r
+       return p_gmac->GMAC_IMR;\r
+}\r
+\r
+/**\r
+ * \brief Execute PHY maintenance command.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_phy_addr   PHY address.\r
+ * \param uc_reg_addr   Register address.\r
+ * \param uc_rw   1 to Read, 0 to write.\r
+ * \param us_data   Data to be performed, write only.\r
+ */\r
+static inline void gmac_maintain_phy(Gmac* p_gmac,\r
+               uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,\r
+               uint16_t us_data)\r
+{\r
+       /* Wait until bus idle */\r
+       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+       /* Write maintain register */\r
+       p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE)\r
+                       | GMAC_MAN_CLTTO\r
+                       | GMAC_MAN_PHYA(uc_phy_addr)\r
+                       | GMAC_MAN_REGA(uc_reg_addr)\r
+                       | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY))\r
+                       | GMAC_MAN_DATA(us_data);\r
+}\r
+\r
+/**\r
+ * \brief Get PHY maintenance data returned.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ *\r
+ * \return Get PHY data.\r
+ */\r
+static inline uint16_t gmac_get_phy_data(Gmac* p_gmac)\r
+{\r
+       /* Wait until bus idle */\r
+       while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0);\r
+       /* Return data */\r
+       return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk);\r
+}\r
+\r
+/**\r
+ * \brief Set Hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ul_hash_top   Hash top.\r
+ * \param ul_hash_bottom   Hash bottom.\r
+ */\r
+static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top,\r
+               uint32_t ul_hash_bottom)\r
+{\r
+       p_gmac->GMAC_HRB = ul_hash_bottom;\r
+       p_gmac->GMAC_HRT = ul_hash_top;\r
+}\r
+\r
+/**\r
+ * \brief Set 64 bits Hash.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param ull_hash   64 bits hash value.\r
+ */\r
+static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash)\r
+{\r
+       p_gmac->GMAC_HRB = (uint32_t) ull_hash;\r
+       p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param p_mac_addr  GMAC address.\r
+ */\r
+static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index,\r
+               uint8_t* p_mac_addr)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24)\r
+                       | (p_mac_addr[2] << 16)\r
+                       | (p_mac_addr[1] << 8)\r
+                       | (p_mac_addr[0]);\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8)\r
+                       | (p_mac_addr[4]);\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via 2 dword.\r
+  *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param ul_mac_top  GMAC top address.\r
+ * \param ul_mac_bottom  GMAC bottom address.\r
+ */\r
+static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index,\r
+               uint32_t ul_mac_top, uint32_t ul_mac_bottom)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom;\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top;\r
+}\r
+\r
+/**\r
+ * \brief Set MAC Address via int64.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param uc_index  GMAC specific address register index.\r
+ * \param ull_mac  64-bit GMAC address.\r
+ */\r
+static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index,\r
+               uint64_t ull_mac)\r
+{\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac;\r
+       p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32);\r
+}\r
+\r
+/**\r
+ * \brief Select media independent interface mode.\r
+ *\r
+ * \param p_gmac   Pointer to the GMAC instance.\r
+ * \param mode   Media independent interface mode.\r
+ */\r
+static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode)\r
+{\r
+       switch (mode) {\r
+               case GMAC_PHY_MII:\r
+               case GMAC_PHY_RMII:\r
+                       p_gmac->GMAC_UR |= GMAC_UR_RMIIMII;\r
+               break;\r
+\r
+               default:\r
+                       p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII;\r
+               break;\r
+       }\r
+}\r
+\r
+uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address,\r
+               uint32_t* p_value);\r
+uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address,\r
+               uint8_t uc_address, uint32_t ul_value);\r
+void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev,\r
+               gmac_options_t* p_opt);\r
+uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame,\r
+               uint32_t ul_frame_size, uint32_t* p_rcv_size);\r
+uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer,\r
+               uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb);\r
+uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev);\r
+void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_rx_cb_t func_rx_cb);\r
+uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev,\r
+               gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);\r
+void gmac_dev_reset(gmac_device_t* p_gmac_dev);\r
+void gmac_handler(gmac_device_t* p_gmac_dev);\r
+\r
+/// @cond 0\r
+/**INDENT-OFF**/\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+/**INDENT-ON**/\r
+/// @endcond\r
+\r
+/**\r
+ * \page gmac_quickstart Quickstart guide for GMAC driver.\r
+ *\r
+ * This is the quickstart guide for the \ref gmac_group "Ethernet MAC",\r
+ * with step-by-step instructions on how to configure and use the driver in a\r
+ * selection of use cases.\r
+ *\r
+ * The use cases contain several code fragments. The code fragments in the\r
+ * steps for setup can be copied into a custom initialization function, while\r
+ * the steps for usage can be copied into, e.g., the main application function.\r
+ *\r
+ * \section gmac_basic_use_case Basic use case\r
+ * In the basic use case, the GMAC driver are configured for:\r
+ * - PHY component KSZ8051MNL is used\r
+ * - GMAC uses MII mode\r
+ * - The number of receive buffer is 16\r
+ * - The number of transfer buffer is 8\r
+ * - MAC address is set to 00-04-25-1c-a0-02\r
+ * - IP address is set to 192.168.0.2\r
+ * - IP address is set to 192.168.0.2\r
+ * - Gateway is set to 192.168.0.1\r
+ * - Network mask is 255.255.255.0\r
+ * - PHY operation max retry count is 1000000\r
+ * - GMAC is configured to not support copy all frame and support broadcast\r
+ * - The data will be read from the ethernet\r
+ *\r
+ * \section gmac_basic_use_case_setup Setup steps\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_prereq Prerequisites\r
+ * -# \ref sysclk_group "System Clock Management (sysclock)"\r
+ * -# \ref pmc_group "Power Management Controller (pmc)"\r
+ * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)"\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_code Example code\r
+ * Content of conf_eth.h\r
+ * \code\r
+ * #define GMAC_RX_BUFFERS                               16\r
+ * #define GMAC_TX_BUFFERS                               8\r
+ * #define MAC_PHY_RETRY_MAX                             1000000\r
+ * #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ * #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ * #define ETHERNET_CONF_ETHADDR1                        0x04\r
+ * #define ETHERNET_CONF_ETHADDR2                        0x25\r
+ * #define ETHERNET_CONF_ETHADDR3                        0x1C\r
+ * #define ETHERNET_CONF_ETHADDR4                        0xA0\r
+ * #define ETHERNET_CONF_ETHADDR5                        0x02\r
+ * #define ETHERNET_CONF_IPADDR0                         192\r
+ * #define ETHERNET_CONF_IPADDR1                         168\r
+ * #define ETHERNET_CONF_IPADDR2                         0\r
+ * #define ETHERNET_CONF_IPADDR3                         2\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR0                   192\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR1                   168\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR2                   0\r
+ * #define ETHERNET_CONF_GATEWAY_ADDR3                   1\r
+ * #define ETHERNET_CONF_NET_MASK0                       255\r
+ * #define ETHERNET_CONF_NET_MASK1                       255\r
+ * #define ETHERNET_CONF_NET_MASK2                       255\r
+ * #define ETHERNET_CONF_NET_MASK3                       0\r
+ * #define ETH_PHY_MODE                                  ETH_PHY_MODE\r
+ * \endcode\r
+ *\r
+ * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined\r
+ * to trace the actual size of the data received.\r
+ * \code\r
+ * static gmac_device_t gs_gmac_dev;\r
+ * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX];\r
+ *\r
+ * uint32_t ul_frm_size;\r
+ * \endcode\r
+ *\r
+ * Add to application C-file:\r
+ * \code\r
+ *   void gmac_init(void)\r
+ *   {\r
+ *       sysclk_init();\r
+ *\r
+ *       board_init();\r
+ *\r
+ *       pmc_enable_periph_clk(ID_GMAC);\r
+ *\r
+ *       gmac_option.uc_copy_all_frame = 0;\r
+ *       gmac_option.uc_no_boardcast = 0;\r
+ *       memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ *       gs_gmac_dev.p_hw = GMAC;\r
+ *\r
+ *       gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ *\r
+ *       NVIC_EnableIRQ(GMAC_IRQn);\r
+ *\r
+ *       ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ *\r
+ *       ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ *\r
+ *       ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_setup_flow Workflow\r
+ * - Ensure that conf_eth.h is present and contains the\r
+ * following configuration symbol. This configuration file is used\r
+ * by the driver and should not be included by the application.\r
+ * -# Define the receiving buffer size used in the internal GMAC driver.\r
+ * The buffer size used for RX is GMAC_RX_BUFFERS * 128.\r
+ * If it was supposed receiving a large number of frame, the\r
+ * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept\r
+ * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least\r
+ * (2048/128)=16, and as there are additional frames coming, a preferred\r
+ * number is 24 depending on a normal Ethernet throughput.\r
+ *   - \code\r
+ *        #define GMAC_RX_BUFFERS                               16\r
+ *   \endcode\r
+ * -# Define the transmitting buffer size used in the internal GMAC driver.\r
+ * The buffer size used for TX is GMAC_TX_BUFFERS * 1518.\r
+ *   - \code\r
+ *        #define GMAC_TX_BUFFERS                               8\r
+ *   \endcode\r
+ * -# Define maximum retry time for a PHY read/write operation.\r
+ *   - \code\r
+ *        #define MAC_PHY_RETRY_MAX                             1000000\r
+ *   \endcode\r
+ * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved\r
+ * for ATMEL, application should always change this address to its' own.\r
+ *   - \code\r
+ *        #define ETHERNET_CONF_ETHADDR0                        0x00\r
+ *        #define ETHERNET_CONF_ETHADDR1                        0x04\r
+ *        #define ETHERNET_CONF_ETHADDR2                        0x25\r
+ *        #define ETHERNET_CONF_ETHADDR3                        0x1C\r
+ *        #define ETHERNET_CONF_ETHADDR4                        0xA0\r
+ *        #define ETHERNET_CONF_ETHADDR5                        0x02\r
+ *   \endcode\r
+ * -# Define the IP address configration used in the application. When DHCP\r
+ *  is enabled, this configuration is not effected.\r
+ *   - \code\r
+ *        #define ETHERNET_CONF_IPADDR0                         192\r
+ *        #define ETHERNET_CONF_IPADDR1                         168\r
+ *        #define ETHERNET_CONF_IPADDR2                         0\r
+ *        #define ETHERNET_CONF_IPADDR3                         2\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR0                   192\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR1                   168\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR2                   0\r
+ *        #define ETHERNET_CONF_GATEWAY_ADDR3                   1\r
+ *        #define ETHERNET_CONF_NET_MASK0                       255\r
+ *        #define ETHERNET_CONF_NET_MASK1                       255\r
+ *        #define ETHERNET_CONF_NET_MASK2                       255\r
+ *        #define ETHERNET_CONF_NET_MASK3                       0\r
+ *   \endcode\r
+ * -# Configure the PHY maintainance interface.\r
+ *   - \code\r
+ *        #define ETH_PHY_MODE                                  GMAC_PHY_MII\r
+ *   \endcode\r
+ * -# Enable the system clock:\r
+ *   - \code sysclk_init(); \endcode\r
+ * -# Enable PIO configurations for GMAC:\r
+ *   - \code board_init(); \endcode\r
+ * -# Enable PMC clock for GMAC:\r
+ *   - \code pmc_enable_periph_clk(ID_GMAC); \endcode\r
+ * -# Set the GMAC options; it's set to copy all frame and support broadcast:\r
+ *   - \code\r
+ *         gmac_option.uc_copy_all_frame = 0;\r
+ *         gmac_option.uc_no_boardcast = 0;\r
+ *         memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));\r
+ *         gs_gmac_dev.p_hw = GMAC;\r
+ * \endcode\r
+ * -# Initialize GMAC device with the filled option:\r
+ *   - \code\r
+ *         gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option);\r
+ * \endcode\r
+ * -# Enable the interrupt service for GMAC:\r
+ *   - \code\r
+ *         NVIC_EnableIRQ(GMAC_IRQn);\r
+ * \endcode\r
+ * -# Initialize the PHY component:\r
+ *   - \code\r
+ *         ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz());\r
+ * \endcode\r
+  * -# The link will be established based on auto negotiation.\r
+ *   - \code\r
+ *         ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR);\r
+ * \endcode\r
+ * -# Establish the ethernet link; the network can be worked from now on:\r
+ *   - \code\r
+ *         ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1);\r
+ * \endcode\r
+ *\r
+ * \section gmac_basic_use_case_usage Usage steps\r
+ * \subsection gmac_basic_use_case_usage_code Example code\r
+ * Add to, e.g., main loop in application C-file:\r
+ * \code\r
+ *    gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));\r
+ * \endcode\r
+ *\r
+ * \subsection gmac_basic_use_case_usage_flow Workflow\r
+ * -# Start reading the data from the ethernet:\r
+ *   - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode\r
+ */\r
+\r
+#      define GMAC_STATS 0\r
+\r
+#if( GMAC_STATS != 0 )\r
+\r
+       /* Here below some code to study the types and\r
+       frequencies of  GMAC interrupts. */\r
+       #define GMAC_IDX_RXUBR 0\r
+       #define GMAC_IDX_TUR   1\r
+       #define GMAC_IDX_RLEX  2\r
+       #define GMAC_IDX_TFC   3\r
+       #define GMAC_IDX_RCOMP 4\r
+       #define GMAC_IDX_TCOMP 5\r
+       #define GMAC_IDX_ROVR  6\r
+       #define GMAC_IDX_HRESP 7\r
+       #define GMAC_IDX_PFNZ  8\r
+       #define GMAC_IDX_PTZ   9\r
+\r
+       struct SGmacStats {\r
+               unsigned recvCount;\r
+               unsigned rovrCount;\r
+               unsigned bnaCount;\r
+               unsigned sendCount;\r
+               unsigned sovrCount;\r
+               unsigned incompCount;\r
+               unsigned truncCount;\r
+\r
+               unsigned intStatus[10];\r
+       };\r
+       extern struct SGmacStats gmacStats;\r
+\r
+       struct SIntPair {\r
+               const char *name;\r
+               unsigned mask;\r
+               int index;\r
+       };\r
+\r
+       #define MK_PAIR( NAME )   #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME\r
+       static const struct SIntPair intPairs[] = {\r
+               { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */\r
+               { MK_PAIR( TUR   ) }, /* Enable transmit underrun interrupt. */\r
+               { MK_PAIR( RLEX  ) }, /* Enable retry limit  exceeded interrupt. */\r
+               { MK_PAIR( TFC   ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */\r
+               { MK_PAIR( RCOMP ) }, /* Receive complete */\r
+               { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */\r
+               { MK_PAIR( ROVR  ) }, /* Enable receive overrun interrupt. */\r
+               { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */\r
+               { MK_PAIR( PFNZ  ) }, /* Enable pause frame received interrupt. */\r
+               { MK_PAIR( PTZ   ) }  /* Enable pause time zero interrupt. */\r
+       };\r
+\r
+       void gmac_show_irq_counts ();\r
+\r
+#endif\r
+\r
+#endif /* GMAC_H_INCLUDED */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC17xx/NetworkInterface.c
new file mode 100644 (file)
index 0000000..66d4282
--- /dev/null
@@ -0,0 +1,293 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 150406 (C) 2015 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB:                                     ***\r
+ ***                                                                         ***\r
+ ***   This product is functional and is already being used in commercial    ***\r
+ ***   products.  Be aware however that we are still refining its design,    ***\r
+ ***   the source code does not yet fully conform to the strict coding and   ***\r
+ ***   style standards mandated by Real Time Engineers ltd., and the         ***\r
+ ***   documentation and testing is not necessarily complete.                ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * - Open source licensing -\r
+ * While FreeRTOS+TCP is in the lab it is provided only under version two of the\r
+ * GNU General Public License (GPL) (which is different to the standard FreeRTOS\r
+ * license).  FreeRTOS+TCP is free to download, use and distribute under the\r
+ * terms of that license provided the copyright notice and this text are not\r
+ * altered or removed from the source files.  The GPL V2 text is available on\r
+ * the gnu.org web site, and on the following\r
+ * URL: http://www.FreeRTOS.org/gpl-2.0.txt.  Active early adopters may, and\r
+ * solely at the discretion of Real Time Engineers Ltd., be offered versions\r
+ * under a license other then the GPL.\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* Hardware abstraction. */\r
+#include "FreeRTOS_IO.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* Driver includes. */\r
+#include "lpc17xx_emac.h"\r
+#include "lpc17xx_pinsel.h"\r
+\r
+/* Demo includes. */\r
+#include "NetworkInterface.h"\r
+\r
+#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+/* When a packet is ready to be sent, if it cannot be sent immediately then the\r
+task performing the transmit will block for niTX_BUFFER_FREE_WAIT\r
+milliseconds.  It will do this a maximum of niMAX_TX_ATTEMPTS before giving\r
+up. */\r
+#define niTX_BUFFER_FREE_WAIT  ( pdMS_TO_TICKS( 2UL ) )\r
+#define niMAX_TX_ATTEMPTS              ( 5 )\r
+\r
+/* The length of the queue used to send interrupt status words from the\r
+interrupt handler to the deferred handler task. */\r
+#define niINTERRUPT_QUEUE_LENGTH       ( 10 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The queue used to communicate Ethernet events with the IP task. */\r
+extern QueueHandle_t xNetworkEventQueue;\r
+\r
+/* The semaphore used to wake the deferred interrupt handler task when an Rx\r
+interrupt is received. */\r
+static SemaphoreHandle_t xEMACRxEventSemaphore = NULL;\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+EMAC_CFG_Type Emac_Config;\r
+PINSEL_CFG_Type xPinConfig;\r
+BaseType_t xStatus, xReturn;\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+       /* Enable Ethernet Pins */\r
+       boardCONFIGURE_ENET_PINS( xPinConfig );\r
+\r
+       Emac_Config.Mode = EMAC_MODE_AUTO;\r
+       Emac_Config.pbEMAC_Addr = ucMACAddress;\r
+       xStatus = EMAC_Init( &Emac_Config );\r
+\r
+       LPC_EMAC->IntEnable &= ~( EMAC_INT_TX_DONE );\r
+\r
+       if( xStatus != ERROR )\r
+       {\r
+               vSemaphoreCreateBinary( xEMACRxEventSemaphore );\r
+               configASSERT( xEMACRxEventSemaphore );\r
+\r
+               /* The handler task is created at the highest possible priority to\r
+               ensure the interrupt handler can return directly to it. */\r
+               xTaskCreate( prvEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );\r
+\r
+               /* Enable the interrupt and set its priority to the minimum\r
+               interrupt priority.  */\r
+               NVIC_SetPriority( ENET_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+               NVIC_EnableIRQ( ENET_IRQn );\r
+\r
+               xReturn = pdPASS;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdFAIL;\r
+       }\r
+\r
+       configASSERT( xStatus != ERROR );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+BaseType_t xReturn = pdFAIL;\r
+int32_t x;\r
+extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength );\r
+extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );\r
+\r
+\r
+       /* Attempt to obtain access to a Tx buffer. */\r
+       for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )\r
+       {\r
+               if( EMAC_CheckTransmitIndex() == TRUE )\r
+               {\r
+                       /* Will the data fit in the Tx buffer? */\r
+                       if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */\r
+                       {\r
+                               /* Assign the buffer to the Tx descriptor that is now known to\r
+                               be free. */\r
+                               EMAC_SetNextPacketToSend( pxNetworkBuffer->pucBuffer );\r
+\r
+                               /* The EMAC now owns the buffer. */\r
+                               pxNetworkBuffer->pucBuffer = NULL;\r
+\r
+                               /* Initiate the Tx. */\r
+                               EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );\r
+                               iptraceNETWORK_INTERFACE_TRANSMIT();\r
+\r
+                               /* The Tx has been initiated. */\r
+                               xReturn = pdPASS;\r
+                       }\r
+                       break;\r
+               }\r
+               else\r
+               {\r
+                       vTaskDelay( niTX_BUFFER_FREE_WAIT );\r
+               }\r
+       }\r
+\r
+       /* Finished with the network buffer. */\r
+       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void ENET_IRQHandler( void )\r
+{\r
+uint32_t ulInterruptCause;\r
+\r
+       while( ( ulInterruptCause = LPC_EMAC->IntStatus ) != 0 )\r
+       {\r
+               /* Clear the interrupt. */\r
+               LPC_EMAC->IntClear = ulInterruptCause;\r
+\r
+               /* Clear fatal error conditions.  NOTE:  The driver does not clear all\r
+               errors, only those actually experienced.  For future reference, range\r
+               errors are not actually errors so can be ignored. */\r
+               if( ( ulInterruptCause & EMAC_INT_TX_UNDERRUN ) != 0U )\r
+               {\r
+                       LPC_EMAC->Command |= EMAC_CR_TX_RES;\r
+               }\r
+\r
+               /* Unblock the deferred interrupt handler task if the event was an\r
+               Rx. */\r
+               if( ( ulInterruptCause & EMAC_INT_RX_DONE ) != 0UL )\r
+               {\r
+                       xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL );\r
+               }\r
+       }\r
+\r
+       /* ulInterruptCause is used for convenience here.  A context switch is\r
+       wanted, but coding portEND_SWITCHING_ISR( 1 ) would likely result in a\r
+       compiler warning. */\r
+       portEND_SWITCHING_ISR( ulInterruptCause );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+size_t xDataLength;\r
+const uint16_t usCRCLength = 4;\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+\r
+/* This is not included in the header file for some reason. */\r
+extern uint8_t *EMAC_NextPacketToRead( void );\r
+\r
+       ( void ) pvParameters;\r
+       configASSERT( xEMACRxEventSemaphore );\r
+\r
+       for( ;; )\r
+       {\r
+               /* Wait for the EMAC interrupt to indicate that another packet has been\r
+               received.  The while() loop is only needed if INCLUDE_vTaskSuspend is\r
+               set to 0 in FreeRTOSConfig.h. */\r
+               while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );\r
+\r
+               /* At least one packet has been received. */\r
+               while( EMAC_CheckReceiveIndex() != FALSE )\r
+               {\r
+                       /* Obtain the length, minus the CRC.  The CRC is four bytes\r
+                       but the length is already minus 1. */\r
+                       xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( usCRCLength - 1U );\r
+\r
+                       if( xDataLength > 0U )\r
+                       {\r
+                               /* Obtain a network buffer to pass this data into the\r
+                               stack.  No storage is required as the network buffer\r
+                               will point directly to the buffer that already holds\r
+                               the     received data. */\r
+                               pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( 0, ( TickType_t ) 0 );\r
+\r
+                               if( pxNetworkBuffer != NULL )\r
+                               {\r
+                                       pxNetworkBuffer->pucBuffer = EMAC_NextPacketToRead();\r
+                                       pxNetworkBuffer->xDataLength = xDataLength;\r
+                                       xRxEvent.pvData = ( void * ) pxNetworkBuffer;\r
+\r
+                                       /* Data was received and stored.  Send a message to the IP\r
+                                       task to let it know. */\r
+                                       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+                                       {\r
+                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                                               iptraceETHERNET_RX_EVENT_LOST();\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       iptraceETHERNET_RX_EVENT_LOST();\r
+                               }\r
+\r
+                               iptraceNETWORK_INTERFACE_RECEIVE();\r
+                       }\r
+\r
+                       /* Release the frame. */\r
+                       EMAC_UpdateRxConsumeIndex();\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/NetworkInterface.c
new file mode 100644 (file)
index 0000000..0f1019a
--- /dev/null
@@ -0,0 +1,1100 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+/* LPCOpen includes. */\r
+#include "chip.h"\r
+#include "lpc_phy.h"\r
+\r
+/* The size of the stack allocated to the task that handles Rx packets. */\r
+#define nwRX_TASK_STACK_SIZE   140\r
+\r
+#ifndef        PHY_LS_HIGH_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+       receiving packets. */\r
+       #define PHY_LS_HIGH_CHECK_TIME_MS       15000\r
+#endif\r
+\r
+#ifndef        PHY_LS_LOW_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still low every second. */\r
+       #define PHY_LS_LOW_CHECK_TIME_MS        1000\r
+#endif\r
+\r
+#ifndef configUSE_RMII\r
+       #define configUSE_RMII 1\r
+#endif\r
+\r
+#ifndef configNUM_RX_DESCRIPTORS\r
+       #error please define configNUM_RX_DESCRIPTORS in your FreeRTOSIPConfig.h\r
+#endif\r
+\r
+#ifndef configNUM_TX_DESCRIPTORS\r
+       #error please define configNUM_TX_DESCRIPTORS in your FreeRTOSIPConfig.h\r
+#endif\r
+\r
+#ifndef NETWORK_IRQHandler\r
+       #error NETWORK_IRQHandler must be defined to the name of the function that is installed in the interrupt vector table to handle Ethernet interrupts.\r
+#endif\r
+\r
+#if !defined( MAC_FF_HMC )\r
+       /* Hash for multicast. */\r
+       #define MAC_FF_HMC     ( 1UL << 2UL )\r
+#endif\r
+\r
+#ifndef iptraceEMAC_TASK_STARTING\r
+       #define iptraceEMAC_TASK_STARTING()     do { } while( 0 )\r
+#endif\r
+\r
+/* Define the bits of .STATUS that indicate a reception error. */\r
+#define nwRX_STATUS_ERROR_BITS \\r
+       ( RDES_CE  /* CRC Error */                        | \\r
+         RDES_RE  /* Receive Error */                    | \\r
+         RDES_DE  /* Descriptor Error */                 | \\r
+         RDES_RWT /* Receive Watchdog Timeout */         | \\r
+         RDES_LC  /* Late Collision */                   | \\r
+         RDES_OE  /* Overflow Error */                   | \\r
+         RDES_SAF /* Source Address Filter Fail */       | \\r
+         RDES_AFM /* Destination Address Filter Fail */  | \\r
+         RDES_LE  /* Length Error */                     )\r
+\r
+/* Define the EMAC status bits that should trigger an interrupt. */\r
+#define nwDMA_INTERRUPT_MASK \\r
+       ( DMA_IE_TIE  /* Transmit interrupt enable */         | \\r
+         DMA_IE_TSE  /* Transmit stopped enable */           | \\r
+         DMA_IE_OVE  /* Overflow interrupt enable */         | \\r
+         DMA_IE_RIE  /* Receive interrupt enable */          | \\r
+         DMA_IE_NIE  /* Normal interrupt summary enable */   | \\r
+         DMA_IE_AIE  /* Abnormal interrupt summary enable */ | \\r
+         DMA_IE_RUE  /* Receive buffer unavailable enable */ | \\r
+         DMA_IE_UNE  /* Underflow interrupt enable. */       | \\r
+         DMA_IE_TJE  /* Transmit jabber timeout enable */    | \\r
+         DMA_IE_RSE  /* Received stopped enable */           | \\r
+         DMA_IE_RWE  /* Receive watchdog timeout enable */   | \\r
+         DMA_IE_FBE )/* Fatal bus error enable */\r
+\r
+/* Interrupt events to process.  Currently only the RX/TX events are processed\r
+although code for other events is included to allow for possible future\r
+expansion. */\r
+#define EMAC_IF_RX_EVENT        1UL\r
+#define EMAC_IF_TX_EVENT        2UL\r
+#define EMAC_IF_ERR_EVENT       4UL\r
+#define EMAC_IF_ALL_EVENT       ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )\r
+\r
+ /* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+ driver will filter incoming packets and only pass the stack those packets it\r
+ considers need processing. */\r
+ #if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+ #else\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+ #endif\r
+\r
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 ) || ( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+       #warning It is adviced to enable both macros\r
+#endif\r
+\r
+#ifndef configPLACE_IN_SECTION_RAM\r
+       #define configPLACE_IN_SECTION_RAM\r
+/*\r
+       #define configPLACE_IN_SECTION_RAM      __attribute__ ((section(".ramfunc")))\r
+*/\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Delay function passed into the library.  The implementation uses FreeRTOS\r
+ * calls so the scheduler must be started before the driver can be used.\r
+ */\r
+static void prvDelay( uint32_t ulMilliSeconds );\r
+\r
+/*\r
+ * Initialises the Tx and Rx descriptors respectively.\r
+ */\r
+static void prvSetupTxDescriptors( void );\r
+static void prvSetupRxDescriptors( void );\r
+\r
+/*\r
+ * A task that processes received frames.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*\r
+ * Sets up the MAC with the results of an auto-negotiation.\r
+ */\r
+static BaseType_t prvSetLinkSpeed( void );\r
+\r
+/*\r
+ * Generates a CRC for a MAC address that is then used to generate a hash index.\r
+ */\r
+static uint32_t prvGenerateCRC32( const uint8_t *ucAddress );\r
+\r
+/*\r
+ * Generates a hash index when setting a filter to permit a MAC address.\r
+ */\r
+static uint32_t prvGetHashIndex( const uint8_t *ucAddress );\r
+\r
+/*\r
+ * Update the hash table to allow a MAC address.\r
+ */\r
+static void prvAddMACAddress( const uint8_t* ucMacAddress );\r
+\r
+/*\r
+ * Sometimes the DMA will report received data as being longer than the actual\r
+ * received from length.  This function checks the reported length and corrects\r
+ * if if necessary.\r
+ */\r
+static void prvRemoveTrailingBytes( NetworkBufferDescriptor_t *pxDescriptor );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Bit map of outstanding ETH interrupt events for processing.  Currently only\r
+the Rx and Tx interrupt is handled, although code is included for other events\r
+to enable future expansion. */\r
+static volatile uint32_t ulISREvents;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+\r
+/* Tx descriptors and index. */\r
+static ENET_ENHTXDESC_T xDMATxDescriptors[ configNUM_TX_DESCRIPTORS ];\r
+\r
+/* ulNextFreeTxDescriptor is declared volatile, because it is accessed from\r
+to different tasks. */\r
+static volatile uint32_t ulNextFreeTxDescriptor;\r
+static uint32_t ulTxDescriptorToClear;\r
+\r
+/* Rx descriptors and index. */\r
+static ENET_ENHRXDESC_T xDMARxDescriptors[ configNUM_RX_DESCRIPTORS ];\r
+static uint32_t ulNextRxDescriptorToProcess;\r
+\r
+/* Must be defined externally - the demo applications define this in main.c. */\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+/* The handle of the task that processes Rx packets.  The handle is required so\r
+the task can be notified when new packets arrive. */\r
+static TaskHandle_t xRxHanderTask = NULL;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       static const uint8_t xLLMNR_MACAddress[] = { '\x01', '\x00', '\x5E', '\x00', '\x00', '\xFC' };\r
+#endif /* ipconfigUSE_LLMNR == 1 */\r
+\r
+/* xTXDescriptorSemaphore is a counting semaphore with\r
+a maximum count of ETH_TXBUFNB, which is the number of\r
+DMA TX descriptors. */\r
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+BaseType_t xReturn = pdPASS;\r
+static BaseType_t xHasInitialised = pdFALSE;\r
+\r
+       if( xHasInitialised == pdFALSE )\r
+       {\r
+               xHasInitialised = pdTRUE;\r
+\r
+               /* The interrupt will be turned on when a link is established. */\r
+               NVIC_DisableIRQ( ETHERNET_IRQn );\r
+\r
+               /* Disable receive and transmit DMA processes. */\r
+               LPC_ETHERNET->DMA_OP_MODE &= ~( DMA_OM_ST | DMA_OM_SR );\r
+\r
+               /* Disable packet reception. */\r
+               LPC_ETHERNET->MAC_CONFIG &= ~( MAC_CFG_RE | MAC_CFG_TE );\r
+\r
+               /* Call the LPCOpen function to initialise the hardware. */\r
+               Chip_ENET_Init( LPC_ETHERNET );\r
+\r
+               /* Save MAC address. */\r
+               Chip_ENET_SetADDR( LPC_ETHERNET, ucMACAddress );\r
+\r
+               /* Clear all MAC address hash entries. */\r
+               LPC_ETHERNET->MAC_HASHTABLE_HIGH = 0;\r
+               LPC_ETHERNET->MAC_HASHTABLE_LOW = 0;\r
+\r
+               #if( ipconfigUSE_LLMNR == 1 )\r
+               {\r
+                       prvAddMACAddress( xLLMNR_MACAddress );\r
+               }\r
+               #endif /* ipconfigUSE_LLMNR == 1 */\r
+\r
+               /* Promiscuous flag (PR) and Receive All flag (RA) set to zero.  The\r
+               registers MAC_HASHTABLE_[LOW|HIGH] will be loaded to allow certain\r
+               multi-cast addresses. */\r
+               LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FF_HMC;\r
+\r
+               #if( configUSE_RMII == 1 )\r
+               {\r
+                       if( lpc_phy_init( pdTRUE, prvDelay ) != SUCCESS )\r
+                       {\r
+                               xReturn = pdFAIL;\r
+                       }\r
+               }\r
+               #else\r
+               {\r
+                       #warning This path has not been tested.\r
+                       if( lpc_phy_init( pdFALSE, prvDelay ) != SUCCESS )\r
+                       {\r
+                               xReturn = pdFAIL;\r
+                       }\r
+               }\r
+               #endif\r
+\r
+               if( xReturn == pdPASS )\r
+               {\r
+                       if( xTXDescriptorSemaphore == NULL )\r
+                       {\r
+                               /* Create a counting semaphore, with a value of 'configNUM_TX_DESCRIPTORS'\r
+                               and a maximum of 'configNUM_TX_DESCRIPTORS'. */\r
+                               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) configNUM_TX_DESCRIPTORS, ( UBaseType_t ) configNUM_TX_DESCRIPTORS );\r
+                               configASSERT( xTXDescriptorSemaphore );\r
+                       }\r
+\r
+                       /* Enable MAC interrupts. */\r
+                       LPC_ETHERNET->DMA_INT_EN = nwDMA_INTERRUPT_MASK;\r
+\r
+                       /* Auto-negotiate was already started.  Wait for it to complete. */\r
+                       xReturn = prvSetLinkSpeed();\r
+\r
+                       if( xReturn == pdPASS )\r
+                       {\r
+                               /* Initialise the descriptors. */\r
+                               prvSetupTxDescriptors();\r
+                               prvSetupRxDescriptors();\r
+\r
+                               /* Clear all interrupts. */\r
+                               LPC_ETHERNET->DMA_STAT = DMA_ST_ALL;\r
+\r
+                               /* Enable receive and transmit DMA processes. */\r
+                               LPC_ETHERNET->DMA_OP_MODE |= DMA_OM_ST | DMA_OM_SR;\r
+\r
+                               /* Set Receiver / Transmitter Enable. */\r
+                               LPC_ETHERNET->MAC_CONFIG |= MAC_CFG_RE | MAC_CFG_TE;\r
+\r
+                               /* Start receive polling. */\r
+                               LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;\r
+\r
+                               /* Enable interrupts in the NVIC. */\r
+                               NVIC_SetPriority( ETHERNET_IRQn, configMAC_INTERRUPT_PRIORITY );\r
+                               NVIC_EnableIRQ( ETHERNET_IRQn );\r
+                       }\r
+                       /* Guard against the task being created more than once and the\r
+                       descriptors being initialised more than once. */\r
+                       if( xRxHanderTask == NULL )\r
+                       {\r
+                               xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", nwRX_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );\r
+                               configASSERT( xReturn );\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* Once prvEMACHandlerTask() has started, the variable\r
+       'ulPHYLinkStatus' will be updated by that task. \r
+       The IP-task will keep on calling this function untill\r
+       it finally returns pdPASS.\r
+       Only then can the DHCP-procedure start (if configured). */\r
+       if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 )\r
+       {\r
+               xReturn = pdPASS;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdFAIL;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#define niBUFFER_1_PACKET_SIZE         1536\r
+\r
+static __attribute__ ((section("._ramAHB32"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+\r
+uint8_t *ucRAMBuffer = ucNetworkPackets;\r
+uint32_t ul;\r
+\r
+       for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+       {\r
+               pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
+               *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
+               ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+static void vClearTXBuffers()\r
+{\r
+uint32_t ulLastDescriptor = ulNextFreeTxDescriptor;\r
+size_t uxCount = ( ( size_t ) configNUM_TX_DESCRIPTORS ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+       uint8_t *ucPayLoad;\r
+#endif\r
+\r
+       /* This function is called after a TX-completion interrupt.\r
+       It will release each Network Buffer used in xNetworkInterfaceOutput().\r
+       'uxCount' represents the number of descriptors given to DMA for transmission.\r
+       After sending a packet, the DMA will clear the 'TDES_OWN' bit. */\r
+       while( ( uxCount > ( size_t ) 0u ) && ( ( xDMATxDescriptors[ ulTxDescriptorToClear ].CTRLSTAT & TDES_OWN ) == 0 ) )\r
+       {\r
+               if( ( ulTxDescriptorToClear == ulLastDescriptor ) && ( uxCount != ( size_t ) configNUM_TX_DESCRIPTORS ) )\r
+               {\r
+                       break;\r
+               }\r
+\r
+\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       ucPayLoad = ( uint8_t * )xDMATxDescriptors[ ulTxDescriptorToClear ].B1ADD;\r
+                       if( ucPayLoad != NULL )\r
+                       {\r
+                               /* B1ADD points to a pucEthernetBuffer of a Network Buffer descriptor. */\r
+                               pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );\r
+\r
+                               configASSERT( pxNetworkBuffer != NULL );\r
+\r
+                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;\r
+                               xDMATxDescriptors[ ulTxDescriptorToClear ].B1ADD = ( uint32_t )0u;\r
+                       }\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+               /* Move onto the next descriptor, wrapping if necessary. */\r
+               ulTxDescriptorToClear++;\r
+               if( ulTxDescriptorToClear >= configNUM_TX_DESCRIPTORS )\r
+               {\r
+                       ulTxDescriptorToClear = 0;\r
+               }\r
+\r
+               uxCount--;\r
+               /* Tell the counting semaphore that one more TX descriptor is available. */\r
+               xSemaphoreGive( xTXDescriptorSemaphore );\r
+       }\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )\r
+{\r
+BaseType_t xReturn = pdFAIL;\r
+const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50 );\r
+\r
+       /* Attempt to obtain access to a Tx descriptor. */\r
+       do\r
+       {\r
+               if( xTXDescriptorSemaphore == NULL )\r
+               {\r
+                       break;\r
+               }\r
+               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
+               {\r
+                       /* Time-out waiting for a free TX descriptor. */\r
+                       break;\r
+               }\r
+\r
+               /* If the descriptor is still owned by the DMA it can't be used. */\r
+               if( ( xDMATxDescriptors[ ulNextFreeTxDescriptor ].CTRLSTAT & TDES_OWN ) != 0 )\r
+               {\r
+                       /* The semaphore was taken, the TX DMA-descriptor is still not available.\r
+                       Actually that should not occur, the 'TDES_OWN' was already confirmed low in vClearTXBuffers(). */\r
+                       xSemaphoreGive( xTXDescriptorSemaphore );\r
+               }\r
+               else\r
+               {\r
+                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+                       {\r
+                               /* bReleaseAfterSend should always be set when using the zero\r
+                               copy driver. */\r
+                               configASSERT( bReleaseAfterSend != pdFALSE );\r
+\r
+                               /* The DMA's descriptor to point directly to the data in the\r
+                               network buffer descriptor.  The data is not copied. */\r
+                               xDMATxDescriptors[ ulNextFreeTxDescriptor ].B1ADD = ( uint32_t ) pxDescriptor->pucEthernetBuffer;\r
+\r
+                               /* The DMA descriptor will 'own' this Network Buffer,\r
+                               until it has been sent.  So don't release it now. */\r
+                               bReleaseAfterSend = pdFALSE;\r
+                       }\r
+                       #else\r
+                       {\r
+                               /* The data is copied from the network buffer descriptor into\r
+                               the DMA's descriptor. */\r
+                               memcpy( ( void * ) xDMATxDescriptors[ ulNextFreeTxDescriptor ].B1ADD, ( void * ) pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength );\r
+                       }\r
+                       #endif\r
+\r
+                       xDMATxDescriptors[ ulNextFreeTxDescriptor ].BSIZE = ( uint32_t ) TDES_ENH_BS1( pxDescriptor->xDataLength );\r
+\r
+                       /* This descriptor is given back to the DMA. */\r
+                       xDMATxDescriptors[ ulNextFreeTxDescriptor ].CTRLSTAT |= TDES_OWN;\r
+\r
+                       /* Ensure the DMA is polling Tx descriptors. */\r
+                       LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1;\r
+\r
+            iptraceNETWORK_INTERFACE_TRANSMIT();\r
+\r
+                       /* Move onto the next descriptor, wrapping if necessary. */\r
+                       ulNextFreeTxDescriptor++;\r
+                       if( ulNextFreeTxDescriptor >= configNUM_TX_DESCRIPTORS )\r
+                       {\r
+                               ulNextFreeTxDescriptor = 0;\r
+                       }\r
+\r
+                       /* The Tx has been initiated. */\r
+                       xReturn = pdPASS;\r
+               }\r
+       } while( 0 );\r
+\r
+       /* The buffer has been sent so can be released. */\r
+       if( bReleaseAfterSend != pdFALSE )\r
+       {\r
+               vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvDelay( uint32_t ulMilliSeconds )\r
+{\r
+       /* Ensure the scheduler was started before attempting to use the scheduler to\r
+       create a delay. */\r
+       configASSERT( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING );\r
+\r
+       vTaskDelay( pdMS_TO_TICKS( ulMilliSeconds ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupTxDescriptors( void )\r
+{\r
+BaseType_t x;\r
+\r
+       /* Start with Tx descriptors clear. */\r
+       memset( ( void * ) xDMATxDescriptors, 0, sizeof( xDMATxDescriptors ) );\r
+\r
+       /* Index to the next Tx descriptor to use. */\r
+       ulNextFreeTxDescriptor = 0ul;\r
+\r
+       /* Index to the next Tx descriptor to clear ( after transmission ). */\r
+       ulTxDescriptorToClear = 0ul;\r
+\r
+       for( x = 0; x < configNUM_TX_DESCRIPTORS; x++ )\r
+       {\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       /* Nothing to do, B1ADD will be set when data is ready to transmit.\r
+                       Currently the memset above will have set it to NULL. */\r
+               }\r
+               #else\r
+               {\r
+                       /* Allocate a buffer to the Tx descriptor.  This is the most basic\r
+                       way of creating a driver as the data is then copied into the\r
+                       buffer. */\r
+                       xDMATxDescriptors[ x ].B1ADD = ( uint32_t ) pvPortMalloc( ipTOTAL_ETHERNET_FRAME_SIZE );\r
+\r
+                       /* Use an assert to check the allocation as +TCP applications will\r
+                       often not use a malloc() failed hook as the TCP stack will recover\r
+                       from allocation failures. */\r
+                       configASSERT( xDMATxDescriptors[ x ].B1ADD );\r
+               }\r
+               #endif\r
+\r
+               /* Buffers hold an entire frame so all buffers are both the start and\r
+               end of a frame. */\r
+               /* TDES_ENH_TCH     Second Address Chained. */\r
+               /* TDES_ENH_CIC(n)  Checksum Insertion Control, tried but it does not work for the LPC18xx... */\r
+               /* TDES_ENH_FS      First Segment. */\r
+               /* TDES_ENH_LS      Last Segment. */\r
+               /* TDES_ENH_IC      Interrupt on Completion. */\r
+               xDMATxDescriptors[ x ].CTRLSTAT = TDES_ENH_TCH | TDES_ENH_CIC( 3 ) | TDES_ENH_FS | TDES_ENH_LS | TDES_ENH_IC;\r
+               xDMATxDescriptors[ x ].B2ADD = ( uint32_t ) &xDMATxDescriptors[ x + 1 ];\r
+       }\r
+\r
+       xDMATxDescriptors[ configNUM_TX_DESCRIPTORS - 1 ].CTRLSTAT |= TDES_ENH_TER;\r
+       xDMATxDescriptors[ configNUM_TX_DESCRIPTORS - 1 ].B2ADD = ( uint32_t ) &xDMATxDescriptors[ 0 ];\r
+\r
+       /* Point the DMA to the base of the descriptor list. */\r
+       LPC_ETHERNET->DMA_TRANS_DES_ADDR = ( uint32_t ) xDMATxDescriptors;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupRxDescriptors( void )\r
+{\r
+BaseType_t x;\r
+#if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+       NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+#endif\r
+\r
+       /* Index to the next Rx descriptor to use. */\r
+       ulNextRxDescriptorToProcess = 0;\r
+\r
+       /* Clear RX descriptor list. */\r
+       memset( ( void * )  xDMARxDescriptors, 0, sizeof( xDMARxDescriptors ) );\r
+\r
+       for( x = 0; x < configNUM_RX_DESCRIPTORS; x++ )\r
+       {\r
+               /* Allocate a buffer of the largest     possible frame size as it is not\r
+               known what size received frames will be. */\r
+\r
+               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+               {\r
+                       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, 0 );\r
+\r
+                       /* During start-up there should be enough Network Buffers available,\r
+                       so it is safe to use configASSERT().\r
+                       In case this assert fails, please check: configNUM_RX_DESCRIPTORS,\r
+                       ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, and in case BufferAllocation_2.c\r
+                       is included, check the amount of available heap. */\r
+                       configASSERT( pxNetworkBuffer != NULL );\r
+\r
+                       /* Pass the actual buffer to DMA. */\r
+                       xDMARxDescriptors[ x ].B1ADD = ( uint32_t ) pxNetworkBuffer->pucEthernetBuffer;\r
+               }\r
+               #else\r
+               {\r
+                       /* All DMA descriptors are populated with permanent memory blocks.\r
+                       Their contents will be copy to Network Buffers. */\r
+                       xDMARxDescriptors[ x ].B1ADD = ( uint32_t ) pvPortMalloc( ipTOTAL_ETHERNET_FRAME_SIZE );\r
+               }\r
+               #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+\r
+               /* Use an assert to check the allocation as +TCP applications will often\r
+               not use a malloc failed hook as the TCP stack will recover from\r
+               allocation failures. */\r
+               configASSERT( xDMARxDescriptors[ x ].B1ADD );\r
+\r
+               xDMARxDescriptors[ x ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ x + 1 ] );\r
+               xDMARxDescriptors[ x ].CTRL = ( uint32_t ) RDES_ENH_BS1( ipTOTAL_ETHERNET_FRAME_SIZE ) | RDES_ENH_RCH;\r
+\r
+               /* The descriptor is available for use by the DMA. */\r
+               xDMARxDescriptors[ x ].STATUS = RDES_OWN;\r
+       }\r
+\r
+       /* RDES_ENH_RER  Receive End of Ring. */\r
+       xDMARxDescriptors[ ( configNUM_RX_DESCRIPTORS - 1 ) ].CTRL |= RDES_ENH_RER;\r
+       xDMARxDescriptors[ configNUM_RX_DESCRIPTORS - 1 ].B2ADD = ( uint32_t ) &( xDMARxDescriptors[ 0 ] );\r
+\r
+       /* Point the DMA to the base of the descriptor list. */\r
+       LPC_ETHERNET->DMA_REC_DES_ADDR = ( uint32_t ) xDMARxDescriptors;\r
+}\r
+/*-----------------------------------------------------------*/\r
+configPLACE_IN_SECTION_RAM\r
+static void prvRemoveTrailingBytes( NetworkBufferDescriptor_t *pxDescriptor )\r
+{\r
+size_t xExpectedLength;\r
+IPPacket_t *pxIPPacket;\r
+\r
+       pxIPPacket = ( IPPacket_t * ) pxDescriptor->pucEthernetBuffer;\r
+       /* Look at the actual length of the packet, translate it to a host-endial notation. */\r
+       xExpectedLength = sizeof( EthernetHeader_t ) + ( size_t ) FreeRTOS_htons( pxIPPacket->xIPHeader.usLength );\r
+\r
+       if( xExpectedLength == ( pxDescriptor->xDataLength + 4 ) )\r
+       {\r
+               pxDescriptor->xDataLength -= 4;\r
+       }\r
+       else\r
+       {\r
+               if( pxDescriptor->xDataLength > xExpectedLength )\r
+               {\r
+                       pxDescriptor->xDataLength = ( size_t ) xExpectedLength;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+configPLACE_IN_SECTION_RAM\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) == 0 )\r
+       {\r
+               xReturn = pdFALSE;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdTRUE;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+static BaseType_t prvNetworkInterfaceInput()\r
+{\r
+BaseType_t xResult = pdFALSE;\r
+uint32_t ulStatus;\r
+eFrameProcessingResult_t eResult;\r
+const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );\r
+const UBaseType_t uxMinimumBuffersRemaining = 3UL;\r
+uint16_t usLength;\r
+NetworkBufferDescriptor_t *pxDescriptor;\r
+#if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+       NetworkBufferDescriptor_t *pxNewDescriptor;\r
+#endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+\r
+       /* Process each descriptor that is not still in use by the DMA. */\r
+       ulStatus = xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS;\r
+       if( ( ulStatus & RDES_OWN ) == 0 )\r
+       {\r
+               /* Check packet for errors */\r
+               if( ( ulStatus & nwRX_STATUS_ERROR_BITS ) != 0 )\r
+               {\r
+                       /* There is some reception error. */\r
+                       /* Clear error bits. */\r
+                       ulStatus &= ~( ( uint32_t )nwRX_STATUS_ERROR_BITS );\r
+               }\r
+               else\r
+               {\r
+                       xResult++;\r
+\r
+                       eResult = ipCONSIDER_FRAME_FOR_PROCESSING( ( const uint8_t * const ) ( xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD ) );\r
+                       if( eResult == eProcessBuffer )\r
+                       {\r
+                               if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) == 0 )\r
+                               {\r
+                                       ulPHYLinkStatus |= PHY_LINK_CONNECTED;\r
+                                       FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d (message received)\n", ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 ) );\r
+                               }\r
+\r
+                       #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+                               if( uxGetNumberOfFreeNetworkBuffers() > uxMinimumBuffersRemaining )\r
+                               {\r
+                                       pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xDescriptorWaitTime );\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Too risky to allocate a new Network Buffer. */\r
+                                       pxNewDescriptor = NULL;\r
+                               }\r
+                               if( pxNewDescriptor != NULL )\r
+                       #else\r
+                               if( uxGetNumberOfFreeNetworkBuffers() > uxMinimumBuffersRemaining )\r
+                       #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+                               {\r
+                       #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+                               const uint8_t *pucBuffer;\r
+                       #endif\r
+\r
+                                       /* Get the actual length. */\r
+                                       usLength = RDES_FLMSK( ulStatus );\r
+\r
+                                       #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+                                       {\r
+                                               /* Replace the character buffer 'B1ADD'. */\r
+                                               pucBuffer = ( const uint8_t * const ) ( xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD );\r
+                                               xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD = ( uint32_t ) pxNewDescriptor->pucEthernetBuffer;\r
+\r
+                                               /* 'B1ADD' contained the address of a 'pucEthernetBuffer' that\r
+                                               belongs to a Network Buffer.  Find the original Network Buffer. */\r
+                                               pxDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );\r
+                                               /* This zero-copy driver makes sure that every 'xDMARxDescriptors' contains\r
+                                               a reference to a Network Buffer at any time.\r
+                                               In case it runs out of Network Buffers, a DMA buffer won't be replaced,\r
+                                               and the received messages is dropped. */\r
+                                               configASSERT( pxDescriptor != NULL );\r
+                                       }\r
+                                       #else\r
+                                       {\r
+                                               /* Create a buffer of exactly the required length. */\r
+                                               pxDescriptor = pxGetNetworkBufferWithDescriptor( usLength, xDescriptorWaitTime );\r
+                                       }\r
+                                       #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+\r
+                                       if( pxDescriptor != NULL )\r
+                                       {\r
+                                               pxDescriptor->xDataLength = ( size_t ) usLength;\r
+                                               #if( ipconfigZERO_COPY_RX_DRIVER == 0 )\r
+                                               {\r
+                                                       /* Copy the data into the allocated buffer. */\r
+                                                       memcpy( ( void * ) pxDescriptor->pucEthernetBuffer, ( void * ) xDMARxDescriptors[ ulNextRxDescriptorToProcess ].B1ADD, usLength );\r
+                                               }\r
+                                               #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+                                               /* It is possible that more data was copied than\r
+                                               actually makes up the frame.  If this is the case\r
+                                               adjust the length to remove any trailing bytes. */\r
+                                               prvRemoveTrailingBytes( pxDescriptor );\r
+\r
+                                               /* Pass the data to the TCP/IP task for processing. */\r
+                                               xRxEvent.pvData = ( void * ) pxDescriptor;\r
+                                               if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )\r
+                                               {\r
+                                                       /* Could not send the descriptor into the TCP/IP\r
+                                                       stack, it must be released. */\r
+                                                       vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       iptraceNETWORK_INTERFACE_RECEIVE();\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       /* Got here because received data was sent to the IP task or the\r
+                       data contained an error and was discarded.  Give the descriptor\r
+                       back to the DMA. */\r
+                       xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS = ulStatus | RDES_OWN;\r
+\r
+                       /* Move onto the next descriptor. */\r
+                       ulNextRxDescriptorToProcess++;\r
+                       if( ulNextRxDescriptorToProcess >= configNUM_RX_DESCRIPTORS )\r
+                       {\r
+                               ulNextRxDescriptorToProcess = 0;\r
+                       }\r
+\r
+                       ulStatus = xDMARxDescriptors[ ulNextRxDescriptorToProcess ].STATUS;\r
+               } /* if( ( ulStatus & nwRX_STATUS_ERROR_BITS ) != 0 ) */\r
+       } /* if( ( ulStatus & RDES_OWN ) == 0 ) */\r
+\r
+       /* Restart receive polling. */\r
+       LPC_ETHERNET->DMA_REC_POLL_DEMAND = 1;\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+void NETWORK_IRQHandler( void )\r
+{\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+uint32_t ulDMAStatus;\r
+const uint32_t ulRxInterruptMask =\r
+       DMA_ST_RI |             /* Receive interrupt */\r
+       DMA_ST_RU;              /* Receive buffer unavailable */\r
+const uint32_t ulTxInterruptMask =\r
+       DMA_ST_TI |             /* Transmit interrupt */\r
+       DMA_ST_TPS;             /* Transmit process stopped */\r
+\r
+       configASSERT( xRxHanderTask );\r
+\r
+       /* Get pending interrupts. */\r
+       ulDMAStatus = LPC_ETHERNET->DMA_STAT;\r
+\r
+       /* RX group interrupt(s). */\r
+       if( ( ulDMAStatus & ulRxInterruptMask ) != 0x00 )\r
+       {\r
+               /* Remember that an RX event has happened. */\r
+               ulISREvents |= EMAC_IF_RX_EVENT;\r
+               vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );\r
+       }\r
+\r
+       /* TX group interrupt(s). */\r
+       if( ( ulDMAStatus & ulTxInterruptMask ) != 0x00 )\r
+       {\r
+               /* Remember that a TX event has happened. */\r
+               ulISREvents |= EMAC_IF_TX_EVENT;\r
+               vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );\r
+       }\r
+\r
+       /* Test for 'Abnormal interrupt summary'. */\r
+       if( ( ulDMAStatus & DMA_ST_AIE ) != 0x00 )\r
+       {\r
+               /* The trace macro must be written such that it can be called from\r
+               an interrupt. */\r
+               iptraceETHERNET_RX_EVENT_LOST();\r
+       }\r
+\r
+       /* Clear pending interrupts */\r
+       LPC_ETHERNET->DMA_STAT = ulDMAStatus;\r
+\r
+       /* Context switch needed? */\r
+       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvSetLinkSpeed( void )\r
+{\r
+BaseType_t xReturn = pdFAIL;\r
+TickType_t xTimeOnEntering;\r
+uint32_t ulPhyStatus;\r
+const TickType_t xAutoNegotiateDelay = pdMS_TO_TICKS( 5000UL );\r
+\r
+       /* Ensure polling does not starve lower priority tasks by temporarily\r
+       setting the priority of this task to that of the idle task. */\r
+       vTaskPrioritySet( NULL, tskIDLE_PRIORITY );\r
+\r
+       xTimeOnEntering = xTaskGetTickCount();\r
+       do\r
+       {\r
+               ulPhyStatus = lpcPHYStsPoll();\r
+               if( ( ulPhyStatus & PHY_LINK_CONNECTED ) != 0x00 )\r
+               {\r
+                       /* Set interface speed and duplex. */\r
+                       if( ( ulPhyStatus & PHY_LINK_SPEED100 ) != 0x00 )\r
+                       {\r
+                               Chip_ENET_SetSpeed( LPC_ETHERNET, 1 );\r
+                       }\r
+                       else\r
+                       {\r
+                               Chip_ENET_SetSpeed( LPC_ETHERNET, 0 );\r
+                       }\r
+\r
+                       if( ( ulPhyStatus & PHY_LINK_FULLDUPLX ) != 0x00 )\r
+                       {\r
+                               Chip_ENET_SetDuplex( LPC_ETHERNET, pdTRUE );\r
+                       }\r
+                       else\r
+                       {\r
+                               Chip_ENET_SetDuplex( LPC_ETHERNET, pdFALSE );\r
+                       }\r
+\r
+                       xReturn = pdPASS;\r
+                       break;\r
+               }\r
+       } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xAutoNegotiateDelay );\r
+\r
+       /* Reset the priority of this task back to its original value. */\r
+       vTaskPrioritySet( NULL, ipconfigIP_TASK_PRIORITY );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvGenerateCRC32( const uint8_t *ucAddress )\r
+{\r
+unsigned int j;\r
+const uint32_t Polynomial = 0xEDB88320;\r
+uint32_t crc = ~0ul;\r
+const uint8_t *pucCurrent = ( const uint8_t * ) ucAddress;\r
+const uint8_t *pucLast = pucCurrent + 6;\r
+\r
+    /* Calculate  normal CRC32 */\r
+    while( pucCurrent < pucLast )\r
+    {\r
+        crc ^= *( pucCurrent++ );\r
+        for( j = 0; j < 8; j++ )\r
+        {\r
+            if( ( crc & 1 ) != 0 )\r
+            {\r
+                crc = (crc >> 1) ^ Polynomial;\r
+            }\r
+            else\r
+            {\r
+                crc >>= 1;\r
+            }\r
+        }\r
+    }\r
+    return ~crc;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvGetHashIndex( const uint8_t *ucAddress )\r
+{\r
+uint32_t ulCrc = prvGenerateCRC32( ucAddress );\r
+uint32_t ulIndex = 0ul;\r
+BaseType_t xCount = 6;\r
+\r
+    /* Take the lowest 6 bits of the CRC32 and reverse them */\r
+    while( xCount-- )\r
+    {\r
+        ulIndex <<= 1;\r
+        ulIndex |= ( ulCrc & 1 );\r
+        ulCrc >>= 1;\r
+    }\r
+\r
+    /* This is the has value of 'ucAddress' */\r
+    return ulIndex;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvAddMACAddress( const uint8_t* ucMacAddress )\r
+{\r
+BaseType_t xIndex;\r
+\r
+    xIndex = prvGetHashIndex( ucMacAddress );\r
+    if( xIndex >= 32 )\r
+    {\r
+        LPC_ETHERNET->MAC_HASHTABLE_HIGH |= ( 1u << ( xIndex - 32 ) );\r
+    }\r
+    else\r
+    {\r
+        LPC_ETHERNET->MAC_HASHTABLE_LOW |= ( 1u << xIndex );\r
+    }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+configPLACE_IN_SECTION_RAM\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult = 0;\r
+uint32_t ulStatus;\r
+const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );\r
+\r
+       /* Remove compiler warning about unused parameter. */\r
+       ( void ) pvParameters;\r
+\r
+       /* A possibility to set some additional task properties. */\r
+       iptraceEMAC_TASK_STARTING();\r
+\r
+       vTaskSetTimeOutState( &xPhyTime );\r
+       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+       for( ;; )\r
+       {\r
+               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+               if( uxLastMinBufferCount != uxCurrentCount )\r
+               {\r
+                       /* The logging produced below may be helpful\r
+                       while tuning +TCP: see how many buffers are in use. */\r
+                       uxLastMinBufferCount = uxCurrentCount;\r
+                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+               }\r
+\r
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+               {\r
+               static UBaseType_t uxLastMinQueueSpace = 0;\r
+\r
+                       uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+                       if( uxLastMinQueueSpace != uxCurrentCount )\r
+                       {\r
+                               /* The logging produced below may be helpful\r
+                               while tuning +TCP: see how many buffers are in use. */\r
+                               uxLastMinQueueSpace = uxCurrentCount;\r
+                               FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+                       }\r
+               }\r
+               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+               ulTaskNotifyTake( pdTRUE, xBlockTime );\r
+\r
+               xResult = ( BaseType_t ) 0;\r
+\r
+               if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
+               {\r
+                       /* Code to release TX buffers if zero-copy is used. */\r
+                       ulISREvents &= ~EMAC_IF_TX_EVENT;\r
+                       {\r
+                               /* Check if DMA packets have been delivered. */\r
+                               vClearTXBuffers();\r
+                       }\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
+               {\r
+                       ulISREvents &= ~EMAC_IF_RX_EVENT;\r
+\r
+                       xResult = prvNetworkInterfaceInput();\r
+                       if( xResult > 0 )\r
+                       {\r
+                               while( prvNetworkInterfaceInput() > 0 )\r
+                               {\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if( xResult > 0 )\r
+               {\r
+                       /* A packet was received. No need to check for the PHY status now,\r
+                       but set a timer to check it later on. */\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       xResult = 0;\r
+               }\r
+               else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )\r
+               {\r
+                       ulStatus = lpcPHYStsPoll();\r
+\r
+                       if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != ( ulStatus & PHY_LINK_CONNECTED ) )\r
+                       {\r
+                               ulPHYLinkStatus = ulStatus;\r
+                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d (polled PHY)\n", ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 ) );\r
+                       }\r
+\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       if( ( ulPHYLinkStatus & PHY_LINK_CONNECTED ) != 0 )\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/ReadMe.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/LPC18xx/ReadMe.txt
new file mode 100644 (file)
index 0000000..86a7f91
--- /dev/null
@@ -0,0 +1,3 @@
+NetworkInterface.c:\r
+Requires NXP's LPCOpen library and was developed on an LPC1830 and LPC1835 Xplorer\r
+boards from NGX.
\ No newline at end of file
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/README_DRIVER_DISCLAIMER.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/README_DRIVER_DISCLAIMER.txt
new file mode 100644 (file)
index 0000000..347bb11
--- /dev/null
@@ -0,0 +1,10 @@
+Network drivers are provided as examples only, and do not form part of the\r
+FreeRTOS+TCP stack itself.  They:\r
+\r
+       + May be based on driver code provided by the chip vendors,\r
+       + May not have been tested in all possible configurations,\r
+       + Will not necessarily be optimised.\r
+       + May have a dependency on a particular PHY part number.\r
+       + May not necessarily comply with any particular coding standard.\r
+       + May have dependencies on chip company libraries.\r
+       + May include other hardware board dependencies.\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/SH2A/NetworkInterface.c
new file mode 100644 (file)
index 0000000..7c715a4
--- /dev/null
@@ -0,0 +1,144 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 150406 (C) 2015 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB:                                     ***\r
+ ***                                                                         ***\r
+ ***   This product is functional and is already being used in commercial    ***\r
+ ***   products.  Be aware however that we are still refining its design,    ***\r
+ ***   the source code does not yet fully conform to the strict coding and   ***\r
+ ***   style standards mandated by Real Time Engineers ltd., and the         ***\r
+ ***   documentation and testing is not necessarily complete.                ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * - Open source licensing -\r
+ * While FreeRTOS+TCP is in the lab it is provided only under version two of the\r
+ * GNU General Public License (GPL) (which is different to the standard FreeRTOS\r
+ * license).  FreeRTOS+TCP is free to download, use and distribute under the\r
+ * terms of that license provided the copyright notice and this text are not\r
+ * altered or removed from the source files.  The GPL V2 text is available on\r
+ * the gnu.org web site, and on the following\r
+ * URL: http://www.FreeRTOS.org/gpl-2.0.txt.  Active early adopters may, and\r
+ * solely at the discretion of Real Time Engineers Ltd., be offered versions\r
+ * under a license other then the GPL.\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_UDP_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* Hardware includes. */\r
+#include "hwEthernet.h"\r
+\r
+/* Demo includes. */\r
+#include "NetworkInterface.h"\r
+\r
+#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+/* When a packet is ready to be sent, if it cannot be sent immediately then the\r
+task performing the transmit will block for niTX_BUFFER_FREE_WAIT\r
+milliseconds.  It will do this a maximum of niMAX_TX_ATTEMPTS before giving\r
+up. */\r
+#define niTX_BUFFER_FREE_WAIT  ( ( TickType_t ) 2UL / portTICK_PERIOD_MS )\r
+#define niMAX_TX_ATTEMPTS              ( 5 )\r
+\r
+/* The length of the queue used to send interrupt status words from the\r
+interrupt handler to the deferred handler task. */\r
+#define niINTERRUPT_QUEUE_LENGTH       ( 10 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes\r
+ */\r
+extern void vEMACHandlerTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The queue used to communicate Ethernet events with the IP task. */\r
+extern QueueHandle_t xNetworkEventQueue;\r
+\r
+/* The semaphore used to wake the deferred interrupt handler task when an Rx\r
+interrupt is received. */\r
+SemaphoreHandle_t xEMACRxEventSemaphore = NULL;\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+BaseType_t xStatus, xReturn;\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+       /* Initialise the MAC. */\r
+       vInitEmac();\r
+\r
+       while( lEMACWaitForLink() != pdPASS )\r
+    {\r
+        vTaskDelay( 20 );\r
+    }\r
+\r
+       vSemaphoreCreateBinary( xEMACRxEventSemaphore );\r
+       configASSERT( xEMACRxEventSemaphore );\r
+\r
+       /* The handler task is created at the highest possible priority to\r
+       ensure the interrupt handler can return directly to it. */\r
+       xTaskCreate( vEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );\r
+       xReturn = pdPASS;\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )\r
+{\r
+extern void vEMACCopyWrite( uint8_t * pucBuffer, uint16_t usLength );\r
+\r
+       vEMACCopyWrite( pxNetworkBuffer->pucBuffer, pxNetworkBuffer->xDataLength );\r
+\r
+       /* Finished with the network buffer. */\r
+       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
new file mode 100644 (file)
index 0000000..d294fe9
--- /dev/null
@@ -0,0 +1,1458 @@
+/*\r
+ * Some constants, hardware definitions and comments taken from ST's HAL driver\r
+ * library, COPYRIGHT(c) 2015 STMicroelectronics.\r
+ */\r
+\r
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "FreeRTOS_DNS.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+/* ST includes. */\r
+#include "stm32f4xx_hal.h"\r
+\r
+#ifndef        BMSR_LINK_STATUS\r
+       #define BMSR_LINK_STATUS            0x0004UL\r
+#endif\r
+\r
+#ifndef        PHY_LS_HIGH_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+       receiving packets. */\r
+       #define PHY_LS_HIGH_CHECK_TIME_MS       15000\r
+#endif\r
+\r
+#ifndef        PHY_LS_LOW_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still low every second. */\r
+       #define PHY_LS_LOW_CHECK_TIME_MS        1000\r
+#endif\r
+\r
+/* Interrupt events to process.  Currently only the Rx event is processed\r
+although code for other events is included to allow for possible future\r
+expansion. */\r
+#define EMAC_IF_RX_EVENT        1UL\r
+#define EMAC_IF_TX_EVENT        2UL\r
+#define EMAC_IF_ERR_EVENT       4UL\r
+#define EMAC_IF_ALL_EVENT       ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )\r
+\r
+#define ETH_DMA_ALL_INTS \\r
+       ( ETH_DMA_IT_TST | ETH_DMA_IT_PMT | ETH_DMA_IT_MMC | ETH_DMA_IT_NIS | ETH_DMA_IT_ER | \\r
+         ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \\r
+         ETH_DMA_IT_TU | ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T )\r
+\r
+/* Naming and numbering of PHY registers. */\r
+#define PHY_REG_00_BMCR                        0x00    /* Basic Mode Control Register. */\r
+#define PHY_REG_01_BMSR                        0x01    /* Basic Mode Status Register. */\r
+#define PHY_REG_02_PHYSID1             0x02    /* PHYS ID 1 */\r
+#define PHY_REG_03_PHYSID2             0x03    /* PHYS ID 2 */\r
+#define PHY_REG_04_ADVERTISE   0x04    /* Advertisement control reg */\r
+\r
+#define PHY_ID_LAN8720         0x0007c0f0\r
+#define PHY_ID_DP83848I                0x20005C90\r
+\r
+#ifndef USE_STM324xG_EVAL\r
+       #define USE_STM324xG_EVAL       1\r
+#endif\r
+\r
+#if( USE_STM324xG_EVAL == 0 )\r
+       #define EXPECTED_PHY_ID                 PHY_ID_LAN8720\r
+       #define PHY_REG_1F_PHYSPCS              0x1F    /* 31 RW PHY Special Control Status */\r
+       /* Use 3 bits in register 31 */\r
+       #define PHYSPCS_SPEED_MASK              0x0C\r
+       #define PHYSPCS_SPEED_10                0x04\r
+       #define PHYSPCS_SPEED_100               0x08\r
+       #define PHYSPCS_FULL_DUPLEX             0x10\r
+#else\r
+       #define EXPECTED_PHY_ID         PHY_ID_DP83848I\r
+\r
+       #define PHY_REG_10_PHY_SR               0x10    /* PHY status register Offset */\r
+       #define PHY_REG_19_PHYCR                0x19    /* 25 RW PHY Control Register */\r
+#endif\r
+\r
+/* Some defines used internally here to indicate preferences about speed, MDIX\r
+(wired direct or crossed), and duplex (half or full). */\r
+#define        PHY_SPEED_10       1\r
+#define        PHY_SPEED_100      2\r
+#define        PHY_SPEED_AUTO     (PHY_SPEED_10|PHY_SPEED_100)\r
+\r
+#define        PHY_MDIX_DIRECT    1\r
+#define        PHY_MDIX_CROSSED   2\r
+#define        PHY_MDIX_AUTO      (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT)\r
+\r
+#define        PHY_DUPLEX_HALF    1\r
+#define        PHY_DUPLEX_FULL    2\r
+#define        PHY_DUPLEX_AUTO    (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF)\r
+\r
+#define PHY_AUTONEGO_COMPLETE    ((uint16_t)0x0020)  /*!< Auto-Negotiation process completed   */\r
+\r
+/*\r
+ * Description of all capabilities that can be advertised to\r
+ * the peer (usually a switch or router).\r
+ */\r
+#define ADVERTISE_CSMA                 0x0001          /* Only selector supported. */\r
+#define ADVERTISE_10HALF               0x0020          /* Try for 10mbps half-duplex. */\r
+#define ADVERTISE_10FULL               0x0040          /* Try for 10mbps full-duplex. */\r
+#define ADVERTISE_100HALF              0x0080          /* Try for 100mbps half-duplex. */\r
+#define ADVERTISE_100FULL              0x0100          /* Try for 100mbps full-duplex. */\r
+\r
+#define ADVERTISE_ALL                  ( ADVERTISE_10HALF | ADVERTISE_10FULL | \\r
+                                                                 ADVERTISE_100HALF | ADVERTISE_100FULL)\r
+\r
+/*\r
+ * Value for the 'PHY_REG_00_BMCR', the PHY's Basic Mode Control Register.\r
+ */\r
+#define BMCR_FULLDPLX                  0x0100          /* Full duplex. */\r
+#define BMCR_ANRESTART                 0x0200          /* Auto negotiation restart. */\r
+#define BMCR_ANENABLE                  0x1000          /* Enable auto negotiation. */\r
+#define BMCR_SPEED100                  0x2000          /* Select 100Mbps. */\r
+#define BMCR_RESET                             0x8000          /* Reset the PHY. */\r
+\r
+#define PHYCR_MDIX_EN                  0x8000          /* Enable Auto MDIX. */\r
+#define PHYCR_MDIX_FORCE               0x4000          /* Force MDIX crossed. */\r
+\r
+#define ipFRAGMENT_OFFSET_BIT_MASK             ( ( uint16_t ) 0x0fff ) /* The bits in the two byte IP header field that make up the fragment offset value. */\r
+\r
+/*\r
+ * Most users will want a PHY that negotiates about\r
+ * the connection properties: speed, dmix and duplex.\r
+ * On some rare cases, you want to select what is being\r
+ * advertised, properties like MDIX and duplex.\r
+ */\r
+\r
+#if !defined( ipconfigETHERNET_AN_ENABLE )\r
+       /* Enable auto-negotiation */\r
+       #define ipconfigETHERNET_AN_ENABLE                              1\r
+#endif\r
+\r
+#if !defined( ipconfigETHERNET_AUTO_CROSS_ENABLE )\r
+       #define ipconfigETHERNET_AUTO_CROSS_ENABLE              1\r
+#endif\r
+\r
+#if( ipconfigETHERNET_AN_ENABLE == 0 )\r
+       /*\r
+        * The following three defines are only used in case there\r
+        * is no auto-negotiation.\r
+        */\r
+       #if !defined( ipconfigETHERNET_CROSSED_LINK )\r
+               #define ipconfigETHERNET_CROSSED_LINK                   1\r
+       #endif\r
+\r
+       #if !defined( ipconfigETHERNET_USE_100MB )\r
+               #define ipconfigETHERNET_USE_100MB                              1\r
+       #endif\r
+\r
+       #if !defined( ipconfigETHERNET_USE_FULL_DUPLEX )\r
+               #define ipconfigETHERNET_USE_FULL_DUPLEX                1\r
+       #endif\r
+#endif /* ipconfigETHERNET_AN_ENABLE == 0 */\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to twice\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+       #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*\r
+ * Force a negotiation with the Switch or Router and wait for LS.\r
+ */\r
+static void prvEthernetUpdateConfig( BaseType_t xForce );\r
+\r
+/*\r
+ * See if there is a new packet and forward it to the IP-task.\r
+ */\r
+static BaseType_t prvNetworkInterfaceInput( void );\r
+\r
+#if( ipconfigUSE_LLMNR != 0 )\r
+       /*\r
+        * For LLMNR, an extra MAC-address must be configured to\r
+        * be able to receive the multicast messages.\r
+        */\r
+       static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr);\r
+#endif\r
+\r
+/*\r
+ * Check if a given packet should be accepted.\r
+ */\r
+static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer );\r
+\r
+/*\r
+ * Initialise the TX descriptors.\r
+ */\r
+static void prvDMATxDescListInit( void );\r
+\r
+/*\r
+ * Initialise the RX descriptors.\r
+ */\r
+static void prvDMARxDescListInit( void );\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       /* After packets have been sent, the network\r
+       buffers will be released. */\r
+       static void vClearTXBuffers( void );\r
+#endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+typedef struct _PhyProperties_t\r
+{\r
+       uint8_t speed;\r
+       uint8_t mdix;\r
+       uint8_t duplex;\r
+       uint8_t spare;\r
+} PhyProperties_t;\r
+\r
+/* Bit map of outstanding ETH interrupt events for processing.  Currently only\r
+the Rx interrupt is handled, although code is included for other events to\r
+enable future expansion. */\r
+static volatile uint32_t ulISREvents;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };\r
+#endif\r
+\r
+/* Ethernet handle. */\r
+static ETH_HandleTypeDef xETH;\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       /* xTXDescriptorSemaphore is a counting semaphore with\r
+       a maximum count of ETH_TXBUFNB, which is the number of\r
+       DMA TX descriptors. */\r
+       static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
+#endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+/*\r
+ * Note: it is adviced to define both\r
+ *\r
+ *     #define  ipconfigZERO_COPY_RX_DRIVER   1\r
+ *     #define  ipconfigZERO_COPY_TX_DRIVER   1\r
+ *\r
+ * The method using memcpy is slower and probaly uses more RAM memory.\r
+ * The possibility is left in the code just for comparison.\r
+ *\r
+ * It is adviced to define ETH_TXBUFNB at least 4. Note that no\r
+ * TX buffers are allocated in a zero-copy driver.\r
+ */\r
+/* MAC buffers: ---------------------------------------------------------*/\r
+__ALIGN_BEGIN ETH_DMADescTypeDef  DMARxDscrTab[ ETH_RXBUFNB ] __ALIGN_END;/* Ethernet Rx MA Descriptor */\r
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 )\r
+       __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END; /* Ethernet Receive Buffer */\r
+#endif\r
+\r
+__ALIGN_BEGIN ETH_DMADescTypeDef  DMATxDscrTab[ ETH_TXBUFNB ] __ALIGN_END;/* Ethernet Tx DMA Descriptor */\r
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+       __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END; /* Ethernet Transmit Buffer */\r
+#endif\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       /* DMATxDescToClear points to the next TX DMA descriptor\r
+       that must be cleared by vClearTXBuffers(). */\r
+       static __IO ETH_DMADescTypeDef  *DMATxDescToClear;\r
+#endif\r
+\r
+/* Value to be written into the 'Basic mode Control Register'. */\r
+static uint32_t ulBCRvalue;\r
+\r
+/* Value to be written into the 'Advertisement Control Register'. */\r
+static uint32_t ulACRValue;\r
+\r
+/* ucMACAddress as it appears in main.c */\r
+extern const uint8_t ucMACAddress[ 6 ];\r
+\r
+/* Holds the handle of the task used as a deferred interrupt processor.  The\r
+handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
+related interrupts. */\r
+static TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+/* For local use only: describe the PHY's properties: */\r
+const PhyProperties_t xPHYProperties =\r
+{\r
+       #if( ipconfigETHERNET_AN_ENABLE != 0 )\r
+               .speed = PHY_SPEED_AUTO,\r
+               .duplex = PHY_DUPLEX_AUTO,\r
+       #else\r
+               #if( ipconfigETHERNET_USE_100MB != 0 )\r
+                       .speed = PHY_SPEED_100,\r
+               #else\r
+                       .speed = PHY_SPEED_10,\r
+               #endif\r
+\r
+               #if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )\r
+                       .duplex = PHY_DUPLEX_FULL,\r
+               #else\r
+                       .duplex = PHY_DUPLEX_HALF,\r
+               #endif\r
+       #endif\r
+\r
+       #if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )\r
+               .mdix = PHY_MDIX_AUTO,\r
+       #elif( ipconfigETHERNET_CROSSED_LINK != 0 )\r
+               .mdix = PHY_MDIX_CROSSED,\r
+       #else\r
+               .mdix = PHY_MDIX_DIRECT,\r
+       #endif\r
+};\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth )\r
+{\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       /* Ethernet RX-Complete callback function, elsewhere declared as weak. */\r
+    ulISREvents |= EMAC_IF_RX_EVENT;\r
+       /* Wakeup the prvEMACHandlerTask. */\r
+       if( xEMACTaskHandle != NULL )\r
+       {\r
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+               portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )\r
+       {\r
+       BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+               /* This call-back is only useful in case packets are being sent\r
+               zero-copy.  Once they're sent, the buffers will be released\r
+               by the function vClearTXBuffers(). */\r
+               ulISREvents |= EMAC_IF_TX_EVENT;\r
+               /* Wakeup the prvEMACHandlerTask. */\r
+               if( xEMACTaskHandle != NULL )\r
+               {\r
+                       vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+                       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+               }\r
+\r
+       }\r
+#endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       static void vClearTXBuffers()\r
+       {\r
+       __IO ETH_DMADescTypeDef  *txLastDescriptor = xETH.TxDesc;\r
+       NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+       uint8_t *ucPayLoad;\r
+       size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
+\r
+               /* This function is called after a TX-completion interrupt.\r
+               It will release each Network Buffer used in xNetworkInterfaceOutput().\r
+               'uxCount' represents the number of descriptors given to DMA for transmission.\r
+               After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */\r
+               while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )\r
+               {\r
+                       if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )\r
+                       {\r
+                               break;\r
+                       }\r
+\r
+                       ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;\r
+\r
+                       if( ucPayLoad != NULL )\r
+                       {\r
+                               pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad );\r
+                               if( pxNetworkBuffer != NULL )\r
+                               {\r
+                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) ;\r
+                               }\r
+                               DMATxDescToClear->Buffer1Addr = ( uint32_t )0u;\r
+                       }\r
+\r
+                       DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );\r
+\r
+                       uxCount--;\r
+                       /* Tell the counting semaphore that one more TX descriptor is available. */\r
+                       xSemaphoreGive( xTXDescriptorSemaphore );\r
+               }\r
+       }\r
+#endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+HAL_StatusTypeDef hal_eth_init_status;\r
+BaseType_t xResult;\r
+\r
+       if( xEMACTaskHandle == NULL )\r
+       {\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       if( xTXDescriptorSemaphore == NULL )\r
+                       {\r
+                               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );\r
+                               configASSERT( xTXDescriptorSemaphore );\r
+                       }\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+               /* Initialise ETH */\r
+\r
+               xETH.Instance = ETH;\r
+               xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;\r
+               xETH.Init.Speed = ETH_SPEED_100M;\r
+               xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
+               xETH.Init.PhyAddress = 1;\r
+\r
+               xETH.Init.MACAddr = ( uint8_t *) ucMACAddress;\r
+               xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;\r
+\r
+               /* using the ETH_CHECKSUM_BY_HARDWARE option:\r
+               both the IP and the protocol checksums will be calculated\r
+               by the peripheral. */\r
+               xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;\r
+\r
+               xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;\r
+               hal_eth_init_status = HAL_ETH_Init( &xETH );\r
+\r
+               /* Only for inspection by debugger. */\r
+               ( void ) hal_eth_init_status;\r
+\r
+               /* Set the TxDesc and RxDesc pointers. */\r
+               xETH.TxDesc = DMATxDscrTab;\r
+               xETH.RxDesc = DMARxDscrTab;\r
+\r
+               /* Make sure that all unused fields are cleared. */\r
+               memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );\r
+               memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );\r
+\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               {\r
+                       /* Initialize Tx Descriptors list: Chain Mode */\r
+                       DMATxDescToClear = DMATxDscrTab;\r
+               }\r
+               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+               /* Initialise TX-descriptors. */\r
+               prvDMATxDescListInit();\r
+\r
+               /* Initialise RX-descriptors. */\r
+               prvDMARxDescListInit();\r
+\r
+               #if( ipconfigUSE_LLMNR != 0 )\r
+               {\r
+                       /* Program the LLMNR address at index 1. */\r
+                       prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );\r
+               }\r
+               #endif\r
+\r
+               /* Force a negotiation with the Switch or Router and wait for LS. */\r
+               prvEthernetUpdateConfig( pdTRUE );\r
+\r
+               /* The deferred interrupt handler task is created at the highest\r
+               possible priority to ensure the interrupt handler can return directly\r
+               to it.  The task's handle is stored in xEMACTaskHandle so interrupts can\r
+               notify the task when there is something to process. */\r
+               xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+       } /* if( xEMACTaskHandle == NULL ) */\r
+\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+       {\r
+               xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;\r
+               xResult = pdPASS;\r
+               FreeRTOS_printf( ( "Link Status is high\n" ) ) ;\r
+       }\r
+       else\r
+       {\r
+               /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running\r
+               and it will keep on checking the PHY and set ulPHYLinkStatus when necessary. */\r
+               xResult = pdFAIL;\r
+               FreeRTOS_printf( ( "Link Status still low\n" ) ) ;\r
+       }\r
+       /* When returning non-zero, the stack will become active and\r
+    start DHCP (in configured) */\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvDMATxDescListInit()\r
+{\r
+ETH_DMADescTypeDef *pxDMADescriptor;\r
+BaseType_t xIndex;\r
+\r
+       /* Get the pointer on the first member of the descriptor list */\r
+       pxDMADescriptor = DMATxDscrTab;\r
+\r
+       /* Fill each DMA descriptor with the right values */\r
+       for( xIndex = 0; xIndex < ETH_TXBUFNB; xIndex++, pxDMADescriptor++ )\r
+       {\r
+               /* Set Second Address Chained bit */\r
+               pxDMADescriptor->Status = ETH_DMATXDESC_TCH;\r
+\r
+               #if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+               {\r
+                       /* Set Buffer1 address pointer */\r
+                       pxDMADescriptor->Buffer1Addr = ( uint32_t )( Tx_Buff[ xIndex ] );\r
+               }\r
+               #endif\r
+\r
+               if( xETH.Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE )\r
+               {\r
+                       /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */\r
+                       pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;\r
+               }\r
+\r
+               /* Initialize the next descriptor with the Next Descriptor Polling Enable */\r
+               if( xIndex < ETH_TXBUFNB - 1 )\r
+               {\r
+                       /* Set next descriptor address register with next descriptor base address */\r
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 );\r
+               }\r
+               else\r
+               {\r
+                       /* For last descriptor, set next descriptor address register equal to the first descriptor base address */\r
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMATxDscrTab;\r
+               }\r
+       }\r
+\r
+       /* Set Transmit Descriptor List Address Register */\r
+       xETH.Instance->DMATDLAR = ( uint32_t ) DMATxDscrTab;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvDMARxDescListInit()\r
+{\r
+ETH_DMADescTypeDef *pxDMADescriptor;\r
+BaseType_t xIndex;\r
+       /*\r
+        * RX-descriptors.\r
+        */\r
+\r
+       /* Get the pointer on the first member of the descriptor list */\r
+       pxDMADescriptor = DMARxDscrTab;\r
+\r
+       /* Fill each DMA descriptor with the right values */\r
+       for( xIndex = 0; xIndex < ETH_RXBUFNB; xIndex++, pxDMADescriptor++ )\r
+       {\r
+\r
+               /* Set Buffer1 size and Second Address Chained bit */\r
+               pxDMADescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;  \r
+\r
+               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+               {\r
+               /* Set Buffer1 address pointer */\r
+               NetworkBufferDescriptor_t *pxBuffer;\r
+\r
+                       pxBuffer = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, 100ul );\r
+                       /* If the assert below fails, make sure that there are at least 'ETH_RXBUFNB'\r
+                       Network Buffers available during start-up ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) */\r
+                       configASSERT( pxBuffer != NULL );\r
+                       if( pxBuffer != NULL )\r
+                       {\r
+                               pxDMADescriptor->Buffer1Addr = (uint32_t)pxBuffer->pucEthernetBuffer;\r
+                               pxDMADescriptor->Status = ETH_DMARXDESC_OWN;\r
+                       }\r
+               }\r
+               #else\r
+               {\r
+                       /* Set Buffer1 address pointer */\r
+                       pxDMADescriptor->Buffer1Addr = ( uint32_t )( Rx_Buff[ xIndex ] );\r
+                       /* Set Own bit of the Rx descriptor Status */\r
+                       pxDMADescriptor->Status = ETH_DMARXDESC_OWN;\r
+               }\r
+               #endif\r
+\r
+               /* Initialize the next descriptor with the Next Descriptor Polling Enable */\r
+               if( xIndex < ETH_RXBUFNB - 1 )\r
+               {\r
+                       /* Set next descriptor address register with next descriptor base address */\r
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t )( pxDMADescriptor + 1 );\r
+               }\r
+               else\r
+               {\r
+                       /* For last descriptor, set next descriptor address register equal to the first descriptor base address */\r
+                       pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMARxDscrTab;\r
+               }\r
+\r
+       }\r
+       /* Set Receive Descriptor List Address Register */\r
+       xETH.Instance->DMARDLAR = ( uint32_t ) DMARxDscrTab;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8_t *Addr)\r
+{\r
+uint32_t ulTempReg;\r
+\r
+       /* Calculate the selected MAC address high register. */\r
+       ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];\r
+\r
+       /* Load the selected MAC address high register. */\r
+       ( *(__IO uint32_t *)( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg;\r
+\r
+       /* Calculate the selected MAC address low register. */\r
+       ulTempReg = ( ( uint32_t ) Addr[ 3 ] << 24 ) | ( ( uint32_t ) Addr[ 2 ] << 16 ) | ( ( uint32_t ) Addr[ 1 ] << 8 ) | Addr[ 0 ];\r
+\r
+       /* Load the selected MAC address low register */\r
+       ( *(__IO uint32_t *) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )\r
+{\r
+BaseType_t xReturn = pdFAIL;\r
+uint32_t ulTransmitSize = 0;\r
+__IO ETH_DMADescTypeDef *pxDmaTxDesc;\r
+/* Do not wait too long for a free TX DMA buffer. */\r
+const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );\r
+\r
+       #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
+       {\r
+       ProtocolPacket_t *pxPacket;\r
+\r
+               /* If the peripheral must calculate the checksum, it wants\r
+               the protocol checksum to have a value of zero. */\r
+               pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );\r
+\r
+               if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP )\r
+               {\r
+                       pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;\r
+               }\r
+       }\r
+       #endif\r
+\r
+       /* Open a do {} while ( 0 ) loop to be able to call break. */\r
+       do\r
+       {\r
+               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+               {\r
+                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+                       {\r
+                               if( xTXDescriptorSemaphore == NULL )\r
+                               {\r
+                                       break;\r
+                               }\r
+                               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
+                               {\r
+                                       /* Time-out waiting for a free TX descriptor. */\r
+                                       break;\r
+                               }\r
+                       }\r
+                       #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+                       /* This function does the actual transmission of the packet. The packet is\r
+                       contained in 'pxDescriptor' that is passed to the function. */\r
+                       pxDmaTxDesc = xETH.TxDesc;\r
+\r
+                       /* Is this buffer available? */\r
+                       if( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 )\r
+                       {\r
+                               /* Is this buffer available? */\r
+                               /* Get bytes in current buffer. */\r
+                               ulTransmitSize = pxDescriptor->xDataLength;\r
+\r
+                               if( ulTransmitSize > ETH_TX_BUF_SIZE )\r
+                               {\r
+                                       ulTransmitSize = ETH_TX_BUF_SIZE;\r
+                               }\r
+\r
+                               #if( ipconfigZERO_COPY_TX_DRIVER == 0 )\r
+                               {\r
+                                       /* Copy the bytes. */\r
+                                       memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize );\r
+                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL;\r
+                               }\r
+                               #else\r
+                               {\r
+                                       /* Move the buffer. */\r
+                                       pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer;\r
+                                       /* Ask to set the IPv4 checksum.\r
+                                       Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */\r
+                                       pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;\r
+                                       /* The Network Buffer has been passed to DMA, no need to release it. */\r
+                                       bReleaseAfterSend = pdFALSE_UNSIGNED;\r
+                               }\r
+                               #endif /* ipconfigZERO_COPY_TX_DRIVER */\r
+\r
+                               /* Prepare transmit descriptors to give to DMA. */\r
+\r
+                               /* Set LAST and FIRST segment */\r
+                               pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;\r
+                               /* Set frame size */\r
+                               pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );\r
+                               /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */\r
+                               pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;\r
+\r
+                               /* Point to next descriptor */\r
+                               xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr );\r
+       \r
+                               /* Resume DMA transmission*/\r
+                               xETH.Instance->DMATPDR = 0;\r
+                               iptraceNETWORK_INTERFACE_TRANSMIT();\r
+                               xReturn = pdPASS;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* The PHY has no Link Status, packet shall be dropped. */\r
+               }\r
+       } while( 0 );\r
+       /* The buffer has been sent so can be released. */\r
+       if( bReleaseAfterSend != pdFALSE )\r
+       {\r
+               vReleaseNetworkBufferAndDescriptor( pxDescriptor );\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t xMayAcceptPacket( uint8_t *pcBuffer )\r
+{\r
+const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;\r
+\r
+       switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType )\r
+       {\r
+       case ipARP_FRAME_TYPE:\r
+               /* Check it later. */\r
+               return pdTRUE;\r
+       case ipIPv4_FRAME_TYPE:\r
+               /* Check it here. */\r
+               break;\r
+       default:\r
+               /* Refuse the packet. */\r
+               return pdFALSE;\r
+       }\r
+\r
+       #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 )\r
+       {\r
+               const IPHeader_t *pxIPHeader = &(pxProtPacket->xTCPPacket.xIPHeader);\r
+               uint32_t ulDestinationIPAddress;\r
+\r
+               /* Ensure that the incoming packet is not fragmented (only outgoing packets\r
+                * can be fragmented) as these are the only handled IP frames currently. */\r
+               if( ( pxIPHeader->usFragmentOffset & FreeRTOS_ntohs( ipFRAGMENT_OFFSET_BIT_MASK ) ) != 0U )\r
+               {\r
+                       return pdFALSE;\r
+               }\r
+               /* HT: Might want to make the following configurable because\r
+                * most IP messages have a standard length of 20 bytes */\r
+\r
+               /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes\r
+                * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */\r
+               if( pxIPHeader->ucVersionHeaderLength < 0x45 || pxIPHeader->ucVersionHeaderLength > 0x4F )\r
+               {\r
+                       return pdFALSE;\r
+               }\r
+\r
+               ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;\r
+               /* Is the packet for this node? */\r
+               if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&\r
+                       /* Is it a broadcast address x.x.x.255 ? */\r
+                       ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) &&\r
+               #if( ipconfigUSE_LLMNR == 1 )\r
+                       ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&\r
+               #endif\r
+                       ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) {\r
+                       FreeRTOS_printf( ( "Drop IP %lxip\n", FreeRTOS_ntohl( ulDestinationIPAddress ) ) );\r
+                       return pdFALSE;\r
+               }\r
+\r
+               if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )\r
+               {\r
+                       uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort;\r
+\r
+                       if( ( xPortHasUDPSocket( port ) == pdFALSE )\r
+                       #if ipconfigUSE_LLMNR == 1\r
+                               && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) )\r
+                       #endif\r
+                       #if ipconfigUSE_NBNS == 1\r
+                               && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) )\r
+                       #endif\r
+                       #if ipconfigUSE_DNS == 1\r
+                               && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) )\r
+                       #endif\r
+                               ) {\r
+                               /* Drop this packet, not for this device. */\r
+                               return pdFALSE;\r
+                       }\r
+               }\r
+       }\r
+       #endif  /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvNetworkInterfaceInput( void )\r
+{\r
+NetworkBufferDescriptor_t *pxCurDescriptor;\r
+NetworkBufferDescriptor_t *pxNewDescriptor = NULL;\r
+BaseType_t xReceivedLength, xAccepted;\r
+__IO ETH_DMADescTypeDef *pxDMARxDescriptor;\r
+xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );\r
+uint8_t *pucBuffer;\r
+\r
+       pxDMARxDescriptor = xETH.RxDesc;\r
+\r
+       if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 )\r
+       {\r
+               /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */\r
+               xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4;\r
+\r
+               pucBuffer = (uint8_t *) pxDMARxDescriptor->Buffer1Addr;\r
+\r
+               /* Update the ETHERNET DMA global Rx descriptor with next Rx descriptor */\r
+               /* Chained Mode */    \r
+               /* Selects the next DMA Rx descriptor list for next buffer to read */ \r
+               xETH.RxDesc = ( ETH_DMADescTypeDef* )pxDMARxDescriptor->Buffer2NextDescAddr;\r
+       }\r
+       else\r
+       {\r
+               xReceivedLength = 0;\r
+       }\r
+\r
+       /* Obtain the size of the packet and put it into the "usReceivedLength" variable. */\r
+\r
+       /* get received frame */\r
+       if( xReceivedLength > 0ul )\r
+       {\r
+               /* In order to make the code easier and faster, only packets in a single buffer\r
+               will be accepted.  This can be done by making the buffers large enough to\r
+               hold a complete Ethernet packet (1536 bytes).\r
+               Therefore, two sanity checks: */\r
+               configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE );\r
+\r
+               if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT )\r
+               {\r
+                       /* Not an Ethernet frame-type or a checmsum error. */\r
+                       xAccepted = pdFALSE;\r
+               }\r
+               else\r
+               {\r
+                       /* See if this packet must be handled. */\r
+                       xAccepted = xMayAcceptPacket( pucBuffer );\r
+               }\r
+\r
+               if( xAccepted != pdFALSE )\r
+               {\r
+                       /* The packet wil be accepted, but check first if a new Network Buffer can\r
+                       be obtained. If not, the packet will still be dropped. */\r
+                       pxNewDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, xDescriptorWaitTime );\r
+\r
+                       if( pxNewDescriptor == NULL )\r
+                       {\r
+                               /* A new descriptor can not be allocated now. This packet will be dropped. */\r
+                               xAccepted = pdFALSE;\r
+                       }\r
+               }\r
+               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+               {\r
+                       /* Find out which Network Buffer was originally passed to the descriptor. */\r
+                       pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer );\r
+                       configASSERT( pxCurDescriptor != NULL );\r
+               }\r
+               #else\r
+               {\r
+                       /* In this mode, the two descriptors are the same. */\r
+                       pxCurDescriptor = pxNewDescriptor;\r
+                       if( pxNewDescriptor != NULL )\r
+                       {\r
+                               /* The packet is acepted and a new Network Buffer was created,\r
+                               copy data to the Network Bufffer. */\r
+                               memcpy( pxNewDescriptor->pucEthernetBuffer, pucBuffer, xReceivedLength );\r
+                       }\r
+               }\r
+               #endif\r
+\r
+               if( xAccepted != pdFALSE )\r
+               {\r
+                       pxCurDescriptor->xDataLength = xReceivedLength;\r
+                       xRxEvent.pvData = ( void * ) pxCurDescriptor;\r
+\r
+                       /* Pass the data to the TCP/IP task for processing. */\r
+                       if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )\r
+                       {\r
+                               /* Could not send the descriptor into the TCP/IP stack, it\r
+                               must be released. */\r
+                               vReleaseNetworkBufferAndDescriptor( pxCurDescriptor );\r
+                               iptraceETHERNET_RX_EVENT_LOST();\r
+                       }\r
+                       else\r
+                       {\r
+                               iptraceNETWORK_INTERFACE_RECEIVE();\r
+                       }\r
+               }\r
+\r
+               /* Release descriptors to DMA */\r
+               #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+               {\r
+                       /* Set Buffer1 address pointer */\r
+                       if( pxNewDescriptor != NULL )\r
+                       {\r
+                               pxDMARxDescriptor->Buffer1Addr = (uint32_t)pxNewDescriptor->pucEthernetBuffer;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* The packet was dropped and the same Network\r
+                               Buffer will be used to receive a new packet. */\r
+                       }\r
+               }\r
+               #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+\r
+               /* Set Buffer1 size and Second Address Chained bit */\r
+               pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;  \r
+               pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN;\r
+\r
+               /* When Rx Buffer unavailable flag is set clear it and resume\r
+               reception. */\r
+               if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 )\r
+               {\r
+                       /* Clear RBUS ETHERNET DMA flag. */\r
+                       xETH.Instance->DMASR = ETH_DMASR_RBUS;\r
+\r
+                       /* Resume DMA reception. */\r
+                       xETH.Instance->DMARPDR = 0;\r
+               }\r
+       }\r
+\r
+       return ( xReceivedLength > 0 );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vMACBProbePhy( void )\r
+{\r
+uint32_t ulConfig, ulAdvertise, ulLower, ulUpper, ulMACPhyID, ulValue;\r
+TimeOut_t xPhyTime;\r
+TickType_t xRemTime = 0;\r
+#if( EXPECTED_PHY_ID == PHY_ID_DP83848I )\r
+       uint32_t ulPhyControl;\r
+#endif\r
+\r
+       HAL_ETH_ReadPHYRegister(&xETH, PHY_REG_03_PHYSID2, &ulLower);\r
+       HAL_ETH_ReadPHYRegister(&xETH, PHY_REG_02_PHYSID1, &ulUpper);\r
+\r
+       ulMACPhyID = ( ( ulUpper << 16 ) & 0xFFFF0000 ) | ( ulLower & 0xFFF0 );\r
+\r
+       /* The expected ID for the 'LAN8720' is 0x0007c0f0. */\r
+       /* The expected ID for the 'DP83848I' is 0x20005C90. */\r
+\r
+       FreeRTOS_printf( ( "PHY ID %lX (%s)\n", ulMACPhyID,\r
+               ( ulMACPhyID == EXPECTED_PHY_ID ) ? "OK" : "Unknown" ) );\r
+\r
+       /* Remove compiler warning if FreeRTOS_printf() is not defined. */\r
+       ( void ) ulMACPhyID;\r
+\r
+    /* Set advertise register. */\r
+       if( ( xPHYProperties.speed == PHY_SPEED_AUTO ) && ( xPHYProperties.duplex == PHY_DUPLEX_AUTO ) )\r
+       {\r
+               ulAdvertise = ADVERTISE_CSMA | ADVERTISE_ALL;\r
+               /* Reset auto-negotiation capability. */\r
+       }\r
+       else\r
+       {\r
+               ulAdvertise = ADVERTISE_CSMA;\r
+\r
+               if( xPHYProperties.speed == PHY_SPEED_AUTO )\r
+               {\r
+                       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )\r
+                       {\r
+                               ulAdvertise |= ADVERTISE_10FULL | ADVERTISE_100FULL;\r
+                       }\r
+                       else\r
+                       {\r
+                               ulAdvertise |= ADVERTISE_10HALF | ADVERTISE_100HALF;\r
+                       }\r
+               }\r
+               else if( xPHYProperties.duplex == PHY_DUPLEX_AUTO )\r
+               {\r
+                       if( xPHYProperties.speed == PHY_SPEED_10 )\r
+                       {\r
+                               ulAdvertise |= ADVERTISE_10FULL | ADVERTISE_10HALF;\r
+                       }\r
+                       else\r
+                       {\r
+                               ulAdvertise |= ADVERTISE_100FULL | ADVERTISE_100HALF;\r
+                       }\r
+               }\r
+               else if( xPHYProperties.speed == PHY_SPEED_100 )\r
+               {\r
+                       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )\r
+                       {\r
+                               ulAdvertise |= ADVERTISE_100FULL;\r
+                       }\r
+                       else\r
+                       {\r
+                               ulAdvertise |= ADVERTISE_100HALF;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )\r
+                       {\r
+                               ulAdvertise |= ADVERTISE_10FULL;\r
+                       }\r
+                       else\r
+                       {\r
+                               ulAdvertise |= ADVERTISE_10HALF;\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* Read Control register. */\r
+       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulConfig );\r
+\r
+       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulConfig | BMCR_RESET );\r
+       xRemTime = ( TickType_t ) pdMS_TO_TICKS( 1000UL );\r
+       vTaskSetTimeOutState( &xPhyTime );\r
+\r
+       for( ; ; )\r
+       {\r
+               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulValue );\r
+               if( ( ulValue & BMCR_RESET ) == 0 )\r
+               {\r
+                       FreeRTOS_printf( ( "BMCR_RESET ready\n" ) );\r
+                       break;\r
+               }\r
+               if( xTaskCheckForTimeOut( &xPhyTime, &xRemTime ) != pdFALSE )\r
+               {\r
+                       FreeRTOS_printf( ( "BMCR_RESET timed out\n" ) );\r
+                       break;\r
+               }\r
+       }\r
+       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulConfig & ~BMCR_RESET );\r
+\r
+       vTaskDelay( pdMS_TO_TICKS( 50ul ) );\r
+\r
+    /* Write advertise register. */\r
+       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_04_ADVERTISE, ulAdvertise );\r
+\r
+       /*\r
+                       AN_EN        AN1         AN0       Forced Mode\r
+                         0           0           0        10BASE-T, Half-Duplex\r
+                         0           0           1        10BASE-T, Full-Duplex\r
+                         0           1           0        100BASE-TX, Half-Duplex\r
+                         0           1           1        100BASE-TX, Full-Duplex\r
+                       AN_EN        AN1         AN0       Advertised Mode\r
+                         1           0           0        10BASE-T, Half/Full-Duplex\r
+                         1           0           1        100BASE-TX, Half/Full-Duplex\r
+                         1           1           0        10BASE-T Half-Duplex\r
+                                                                                          100BASE-TX, Half-Duplex\r
+                         1           1           1        10BASE-T, Half/Full-Duplex\r
+                                                                                          100BASE-TX, Half/Full-Duplex\r
+       */\r
+\r
+    /* Read Control register. */\r
+       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulConfig );\r
+\r
+       ulConfig &= ~( BMCR_ANRESTART | BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX );\r
+\r
+       /* HT 12/9/14: always set AN-restart and AN-enable, even though the choices\r
+       are limited. */\r
+       ulConfig |= (BMCR_ANRESTART | BMCR_ANENABLE);\r
+\r
+       if( xPHYProperties.speed == PHY_SPEED_100 )\r
+       {\r
+               ulConfig |= BMCR_SPEED100;\r
+       }\r
+       else if( xPHYProperties.speed == PHY_SPEED_10 )\r
+       {\r
+               ulConfig &= ~BMCR_SPEED100;\r
+       }\r
+\r
+       if( xPHYProperties.duplex == PHY_DUPLEX_FULL )\r
+       {\r
+               ulConfig |= BMCR_FULLDPLX;\r
+       }\r
+       else if( xPHYProperties.duplex == PHY_DUPLEX_HALF )\r
+       {\r
+               ulConfig &= ~BMCR_FULLDPLX;\r
+       }\r
+\r
+       #if( EXPECTED_PHY_ID == PHY_ID_LAN8720 )\r
+       {\r
+       }\r
+       #elif( EXPECTED_PHY_ID == PHY_ID_DP83848I )\r
+       {\r
+               /* Read PHY Control register. */\r
+               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_19_PHYCR, &ulPhyControl );\r
+\r
+               /* Clear bits which might get set: */\r
+               ulPhyControl &= ~( PHYCR_MDIX_EN|PHYCR_MDIX_FORCE );\r
+\r
+               if( xPHYProperties.mdix == PHY_MDIX_AUTO )\r
+               {\r
+                       ulPhyControl |= PHYCR_MDIX_EN;\r
+               }\r
+               else if( xPHYProperties.mdix == PHY_MDIX_CROSSED )\r
+               {\r
+                       /* Force direct link = Use crossed RJ45 cable. */\r
+                       ulPhyControl &= ~PHYCR_MDIX_FORCE;\r
+               }\r
+               else\r
+               {\r
+                       /* Force crossed link = Use direct RJ45 cable. */\r
+                       ulPhyControl |= PHYCR_MDIX_FORCE;\r
+               }\r
+               /* update PHY Control Register. */\r
+               HAL_ETH_WritePHYRegister( &xETH, PHY_REG_19_PHYCR, ulPhyControl );\r
+       }\r
+       #endif\r
+       FreeRTOS_printf( ( "+TCP: advertise: %lX config %lX\n", ulAdvertise, ulConfig ) );\r
+\r
+       /* Now the two values to global values for later use. */\r
+       ulBCRvalue = ulConfig;\r
+       ulACRValue = ulAdvertise;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEthernetUpdateConfig( BaseType_t xForce )\r
+{\r
+__IO uint32_t ulTimeout = 0;\r
+uint32_t ulRegValue = 0;\r
+\r
+       FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS %d Force %d\n",\r
+               ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ,\r
+               xForce ) );\r
+\r
+       if( ( xForce != pdFALSE ) || ( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) )\r
+       {\r
+               /* Restart the auto-negotiation. */\r
+               if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE )\r
+               {\r
+                       /* Enable Auto-Negotiation. */\r
+                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulBCRvalue | BMCR_ANRESTART );\r
+                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_04_ADVERTISE, ulACRValue);\r
+\r
+                       /* Wait until the auto-negotiation will be completed */\r
+                       do\r
+                       {\r
+                               ulTimeout++;\r
+                               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &ulRegValue );\r
+                       } while( ( ( ulRegValue & PHY_AUTONEGO_COMPLETE) == 0 ) && ( ulTimeout < PHY_READ_TO ) );\r
+\r
+                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulBCRvalue & ~BMCR_ANRESTART );\r
+\r
+                       if( ulTimeout < PHY_READ_TO )\r
+                       {\r
+                               /* Reset Timeout counter. */\r
+                               ulTimeout = 0;\r
+\r
+                               HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &ulRegValue);\r
+                               if( ( ulRegValue & BMSR_LINK_STATUS ) != 0 )\r
+                               {\r
+                                       ulPHYLinkStatus |= BMSR_LINK_STATUS;\r
+                               }\r
+                               else\r
+                               {\r
+                                       ulPHYLinkStatus &= ~( BMSR_LINK_STATUS );\r
+                               }\r
+\r
+                               #if( EXPECTED_PHY_ID == PHY_ID_LAN8720 )\r
+                               {\r
+                               /* 31 RW PHY Special Control Status */\r
+                               uint32_t ulControlStatus;\r
+\r
+                                       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_1F_PHYSPCS, &ulControlStatus);\r
+                                       ulRegValue = 0;\r
+                                       if( ( ulControlStatus & PHYSPCS_FULL_DUPLEX ) != 0 )\r
+                                       {\r
+                                               ulRegValue |= PHY_DUPLEX_STATUS;\r
+                                       }\r
+                                       if( ( ulControlStatus & PHYSPCS_SPEED_MASK ) == PHYSPCS_SPEED_10 )\r
+                                       {\r
+                                               ulRegValue |= PHY_SPEED_STATUS;\r
+                                       }\r
+\r
+                               }\r
+                               #elif( EXPECTED_PHY_ID == PHY_ID_DP83848I )\r
+                               {\r
+                                       /* Read the result of the auto-negotiation. */\r
+                                       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_10_PHY_SR, &ulRegValue);\r
+                               }\r
+                               #endif\r
+                               FreeRTOS_printf( ( ">> Autonego ready: %08lx: %s duplex %u mbit %s status\n",\r
+                                       ulRegValue,\r
+                                       (ulRegValue & PHY_DUPLEX_STATUS) ? "full" : "half",\r
+                                       (ulRegValue & PHY_SPEED_STATUS) ? 10 : 100,\r
+                                       ((ulPHYLinkStatus |= BMSR_LINK_STATUS) != 0) ? "high" : "low" ) );\r
+\r
+                               /* Configure the MAC with the Duplex Mode fixed by the\r
+                               auto-negotiation process. */\r
+                               if( ( ulRegValue & PHY_DUPLEX_STATUS ) != ( uint32_t ) RESET )\r
+                               {\r
+                                       /* Set Ethernet duplex mode to Full-duplex following the\r
+                                       auto-negotiation. */\r
+                                       xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Set Ethernet duplex mode to Half-duplex following the\r
+                                       auto-negotiation. */\r
+                                       xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;\r
+                               }\r
+\r
+                               /* Configure the MAC with the speed fixed by the\r
+                               auto-negotiation process. */\r
+                               if( ( ulRegValue & PHY_SPEED_STATUS) != 0 )\r
+                               {\r
+                                       /* Set Ethernet speed to 10M following the\r
+                                       auto-negotiation. */\r
+                                       xETH.Init.Speed = ETH_SPEED_10M;\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Set Ethernet speed to 100M following the\r
+                                       auto-negotiation. */\r
+                                       xETH.Init.Speed = ETH_SPEED_100M;\r
+                               }\r
+                       }       /* if( ulTimeout < PHY_READ_TO ) */\r
+               }\r
+               else /* AutoNegotiation Disable */\r
+               {\r
+               uint16_t usValue;\r
+\r
+                       /* Check parameters */\r
+                       assert_param( IS_ETH_SPEED( xETH.Init.Speed ) );\r
+                       assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) );\r
+\r
+                       /* Set MAC Speed and Duplex Mode to PHY */\r
+                       usValue = ( uint16_t ) ( xETH.Init.DuplexMode >> 3 ) | ( uint16_t ) ( xETH.Init.Speed >> 1 );\r
+                       HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, usValue );\r
+               }\r
+\r
+               /* ETHERNET MAC Re-Configuration */\r
+               HAL_ETH_ConfigMAC( &xETH, (ETH_MACInitTypeDef *) NULL);\r
+\r
+               /* Restart MAC interface */\r
+               HAL_ETH_Start( &xETH);\r
+       }\r
+       else\r
+       {\r
+               /* Stop MAC interface */\r
+               HAL_ETH_Stop( &xETH );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+       {\r
+               xReturn = pdPASS;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdFAIL;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+UBaseType_t uxLastMinQueueSpace = 0;\r
+#endif\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult = 0;\r
+uint32_t xStatus;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       vTaskSetTimeOutState( &xPhyTime );\r
+       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+       for( ;; )\r
+       {\r
+               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+               if( uxLastMinBufferCount != uxCurrentCount )\r
+               {\r
+                       /* The logging produced below may be helpful\r
+                       while tuning +TCP: see how many buffers are in use. */\r
+                       uxLastMinBufferCount = uxCurrentCount;\r
+                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+               }\r
+\r
+               #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               if( xTXDescriptorSemaphore != NULL )\r
+               {\r
+               static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1;\r
+\r
+                       uxCurrentCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
+                       if( uxLowestSemCount > uxCurrentCount )\r
+                       {\r
+                               uxLowestSemCount = uxCurrentCount;\r
+                               FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );\r
+                       }\r
+\r
+               }\r
+               #endif\r
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+               {\r
+                       uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+                       if( uxLastMinQueueSpace != uxCurrentCount )\r
+                       {\r
+                               /* The logging produced below may be helpful\r
+                               while tuning +TCP: see how many buffers are in use. */\r
+                               uxLastMinQueueSpace = uxCurrentCount;\r
+                               FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+                       }\r
+               }\r
+               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+               if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )\r
+               {\r
+                       /* No events to process now, wait for the next. */\r
+                       ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
+               {\r
+                       ulISREvents &= ~EMAC_IF_RX_EVENT;\r
+\r
+                       xResult = prvNetworkInterfaceInput();\r
+                       if( xResult > 0 )\r
+                       {\r
+                               while( prvNetworkInterfaceInput() > 0 )\r
+                               {\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
+               {\r
+                       /* Code to release TX buffers if zero-copy is used. */\r
+                       ulISREvents &= ~EMAC_IF_TX_EVENT;\r
+                       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+                       {\r
+                               /* Check if DMA packets have been delivered. */\r
+                               vClearTXBuffers();\r
+                       }\r
+                       #endif\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )\r
+               {\r
+                       /* Future extension: logging about errors that occurred. */\r
+                       ulISREvents &= ~EMAC_IF_ERR_EVENT;\r
+               }\r
+\r
+               if( xResult > 0 )\r
+               {\r
+                       /* A packet was received. No need to check for the PHY status now,\r
+                       but set a timer to check it later on. */\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       xResult = 0;\r
+               }\r
+               else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )\r
+               {\r
+                       HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &xStatus );\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )\r
+                       {\r
+                               ulPHYLinkStatus = xStatus;\r
+                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );\r
+                               prvEthernetUpdateConfig( pdFALSE );\r
+                       }\r
+\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void ETH_IRQHandler( void )\r
+{\r
+       HAL_ETH_IRQHandler( &xETH );\r
+}\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/FaultInjection.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/FaultInjection.c
new file mode 100644 (file)
index 0000000..e100a4e
--- /dev/null
@@ -0,0 +1,173 @@
+#define xBUFFER_CACHE_SIZE                     10\r
+#define xMAX_FAULT_INJECTION_RATE      15\r
+#define xMIN_FAULT_INJECTION_RATE      3\r
+#define xNUM_FAULT_TYPES                       1\r
+\r
+static NetworkBufferDescriptor_t *xNetworkBufferCache[ xBUFFER_CACHE_SIZE ] = { 0 };\r
+\r
+#define xFAULT_LOG_SIZE 2048\r
+uint32_t ulInjectedFault[ xFAULT_LOG_SIZE ];\r
+uint32_t ulFaultLogIndex = 0;\r
+\r
+static BaseType_t prvCachePacket( NetworkBufferDescriptor_t *pxNetworkBufferIn )\r
+{\r
+BaseType_t x, xReturn = pdFALSE;\r
+\r
+       for( x = 0; x < xBUFFER_CACHE_SIZE; x++ )\r
+       {\r
+               if( xNetworkBufferCache[ x ] == NULL )\r
+               {\r
+                       xNetworkBufferCache[ x ] = pxNetworkBufferIn;\r
+                       xReturn = pdTRUE;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static NetworkBufferDescriptor_t *prvGetCachedPacket( void )\r
+{\r
+BaseType_t x;\r
+NetworkBufferDescriptor_t *pxReturn = NULL;\r
+\r
+       for( x = ( xBUFFER_CACHE_SIZE - 1 ); x >= 0; x-- )\r
+       {\r
+               if( xNetworkBufferCache[ x ] != NULL )\r
+               {\r
+                       pxReturn = xNetworkBufferCache[ x ];\r
+                       xNetworkBufferCache[ x ] = NULL;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static NetworkBufferDescriptor_t *prvDuplicatePacket( NetworkBufferDescriptor_t * pxOriginalPacket, const uint8_t *pucPacketData )\r
+{\r
+NetworkBufferDescriptor_t *pxReturn;\r
+\r
+       /* Obtain a new descriptor. */\r
+       pxReturn = pxGetNetworkBufferWithDescriptor( pxOriginalPacket->xDataLength, 0 );\r
+\r
+       if( pxReturn != NULL )\r
+       {\r
+               /* Copy in the packet data. */\r
+               pxReturn->xDataLength = pxOriginalPacket->xDataLength;\r
+               memcpy( pxReturn->pucEthernetBuffer, pucPacketData, pxOriginalPacket->xDataLength );\r
+       }\r
+\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static NetworkBufferDescriptor_t *prvRxFaultInjection( NetworkBufferDescriptor_t *pxNetworkBufferIn, const uint8_t *pucPacketData )\r
+{\r
+static uint32_t ulCallCount = 0, ulNextFaultCallCount = 0;\r
+NetworkBufferDescriptor_t *pxReturn = pxNetworkBufferIn;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+uint32_t ulFault;\r
+\r
+return pxNetworkBufferIn;\r
+\r
+       ulCallCount++;\r
+\r
+       if( ulCallCount > ulNextFaultCallCount )\r
+       {\r
+               ulNextFaultCallCount = ipconfigRAND32() % xMAX_FAULT_INJECTION_RATE;\r
+               if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE )\r
+               {\r
+                       ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE;\r
+               }\r
+\r
+               ulCallCount = 0;\r
+\r
+               ulFault = ipconfigRAND32() % xNUM_FAULT_TYPES;\r
+\r
+               if( ulFaultLogIndex < xFAULT_LOG_SIZE )\r
+               {\r
+                       ulInjectedFault[ ulFaultLogIndex ] = ulFault;\r
+                       ulFaultLogIndex++;\r
+               }\r
+\r
+               switch( ulFault )\r
+               {\r
+                       case 0:\r
+                               /* Just drop the packet. */\r
+                               vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+                               pxReturn = NULL;\r
+                               break;\r
+\r
+                       case 1:\r
+                               /* Store the packet in the cache for later. */\r
+                               if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )\r
+                               {\r
+                                       /* The packet may get sent later, it is not being sent\r
+                                       now. */\r
+                                       pxReturn = NULL;\r
+                               }\r
+                               break;\r
+\r
+                       case 2:\r
+                               /* Send a cached packet. */\r
+                               pxReturn = prvGetCachedPacket();\r
+                               if( pxReturn != NULL )\r
+                               {\r
+                                       /* A cached packet was obtained so drop the original\r
+                                       packet. */\r
+                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Could not obtain a packet from the cache so just return\r
+                                       the packet that was passed in. */\r
+                                       pxReturn = pxNetworkBufferIn;\r
+                               }\r
+                               break;\r
+\r
+                       case 4:\r
+\r
+                               /* Send a duplicate of the packet right away. */\r
+                               pxReturn = prvDuplicatePacket( pxNetworkBufferIn, pucPacketData );\r
+\r
+                               /* Send the original packet to the stack. */\r
+                               xRxEvent.pvData = ( void * ) pxNetworkBufferIn;\r
+                               if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+                               {\r
+                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+                               }\r
+                               break;\r
+\r
+                       case 5:\r
+\r
+                               /* Send both a cached packet and the current packet. */\r
+                               xRxEvent.pvData = ( void * ) prvGetCachedPacket();\r
+                               if( xRxEvent.pvData != NULL )\r
+                               {\r
+                                       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+                                       {\r
+                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );\r
+                                       }\r
+                               }\r
+                               break;\r
+\r
+                       case 6:\r
+                       case 7:\r
+                       case 8:\r
+                               /* Store the packet in the cache for later. */\r
+                               if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )\r
+                               {\r
+                                       /* The packet may get sent later, it is not being sent\r
+                                       now. */\r
+                                       pxReturn = NULL;\r
+                               }\r
+                               break;\r
+               }\r
+       }\r
+\r
+       return pxReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/WinPCap/NetworkInterface.c
new file mode 100644 (file)
index 0000000..1d92ade
--- /dev/null
@@ -0,0 +1,631 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* WinPCap includes. */\r
+#define HAVE_REMOTE\r
+#include "pcap.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+/* Thread-safe circular buffers are being used to pass data to and from the PCAP\r
+access functions. */\r
+#include "Win32-Extensions.h"\r
+#include "FreeRTOS_Stream_Buffer.h"\r
+\r
+/* Sizes of the thread safe circular buffers used to pass data to and from the\r
+WinPCAP Windows threads. */\r
+#define xSEND_BUFFER_SIZE  32768\r
+#define xRECV_BUFFER_SIZE  32768\r
+\r
+/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet\r
+driver will filter incoming packets and only pass the stack those packets it\r
+considers need processing. */\r
+#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer\r
+#else\r
+       #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )\r
+#endif\r
+\r
+/* Used to insert test code only. */\r
+#define niDISRUPT_PACKETS      0\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Windows threads that are outside of the control of the FreeRTOS simulator are\r
+ * used to interface with the WinPCAP libraries.\r
+ */\r
+DWORD WINAPI prvWinPcapRecvThread( void *pvParam );\r
+DWORD WINAPI prvWinPcapSendThread( void *pvParam );\r
+\r
+/*\r
+ * Print out a numbered list of network interfaces that are available on the\r
+ * host computer.\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
+static void prvOpenInterface( const char *pucName );\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
+/*\r
+ * A function that simulates Ethernet interrupts by periodically polling the\r
+ * WinPCap interface for new data.\r
+ */\r
+static void prvInterruptSimulatorTask( void *pvParameters );\r
+\r
+/*\r
+ * Create the buffers that are used to pass data between the FreeRTOS simulator\r
+ * and the Win32 threads that manage WinPCAP.\r
+ */\r
+static void prvCreateThreadSafeBuffers( void );\r
+\r
+/*\r
+ * Utility function used to format print messages only.\r
+ */\r
+static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Required by the WinPCap library. */\r
+static char cErrorBuffer[ PCAP_ERRBUF_SIZE ];\r
+\r
+/* An event used to wake up the Win32 thread that sends data through the WinPCAP\r
+library. */\r
+static void *pvSendEvent = NULL;\r
+\r
+/* _HT_ made the PCAP interface number configurable through the program's\r
+parameters in order to test in different machines. */\r
+static BaseType_t xConfigNextworkInterfaceToUse = configNETWORK_INTERFACE_TO_USE;\r
+\r
+/* Handles to the Windows threads that handle the PCAP IO. */\r
+static HANDLE vWinPcapRecvThreadHandle = NULL;\r
+static HANDLE vWinPcapSendThreadHandle = NULL;;\r
+\r
+/* The interface being used by WinPCap. */\r
+static pcap_t *pxOpenedInterfaceHandle = NULL;\r
+\r
+/* Circular buffers used by the PCAP Win32 threads. */\r
+static StreamBuffer_t *xSendBuffer = NULL;\r
+static StreamBuffer_t *xRecvBuffer = NULL;\r
+\r
+/* The MAC address initially set to the constants defined in FreeRTOSConfig.h. */\r
+extern uint8_t ucMACAddress[ 6 ];\r
+\r
+/* Logs the number of WinPCAP send failures, for viewing in the debugger only. */\r
+static volatile uint32_t ulWinPCAPSendFailures = 0;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+BaseType_t xReturn = pdFALSE;\r
+pcap_if_t *pxAllNetworkInterfaces;\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
+       if( pxOpenedInterfaceHandle != NULL )\r
+       {\r
+               xReturn = pdPASS;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvCreateThreadSafeBuffers( void )\r
+{\r
+       /* The buffer used to pass data to be transmitted from a FreeRTOS task to\r
+       the Win32 thread that sends via the WinPCAP library. */\r
+       if( xSendBuffer == NULL)\r
+       {\r
+               xSendBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) + xSEND_BUFFER_SIZE + 1 );\r
+               configASSERT( xSendBuffer );\r
+               memset( xSendBuffer, '\0', sizeof( *xSendBuffer ) - sizeof( xSendBuffer->ucArray ) );\r
+               xSendBuffer->LENGTH = xSEND_BUFFER_SIZE + 1;\r
+       }\r
+\r
+       /* The buffer used to pass received data from the Win32 thread that receives\r
+       via the WinPCAP library to the FreeRTOS task. */\r
+       if( xRecvBuffer == NULL)\r
+       {\r
+               xRecvBuffer = ( StreamBuffer_t * ) malloc( sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) + xRECV_BUFFER_SIZE + 1 );\r
+               configASSERT( xRecvBuffer );\r
+               memset( xRecvBuffer, '\0', sizeof( *xRecvBuffer ) - sizeof( xRecvBuffer->ucArray ) );\r
+               xRecvBuffer->LENGTH = xRECV_BUFFER_SIZE + 1;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )\r
+{\r
+size_t xSpace;\r
+\r
+       iptraceNETWORK_INTERFACE_TRANSMIT();\r
+       configASSERT( xIsCallingFromIPTask() == pdTRUE );\r
+\r
+       /* Both the length of the data being sent and the actual data being sent\r
+       are placed in the thread safe buffer used to pass data between the FreeRTOS\r
+       tasks and the Win32 thread that sends data via the WinPCAP library.  Drop\r
+       the packet if there is insufficient space in the buffer to hold both. */\r
+       xSpace = uxStreamBufferGetSpace( xSendBuffer );\r
+\r
+       if( ( pxNetworkBuffer->xDataLength <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&\r
+               ( xSpace >= ( pxNetworkBuffer->xDataLength + sizeof( pxNetworkBuffer->xDataLength ) ) ) )\r
+       {\r
+               /* First write in the length of the data, then write in the data\r
+               itself. */\r
+               uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) &( pxNetworkBuffer->xDataLength ), sizeof( pxNetworkBuffer->xDataLength ) );\r
+               uxStreamBufferAdd( xSendBuffer, 0, ( const uint8_t * ) pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );\r
+       }\r
+       else\r
+       {\r
+               FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: send buffers full to store %lu\n", pxNetworkBuffer->xDataLength ) );\r
+       }\r
+\r
+       /* Kick the Tx task in either case in case it doesn't know the buffer is\r
+       full. */\r
+       SetEvent( pvSendEvent );\r
+\r
+       /* The buffer has been sent so can be released. */\r
+       if( bReleaseAfterSend != pdFALSE )\r
+       {\r
+               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+       }\r
+\r
+       return pdPASS;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static pcap_if_t * prvPrintAvailableNetworkInterfaces( void )\r
+{\r
+pcap_if_t * pxAllNetworkInterfaces = NULL, *xInterface;\r
+int32_t lInterfaceNumber = 1;\r
+char cBuffer[ 512 ];\r
+\r
+       if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &pxAllNetworkInterfaces, cErrorBuffer ) == -1 )\r
+       {\r
+               printf( "Could not obtain a list of network interfaces\n%s\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
+                       /* The descriptions of the devices can be full of spaces, clean them\r
+                       a little.  printf() can only be used here because the network is not\r
+                       up yet - so no other network tasks will be running. */\r
+                       printf( "%d. %s\n", lInterfaceNumber, prvRemoveSpaces( cBuffer, sizeof( cBuffer ), xInterface->name ) );\r
+                       printf( "   (%s)\n", prvRemoveSpaces(cBuffer, sizeof( cBuffer ), xInterface->description ? xInterface->description : "No description" ) );\r
+                       printf( "\n" );\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( " \nNo network interfaces were found.\n" );\r
+               pxAllNetworkInterfaces = NULL;\r
+       }\r
+\r
+       printf( "The interface that will be opened is set by\n" );\r
+       printf( "\"configNETWORK_INTERFACE_TO_USE\" which should be defined in FreeRTOSConfig.h\n" );\r
+       printf( "Attempting to open interface number %d.\n", xConfigNextworkInterfaceToUse );\r
+\r
+       if( ( xConfigNextworkInterfaceToUse < 1L ) || ( xConfigNextworkInterfaceToUse > lInterfaceNumber ) )\r
+       {\r
+               printf( "configNETWORK_INTERFACE_TO_USE is not in the valid range.\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 prvOpenInterface( const char *pucName )\r
+{\r
+static char pucInterfaceName[ 256 ];\r
+\r
+       if( pucName != NULL )\r
+       {\r
+               strncpy( pucInterfaceName, pucName, sizeof( pucInterfaceName ) );\r
+       }\r
+\r
+       pxOpenedInterfaceHandle = pcap_open(    pucInterfaceName,               /* The name of the selected interface. */\r
+                                                                                       ipTOTAL_ETHERNET_FRAME_SIZE, /* The size of the packet to capture. */\r
+                                                                                       PCAP_OPENFLAG_PROMISCUOUS,      /* Open in promiscuous 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
+                                                                                                                                               traffic to the simulated IP address to be routed\r
+                                                                                                                                               to uIP, and traffic to the real IP address to be\r
+                                                                                                                                               routed to the Windows TCP/IP stack. */\r
+                                                                                       100,\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( "\n%s is not supported by WinPcap and cannot be opened\n", pucInterfaceName );\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
+/*-----------------------------------------------------------*/\r
+\r
+static void prvOpenSelectedNetworkInterface( pcap_if_t *pxAllNetworkInterfaces )\r
+{\r
+pcap_if_t *xInterface;\r
+int32_t x;\r
+\r
+       /* Walk the list of devices until the selected device is located. */\r
+       xInterface = pxAllNetworkInterfaces;\r
+       for( x = 0L; x < ( xConfigNextworkInterfaceToUse - 1L ); x++ )\r
+       {\r
+               xInterface = xInterface->next;\r
+       }\r
+\r
+       /* Open the selected interface. */\r
+       prvOpenInterface( xInterface->name );\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
+uint32_t ulNetMask;\r
+\r
+       /* Set up a filter so only the packets of interest are passed to the IP\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 ether host %x:%x:%x:%x:%x:%x",\r
+               ucMACAddress[0], ucMACAddress[1], ucMACAddress[2], ucMACAddress[3], ucMACAddress[4], ucMACAddress[5] );\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( "\nThe packet filter string is invalid\n" );\r
+       }\r
+       else\r
+       {\r
+               if( pcap_setfilter( pxOpenedInterfaceHandle, &xFilterCode ) < 0 )\r
+               {\r
+                       printf( "\nAn error occurred setting the packet filter.\n" );\r
+               }\r
+       }\r
+\r
+       /* Create the buffers used to pass packets between the FreeRTOS simulator\r
+       and the Win32 threads that are handling WinPCAP. */\r
+       prvCreateThreadSafeBuffers();\r
+\r
+       if( pvSendEvent == NULL )\r
+       {\r
+               /* Create event used to signal the Win32 WinPCAP Tx thread. */\r
+               pvSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL );\r
+\r
+               /* Create the Win32 thread that handles WinPCAP Rx. */\r
+               vWinPcapRecvThreadHandle = CreateThread(\r
+                       NULL,   /* Pointer to thread security attributes. */\r
+                       0,              /* Initial thread stack size, in bytes. */\r
+                       prvWinPcapRecvThread,   /* Pointer to thread function. */\r
+                       NULL,   /* Argument for new thread. */\r
+                       0,              /* Creation flags. */\r
+                       NULL );\r
+\r
+               /* Use the cores that are not used by the FreeRTOS tasks. */\r
+               SetThreadAffinityMask( vWinPcapRecvThreadHandle, ~0x01u );\r
+\r
+               /* Create the Win32 thread that handlers WinPCAP Tx. */\r
+               vWinPcapSendThreadHandle = CreateThread(\r
+                       NULL,   /* Pointer to thread security attributes. */\r
+                       0,              /* initial thread stack size, in bytes. */\r
+                       prvWinPcapSendThread,   /* Pointer to thread function. */\r
+                       NULL,   /* Argument for new thread. */\r
+                       0,              /* Creation flags. */\r
+                       NULL );\r
+\r
+               /* Use the cores that are not used by the FreeRTOS tasks. */\r
+               SetThreadAffinityMask( vWinPcapSendThreadHandle, ~0x01u );\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 IP task when data\r
+               is available. */\r
+               xTaskCreate( prvInterruptSimulatorTask, "MAC_ISR", configMINIMAL_STACK_SIZE, NULL, configMAC_ISR_SIMULATOR_PRIORITY, NULL );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* WinPCAP function. */\r
+void pcap_callback( u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data )\r
+{\r
+       (void)user;\r
+\r
+       /* THIS IS CALLED FROM A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS\r
+       OR TO PRINT OUT MESSAGES HERE. */\r
+\r
+       /* Pass data to the FreeRTOS simulator on a thread safe circular buffer. */\r
+       if( ( pkt_header->caplen <= ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) ) &&\r
+               ( uxStreamBufferGetSpace( xRecvBuffer ) >= ( ( ( size_t ) pkt_header->caplen ) + sizeof( *pkt_header ) ) ) )\r
+       {\r
+               uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_header, sizeof( *pkt_header ) );\r
+               uxStreamBufferAdd( xRecvBuffer, 0, ( const uint8_t* ) pkt_data, ( size_t ) pkt_header->caplen );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+DWORD WINAPI prvWinPcapRecvThread ( void *pvParam )\r
+{\r
+       ( void ) pvParam;\r
+\r
+       /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT\r
+       OUT MESSAGES HERE. */\r
+\r
+       for( ;; )\r
+       {\r
+               pcap_dispatch( pxOpenedInterfaceHandle, 1, pcap_callback, ( u_char * ) "mydata" );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+DWORD WINAPI prvWinPcapSendThread( void *pvParam )\r
+{\r
+size_t xLength;\r
+uint8_t ucBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];\r
+static char cErrorMessage[ 1024 ];\r
+const DWORD xMaxMSToWait = 1000;\r
+\r
+       /* THIS IS A WINDOWS THREAD - DO NOT ATTEMPT ANY FREERTOS CALLS OR TO PRINT\r
+       OUT MESSAGES HERE. */\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParam;\r
+\r
+       for( ;; )\r
+       {\r
+               /* Wait until notified of something to send. */\r
+               WaitForSingleObject( pvSendEvent, xMaxMSToWait );\r
+\r
+               /* Is there more than the length value stored in the circular buffer\r
+               used to pass data from the FreeRTOS simulator into this Win32 thread? */\r
+               while( uxStreamBufferGetSize( xSendBuffer ) > sizeof( xLength ) )\r
+               {\r
+                       uxStreamBufferGet( xSendBuffer, 0, ( uint8_t * ) &xLength, sizeof( xLength ), pdFALSE );\r
+                       uxStreamBufferGet( xSendBuffer, 0, ( uint8_t* ) ucBuffer, xLength, pdFALSE );\r
+                       if( pcap_sendpacket( pxOpenedInterfaceHandle, ucBuffer, xLength  ) != 0 )\r
+                       {\r
+                               ulWinPCAPSendFailures++;\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvInterruptSimulatorTask( void *pvParameters )\r
+{\r
+struct pcap_pkthdr xHeader;\r
+static struct pcap_pkthdr *pxHeader;\r
+const uint8_t *pucPacketData;\r
+uint8_t ucRecvBuffer[ ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ];\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+eFrameProcessingResult_t eResult;\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       for( ;; )\r
+       {\r
+               /* Does the circular buffer used to pass data from the Win32 thread that\r
+               handles WinPCAP Rx into the FreeRTOS simulator contain another packet? */\r
+               if( uxStreamBufferGetSize( xRecvBuffer ) > sizeof( xHeader ) )\r
+               {\r
+                       /* Get the next packet. */\r
+                       uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)&xHeader, sizeof( xHeader ), pdFALSE );\r
+                       uxStreamBufferGet( xRecvBuffer, 0, (uint8_t*)ucRecvBuffer, ( size_t ) xHeader.len, pdFALSE );\r
+                       pucPacketData = ucRecvBuffer;\r
+                       pxHeader = &xHeader;\r
+\r
+                       iptraceNETWORK_INTERFACE_RECEIVE();\r
+\r
+                       eResult = ipCONSIDER_FRAME_FOR_PROCESSING( pucPacketData );\r
+                       if( eResult == eProcessBuffer )\r
+                       {\r
+                               /* Will the data fit into the frame buffer? */\r
+                               if( pxHeader->len <= ipTOTAL_ETHERNET_FRAME_SIZE )\r
+                               {\r
+                                       /* Obtain a buffer into which the data can be placed.  This\r
+                                       is only an interrupt simulator, not a real interrupt, so it\r
+                                       is ok to call the task level function here, but note that\r
+                                       some buffer implementations cannot be called from a real\r
+                                       interrupt. */\r
+                                       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( pxHeader->len, 0 );\r
+\r
+                                       if( pxNetworkBuffer != NULL )\r
+                                       {\r
+                                               memcpy( pxNetworkBuffer->pucEthernetBuffer, pucPacketData, pxHeader->len );\r
+                                               pxNetworkBuffer->xDataLength = ( size_t ) pxHeader->len;\r
+\r
+                                               #if( niDISRUPT_PACKETS == 1 )\r
+                                               {\r
+                                                       pxNetworkBuffer = vRxFaultInjection( pxNetworkBuffer, pucPacketData );\r
+                                               }\r
+                                               #endif /* niDISRUPT_PACKETS */\r
+\r
+                                               if( pxNetworkBuffer != NULL )\r
+                                               {\r
+                                                       xRxEvent.pvData = ( void * ) pxNetworkBuffer;\r
+\r
+                                                       /* Data was received and stored.  Send a message to\r
+                                                       the IP task to let it know. */\r
+                                                       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )\r
+                                                       {\r
+                                                               /* The buffer could not be sent to the stack so\r
+                                                               must be released again.  This is only an\r
+                                                               interrupt simulator, not a real interrupt, so it\r
+                                                               is ok to use the task level function here, but\r
+                                                               note no all buffer implementations will allow\r
+                                                               this function to be executed from a real\r
+                                                               interrupt. */\r
+                                                               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                                                               iptraceETHERNET_RX_EVENT_LOST();\r
+                                                       }\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       /* The packet was already released or stored inside\r
+                                                       vRxFaultInjection().  Don't release it here. */\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               iptraceETHERNET_RX_EVENT_LOST();\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* Log that a packet was dropped because it would have\r
+                                       overflowed the buffer, but there may be more buffers to\r
+                                       process. */\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* There is no real way of simulating an interrupt.  Make sure\r
+                       other tasks can run. */\r
+                       vTaskDelay( configWINDOWS_MAC_INTERRUPT_SIMULATOR_DELAY );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static const char *prvRemoveSpaces( char *pcBuffer, int aBuflen, const char *pcMessage )\r
+{\r
+       char *pcTarget = pcBuffer;\r
+\r
+       /* Utility function used to formap messages being printed only. */\r
+       while( ( *pcMessage != 0 ) && ( pcTarget < ( pcBuffer + aBuflen - 1 ) ) )\r
+       {\r
+               *( pcTarget++ ) = *pcMessage;\r
+\r
+               if( isspace( *pcMessage ) != pdFALSE )\r
+               {\r
+                       while( isspace( *pcMessage ) != pdFALSE )\r
+                       {\r
+                               pcMessage++;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       pcMessage++;\r
+               }\r
+       }\r
+\r
+       *pcTarget = '\0';\r
+\r
+       return pcBuffer;\r
+}\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/NetworkInterface.c
new file mode 100644 (file)
index 0000000..6cbda27
--- /dev/null
@@ -0,0 +1,430 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 200417 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+/* Xilinx library files. */\r
+#include <xemacps.h>\r
+#include "Zynq/x_topology.h"\r
+#include "Zynq/x_emacpsif.h"\r
+#include "Zynq/x_emacpsif_hw.h"\r
+\r
+/* Provided memory configured as uncached. */\r
+#include "uncached_memory.h"\r
+\r
+#ifndef        BMSR_LINK_STATUS\r
+       #define BMSR_LINK_STATUS            0x0004UL\r
+#endif\r
+\r
+#ifndef        PHY_LS_HIGH_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+       receiving packets. */\r
+       #define PHY_LS_HIGH_CHECK_TIME_MS       15000\r
+#endif\r
+\r
+#ifndef        PHY_LS_LOW_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still low every second. */\r
+       #define PHY_LS_LOW_CHECK_TIME_MS        1000\r
+#endif\r
+\r
+/* The size of each buffer when BufferAllocation_1 is used:\r
+http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */\r
+#define niBUFFER_1_PACKET_SIZE         1536\r
+\r
+/* Naming and numbering of PHY registers. */\r
+#define PHY_REG_01_BMSR                        0x01    /* Basic mode status register */\r
+\r
+#ifndef iptraceEMAC_TASK_STARTING\r
+       #define iptraceEMAC_TASK_STARTING()     do { } while( 0 )\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to twice\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+       #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Look for the link to be up every few milliseconds until either xMaxTime time\r
+ * has passed or a link is found.\r
+ */\r
+static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );\r
+\r
+/*\r
+ * A deferred interrupt handler for all MAC/DMA interrupt sources.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* EMAC data/descriptions. */\r
+static xemacpsif_s xEMACpsif;\r
+struct xtopology_t xXTopology =\r
+{\r
+       .emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,\r
+       .emac_type = xemac_type_emacps,\r
+       .intc_baseaddr = 0x0,\r
+       .intc_emac_intr = 0x0,\r
+       .scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,\r
+       .scugic_emac_intr = 0x36,\r
+};\r
+\r
+XEmacPs_Config mac_config =\r
+{\r
+       .DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID,      /**< Unique ID  of device */\r
+       .BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */\r
+};\r
+\r
+extern int phy_detected;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+\r
+#if( ipconfigUSE_LLMNR == 1 )\r
+       static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };\r
+#endif\r
+\r
+/* ucMACAddress as it appears in main.c */\r
+extern const uint8_t ucMACAddress[ 6 ];\r
+\r
+/* Holds the handle of the task used as a deferred interrupt processor.  The\r
+handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
+related interrupts. */\r
+TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+uint32_t ulLinkSpeed, ulDMAReg;\r
+BaseType_t xStatus, xLinkStatus;\r
+XEmacPs *pxEMAC_PS;\r
+const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );\r
+\r
+       /* Guard against the init function being called more than once. */\r
+       if( xEMACTaskHandle == NULL )\r
+       {\r
+               pxEMAC_PS = &( xEMACpsif.emacps );\r
+               memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );\r
+\r
+               xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);\r
+               if( xStatus != XST_SUCCESS )\r
+               {\r
+                       FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );\r
+               }\r
+\r
+               /* Initialize the mac and set the MAC address. */\r
+               XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );\r
+\r
+               #if( ipconfigUSE_LLMNR == 1 )\r
+               {\r
+                       /* Also add LLMNR multicast MAC address. */\r
+                       XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );\r
+               }\r
+               #endif  /* ipconfigUSE_LLMNR == 1 */\r
+\r
+               XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );\r
+               ulLinkSpeed = Phy_Setup( pxEMAC_PS );\r
+               XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);\r
+\r
+               /* Setting the operating speed of the MAC needs a delay. */\r
+               vTaskDelay( pdMS_TO_TICKS( 25UL ) );\r
+\r
+               ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);\r
+\r
+               /* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive\r
+               packets from the receiver packet buffer memory when no AHB resource is available. */\r
+               XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,\r
+                       ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);\r
+\r
+               setup_isr( &xEMACpsif );\r
+               init_dma( &xEMACpsif );\r
+               start_emacps( &xEMACpsif );\r
+\r
+               prvGMACWaitLS( xWaitLinkDelay );\r
+\r
+               /* The deferred interrupt handler task is created at the highest\r
+               possible priority to ensure the interrupt handler can return directly\r
+               to it.  The task's handle is stored in xEMACTaskHandle so interrupts can\r
+               notify the task when there is something to process. */\r
+               xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+       }\r
+       else\r
+       {\r
+               /* Initialisation was already performed, just wait for the link. */\r
+               prvGMACWaitLS( xWaitRelinkDelay );\r
+       }\r
+\r
+       /* Only return pdTRUE when the Link Status of the PHY is high, otherwise the\r
+       DHCP process and all other communication will fail. */\r
+       xLinkStatus = xGetPhyLinkStatus();\r
+\r
+       return ( xLinkStatus != pdFALSE );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )\r
+{\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+       {\r
+               iptraceNETWORK_INTERFACE_TRANSMIT();\r
+               emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );\r
+       }\r
+       else if( bReleaseAfterSend != pdFALSE )\r
+       {\r
+               /* No link. */\r
+               vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+       }\r
+\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static inline unsigned long ulReadMDIO( unsigned ulRegister )\r
+{\r
+uint16_t usValue;\r
+\r
+       XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );\r
+       return usValue;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )\r
+{\r
+TickType_t xStartTime, xEndTime;\r
+const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );\r
+BaseType_t xReturn;\r
+\r
+       xStartTime = xTaskGetTickCount();\r
+\r
+       for( ;; )\r
+       {\r
+               xEndTime = xTaskGetTickCount();\r
+\r
+               if( xEndTime - xStartTime > xMaxTime )\r
+               {\r
+                       xReturn = pdFALSE;\r
+                       break;\r
+               }\r
+               ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+               {\r
+                       xReturn = pdTRUE;\r
+                       break;\r
+               }\r
+\r
+               vTaskDelay( xShortDelay );\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
+{\r
+static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
+uint8_t *ucRAMBuffer = ucNetworkPackets;\r
+uint32_t ul;\r
+\r
+       for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )\r
+       {\r
+               pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;\r
+               *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );\r
+               ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )\r
+       {\r
+               xReturn = pdFALSE;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdTRUE;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult = 0;\r
+uint32_t xStatus;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       /* A possibility to set some additional task properties like calling\r
+       portTASK_USES_FLOATING_POINT() */\r
+       iptraceEMAC_TASK_STARTING();\r
+\r
+       vTaskSetTimeOutState( &xPhyTime );\r
+       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+\r
+       for( ;; )\r
+       {\r
+               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+               if( uxLastMinBufferCount != uxCurrentCount )\r
+               {\r
+                       /* The logging produced below may be helpful\r
+                       while tuning +TCP: see how many buffers are in use. */\r
+                       uxLastMinBufferCount = uxCurrentCount;\r
+                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+               }\r
+\r
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+               {\r
+               static UBaseType_t uxLastMinQueueSpace = 0;\r
+\r
+                       uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+                       if( uxLastMinQueueSpace != uxCurrentCount )\r
+                       {\r
+                               /* The logging produced below may be helpful\r
+                               while tuning +TCP: see how many buffers are in use. */\r
+                               uxLastMinQueueSpace = uxCurrentCount;\r
+                               FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+                       }\r
+               }\r
+               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )\r
+               {\r
+                       /* No events to process now, wait for the next. */\r
+                       ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );\r
+               }\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )\r
+               {\r
+                       xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;\r
+                       xResult = emacps_check_rx( &xEMACpsif );\r
+               }\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )\r
+               {\r
+                       xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;\r
+                       emacps_check_tx( &xEMACpsif );\r
+               }\r
+\r
+               if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )\r
+               {\r
+                       xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;\r
+                       emacps_check_errors( &xEMACpsif );\r
+               }\r
+\r
+               if( xResult > 0 )\r
+               {\r
+                       /* A packet was received. No need to check for the PHY status now,\r
+                       but set a timer to check it later on. */\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       xResult = 0;\r
+               }\r
+               else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )\r
+               {\r
+                       xStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )\r
+                       {\r
+                               ulPHYLinkStatus = xStatus;\r
+                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );\r
+                       }\r
+\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/README.txt
new file mode 100644 (file)
index 0000000..74b241d
--- /dev/null
@@ -0,0 +1,25 @@
+\r
+\r
+NetworkInterface for Xilinx' Zynq\r
+\r
+Please include the following source files:\r
+\r
+       $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/NetworkInterface.c\r
+       $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_dma.c\r
+       $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c\r
+       $(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_hw.c\r
+\r
+And include the following source files from the Xilinx library:\r
+\r
+       $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps.c\r
+       $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_control.c\r
+       $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_g.c\r
+       $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_intr.c\r
+\r
+       E.g. ps7_cortexa9_0/libsrc/emacps_v2_0/src/xemacps_intr.c\r
+\r
+The following source files are NOT used for the FreeRTOS+TCP interface:\r
+\r
+       $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_bdring.c\r
+       $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_hw.c\r
+       $(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_sinit.c\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif.h
new file mode 100644 (file)
index 0000000..823dee0
--- /dev/null
@@ -0,0 +1,144 @@
+/*\r
+ * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+#ifndef __NETIF_XEMACPSIF_H__\r
+#define __NETIF_XEMACPSIF_H__\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#include <stdint.h>\r
+\r
+#include "xstatus.h"\r
+#include "sleep.h"\r
+#include "xparameters.h"\r
+#include "xparameters_ps.h"    /* defines XPAR values */\r
+#include "xil_types.h"\r
+#include "xil_assert.h"\r
+#include "xil_io.h"\r
+#include "xil_exception.h"\r
+#include "xpseudo_asm.h"\r
+#include "xil_cache.h"\r
+#include "xil_printf.h"\r
+#include "xuartps.h"\r
+#include "xscugic.h"\r
+#include "xemacps.h"           /* defines XEmacPs API */\r
+\r
+//#include "netif/xpqueue.h"\r
+//#include "xlwipconfig.h"\r
+\r
+void   xemacpsif_setmac(uint32_t index, uint8_t *addr);\r
+uint8_t*       xemacpsif_getmac(uint32_t index);\r
+//int  xemacpsif_init(struct netif *netif);\r
+//int  xemacpsif_input(struct netif *netif);\r
+#ifdef NOTNOW_BHILL\r
+unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp);\r
+#endif\r
+\r
+/* xaxiemacif_hw.c */\r
+void   xemacps_error_handler(XEmacPs * Temac);\r
+\r
+struct xBD_TYPE {\r
+       uint32_t address;\r
+       uint32_t flags;\r
+};\r
+\r
+/*\r
+ * Missing declaration in 'src/xemacps_hw.h' :\r
+ * When set, the GEM DMA will automatically\r
+ * discard receive packets from the receiver packet\r
+ * buffer memory when no AHB resource is\r
+ * available.\r
+ * When low, then received packets will remain to be\r
+ * stored in the SRAM based packet buffer until\r
+ * AHB buffer resource next becomes available.\r
+ */\r
+#define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK            0x01000000\r
+\r
+#define EMAC_IF_RX_EVENT       1\r
+#define EMAC_IF_TX_EVENT       2\r
+#define EMAC_IF_ERR_EVENT      4\r
+#define EMAC_IF_ALL_EVENT      7\r
+\r
+/* structure within each netif, encapsulating all information required for\r
+ * using a particular temac instance\r
+ */\r
+typedef struct {\r
+       XEmacPs emacps;\r
+\r
+       /* pointers to memory holding buffer descriptors (used only with SDMA) */\r
+       struct xBD_TYPE *rxSegments;\r
+       struct xBD_TYPE *txSegments;\r
+\r
+       unsigned char *tx_space;\r
+       unsigned uTxUnitSize;\r
+\r
+       char *remain_mem;\r
+       unsigned remain_siz;\r
+\r
+       volatile int rxHead, rxTail;\r
+       volatile int txHead, txTail;\r
+\r
+       volatile int txBusy;\r
+\r
+       volatile uint32_t isr_events;\r
+\r
+       unsigned int last_rx_frms_cntr;\r
+\r
+} xemacpsif_s;\r
+\r
+//extern xemacpsif_s xemacpsif;\r
+\r
+int    is_tx_space_available(xemacpsif_s *emac);\r
+\r
+/* xaxiemacif_dma.c */\r
+\r
+struct xNETWORK_BUFFER;\r
+\r
+int emacps_check_rx( xemacpsif_s *xemacpsif );\r
+void emacps_check_tx( xemacpsif_s *xemacpsif );\r
+int emacps_check_errors( xemacpsif_s *xemacps );\r
+void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount );\r
+\r
+extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend );\r
+extern unsigned Phy_Setup( XEmacPs *xemacpsp );\r
+extern void setup_isr( xemacpsif_s *xemacpsif );\r
+extern XStatus init_dma( xemacpsif_s *xemacpsif );\r
+extern void start_emacps( xemacpsif_s *xemacpsif );\r
+\r
+void EmacEnableIntr(void);\r
+void EmacDisableIntr(void);\r
+\r
+XStatus init_axi_dma(xemacpsif_s *xemacpsif);\r
+void process_sent_bds( xemacpsif_s *xemacpsif );\r
+\r
+void emacps_send_handler(void *arg);\r
+void emacps_recv_handler(void *arg);\r
+void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord);\r
+void HandleTxErrors(xemacpsif_s *xemacpsif);\r
+XEmacPs_Config *xemacps_lookup_config(unsigned mac_base);\r
+\r
+void clean_dma_txdescs(xemacpsif_s *xemacpsif);\r
+void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* __NETIF_XAXIEMACIF_H__ */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_dma.c
new file mode 100644 (file)
index 0000000..7a8f204
--- /dev/null
@@ -0,0 +1,657 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 200417 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#include "Zynq/x_emacpsif.h"\r
+#include "Zynq/x_topology.h"\r
+#include "xstatus.h"\r
+\r
+#include "xparameters.h"\r
+#include "xparameters_ps.h"\r
+#include "xil_exception.h"\r
+#include "xil_mmu.h"\r
+\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "timers.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+#include "uncached_memory.h"\r
+\r
+/* Two defines used to set or clear the EMAC interrupt */\r
+#define INTC_BASE_ADDR         XPAR_SCUGIC_CPU_BASEADDR\r
+#define INTC_DIST_BASE_ADDR    XPAR_SCUGIC_DIST_BASEADDR\r
+\r
+\r
+\r
+#if( ipconfigPACKET_FILLER_SIZE != 2 )\r
+       #error Please define ipconfigPACKET_FILLER_SIZE as the value '2'\r
+#endif\r
+#define TX_OFFSET                              ipconfigPACKET_FILLER_SIZE\r
+\r
+/* Defined in NetworkInterface.c */\r
+extern TaskHandle_t xEMACTaskHandle;\r
+\r
+/*\r
+       pxDMA_tx_buffers: these are character arrays, each one is big enough to hold 1 MTU.\r
+       The actual TX buffers are located in uncached RAM.\r
+*/\r
+static unsigned char *pxDMA_tx_buffers[ ipconfigNIC_N_TX_DESC ] = { NULL };\r
+\r
+/*\r
+       pxDMA_rx_buffers: these are pointers to 'NetworkBufferDescriptor_t'.\r
+       Once a message has been received by the EMAC, the descriptor can be passed\r
+       immediately to the IP-task.\r
+*/\r
+static NetworkBufferDescriptor_t *pxDMA_rx_buffers[ ipconfigNIC_N_RX_DESC ] = { NULL };\r
+\r
+/*\r
+       The FreeRTOS+TCP port is using a fixed 'topology', which is declared in\r
+       ./portable/NetworkInterface/Zynq/NetworkInterface.c\r
+*/\r
+extern struct xtopology_t xXTopology;\r
+\r
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
+\r
+/*\r
+       The FreeRTOS+TCP port does not make use of "src/xemacps_bdring.c".\r
+       In stead 'struct xemacpsif_s' has a "head" and a "tail" index.\r
+       "head" is the next index to be written, used.\r
+       "tail" is the next index to be read, freed.\r
+*/\r
+\r
+int is_tx_space_available( xemacpsif_s *xemacpsif )\r
+{\r
+size_t uxCount;\r
+\r
+       if( xTXDescriptorSemaphore != NULL )\r
+       {\r
+               uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
+       }\r
+       else\r
+       {\r
+               uxCount = ( UBaseType_t ) 0u;\r
+       }\r
+\r
+       return uxCount;\r
+}\r
+\r
+void emacps_check_tx( xemacpsif_s *xemacpsif )\r
+{\r
+int tail = xemacpsif->txTail;\r
+int head = xemacpsif->txHead;\r
+size_t uxCount = ( ( UBaseType_t ) ipconfigNIC_N_TX_DESC ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
+\r
+       /* uxCount is the number of TX descriptors that are in use by the DMA. */\r
+       /* When done, "TXBUF_USED" will be set. */\r
+\r
+       while( ( uxCount > 0 ) && ( ( xemacpsif->txSegments[ tail ].flags & XEMACPS_TXBUF_USED_MASK ) != 0 ) )\r
+       {\r
+               if( ( tail == head ) && ( uxCount != ipconfigNIC_N_TX_DESC ) )\r
+               {\r
+                       break;\r
+               }\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+#warning ipconfigZERO_COPY_TX_DRIVER is defined\r
+               {\r
+               void *pvBuffer = pxDMA_tx_buffers[ tail ];\r
+               NetworkBufferDescriptor_t *pxBuffer;\r
+\r
+                       if( pvBuffer != NULL )\r
+                       {\r
+                               pxDMA_tx_buffers[ tail ] = NULL;\r
+                               pxBuffer = pxPacketBuffer_to_NetworkBuffer( pvBuffer );\r
+                               if( pxBuffer != NULL )\r
+                               {\r
+                                       vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+                               }\r
+                               else\r
+                               {\r
+                                       FreeRTOS_printf( ( "emacps_check_tx: Can not find network buffer\n" ) );\r
+                               }\r
+                       }\r
+               }\r
+#endif\r
+               /* Clear all but the "used" and "wrap" bits. */\r
+               if( tail < ipconfigNIC_N_TX_DESC - 1 )\r
+               {\r
+                       xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK;\r
+               }\r
+               else\r
+               {\r
+                       xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;\r
+               }\r
+               uxCount--;\r
+               /* Tell the counting semaphore that one more TX descriptor is available. */\r
+               xSemaphoreGive( xTXDescriptorSemaphore );\r
+               if( ++tail == ipconfigNIC_N_TX_DESC )\r
+               {\r
+                       tail = 0;\r
+               }\r
+               xemacpsif->txTail = tail;\r
+       }\r
+\r
+       return;\r
+}\r
+\r
+void emacps_send_handler(void *arg)\r
+{\r
+xemacpsif_s   *xemacpsif;\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       xemacpsif = (xemacpsif_s *)(arg);\r
+\r
+       /* In this port for FreeRTOS+TCP, the EMAC interrupts will only set a bit in\r
+       "isr_events". The task in NetworkInterface will wake-up and do the necessary work.\r
+       */\r
+       xemacpsif->isr_events |= EMAC_IF_TX_EVENT;\r
+       xemacpsif->txBusy = pdFALSE;\r
+\r
+       if( xEMACTaskHandle != NULL )\r
+       {\r
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+       }\r
+\r
+       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+\r
+static BaseType_t xValidLength( BaseType_t xLength )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       if( ( xLength >= ( BaseType_t ) sizeof( struct xARP_PACKET ) ) && ( ( ( uint32_t ) xLength ) <= ipTOTAL_ETHERNET_FRAME_SIZE ) )\r
+       {\r
+               xReturn = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xReturn =  pdFALSE;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+\r
+XStatus emacps_send_message(xemacpsif_s *xemacpsif, NetworkBufferDescriptor_t *pxBuffer, int iReleaseAfterSend )\r
+{\r
+int head = xemacpsif->txHead;\r
+int tail = xemacpsif->txTail;\r
+int iHasSent = 0;\r
+uint32_t ulBaseAddress = xemacpsif->emacps.Config.BaseAddress;\r
+TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000u );\r
+\r
+       #if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+       {\r
+               /* This driver wants to own all network buffers which are to be transmitted. */\r
+               configASSERT( iReleaseAfterSend != pdFALSE );\r
+       }\r
+       #endif\r
+\r
+       /* Open a do {} while ( 0 ) loop to be able to call break. */\r
+       do\r
+       {\r
+       uint32_t ulFlags = 0;\r
+\r
+               if( xValidLength( pxBuffer->xDataLength ) != pdTRUE )\r
+               {\r
+                       break;\r
+               }\r
+\r
+               if( xTXDescriptorSemaphore == NULL )\r
+               {\r
+                       break;\r
+               }\r
+\r
+               if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
+               {\r
+                       FreeRTOS_printf( ( "emacps_send_message: Time-out waiting for TX buffer\n" ) );\r
+                       break;\r
+               }\r
+\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               /* Pass the pointer (and its ownership) directly to DMA. */\r
+               pxDMA_tx_buffers[ head ] = pxBuffer->pucEthernetBuffer;\r
+               if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )\r
+               {\r
+                       Xil_DCacheFlushRange( ( unsigned )pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );\r
+               }\r
+               /* Buffer has been transferred, do not release it. */\r
+               iReleaseAfterSend = pdFALSE;\r
+#else\r
+               if( pxDMA_tx_buffers[ head ] == NULL )\r
+               {\r
+                       FreeRTOS_printf( ( "emacps_send_message: pxDMA_tx_buffers[ %d ] == NULL\n", head ) );\r
+                       break;\r
+               }\r
+               /* Copy the message to unbuffered space in RAM. */\r
+               memcpy( pxDMA_tx_buffers[ head ], pxBuffer->pucEthernetBuffer, pxBuffer->xDataLength );\r
+#endif\r
+               /* Packets will be sent one-by-one, so for each packet\r
+               the TXBUF_LAST bit will be set. */\r
+               ulFlags |= XEMACPS_TXBUF_LAST_MASK;\r
+               ulFlags |= ( pxBuffer->xDataLength & XEMACPS_TXBUF_LEN_MASK );\r
+               if( head == ( ipconfigNIC_N_TX_DESC - 1 ) )\r
+               {\r
+                       ulFlags |= XEMACPS_TXBUF_WRAP_MASK;\r
+               }\r
+\r
+               /* Copy the address of the buffer and set the flags. */\r
+               xemacpsif->txSegments[ head ].address = ( uint32_t )pxDMA_tx_buffers[ head ];\r
+               xemacpsif->txSegments[ head ].flags = ulFlags;\r
+\r
+               iHasSent = pdTRUE;\r
+               if( ++head == ipconfigNIC_N_TX_DESC )\r
+               {\r
+                       head = 0;\r
+               }\r
+               /* Update the TX-head index. These variable are declared volatile so they will be\r
+               accessed as little as possible. */\r
+               xemacpsif->txHead = head;\r
+       } while( pdFALSE );\r
+\r
+       if( iReleaseAfterSend != pdFALSE )\r
+       {\r
+               vReleaseNetworkBufferAndDescriptor( pxBuffer );\r
+               pxBuffer = NULL;\r
+       }\r
+\r
+       /* Data Synchronization Barrier */\r
+       dsb();\r
+\r
+       if( iHasSent != pdFALSE )\r
+       {\r
+               /* Make STARTTX high */\r
+               uint32_t ulValue = XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET);\r
+               /* Start transmit */\r
+               xemacpsif->txBusy = pdTRUE;\r
+               XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) );\r
+       }\r
+       dsb();\r
+\r
+       return 0;\r
+}\r
+\r
+void emacps_recv_handler(void *arg)\r
+{\r
+       xemacpsif_s *xemacpsif;\r
+       BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+       xemacpsif = (xemacpsif_s *)(arg);\r
+       xemacpsif->isr_events |= EMAC_IF_RX_EVENT;\r
+\r
+       if( xEMACTaskHandle != NULL )\r
+       {\r
+               vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+       }\r
+\r
+       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+\r
+static NetworkBufferDescriptor_t *ethMsg = NULL;\r
+static NetworkBufferDescriptor_t *ethLast = NULL;\r
+\r
+static void passEthMessages( void )\r
+{\r
+IPStackEvent_t xRxEvent;\r
+\r
+       xRxEvent.eEventType = eNetworkRxEvent;\r
+       xRxEvent.pvData = ( void * ) ethMsg;\r
+\r
+       if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS )\r
+       {\r
+               /* The buffer could not be sent to the stack so must be released again.\r
+               This is a deferred handler taskr, not a real interrupt, so it is ok to\r
+               use the task level function here. */\r
+               do\r
+               {\r
+                       NetworkBufferDescriptor_t *xNext = ethMsg->pxNextBuffer;\r
+                       vReleaseNetworkBufferAndDescriptor( ethMsg );\r
+                       ethMsg = xNext;\r
+               } while( ethMsg != NULL );\r
+\r
+               iptraceETHERNET_RX_EVENT_LOST();\r
+               FreeRTOS_printf( ( "passEthMessages: Can not queue return packet!\n" ) );\r
+       }\r
+\r
+       ethMsg = ethLast = NULL;\r
+}\r
+\r
+int emacps_check_rx( xemacpsif_s *xemacpsif )\r
+{\r
+NetworkBufferDescriptor_t *pxBuffer, *pxNewBuffer;\r
+int rx_bytes;\r
+volatile int msgCount = 0;\r
+int head = xemacpsif->rxHead;\r
+\r
+       /* There seems to be an issue (SI# 692601), see comments below. */\r
+       resetrx_on_no_rxdata(xemacpsif);\r
+\r
+       /* This FreeRTOS+TCP driver shall be compiled with the option\r
+       "ipconfigUSE_LINKED_RX_MESSAGES" enabled.  It allows the driver to send a\r
+       chain of RX messages within one message to the IP-task. */\r
+       for( ;; )\r
+       {\r
+               if( ( ( xemacpsif->rxSegments[ head ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) ||\r
+                       ( pxDMA_rx_buffers[ head ] == NULL ) )\r
+               {\r
+                       break;\r
+               }\r
+\r
+               pxNewBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, ( TickType_t ) 0 );\r
+               if( pxNewBuffer == NULL )\r
+               {\r
+                       /* A packet has been received, but there is no replacement for this Network Buffer.\r
+                       The packet will be dropped, and it Network Buffer will stay in place. */\r
+                       FreeRTOS_printf( ("emacps_check_rx: unable to allocate a Netwrok Buffer\n" ) );\r
+                       pxNewBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];\r
+               }\r
+               else\r
+               {\r
+                       pxBuffer = ( NetworkBufferDescriptor_t * )pxDMA_rx_buffers[ head ];\r
+\r
+                       /* Just avoiding to use or refer to the same buffer again */\r
+                       pxDMA_rx_buffers[ head ] = pxNewBuffer;\r
+\r
+                       /*\r
+                        * Adjust the buffer size to the actual number of bytes received.\r
+                        */\r
+                       rx_bytes = xemacpsif->rxSegments[ head ].flags & XEMACPS_RXBUF_LEN_MASK;\r
+\r
+                       pxBuffer->xDataLength = rx_bytes;\r
+\r
+                       if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )\r
+                       {\r
+                               Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)rx_bytes );\r
+                       }\r
+\r
+                       /* store it in the receive queue, where it'll be processed by a\r
+                       different handler. */\r
+                       iptraceNETWORK_INTERFACE_RECEIVE();\r
+                       pxBuffer->pxNextBuffer = NULL;\r
+\r
+                       if( ethMsg == NULL )\r
+                       {\r
+                               // Becomes the first message\r
+                               ethMsg = pxBuffer;\r
+                       }\r
+                       else if( ethLast != NULL )\r
+                       {\r
+                               // Add to the tail\r
+                               ethLast->pxNextBuffer = pxBuffer;\r
+                       }\r
+\r
+                       ethLast = pxBuffer;\r
+                       msgCount++;\r
+               }\r
+               {\r
+                       if( ucIsCachedMemory( pxNewBuffer->pucEthernetBuffer ) != 0 )\r
+                       {\r
+                               Xil_DCacheInvalidateRange( ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE );\r
+                       }\r
+                       {\r
+                               uint32_t addr = ( ( uint32_t )pxNewBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;\r
+                               if( head == ( ipconfigNIC_N_RX_DESC - 1 ) )\r
+                               {\r
+                                       addr |= XEMACPS_RXBUF_WRAP_MASK;\r
+                               }\r
+                               /* Clearing 'XEMACPS_RXBUF_NEW_MASK'       0x00000001 *< Used bit.. */\r
+                               xemacpsif->rxSegments[ head ].address = addr;\r
+                               xemacpsif->rxSegments[ head ].flags = 0;\r
+                       }\r
+               }\r
+\r
+               if( ++head == ipconfigNIC_N_RX_DESC )\r
+               {\r
+                       head = 0;\r
+               }\r
+               xemacpsif->rxHead = head;\r
+       }\r
+\r
+       if( ethMsg != NULL )\r
+       {\r
+               passEthMessages( );\r
+       }\r
+\r
+       return msgCount;\r
+}\r
+\r
+void clean_dma_txdescs(xemacpsif_s *xemacpsif)\r
+{\r
+int index;\r
+unsigned char *ucTxBuffer;\r
+\r
+       /* Clear all TX descriptors and assign uncached memory to each descriptor.\r
+       "tx_space" points to the first available TX buffer. */\r
+       ucTxBuffer = xemacpsif->tx_space;\r
+\r
+       for( index = 0; index < ipconfigNIC_N_TX_DESC; index++ )\r
+       {\r
+               xemacpsif->txSegments[ index ].address = ( uint32_t )ucTxBuffer;\r
+               xemacpsif->txSegments[ index ].flags = XEMACPS_TXBUF_USED_MASK;\r
+#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
+               pxDMA_tx_buffers[ index ] = ( void* )NULL;\r
+#else\r
+               pxDMA_tx_buffers[ index ] = ( void* )( ucTxBuffer + TX_OFFSET );\r
+#endif\r
+               ucTxBuffer += xemacpsif->uTxUnitSize;\r
+       }\r
+       xemacpsif->txSegments[ ipconfigNIC_N_TX_DESC - 1 ].flags =\r
+               XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK;\r
+}\r
+\r
+XStatus init_dma(xemacpsif_s *xemacpsif)\r
+{\r
+       NetworkBufferDescriptor_t *pxBuffer;\r
+\r
+       int iIndex;\r
+       UBaseType_t xRxSize;\r
+       UBaseType_t xTxSize;\r
+       struct xtopology_t *xtopologyp = &xXTopology;\r
+\r
+       xRxSize = ipconfigNIC_N_RX_DESC * sizeof( xemacpsif->rxSegments[ 0 ] );\r
+\r
+       xTxSize = ipconfigNIC_N_TX_DESC * sizeof( xemacpsif->txSegments[ 0 ] );\r
+\r
+       /* Also round-up to 4KB */\r
+       xemacpsif->uTxUnitSize = ( ipTOTAL_ETHERNET_FRAME_SIZE + 0x1000ul ) & ~0xffful;\r
+       /*\r
+        * We allocate 65536 bytes for RX BDs which can accommodate a\r
+        * maximum of 8192 BDs which is much more than any application\r
+        * will ever need.\r
+        */\r
+       xemacpsif->rxSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xRxSize )  );\r
+       xemacpsif->txSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xTxSize ) );\r
+       xemacpsif->tx_space   = ( unsigned char *   )( pucGetUncachedMemory ( ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ) );\r
+\r
+       /* These variables will be used in XEmacPs_Start (see src/xemacps.c). */\r
+       xemacpsif->emacps.RxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->rxSegments;\r
+       xemacpsif->emacps.TxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->txSegments;\r
+\r
+       if( xTXDescriptorSemaphore == NULL )\r
+       {\r
+               xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNIC_N_TX_DESC, ( UBaseType_t ) ipconfigNIC_N_TX_DESC );\r
+               configASSERT( xTXDescriptorSemaphore );\r
+       }\r
+       /*\r
+        * Allocate RX descriptors, 1 RxBD at a time.\r
+        */\r
+       for( iIndex = 0; iIndex < ipconfigNIC_N_RX_DESC; iIndex++ )\r
+       {\r
+               pxBuffer = pxDMA_rx_buffers[ iIndex ];\r
+               if( pxBuffer == NULL )\r
+               {\r
+                       pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, ( TickType_t ) 0 );\r
+                       if( pxBuffer == NULL )\r
+                       {\r
+                               FreeRTOS_printf( ("Unable to allocate a network buffer in recv_handler\n" ) );\r
+                               return -1;\r
+                       }\r
+               }\r
+\r
+               xemacpsif->rxSegments[ iIndex ].flags = 0;\r
+               xemacpsif->rxSegments[ iIndex ].address = ( ( uint32_t )pxBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK;\r
+\r
+               pxDMA_rx_buffers[ iIndex ] = pxBuffer;\r
+               /* Make sure this memory is not in cache for now. */\r
+               if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 )\r
+               {\r
+                       Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE,\r
+                               (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE );\r
+               }\r
+       }\r
+\r
+       xemacpsif->rxSegments[ ipconfigNIC_N_RX_DESC - 1 ].address |= XEMACPS_RXBUF_WRAP_MASK;\r
+\r
+       memset( xemacpsif->tx_space, '\0', ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize );\r
+\r
+       clean_dma_txdescs( xemacpsif );\r
+\r
+       {\r
+               uint32_t value;\r
+               value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET );\r
+\r
+               // 1xxxx: Attempt to use INCR16 AHB bursts\r
+               value = ( value & ~( XEMACPS_DMACR_BLENGTH_MASK ) ) | XEMACPS_DMACR_INCR16_AHB_BURST;\r
+#if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
+               value |= XEMACPS_DMACR_TCPCKSUM_MASK;\r
+#else\r
+#warning Are you sure the EMAC should not calculate outgoing checksums?\r
+               value &= ~XEMACPS_DMACR_TCPCKSUM_MASK;\r
+#endif\r
+               XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, value );\r
+       }\r
+       {\r
+               uint32_t value;\r
+               value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET );\r
+\r
+               /* Network buffers are 32-bit aligned + 2 bytes (because ipconfigPACKET_FILLER_SIZE = 2 ).\r
+               Now tell the EMAC that received messages should be stored at "address + 2". */\r
+               value = ( value & ~XEMACPS_NWCFG_RXOFFS_MASK ) | 0x8000;\r
+\r
+#if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 )\r
+               value |= XEMACPS_NWCFG_RXCHKSUMEN_MASK;\r
+#else\r
+#warning Are you sure the EMAC should not calculate incoming checksums?\r
+               value &= ~XEMACPS_NWCFG_RXCHKSUMEN_MASK;\r
+#endif\r
+               XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET, value );\r
+       }\r
+\r
+       /*\r
+        * Connect the device driver handler that will be called when an\r
+        * interrupt for the device occurs, the handler defined above performs\r
+        * the specific interrupt processing for the device.\r
+        */\r
+       XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr,\r
+               (Xil_ExceptionHandler)XEmacPs_IntrHandler,\r
+               (void *)&xemacpsif->emacps);\r
+       /*\r
+        * Enable the interrupt for emacps.\r
+        */\r
+       EmacEnableIntr( );\r
+\r
+       return 0;\r
+}\r
+\r
+/*\r
+ * resetrx_on_no_rxdata():\r
+ *\r
+ * It is called at regular intervals through the API xemacpsif_resetrx_on_no_rxdata\r
+ * called by the user.\r
+ * The EmacPs has a HW bug (SI# 692601) on the Rx path for heavy Rx traffic.\r
+ * Under heavy Rx traffic because of the HW bug there are times when the Rx path\r
+ * becomes unresponsive. The workaround for it is to check for the Rx path for\r
+ * traffic (by reading the stats registers regularly). If the stats register\r
+ * does not increment for sometime (proving no Rx traffic), the function resets\r
+ * the Rx data path.\r
+ *\r
+ */\r
+\r
+void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif)\r
+{\r
+       unsigned long regctrl;\r
+       unsigned long tempcntr;\r
+\r
+       tempcntr = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXCNT_OFFSET );\r
+       if ( ( tempcntr == 0 ) && ( xemacpsif->last_rx_frms_cntr == 0 ) )\r
+       {\r
+               regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,\r
+                               XEMACPS_NWCTRL_OFFSET);\r
+               regctrl &= (~XEMACPS_NWCTRL_RXEN_MASK);\r
+               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,\r
+                               XEMACPS_NWCTRL_OFFSET, regctrl);\r
+               regctrl = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET);\r
+               regctrl |= (XEMACPS_NWCTRL_RXEN_MASK);\r
+               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCTRL_OFFSET, regctrl);\r
+       }\r
+       xemacpsif->last_rx_frms_cntr = tempcntr;\r
+}\r
+\r
+void EmacDisableIntr(void)\r
+{\r
+       XScuGic_DisableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);\r
+}\r
+\r
+void EmacEnableIntr(void)\r
+{\r
+       XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, xXTopology.scugic_emac_intr);\r
+}\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.c
new file mode 100644 (file)
index 0000000..e9443cd
--- /dev/null
@@ -0,0 +1,243 @@
+/*\r
+ * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+#include "Zynq/x_emacpsif.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+\r
+///* FreeRTOS+TCP includes. */\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+extern TaskHandle_t xEMACTaskHandle;\r
+\r
+/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c\r
+ *** to run it on a PEEP board\r
+ ***/\r
+\r
+unsigned int link_speed = 100;\r
+\r
+void setup_isr( xemacpsif_s *xemacpsif )\r
+{\r
+       /*\r
+        * Setup callbacks\r
+        */\r
+       XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,\r
+               (void *) emacps_send_handler,\r
+               (void *) xemacpsif);\r
+\r
+       XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,\r
+               (void *) emacps_recv_handler,\r
+               (void *) xemacpsif);\r
+\r
+       XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,\r
+               (void *) emacps_error_handler,\r
+               (void *) xemacpsif);\r
+}\r
+\r
+void start_emacps (xemacpsif_s *xemacps)\r
+{\r
+       /* start the temac */\r
+       XEmacPs_Start(&xemacps->emacps);\r
+}\r
+\r
+extern struct xtopology_t xXTopology;\r
+\r
+volatile int error_msg_count = 0;\r
+volatile const char *last_err_msg = "";\r
+\r
+struct xERROR_MSG {\r
+       void *arg;\r
+       u8 Direction;\r
+       u32 ErrorWord;\r
+};\r
+\r
+static struct xERROR_MSG xErrorList[ 8 ];\r
+static BaseType_t xErrorHead, xErrorTail;\r
+\r
+void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord)\r
+{\r
+       BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+       xemacpsif_s *xemacpsif;\r
+       BaseType_t xNextHead = xErrorHead;\r
+\r
+       xemacpsif = (xemacpsif_s *)(arg);\r
+\r
+       if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )\r
+       {\r
+               if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )\r
+                       xNextHead = 0;\r
+               if( xNextHead != xErrorTail )\r
+               {\r
+\r
+                       xErrorList[ xErrorHead ].arg = arg;\r
+                       xErrorList[ xErrorHead ].Direction = Direction;\r
+                       xErrorList[ xErrorHead ].ErrorWord = ErrorWord;\r
+\r
+                       xErrorHead = xNextHead;\r
+\r
+                       xemacpsif = (xemacpsif_s *)(arg);\r
+                       xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;\r
+               }\r
+\r
+               if( xEMACTaskHandle != NULL )\r
+               {\r
+                       vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+               }\r
+\r
+       }\r
+\r
+       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+\r
+static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord);\r
+\r
+int emacps_check_errors( xemacpsif_s *xemacps )\r
+{\r
+int xResult;\r
+\r
+       ( void ) xemacps;\r
+\r
+       if( xErrorHead == xErrorTail )\r
+       {\r
+               xResult = 0;\r
+       }\r
+       else\r
+       {\r
+               xResult = 1;\r
+               emacps_handle_error(\r
+                       xErrorList[ xErrorTail ].arg,\r
+                       xErrorList[ xErrorTail ].Direction,\r
+                       xErrorList[ xErrorTail ].ErrorWord );\r
+       }\r
+\r
+       return xResult;\r
+}\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void );\r
+\r
+static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)\r
+{\r
+       xemacpsif_s   *xemacpsif;\r
+       struct xtopology_t *xtopologyp;\r
+       XEmacPs *xemacps;\r
+\r
+       xemacpsif = (xemacpsif_s *)(arg);\r
+\r
+       xtopologyp = &xXTopology;\r
+\r
+       xemacps = &xemacpsif->emacps;\r
+\r
+       /* Do not appear to be used. */\r
+       ( void ) xemacps;\r
+       ( void ) xtopologyp;\r
+\r
+       last_err_msg = NULL;\r
+\r
+       if( ErrorWord != 0 )\r
+       {\r
+               switch (Direction) {\r
+               case XEMACPS_RECV:\r
+                       if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Receive DMA error";\r
+                               xNetworkInterfaceInitialise( );\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Receive over run";\r
+                               emacps_recv_handler(arg);\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Receive buffer not available";\r
+                               emacps_recv_handler(arg);\r
+                       }\r
+                       break;\r
+               case XEMACPS_SEND:\r
+                       if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Transmit DMA error";\r
+                               xNetworkInterfaceInitialise( );\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Transmit under run";\r
+                               HandleTxErrors( xemacpsif );\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Transmit buffer exhausted";\r
+                               HandleTxErrors( xemacpsif );\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Transmit retry excessed limits";\r
+                               HandleTxErrors( xemacpsif );\r
+                       }\r
+                       if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )\r
+                       {\r
+                               last_err_msg = "Transmit collision";\r
+                               emacps_check_tx( xemacpsif );\r
+                       }\r
+                       break;\r
+               }\r
+       }\r
+       // Break on this statement and inspect error_msg if you like\r
+       if( last_err_msg != NULL )\r
+       {\r
+               error_msg_count++;\r
+               FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );\r
+       }\r
+}\r
+\r
+extern XEmacPs_Config mac_config;\r
+\r
+void HandleTxErrors(xemacpsif_s *xemacpsif)\r
+{\r
+       u32 netctrlreg;\r
+\r
+       //taskENTER_CRITICAL()\r
+       {\r
+               netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,\r
+                                                                                                       XEMACPS_NWCTRL_OFFSET);\r
+               netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);\r
+               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,\r
+                                                                               XEMACPS_NWCTRL_OFFSET, netctrlreg);\r
+\r
+               clean_dma_txdescs( xemacpsif );\r
+               netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,\r
+                                                                                                               XEMACPS_NWCTRL_OFFSET);\r
+               netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);\r
+               XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,\r
+                                                                                       XEMACPS_NWCTRL_OFFSET, netctrlreg);\r
+       }\r
+       //taskEXIT_CRITICAL( );\r
+}\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_hw.h
new file mode 100644 (file)
index 0000000..f3c424a
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+#ifndef __XEMACPSIF_HW_H_\r
+#define __XEMACPSIF_HW_H_\r
+\r
+#include "Zynq/x_emacpsif.h"\r
+//#include "lwip/netif.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+XEmacPs_Config * lookup_config(unsigned mac_base);\r
+\r
+//void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif);\r
+\r
+int emacps_check_errors( xemacpsif_s *xemacps );\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
new file mode 100644 (file)
index 0000000..12b8c60
--- /dev/null
@@ -0,0 +1,585 @@
+/*\r
+ * Copyright (c) 2007-2008, Advanced Micro Devices, Inc.\r
+ *               All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ *    * Redistributions of source code must retain the above copyright\r
+ *      notice, this list of conditions and the following disclaimer.\r
+ *    * Redistributions in binary form must reproduce the above copyright\r
+ *      notice, this list of conditions and the following disclaimer in\r
+ *      the documentation and/or other materials provided with the\r
+ *      distribution.\r
+ *    * Neither the name of Advanced Micro Devices, Inc. nor the names\r
+ *      of its contributors may be used to endorse or promote products\r
+ *      derived from this software without specific prior written\r
+ *      permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+/*\r
+ * Some portions copyright (c) 2010-2013 Xilinx, Inc.  All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+#include "Zynq/x_emacpsif.h"\r
+//#include "lwipopts.h"\r
+#include "xparameters_ps.h"\r
+#include "xparameters.h"\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+///* FreeRTOS+TCP includes. */\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+\r
+int phy_detected = 0;\r
+\r
+/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c\r
+ *** to run it on a PEEP board\r
+ ***/\r
+\r
+/* Advertisement control register. */\r
+#define ADVERTISE_10HALF               0x0020  /* Try for 10mbps half-duplex  */\r
+#define ADVERTISE_10FULL               0x0040  /* Try for 10mbps full-duplex  */\r
+#define ADVERTISE_100HALF              0x0080  /* Try for 100mbps half-duplex */\r
+#define ADVERTISE_100FULL              0x0100  /* Try for 100mbps full-duplex */\r
+\r
+#define ADVERTISE_100_AND_10   (ADVERTISE_10FULL | ADVERTISE_100FULL | \\r
+                                                               ADVERTISE_10HALF | ADVERTISE_100HALF)\r
+#define ADVERTISE_100                  (ADVERTISE_100FULL | ADVERTISE_100HALF)\r
+#define ADVERTISE_10                   (ADVERTISE_10FULL | ADVERTISE_10HALF)\r
+\r
+#define ADVERTISE_1000                 0x0300\r
+\r
+\r
+//#define PHY_REG_00_BMCR            0x00 // Basic mode control register\r
+//#define PHY_REG_01_BMSR            0x01 // Basic mode status register\r
+//#define PHY_REG_02_PHYSID1         0x02 // PHYS ID 1\r
+//#define PHY_REG_03_PHYSID2         0x03 // PHYS ID 2\r
+//#define PHY_REG_04_ADVERTISE       0x04 // Advertisement control reg\r
+\r
+#define IEEE_CONTROL_REG_OFFSET                                0\r
+#define IEEE_STATUS_REG_OFFSET                         1\r
+#define IEEE_AUTONEGO_ADVERTISE_REG                    4\r
+#define IEEE_PARTNER_ABILITIES_1_REG_OFFSET    5\r
+#define IEEE_1000_ADVERTISE_REG_OFFSET         9\r
+#define IEEE_PARTNER_ABILITIES_3_REG_OFFSET    10\r
+#define IEEE_COPPER_SPECIFIC_CONTROL_REG       16\r
+#define IEEE_SPECIFIC_STATUS_REG                       17\r
+#define IEEE_COPPER_SPECIFIC_STATUS_REG_2      19\r
+#define IEEE_CONTROL_REG_MAC                           21\r
+#define IEEE_PAGE_ADDRESS_REGISTER                     22\r
+\r
+\r
+#define IEEE_CTRL_1GBPS_LINKSPEED_MASK         0x2040\r
+#define IEEE_CTRL_LINKSPEED_MASK                       0x0040\r
+#define IEEE_CTRL_LINKSPEED_1000M                      0x0040\r
+#define IEEE_CTRL_LINKSPEED_100M                       0x2000\r
+#define IEEE_CTRL_LINKSPEED_10M                                0x0000\r
+#define IEEE_CTRL_RESET_MASK                           0x8000\r
+#define IEEE_CTRL_AUTONEGOTIATE_ENABLE         0x1000\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#define IEEE_CTRL_RESET                         0x9140\r
+#define IEEE_CTRL_ISOLATE_DISABLE               0xFBFF\r
+#endif\r
+#define IEEE_STAT_AUTONEGOTIATE_CAPABLE                0x0008\r
+#define IEEE_STAT_AUTONEGOTIATE_COMPLETE       0x0020\r
+#define IEEE_STAT_AUTONEGOTIATE_RESTART                0x0200\r
+#define IEEE_STAT_1GBPS_EXTENSIONS                     0x0100\r
+#define IEEE_AN1_ABILITY_MASK                          0x1FE0\r
+#define IEEE_AN3_ABILITY_MASK_1GBPS                    0x0C00\r
+#define IEEE_AN1_ABILITY_MASK_100MBPS          0x0380\r
+#define IEEE_AN1_ABILITY_MASK_10MBPS           0x0060\r
+#define IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK     0x0030\r
+\r
+#define IEEE_ASYMMETRIC_PAUSE_MASK                     0x0800\r
+#define IEEE_PAUSE_MASK                                                0x0400\r
+#define IEEE_AUTONEG_ERROR_MASK                                0x8000\r
+\r
+#define PHY_DETECT_REG  1\r
+#define PHY_DETECT_MASK 0x1808\r
+\r
+#define XEMACPS_GMII2RGMII_SPEED1000_FD                0x140\r
+#define XEMACPS_GMII2RGMII_SPEED100_FD         0x2100\r
+#define XEMACPS_GMII2RGMII_SPEED10_FD          0x100\r
+#define XEMACPS_GMII2RGMII_REG_NUM                     0x10\r
+\r
+/* Frequency setting */\r
+#define SLCR_LOCK_ADDR                 (XPS_SYS_CTRL_BASEADDR + 0x4)\r
+#define SLCR_UNLOCK_ADDR               (XPS_SYS_CTRL_BASEADDR + 0x8)\r
+#define SLCR_GEM0_CLK_CTRL_ADDR        (XPS_SYS_CTRL_BASEADDR + 0x140)\r
+#define SLCR_GEM1_CLK_CTRL_ADDR        (XPS_SYS_CTRL_BASEADDR + 0x144)\r
+#ifdef PEEP\r
+#define SLCR_GEM_10M_CLK_CTRL_VALUE            0x00103031\r
+#define SLCR_GEM_100M_CLK_CTRL_VALUE   0x00103001\r
+#define SLCR_GEM_1G_CLK_CTRL_VALUE             0x00103011\r
+#endif\r
+#define SLCR_LOCK_KEY_VALUE                    0x767B\r
+#define SLCR_UNLOCK_KEY_VALUE                  0xDF0D\r
+#define SLCR_ADDR_GEM_RST_CTRL                 (XPS_SYS_CTRL_BASEADDR + 0x214)\r
+#define EMACPS_SLCR_DIV_MASK                   0xFC0FC0FF\r
+\r
+#define EMAC0_BASE_ADDRESS                             0xE000B000\r
+#define EMAC1_BASE_ADDRESS                             0xE000C000\r
+\r
+static int detect_phy(XEmacPs *xemacpsp)\r
+{\r
+       u16 phy_reg;\r
+       u32 phy_addr;\r
+\r
+       for (phy_addr = 31; phy_addr > 0; phy_addr--) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, PHY_DETECT_REG,\r
+                                                       &phy_reg);\r
+\r
+               if ((phy_reg != 0xFFFF) &&\r
+                       ((phy_reg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {\r
+                       /* Found a valid PHY address */\r
+                       FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected at address %d.\r\n",\r
+                                                                                                                                       phy_addr));\r
+                       FreeRTOS_printf( ("XEmacPs detect_phy: PHY detected.\n" ) );\r
+                       phy_detected = phy_addr;\r
+                       return phy_addr;\r
+               }\r
+       }\r
+\r
+       FreeRTOS_printf( ("XEmacPs detect_phy: No PHY detected.  Assuming a PHY at address 0\n" ) );\r
+\r
+        /* default to zero */\r
+       return 0;\r
+}\r
+\r
+#ifdef PEEP\r
+unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
+{\r
+\r
+       u16 control;\r
+       u16 status;\r
+       u16 partner_capabilities;\r
+       u16 partner_capabilities_1000;\r
+       u16 phylinkspeed;\r
+       u32 phy_addr = detect_phy(xemacpsp);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+                                                                                                                       ADVERTISE_1000);\r
+       /* Advertise PHY speed of 100 and 10 Mbps */\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
+                                                                                                       ADVERTISE_100_AND_10);\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
+                                                                                                                               &control);\r
+       control |= (IEEE_CTRL_AUTONEGOTIATE_ENABLE |\r
+                                       IEEE_STAT_AUTONEGOTIATE_RESTART);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
+\r
+       /* Read PHY control and status registers is successful. */\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
+\r
+       if ((control & IEEE_CTRL_AUTONEGOTIATE_ENABLE) && (status &\r
+                                       IEEE_STAT_AUTONEGOTIATE_CAPABLE)) {\r
+\r
+               while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
+                       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
+                                                                                                                               &status);\r
+               }\r
+\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_1_REG_OFFSET,\r
+                                                                                                                       &partner_capabilities);\r
+\r
+               if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
+                       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_PARTNER_ABILITIES_3_REG_OFFSET,\r
+                                                                                                               &partner_capabilities_1000);\r
+                       if (partner_capabilities_1000 & IEEE_AN3_ABILITY_MASK_1GBPS)\r
+                               return 1000;\r
+               }\r
+\r
+               if (partner_capabilities & IEEE_AN1_ABILITY_MASK_100MBPS)\r
+                       return 100;\r
+               if (partner_capabilities & IEEE_AN1_ABILITY_MASK_10MBPS)\r
+                       return 10;\r
+\r
+               xil_printf("%s: unknown PHY link speed, setting TEMAC speed to be 10 Mbps\r\n",\r
+                               __FUNCTION__);\r
+               return 10;\r
+\r
+       } else {\r
+\r
+               /* Update TEMAC speed accordingly */\r
+               if (status & IEEE_STAT_1GBPS_EXTENSIONS) {\r
+                       /* Get commanded link speed */\r
+                       phylinkspeed = control & IEEE_CTRL_1GBPS_LINKSPEED_MASK;\r
+\r
+                       switch (phylinkspeed) {\r
+                               case (IEEE_CTRL_LINKSPEED_1000M):\r
+                                       return 1000;\r
+                               case (IEEE_CTRL_LINKSPEED_100M):\r
+                                       return 100;\r
+                               case (IEEE_CTRL_LINKSPEED_10M):\r
+                                       return 10;\r
+                               default:\r
+                                       xil_printf("%s: unknown PHY link speed (%d), setting TEMAC speed to be 10 Mbps\r\n",\r
+                                                       __FUNCTION__, phylinkspeed);\r
+                                       return 10;\r
+                       }\r
+\r
+               } else {\r
+\r
+                       return (control & IEEE_CTRL_LINKSPEED_MASK) ? 100 : 10;\r
+\r
+               }\r
+       }\r
+}\r
+\r
+#else /* Zynq */\r
+unsigned get_IEEE_phy_speed(XEmacPs *xemacpsp)\r
+{\r
+       u16 temp;\r
+       u16 control;\r
+       u16 status;\r
+       u16 partner_capabilities;\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+       u32 phy_addr = XPAR_PCSPMA_SGMII_PHYADDR;\r
+#else\r
+       u32 phy_addr = detect_phy(xemacpsp);\r
+#endif\r
+       xil_printf("Start PHY autonegotiation \r\n");\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+       XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
+       control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
+       control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
+       control |= IEEE_PAUSE_MASK;\r
+       control |= ADVERTISE_100;\r
+       control |= ADVERTISE_10;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+                                                                                                                                       &control);\r
+       control |= ADVERTISE_1000;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+                                                                                                                                       control);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
+                                                                                                                               &control);\r
+       control |= (7 << 12);   /* max number of gigabit attempts */\r
+       control |= (1 << 11);   /* enable downshift */\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_CONTROL_REG,\r
+                                                                                                                               control);\r
+#endif\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+       control |= IEEE_CTRL_AUTONEGOTIATE_ENABLE;\r
+       control |= IEEE_STAT_AUTONEGOTIATE_RESTART;\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+    control &= IEEE_CTRL_ISOLATE_DISABLE;\r
+#endif\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
+\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+       control |= IEEE_CTRL_RESET_MASK;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, control);\r
+\r
+       while (1) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+               if (control & IEEE_CTRL_RESET_MASK)\r
+                       continue;\r
+               else\r
+                       break;\r
+       }\r
+#endif\r
+       xil_printf("Waiting for PHY to complete autonegotiation.\r\n");\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);\r
+       while ( !(status & IEEE_STAT_AUTONEGOTIATE_COMPLETE) ) {\r
+               sleep(1);\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_COPPER_SPECIFIC_STATUS_REG_2,\r
+                                                                                                                                       &temp);\r
+               if (temp & IEEE_AUTONEG_ERROR_MASK) {\r
+                       xil_printf("Auto negotiation error \r\n");\r
+               }\r
+#endif\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_STATUS_REG_OFFSET,\r
+                                                                                                                               &status);\r
+               }\r
+\r
+       xil_printf("autonegotiation complete \r\n");\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+#else\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_SPECIFIC_STATUS_REG, &partner_capabilities);\r
+#endif\r
+\r
+#if XPAR_GIGE_PCS_PMA_CORE_PRESENT == 1\r
+       xil_printf("Waiting for Link to be up; Polling for SGMII core Reg \r\n");\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
+       while(!(temp & 0x8000)) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, 5, &temp);\r
+       }\r
+       if((temp & 0x0C00) == 0x0800) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+               return 1000;\r
+       }\r
+       else if((temp & 0x0C00) == 0x0400) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+               return 100;\r
+       }\r
+       else if((temp & 0x0C00) == 0x0000) {\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+               return 10;\r
+       } else {\r
+               xil_printf("get_IEEE_phy_speed(): Invalid speed bit value, Deafulting to Speed = 10 Mbps\r\n");\r
+               XEmacPs_PhyRead(xemacpsp, phy_addr, 0, &temp);\r
+               XEmacPs_PhyWrite(xemacpsp, phy_addr, 0, 0x0100);\r
+               return 10;\r
+       }\r
+#else\r
+       if ( ((partner_capabilities >> 14) & 3) == 2)/* 1000Mbps */\r
+               return 1000;\r
+       else if ( ((partner_capabilities >> 14) & 3) == 1)/* 100Mbps */\r
+               return 100;\r
+       else                                    /* 10Mbps */\r
+               return 10;\r
+#endif\r
+}\r
+#endif\r
+\r
+unsigned configure_IEEE_phy_speed(XEmacPs *xemacpsp, unsigned speed)\r
+{\r
+       u16 control;\r
+       u32 phy_addr = detect_phy(xemacpsp);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp,phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 2);\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, &control);\r
+       control |= IEEE_RGMII_TXRX_CLOCK_DELAYED_MASK;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_MAC, control);\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_PAGE_ADDRESS_REGISTER, 0);\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, &control);\r
+       control |= IEEE_ASYMMETRIC_PAUSE_MASK;\r
+       control |= IEEE_PAUSE_MASK;\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG, control);\r
+\r
+       XEmacPs_PhyRead(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET, &control);\r
+       control &= ~IEEE_CTRL_LINKSPEED_1000M;\r
+       control &= ~IEEE_CTRL_LINKSPEED_100M;\r
+       control &= ~IEEE_CTRL_LINKSPEED_10M;\r
+\r
+       if (speed == 1000) {\r
+               control |= IEEE_CTRL_LINKSPEED_1000M;\r
+       }\r
+\r
+       else if (speed == 100) {\r
+               control |= IEEE_CTRL_LINKSPEED_100M;\r
+               /* Dont advertise PHY speed of 1000 Mbps */\r
+               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET, 0);\r
+               /* Dont advertise PHY speed of 10 Mbps */\r
+               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
+                                                                                                                               ADVERTISE_100);\r
+       }\r
+\r
+       else if (speed == 10) {\r
+               control |= IEEE_CTRL_LINKSPEED_10M;\r
+               /* Dont advertise PHY speed of 1000 Mbps */\r
+               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_1000_ADVERTISE_REG_OFFSET,\r
+                                                                                                                                                       0);\r
+               /* Dont advertise PHY speed of 100 Mbps */\r
+               XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_AUTONEGO_ADVERTISE_REG,\r
+                                                                                                                               ADVERTISE_10);\r
+       }\r
+\r
+       XEmacPs_PhyWrite(xemacpsp, phy_addr, IEEE_CONTROL_REG_OFFSET,\r
+                                                                                       control | IEEE_CTRL_RESET_MASK);\r
+       {\r
+               volatile int wait;\r
+               for (wait=0; wait < 100000; wait++);\r
+       }\r
+       return 0;\r
+}\r
+\r
+static void SetUpSLCRDivisors(int mac_baseaddr, int speed)\r
+{\r
+       volatile u32 slcrBaseAddress;\r
+#ifndef PEEP\r
+       u32 SlcrDiv0;\r
+       u32 SlcrDiv1=0;\r
+       u32 SlcrTxClkCntrl;\r
+#endif\r
+\r
+       *(volatile unsigned int *)(SLCR_UNLOCK_ADDR) = SLCR_UNLOCK_KEY_VALUE;\r
+\r
+       if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+               slcrBaseAddress = SLCR_GEM0_CLK_CTRL_ADDR;\r
+       } else {\r
+               slcrBaseAddress = SLCR_GEM1_CLK_CTRL_ADDR;\r
+       }\r
+#ifdef PEEP\r
+       if (speed == 1000) {\r
+               *(volatile unsigned int *)(slcrBaseAddress) =\r
+                                                                                       SLCR_GEM_1G_CLK_CTRL_VALUE;\r
+       } else if (speed == 100) {\r
+               *(volatile unsigned int *)(slcrBaseAddress) =\r
+                                                                                       SLCR_GEM_100M_CLK_CTRL_VALUE;\r
+       } else {\r
+               *(volatile unsigned int *)(slcrBaseAddress) =\r
+                                                                                       SLCR_GEM_10M_CLK_CTRL_VALUE;\r
+       }\r
+#else\r
+       if (speed == 1000) {\r
+               if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_1000MBPS_DIV1;\r
+#endif\r
+               } else {\r
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_1000MBPS_DIV1;\r
+#endif\r
+               }\r
+       } else if (speed == 100) {\r
+               if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_100MBPS_DIV1;\r
+#endif\r
+               } else {\r
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_100MBPS_DIV1;\r
+#endif\r
+               }\r
+       } else {\r
+               if ((unsigned long)mac_baseaddr == EMAC0_BASE_ADDRESS) {\r
+#ifdef XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_0_ENET_SLCR_10MBPS_DIV1;\r
+#endif\r
+               } else {\r
+#ifdef XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0\r
+                       SlcrDiv0 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV0;\r
+                       SlcrDiv1 = XPAR_PS7_ETHERNET_1_ENET_SLCR_10MBPS_DIV1;\r
+#endif\r
+               }\r
+       }\r
+       SlcrTxClkCntrl = *(volatile unsigned int *)(slcrBaseAddress);\r
+       SlcrTxClkCntrl &= EMACPS_SLCR_DIV_MASK;\r
+       SlcrTxClkCntrl |= (SlcrDiv1 << 20);\r
+       SlcrTxClkCntrl |= (SlcrDiv0 << 8);\r
+       *(volatile unsigned int *)(slcrBaseAddress) = SlcrTxClkCntrl;\r
+#endif\r
+       *(volatile unsigned int *)(SLCR_LOCK_ADDR) = SLCR_LOCK_KEY_VALUE;\r
+       return;\r
+}\r
+\r
+\r
+unsigned link_speed;\r
+unsigned Phy_Setup (XEmacPs *xemacpsp)\r
+{\r
+       unsigned long conv_present = 0;\r
+       unsigned long convspeeddupsetting = 0;\r
+       unsigned long convphyaddr = 0;\r
+\r
+#ifdef XPAR_GMII2RGMIICON_0N_ETH0_ADDR\r
+       convphyaddr = XPAR_GMII2RGMIICON_0N_ETH0_ADDR;\r
+       conv_present = 1;\r
+#else\r
+#ifdef XPAR_GMII2RGMIICON_0N_ETH1_ADDR\r
+       convphyaddr = XPAR_GMII2RGMIICON_0N_ETH1_ADDR;\r
+       conv_present = 1;\r
+#endif\r
+#endif\r
+\r
+#ifdef  ipconfigNIC_LINKSPEED_AUTODETECT\r
+       link_speed = get_IEEE_phy_speed(xemacpsp);\r
+       if (link_speed == 1000) {\r
+               SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
+               convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
+       } else if (link_speed == 100) {\r
+               SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
+               convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
+       } else {\r
+               SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
+               convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
+       }\r
+#elif  defined(ipconfigNIC_LINKSPEED1000)\r
+       SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,1000);\r
+       link_speed = 1000;\r
+       configure_IEEE_phy_speed(xemacpsp, link_speed);\r
+       convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED1000_FD;\r
+       sleep(1);\r
+#elif  defined(ipconfigNIC_LINKSPEED100)\r
+       SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,100);\r
+       link_speed = 100;\r
+       configure_IEEE_phy_speed(xemacpsp, link_speed);\r
+       convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED100_FD;\r
+       sleep(1);\r
+#elif  defined(ipconfigNIC_LINKSPEED10)\r
+       SetUpSLCRDivisors(xemacpsp->Config.BaseAddress,10);\r
+       link_speed = 10;\r
+       configure_IEEE_phy_speed(xemacpsp, link_speed);\r
+       convspeeddupsetting = XEMACPS_GMII2RGMII_SPEED10_FD;\r
+       sleep(1);\r
+#endif\r
+       if (conv_present) {\r
+               XEmacPs_PhyWrite(xemacpsp, convphyaddr,\r
+               XEMACPS_GMII2RGMII_REG_NUM, convspeeddupsetting);\r
+       }\r
+\r
+       xil_printf("link speed: %d\r\n", link_speed);\r
+       return link_speed;\r
+}\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_topology.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/x_topology.h
new file mode 100644 (file)
index 0000000..bb51783
--- /dev/null
@@ -0,0 +1,46 @@
+/*\r
+ * Copyright (c) 2007-2013 Xilinx, Inc.  All rights reserved.\r
+ *\r
+ * Xilinx, Inc.\r
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A\r
+ * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS\r
+ * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR\r
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION\r
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE\r
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.\r
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO\r
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO\r
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE\r
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY\r
+ * AND FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+#ifndef __XTOPOLOGY_H_\r
+#define __XTOPOLOGY_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };\r
+\r
+struct xtopology_t {\r
+       unsigned emac_baseaddr;\r
+       enum xemac_types emac_type;\r
+       unsigned intc_baseaddr;\r
+       unsigned intc_emac_intr;        /* valid only for xemac_type_xps_emaclite */\r
+       unsigned scugic_baseaddr; /* valid only for Zynq */\r
+       unsigned scugic_emac_intr; /* valid only for GEM */\r
+};\r
+\r
+extern int x_topology_n_emacs;\r
+extern struct xtopology_t x_topology[];\r
+\r
+int x_topology_find_index(unsigned base);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/ksz8851snl/NetworkInterface.c
new file mode 100644 (file)
index 0000000..5ed7ae8
--- /dev/null
@@ -0,0 +1,1304 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_IP_Private.h"\r
+#include "NetworkBufferManagement.h"\r
+#include "NetworkInterface.h"\r
+\r
+#include "sam4e_xplained_pro.h"\r
+#include "hr_gettime.h"\r
+#include "conf_eth.h"\r
+#include "ksz8851snl.h"\r
+#include "ksz8851snl_reg.h"\r
+\r
+/* Some files from the Atmel Software Framework */\r
+#include <sysclk.h>\r
+#include <pdc/pdc.h>\r
+#include <spi/spi.h>\r
+\r
+/*\r
+       Sending a packet:\r
+\r
+               1) Called by UP-task, add buffer to the TX-list:\r
+                       xNetworkInterfaceOutput()\r
+                               tx_buffers[ us_tx_head ] = pxNetworkBuffer;\r
+                               tx_busy[ us_tx_head ] = pdTRUE;\r
+                               us_tx_head++;\r
+\r
+               2) Called by EMAC-Task: start SPI transfer\r
+                       ksz8851snl_update()\r
+                       if( ul_spi_pdc_status == SPI_PDC_IDLE )\r
+                       {\r
+                               if( ( tx_busy[ us_tx_tail ] != pdFALSE ) &&\r
+                                       ( us_pending_frame == 0 ) &&\r
+                                       ( ul_had_intn_interrupt == 0 ) )\r
+                               {\r
+                                       // disable all interrupts.\r
+                                       ksz8851_reg_write( REG_INT_MASK, 0 );\r
+                                       Bring KSZ8851SNL_CSN_GPIO low\r
+                                       ksz8851_fifo_write( pxNetworkBuffer->pucEthernetBuffer, xLength, xLength );\r
+                                       ul_spi_pdc_status = SPI_PDC_TX_START;\r
+                                       tx_cur_buffer = pxNetworkBuffer;\r
+                               }\r
+                       }\r
+               3) Wait for SPI RXBUFF interrupt\r
+                       SPI_Handler()\r
+                               if( ul_spi_pdc_status == SPI_PDC_TX_START )\r
+                               {\r
+                                       if( SPI_Status & SPI_SR_RXBUFF )\r
+                                       {\r
+                                               ul_spi_pdc_status = SPI_PDC_TX_COMPLETE;\r
+                                       }\r
+                               }\r
+\r
+               4) Called by EMAC-Task: finish SPI transfer\r
+                       ksz8851snl_update()\r
+                               if( ul_spi_pdc_status == SPI_PDC_TX_COMPLETE )\r
+                               {\r
+                                       ul_spi_pdc_status = SPI_PDC_IDLE;\r
+                                       Bring KSZ8851SNL_CSN_GPIO high\r
+                                       // TX step12: disable TXQ write access.\r
+                                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+                                       // TX step12.1: enqueue frame in TXQ.\r
+                                       ksz8851_reg_setbits( REG_TXQ_CMD, TXQ_ENQUEUE );\r
+\r
+                                       // RX step13: enable INT_RX flag.\r
+                                       ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+\r
+                                       // Buffer sent, free the corresponding buffer and mark descriptor as owned by software.\r
+                                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+                                       tx_buffers[ us_tx_tail ] = NULL;\r
+                                       tx_busy[ us_tx_tail ] = pdFALSE;\r
+                                       us_tx_tail++\r
+                               }\r
+\r
+       Receiving a packet:\r
+\r
+               1) Wait for a INTN interrupt\r
+                       INTN_Handler()\r
+                               ul_had_intn_interrupt = 1\r
+                               vTaskNotifyGiveFromISR();       // Wake up the EMAC task\r
+\r
+               2) Called by EMAC-Task: check for new fragments and start SPI transfer\r
+                       ksz8851snl_update()\r
+                               if( ul_spi_pdc_status == SPI_PDC_IDLE )\r
+                               {\r
+                                       if( ( ul_had_intn_interrupt != 0 ) || ( us_pending_frame > 0 ) )\r
+                                       {\r
+                                               if( us_pending_frame == 0 )\r
+                                               {\r
+                                                       us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;\r
+                                                       if( us_pending_frame == 0 )\r
+                                                       {\r
+                                                               break;\r
+                                                       }\r
+                                               }\r
+                                               // RX step2: disable all interrupts.\r
+                                               ksz8851_reg_write( REG_INT_MASK, 0 );\r
+                                               Check if there is a valid packet: REG_RX_FHR_STATUS\r
+                                               Read the length of the next fragment: REG_RX_FHR_BYTE_CNT\r
+                                               ul_spi_pdc_status = SPI_PDC_RX_START;\r
+                                               gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);\r
+                                               // Start SPI data transfer\r
+                                               ksz8851_fifo_read( pxNetworkBuffer->pucEthernetBuffer, xReadLength );\r
+                                       }\r
+                               }\r
+\r
+               3) Wait for SPI RXBUFF interrupt\r
+                       SPI_Handler()\r
+                       if( ul_spi_pdc_status == SPI_PDC_RX_START:\r
+                       {\r
+                               if( ( ulCurrentSPIStatus & SPI_SR_RXBUFF ) != 0 )\r
+                               {\r
+                                       // Transfer complete, disable SPI RXBUFF interrupt.\r
+                                       spi_disable_interrupt( KSZ8851SNL_SPI, SPI_IDR_RXBUFF );\r
+\r
+                                       ul_spi_pdc_status = SPI_PDC_RX_COMPLETE;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               4) Finish SPI transfer\r
+                       ksz8851snl_update()\r
+                               if( ul_spi_pdc_status == SPI_PDC_RX_COMPLETE )\r
+                               {\r
+                                       ul_spi_pdc_status = SPI_PDC_IDLE;\r
+                                       Bring KSZ8851SNL_CSN_GPIO high\r
+                                       // RX step21: end RXQ read access.\r
+                                       ksz8851_reg_clrbits(REG_RXQ_CMD, RXQ_START);\r
+                                       // RX step22-23: update frame count to be read.\r
+                                       us_pending_frame--\r
+                                       // RX step24: enable INT_RX flag if transfer complete.\r
+                                       if( us_pending_frame == 0 )\r
+                                       {\r
+                                               // Allow more RX interrupts.\r
+                                               ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+                                       }\r
+\r
+                                       // Mark descriptor ready to be read.\r
+                                       rx_ready[ rxHead ] = pdTRUE;\r
+                                       rxHead++\r
+                               }\r
+*/\r
+\r
+#define PHY_REG_00_BMCR            0x00 // Basic mode control register\r
+#define PHY_REG_01_BMSR            0x01 // Basic mode status register\r
+#define PHY_REG_02_PHYSID1         0x02 // PHYS ID 1\r
+#define PHY_REG_03_PHYSID2         0x03 // PHYS ID 2\r
+#define PHY_REG_04_ADVERTISE       0x04 // Advertisement control reg\r
+#define PHY_REG_05_LPA             0x05 // Link partner ability reg\r
+#define        PHY_REG_06_ANER            0x06 //      6       RW              Auto-Negotiation Expansion Register\r
+#define        PHY_REG_07_ANNPTR          0x07 //      7       RW              Auto-Negotiation Next Page TX\r
+#define        PHY_REG_08_RESERVED0       0x08 // 0x08..0x0Fh  8-15    RW              RESERVED\r
+\r
+#define BMSR_LINK_STATUS            0x0004  //!< Link status\r
+\r
+#ifndef        PHY_LS_HIGH_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not\r
+       receiving packets. */\r
+       #define PHY_LS_HIGH_CHECK_TIME_MS       15000\r
+#endif\r
+\r
+#ifndef        PHY_LS_LOW_CHECK_TIME_MS\r
+       /* Check if the LinkSStatus in the PHY is still low every second. */\r
+       #define PHY_LS_LOW_CHECK_TIME_MS        1000\r
+#endif\r
+\r
+/* Interrupt events to process.  Currently only the Rx event is processed\r
+although code for other events is included to allow for possible future\r
+expansion. */\r
+#define EMAC_IF_RX_EVENT                               1UL\r
+#define EMAC_IF_TX_EVENT                               2UL\r
+#define EMAC_IF_ERR_EVENT                              4UL\r
+#define EMAC_IF_ALL_EVENT                              ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT )\r
+\r
+#define ETHERNET_CONF_PHY_ADDR BOARD_GMAC_PHY_ADDR\r
+\r
+#ifdef ipconfigHAS_TX_CRC_OFFLOADING\r
+       #undef ipconfigHAS_TX_CRC_OFFLOADING\r
+#endif\r
+/* Override this define because the KSZ8851 is programmed to set all outgoing CRC's */\r
+#define        ipconfigHAS_TX_CRC_OFFLOADING   1\r
+\r
+#ifndef        EMAC_MAX_BLOCK_TIME_MS\r
+       #define EMAC_MAX_BLOCK_TIME_MS  100ul\r
+#endif\r
+\r
+/* Default the size of the stack used by the EMAC deferred handler task to 4x\r
+the size of the stack used by the idle task - but allow this to be overridden in\r
+FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */\r
+#ifndef configEMAC_TASK_STACK_SIZE\r
+       #define configEMAC_TASK_STACK_SIZE ( 6 * configMINIMAL_STACK_SIZE )\r
+#endif\r
+\r
+#define SPI_PDC_IDLE                   0\r
+#define SPI_PDC_RX_START               1\r
+#define SPI_PDC_TX_ERROR               2\r
+#define SPI_PDC_RX_COMPLETE            3\r
+#define SPI_PDC_TX_START               4\r
+#define SPI_PDC_RX_ERROR               5\r
+#define SPI_PDC_TX_COMPLETE            6\r
+\r
+/**\r
+ * ksz8851snl driver structure.\r
+ */\r
+typedef struct {\r
+       /** Set to 1 when owner is software (ready to read), 0 for Micrel. */\r
+       uint32_t rx_ready[MICREL_RX_BUFFERS];\r
+       /** Set to 1 when owner is Micrel, 0 for software. */\r
+       uint32_t tx_busy[MICREL_TX_BUFFERS];\r
+       /** RX NetworkBufferDescriptor_t pointer list */\r
+       NetworkBufferDescriptor_t *rx_buffers[MICREL_RX_BUFFERS];\r
+       /** TX NetworkBufferDescriptor_t pointer list */\r
+       NetworkBufferDescriptor_t *tx_buffers[MICREL_TX_BUFFERS];\r
+       NetworkBufferDescriptor_t *tx_cur_buffer;\r
+\r
+       /** Circular buffer head pointer for packet received. */\r
+       uint32_t us_rx_head;\r
+       /** Circular buffer tail pointer for packet to be read. */\r
+       uint32_t us_rx_tail;\r
+       /** Circular buffer head pointer by upper layer (buffer to be sent). */\r
+       uint32_t us_tx_head;\r
+       /** Circular buffer tail pointer incremented by handlers (buffer sent). */\r
+       uint32_t us_tx_tail;\r
+\r
+       uint32_t ul_total_tx;\r
+       uint32_t ul_total_rx;\r
+       uint32_t tx_space;\r
+\r
+       /** Still experimental: hash table to allow certain multicast addresses. */\r
+       uint16_t pusHashTable[ 4 ];\r
+\r
+       /* ul_spi_pdc_status has "SPI_PDC_xxx" values. */\r
+       volatile uint32_t ul_spi_pdc_status;\r
+\r
+       /* ul_had_intn_interrupt becomes true within the INTN interrupt. */\r
+       volatile uint32_t ul_had_intn_interrupt;\r
+\r
+       uint16_t us_pending_frame;\r
+} xKSZ8851_Device_t;\r
+\r
+/* SPI PDC register base.\r
+Declared in ASF\sam\components\ksz8851snl\ksz8851snl.c */\r
+extern Pdc *g_p_spi_pdc;\r
+\r
+/* Temporary buffer for PDC reception.\r
+declared in ASF\sam\components\ksz8851snl\ksz8851snl.c */\r
+extern uint8_t tmpbuf[1536];\r
+\r
+COMPILER_ALIGNED(8)\r
+static xKSZ8851_Device_t xMicrelDevice;\r
+\r
+static TaskHandle_t xTransmitHandle;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Wait a fixed time for the link status to indicate the network is up.\r
+ */\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime );\r
+\r
+/*\r
+ * A deferred interrupt handler task that processes GMAC interrupts.\r
+ */\r
+static void prvEMACHandlerTask( void *pvParameters );\r
+\r
+/*\r
+ * Try to obtain an Rx packet from the hardware.\r
+ */\r
+static uint32_t prvEMACRxPoll( void );\r
+\r
+static inline unsigned long ulReadMDIO( unsigned uAddress );\r
+\r
+static void ksz8851snl_low_level_init( void );\r
+\r
+static NetworkBufferDescriptor_t *ksz8851snl_low_level_input( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Bit map of outstanding ETH interrupt events for processing.  Currently only\r
+the Rx interrupt is handled, although code is included for other events to\r
+enable future expansion. */\r
+static volatile uint32_t ulISREvents;\r
+\r
+/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */\r
+static uint32_t ulPHYLinkStatus = 0;\r
+static volatile BaseType_t xGMACSwitchRequired;\r
+\r
+static void ksz8851snl_update( void );\r
+\r
+static void ksz8851snl_rx_init( void );\r
+\r
+static void ksz8851snl_tx_init( void );\r
+\r
+/* Holds the handle of the task used as a deferred interrupt processor.  The\r
+handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
+related interrupts. */\r
+TaskHandle_t xEMACTaskHandle = NULL;\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+const TickType_t x5_Seconds = 5000UL;\r
+\r
+       if( xEMACTaskHandle == NULL )\r
+       {\r
+               ksz8851snl_low_level_init();\r
+\r
+               /* Wait at most 5 seconds for a Link Status in the PHY. */\r
+               xGMACWaitLS( pdMS_TO_TICKS( x5_Seconds ) );\r
+\r
+               /* The handler task is created at the highest possible priority to\r
+               ensure the interrupt handler can return directly to it. */\r
+               xTaskCreate( prvEMACHandlerTask, "KSZ8851", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+               configASSERT( xEMACTaskHandle );\r
+       }\r
+\r
+       /* When returning non-zero, the stack will become active and\r
+    start DHCP (in configured) */\r
+       ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+       return ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xGetPhyLinkStatus( void )\r
+{\r
+BaseType_t xResult;\r
+\r
+       /* This function returns true if the Link Status in the PHY is high. */\r
+       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+       {\r
+               xResult = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xResult = pdFALSE;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t bReleaseAfterSend )\r
+{\r
+BaseType_t xResult = pdFALSE;\r
+int txHead = xMicrelDevice.us_tx_head;\r
+\r
+       /* Make sure the next descriptor is free. */\r
+       if( xMicrelDevice.tx_busy[ txHead ] != pdFALSE )\r
+       {\r
+               /* All TX buffers busy. */\r
+       }\r
+       else if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )\r
+       {\r
+               /* Output: LS low. */\r
+       }\r
+       else\r
+       {\r
+               /* Pass the packet. */\r
+               xMicrelDevice.tx_buffers[ txHead ] = pxNetworkBuffer;\r
+               /* The descriptor is now owned by Micrel. */\r
+               xMicrelDevice.tx_busy[ txHead ] = pdTRUE;\r
+\r
+               /* Move the head pointer. */\r
+               if( ++txHead == MICREL_TX_BUFFERS )\r
+               {\r
+                       txHead = 0;\r
+               }\r
+               xMicrelDevice.us_tx_head = txHead;\r
+               if( xEMACTaskHandle != NULL )\r
+               {\r
+                       xTaskNotifyGive( xEMACTaskHandle );\r
+               }\r
+\r
+       #if( ipconfigZERO_COPY_TX_DRIVER != 1 )\r
+               #warning Please ipconfigZERO_COPY_TX_DRIVER as 1\r
+       #endif\r
+               configASSERT( bReleaseAfterSend != pdFALSE );\r
+               xResult = pdTRUE;\r
+       }\r
+       if( ( xResult == pdFALSE ) && ( bReleaseAfterSend  != pdFALSE ) )\r
+       {\r
+               vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+       }\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* This Micrel has numbered it's PHY registers in a different way.\r
+Translate the register index. */\r
+static int ks8851_phy_reg( int reg )\r
+{\r
+       switch (reg) {\r
+       case PHY_REG_00_BMCR:\r
+               return REG_PHY_CNTL;    // P1MBCR;\r
+       case PHY_REG_01_BMSR:\r
+               return REG_PHY_STATUS;\r
+       case PHY_REG_02_PHYSID1:\r
+               return REG_PHY_ID_LOW;\r
+       case PHY_REG_03_PHYSID2:\r
+               return REG_PHY_ID_HIGH;\r
+       case PHY_REG_04_ADVERTISE:\r
+               return REG_PHY_AUTO_NEGOTIATION;\r
+       case PHY_REG_05_LPA:\r
+               return REG_PHY_REMOTE_CAPABILITY;\r
+       }\r
+\r
+       return 0x0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static inline unsigned long ulReadMDIO( unsigned uAddress )\r
+{\r
+uint16_t usPHYStatus;\r
+int ks8851_reg = ks8851_phy_reg( uAddress );\r
+\r
+       if( ks8851_reg != 0 )\r
+       {\r
+               usPHYStatus = ksz8851_reg_read( ks8851_reg );\r
+       }\r
+       else\r
+       {\r
+               /* Other addresses not yet implemented. */\r
+               usPHYStatus = 0;\r
+       }\r
+       return usPHYStatus;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t xGMACWaitLS( TickType_t xMaxTime )\r
+{\r
+TickType_t xStartTime = xTaskGetTickCount();\r
+TickType_t xEndTime;\r
+BaseType_t xReturn;\r
+const TickType_t xShortTime = pdMS_TO_TICKS( 100UL );\r
+const uint32_t ulHz_Per_MHz = 1000000UL;\r
+\r
+       for( ;; )\r
+       {\r
+               xEndTime = xTaskGetTickCount();\r
+\r
+               if( ( xEndTime - xStartTime ) > xMaxTime )\r
+               {\r
+                       /* Wated more than xMaxTime, return. */\r
+                       xReturn = pdFALSE;\r
+                       break;\r
+               }\r
+\r
+               /* Check the link status again. */\r
+               ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+               if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+               {\r
+                       /* Link is up - return. */\r
+                       xReturn = pdTRUE;\r
+                       break;\r
+               }\r
+\r
+               /* Link is down - wait in the Blocked state for a short while (to allow\r
+               other tasks to execute) before checking again. */\r
+               vTaskDelay( xShortTime );\r
+       }\r
+\r
+       FreeRTOS_printf( ( "xGMACWaitLS: %ld freq %lu Mz\n",\r
+               xReturn,\r
+               sysclk_get_cpu_hz() / ulHz_Per_MHz ) );\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void vPioSetPinHigh(uint32_t ul_pin)\r
+{\r
+       Pio *p_pio = (Pio *)((uint32_t)PIOA + (PIO_DELTA * (ul_pin >> 5)));\r
+       // Value to be driven on the I/O line: 1.\r
+       p_pio->PIO_SODR = 1 << (ul_pin & 0x1F);\r
+}\r
+\r
+/**\r
+ * \brief Handler for SPI interrupt.\r
+ */\r
+void SPI_Handler(void)\r
+{\r
+BaseType_t xDoWakeup = pdFALSE;\r
+BaseType_t xKSZTaskWoken = pdFALSE;\r
+uint32_t ulCurrentSPIStatus;\r
+uint32_t ulEnabledSPIStatus;\r
+\r
+       ulCurrentSPIStatus = spi_read_status( KSZ8851SNL_SPI );\r
+       ulEnabledSPIStatus = spi_read_interrupt_mask( KSZ8851SNL_SPI );\r
+       ulCurrentSPIStatus &= ulEnabledSPIStatus;\r
+       spi_disable_interrupt( KSZ8851SNL_SPI, ulCurrentSPIStatus );\r
+\r
+\r
+       switch( xMicrelDevice.ul_spi_pdc_status )\r
+       {\r
+               case SPI_PDC_RX_START:\r
+               {\r
+                       if( ( ulCurrentSPIStatus & SPI_SR_OVRES ) != 0 )\r
+                       {\r
+                               pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);\r
+                               xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_ERROR;\r
+                               xDoWakeup = pdTRUE;\r
+                       }\r
+                       else\r
+                       {\r
+                               if( ( ulCurrentSPIStatus & SPI_SR_RXBUFF ) != 0 )\r
+                               {\r
+                                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_COMPLETE;\r
+                                       xDoWakeup = pdTRUE;\r
+                               }\r
+                       }\r
+               }\r
+               break;\r
+\r
+               case SPI_PDC_TX_START:\r
+               {\r
+                       /* Middle of TX. */\r
+                       if( ( ulCurrentSPIStatus & SPI_SR_OVRES ) != 0 )\r
+                       {\r
+                               pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);\r
+                               xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_ERROR;\r
+                               xDoWakeup = pdTRUE;\r
+                       }\r
+                       else\r
+                       {\r
+                               if( ( ulCurrentSPIStatus & SPI_SR_ENDRX ) != 0 )\r
+                               {\r
+                                       /* Enable RX complete interrupt. */\r
+                                       spi_enable_interrupt( KSZ8851SNL_SPI, SPI_IER_RXBUFF );\r
+                               }\r
+                               /* End of TX. */\r
+                               if( ( ulCurrentSPIStatus & SPI_END_OF_TX ) != 0 )\r
+                               {\r
+                                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_COMPLETE;\r
+                                       xDoWakeup = pdTRUE;\r
+                               }\r
+                       }\r
+               }\r
+               break;\r
+       }       /* switch( xMicrelDevice.ul_spi_pdc_status ) */\r
+\r
+       if( xDoWakeup != pdFALSE )\r
+       {\r
+               if( xEMACTaskHandle != NULL )\r
+               {\r
+                       vTaskNotifyGiveFromISR( xEMACTaskHandle, ( BaseType_t * ) &xKSZTaskWoken );\r
+               }\r
+       }\r
+       else\r
+       {\r
+       }\r
+       portEND_SWITCHING_ISR( xKSZTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void INTN_Handler(uint32_t id, uint32_t mask)\r
+{\r
+BaseType_t xKSZTaskWoken = pdFALSE;\r
+\r
+       if( ( id == INTN_ID ) &&\r
+               ( mask == INTN_PIN_MSK ) )\r
+       {\r
+               /* Clear the PIO interrupt flags. */\r
+               pio_get_interrupt_status( INTN_PIO );\r
+\r
+               /* Set the INTN flag. */\r
+               xMicrelDevice.ul_had_intn_interrupt++;\r
+               if( xEMACTaskHandle != NULL )\r
+               {\r
+                       vTaskNotifyGiveFromISR( xEMACTaskHandle, &( xKSZTaskWoken ) );\r
+               }\r
+       }\r
+       portEND_SWITCHING_ISR( xKSZTaskWoken );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/**\r
+ * \brief Populate the RX descriptor ring buffers with pbufs.\r
+ *\r
+ * \param p_ksz8851snl_dev Pointer to driver data structure.\r
+ */\r
+static void ksz8851snl_rx_populate_queue( void )\r
+{\r
+       uint32_t ul_index = 0;\r
+       NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+\r
+       /* Set up the RX descriptors */\r
+       for (ul_index = 0; ul_index < MICREL_RX_BUFFERS; ul_index++) {\r
+               if( xMicrelDevice.rx_buffers[ ul_index ] == NULL )\r
+               {\r
+                       /* Allocate a new NetworkBufferDescriptor_t with the maximum size. */\r
+                       pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( ipconfigNETWORK_MTU + 36, 100 );\r
+                       if( pxNetworkBuffer == NULL )\r
+                       {\r
+                               FreeRTOS_printf( ( "ksz8851snl_rx_populate_queue: NetworkBufferDescriptor_t allocation failure\n" ) );\r
+                               configASSERT( 1 == 2 );\r
+                       }\r
+\r
+                       /* Make sure lwIP is well configured so one NetworkBufferDescriptor_t can contain the maximum packet size. */\r
+                       //LWIP_ASSERT("ksz8851snl_rx_populate_queue: NetworkBufferDescriptor_t size too small!", pbuf_clen(pxNetworkBuffer) <= 1);\r
+\r
+                       /* Save NetworkBufferDescriptor_t pointer to be sent to lwIP upper layer. */\r
+                       xMicrelDevice.rx_buffers[ ul_index ] = pxNetworkBuffer;\r
+                       /* Pass it to Micrel for reception. */\r
+                       xMicrelDevice.rx_ready[ ul_index ] = pdFALSE;\r
+               }\r
+       }\r
+}\r
+\r
+unsigned tx_space, wait_tx_space, tx_status, fhr_status;\r
+unsigned rx_debug = 0;\r
+/**\r
+ * \brief Update Micrel state machine and perform required actions.\r
+ *\r
+ * \param netif the lwIP network interface structure for this ethernetif.\r
+ */\r
+static void ksz8851snl_update()\r
+{\r
+       uint16_t txmir = 0;\r
+\r
+/* Check for free PDC. */\r
+       switch( xMicrelDevice.ul_spi_pdc_status )\r
+       {\r
+       case SPI_PDC_TX_ERROR:\r
+               {\r
+               uint32_t ulValue;\r
+       //              /* TX step11: end TX transfer. */\r
+                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+                       vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+                       vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+                       vTaskDelay( 1 );\r
+\r
+                       /* Disable asynchronous transfer mode. */\r
+                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+                       /* TX step12: disable TXQ write access. */\r
+                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+\r
+                       ulValue = ksz8851snl_reset_tx();\r
+\r
+                       xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;\r
+\r
+                       FreeRTOS_printf( ("SPI_PDC_TX_ERROR %02X\n", ulValue ) );\r
+               }\r
+               break;\r
+\r
+       case SPI_PDC_RX_ERROR:\r
+               {\r
+               uint32_t ulValue;\r
+                       /* TX step11: end TX transfer. */\r
+                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+                       vTaskDelay( 2 ); gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+                       vTaskDelay( 1 ); gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+                       vTaskDelay( 1 );\r
+\r
+                       /* Disable asynchronous transfer mode. */\r
+                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+                       /* TX step12: disable TXQ write access. */\r
+                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+\r
+                       //ulValue = ksz8851snl_reset_rx();\r
+                       ulValue = ksz8851snl_reinit();\r
+\r
+                       xGMACWaitLS( pdMS_TO_TICKS( 5000UL ) );\r
+\r
+                       FreeRTOS_printf( ("SPI_PDC_RX_ERROR %02X\n", ulValue ) );\r
+               }\r
+               break;\r
+       }\r
+       switch( xMicrelDevice.ul_spi_pdc_status )\r
+       {\r
+               case SPI_PDC_IDLE:\r
+               {\r
+               int txTail = xMicrelDevice.us_tx_tail;\r
+\r
+                       /*\r
+                        * ========================== Handle RX ==========================\r
+                        */\r
+                       if( ( xMicrelDevice.ul_had_intn_interrupt != 0 ) || ( xMicrelDevice.us_pending_frame > 0 ) )\r
+                       {\r
+                       int rxHead = xMicrelDevice.us_rx_head;\r
+                       NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+#warning try\r
+                               xMicrelDevice.ul_had_intn_interrupt = 0;\r
+\r
+                               if( xMicrelDevice.us_pending_frame == 0 )\r
+                               {\r
+                               uint16_t int_status;\r
+                                       /* RX step1: read interrupt status for INT_RX flag. */\r
+                                       int_status = ksz8851_reg_read( REG_INT_STATUS );\r
+\r
+\r
+                                       /* RX step2: disable all interrupts. */\r
+                                       ksz8851_reg_write( REG_INT_MASK, 0 );\r
+\r
+                                       /* RX step3: clear INT_RX flag. */\r
+                                       ksz8851_reg_setbits( REG_INT_STATUS, INT_RX );\r
+\r
+                                       /* RX step4-5: check for received frames. */\r
+                                       xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;\r
+                                       if( xMicrelDevice.us_pending_frame == 0 )\r
+                                       {\r
+                                               /* RX step24: enable INT_RX flag. */\r
+                                               ksz8851_reg_write(REG_INT_MASK, INT_RX);\r
+                                               return;\r
+                                       }\r
+                               }\r
+#warning try\r
+                               xMicrelDevice.ul_had_intn_interrupt = 0;\r
+\r
+                               /* Now xMicrelDevice.us_pending_frame != 0 */\r
+\r
+                               /* Don't break Micrel state machine, wait for a free descriptor first! */\r
+                               if( xMicrelDevice.rx_ready[ rxHead ] != pdFALSE )\r
+                               {\r
+                                       FreeRTOS_printf( ( "ksz8851snl_update: out of free descriptor! [tail=%u head=%u]\n",\r
+                                                       xMicrelDevice.us_rx_tail, rxHead ) );\r
+                                       return;\r
+                               }\r
+                               pxNetworkBuffer = xMicrelDevice.rx_buffers[ rxHead ];\r
+\r
+                               if( pxNetworkBuffer == NULL )\r
+                               {\r
+                                       ksz8851snl_rx_populate_queue();\r
+                                       FreeRTOS_printf( ( "ksz8851snl_update: no buffer set [head=%u]\n", rxHead ) );\r
+                                       return;\r
+                               }\r
+\r
+                               /* RX step6: get RX packet status. */\r
+                               fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );\r
+                               if( ( ( fhr_status & RX_VALID ) == 0 ) || ( ( fhr_status & RX_ERRORS ) != 0 ) )\r
+                               {\r
+                                       ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_CMD_FREE_PACKET);\r
+                                       FreeRTOS_printf( ( "ksz8851snl_update: RX packet error!\n" ) );\r
+\r
+                                       /* RX step4-5: check for received frames. */\r
+                                       xMicrelDevice.us_pending_frame = ksz8851_reg_read(REG_RX_FRAME_CNT_THRES) >> 8;\r
+                                       if( xMicrelDevice.us_pending_frame == 0 )\r
+                                       {\r
+                                               /* RX step24: enable INT_RX flag. */\r
+                                               ksz8851_reg_write(REG_INT_MASK, INT_RX);\r
+                                       }\r
+                                       ulISREvents |= EMAC_IF_ERR_EVENT;\r
+                               }\r
+                               else\r
+                               {\r
+                               size_t xLength;\r
+                                       /* RX step7: read frame length. */\r
+                                       xLength = ksz8851_reg_read(REG_RX_FHR_BYTE_CNT) & RX_BYTE_CNT_MASK;\r
+\r
+                                       /* RX step8: Drop packet if len is invalid or no descriptor available. */\r
+                                       if( xLength == 0 )\r
+                                       {\r
+                                               ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_CMD_FREE_PACKET );\r
+                                               FreeRTOS_printf( ( "ksz8851snl_update: RX bad len!\n" ) );\r
+                                               ulISREvents |= EMAC_IF_ERR_EVENT;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                       size_t xReadLength = xLength;\r
+\r
+                                               xMicrelDevice.ul_total_rx++;\r
+                                               /* RX step9: reset RX frame pointer. */\r
+                                               ksz8851_reg_clrbits(REG_RX_ADDR_PTR, ADDR_PTR_MASK);\r
+\r
+                                               /* RX step10: start RXQ read access. */\r
+                                               ksz8851_reg_setbits(REG_RXQ_CMD, RXQ_START);\r
+                                               /* RX step11-17: start asynchronous FIFO read operation. */\r
+                                               xMicrelDevice.ul_spi_pdc_status = SPI_PDC_RX_START;\r
+                                               gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+                                               if( ( xReadLength & ( sizeof( size_t ) - 1 ) ) != 0 )\r
+                                               {\r
+                                                       xReadLength = ( xReadLength | ( sizeof( size_t ) - 1 ) ) + 1;\r
+                                               }\r
+\r
+                                               /* Pass the buffer minus 2 bytes, see ksz8851snl.c: RXQ_TWOBYTE_OFFSET. */\r
+                                               ksz8851_fifo_read( pxNetworkBuffer->pucEthernetBuffer - 2, xReadLength );\r
+                                               /* Remove CRC and update buffer length. */\r
+                                               xLength -= 4;\r
+                                               pxNetworkBuffer->xDataLength = xLength;\r
+                                               /* Wait for SPI interrupt to set status 'SPI_PDC_RX_COMPLETE'. */\r
+                                       }\r
+                               }\r
+                               break;\r
+                       } /* ul_had_intn_interrupt || us_pending_frame */\r
+                       /*\r
+                        * ========================== Handle TX ==========================\r
+                        */\r
+\r
+                       /* Fetch next packet to be sent. */\r
+                       if( ( xMicrelDevice.tx_busy[ txTail ] != pdFALSE ) &&\r
+                               ( xMicrelDevice.us_pending_frame == 0 ) &&\r
+                               ( xMicrelDevice.ul_had_intn_interrupt == 0 ) )\r
+                       {\r
+                       NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];\r
+                       size_t xLength = pxNetworkBuffer->xDataLength;\r
+                       int iIndex = xLength;\r
+\r
+                               xLength = 4 * ( ( xLength + 3 ) / 4 );\r
+                               while( iIndex < ( int ) xLength )\r
+                               {\r
+                                       pxNetworkBuffer->pucEthernetBuffer[ iIndex ] = '\0';\r
+                                       iIndex++;\r
+                               }\r
+                               pxNetworkBuffer->xDataLength = xLength;\r
+\r
+                               /* TX step1: check if TXQ memory size is available for transmit. */\r
+                               txmir = ksz8851_reg_read( REG_TX_MEM_INFO );\r
+                               txmir = txmir & TX_MEM_AVAILABLE_MASK;\r
+\r
+                               if( txmir < ( xLength + 8 ) )\r
+                               {\r
+                                       if( wait_tx_space == pdFALSE )\r
+                                       {\r
+                                               tx_status = ksz8851_reg_read( REG_TX_STATUS );\r
+                                               fhr_status = ksz8851_reg_read( REG_RX_FHR_STATUS );\r
+                                               wait_tx_space = pdTRUE;\r
+                                       }\r
+                                       //return;\r
+                                       rx_debug = 1;\r
+                                       tx_space = txmir;\r
+                               }\r
+                               else\r
+                               {\r
+                                       tx_space = txmir;\r
+\r
+                                       /* TX step2: disable all interrupts. */\r
+                                       ksz8851_reg_write( REG_INT_MASK, 0 );\r
+\r
+                                       xMicrelDevice.tx_space -= xLength;\r
+\r
+                                       /* TX step3: enable TXQ write access. */\r
+                                       ksz8851_reg_setbits( REG_RXQ_CMD, RXQ_START );\r
+                                       /* TX step4-8: perform FIFO write operation. */\r
+                                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_TX_START;\r
+                                       xMicrelDevice.tx_cur_buffer = pxNetworkBuffer;\r
+                                       /* Bring SPI SS low. */\r
+                                       gpio_set_pin_low( KSZ8851SNL_CSN_GPIO );\r
+                                       xMicrelDevice.ul_total_tx++;\r
+\r
+                                       ksz8851_fifo_write( pxNetworkBuffer->pucEthernetBuffer, xLength, xLength );\r
+                               }\r
+                       }\r
+               }\r
+               break;  /* SPI_PDC_IDLE */\r
+\r
+       case SPI_PDC_RX_COMPLETE:\r
+               {\r
+               int rxHead = xMicrelDevice.us_rx_head;\r
+                       /* RX step18-19: pad with dummy data to keep dword alignment. */\r
+                       /* Packet lengths will be rounded up to a multiple of "sizeof size_t". */\r
+//                     xLength = xMicrelDevice.rx_buffers[ rxHead ]->xDataLength & 3;\r
+//                     if( xLength != 0 )\r
+//                     {\r
+//                             ksz8851_fifo_dummy( 4 - xLength );\r
+//                     }\r
+\r
+                       /* RX step20: end RX transfer. */\r
+                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+                       /* Disable asynchronous transfer mode. */\r
+                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+                       /* RX step21: end RXQ read access. */\r
+                       ksz8851_reg_clrbits(REG_RXQ_CMD, RXQ_START);\r
+\r
+                       /* RX step22-23: update frame count to be read. */\r
+                       xMicrelDevice.us_pending_frame -= 1;\r
+\r
+                       /* RX step24: enable INT_RX flag if transfer complete. */\r
+                       if( xMicrelDevice.us_pending_frame == 0 )\r
+                       {\r
+                               ksz8851_reg_write(REG_INT_MASK, INT_RX);\r
+                       }\r
+\r
+                       /* Mark descriptor ready to be read. */\r
+                       xMicrelDevice.rx_ready[ rxHead ] = pdTRUE;\r
+                       if( ++rxHead == MICREL_RX_BUFFERS )\r
+                       {\r
+                               rxHead = 0;\r
+                       }\r
+                       xMicrelDevice.us_rx_head = rxHead;\r
+                       if( rx_debug != 0 )\r
+                       {\r
+                       uint32_t txmir;\r
+                               rx_debug = 0;\r
+                               txmir = ksz8851_reg_read( REG_TX_MEM_INFO );\r
+                               txmir = txmir & TX_MEM_AVAILABLE_MASK;\r
+                       }\r
+                       /* Tell prvEMACHandlerTask that RX packets are available. */\r
+                       ulISREvents |= EMAC_IF_RX_EVENT;\r
+               }       /* case SPI_PDC_RX_COMPLETE */\r
+               break;\r
+\r
+       case SPI_PDC_TX_COMPLETE:\r
+               {\r
+               int txTail = xMicrelDevice.us_tx_tail;\r
+               NetworkBufferDescriptor_t *pxNetworkBuffer = xMicrelDevice.tx_buffers[ txTail ];\r
+\r
+               size_t xLength;\r
+                       /* TX step9-10: pad with dummy data to keep dword alignment. */\r
+                       /* Not necessary: length is already a multiple of 4. */\r
+                       xLength = pxNetworkBuffer->xDataLength & 3;\r
+                       if( xLength != 0 )\r
+                       {\r
+//                             ksz8851_fifo_dummy( 4 - xLength );\r
+                       }\r
+\r
+//                     /* TX step11: end TX transfer. */\r
+                       gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );\r
+\r
+                       /* Disable asynchronous transfer mode. */\r
+                       xMicrelDevice.ul_spi_pdc_status = SPI_PDC_IDLE;\r
+\r
+                       /* TX step12: disable TXQ write access. */\r
+                       ksz8851_reg_clrbits( REG_RXQ_CMD, RXQ_START );\r
+\r
+                       xMicrelDevice.tx_space = ksz8851_reg_read( REG_TX_MEM_INFO ) & TX_MEM_AVAILABLE_MASK;\r
+\r
+                       /* TX step12.1: enqueue frame in TXQ. */\r
+                       ksz8851_reg_setbits( REG_TXQ_CMD, TXQ_ENQUEUE );\r
+\r
+                       /* RX step13: enable INT_RX flag. */\r
+//                     ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+                       /* Buffer sent, free the corresponding buffer and mark descriptor as owned by software. */\r
+                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+\r
+                       xMicrelDevice.tx_buffers[ txTail ] = NULL;\r
+                       xMicrelDevice.tx_busy[ txTail ] = pdFALSE;\r
+                       if( ++txTail == MICREL_TX_BUFFERS )\r
+                       {\r
+                               txTail = 0;\r
+                       }\r
+\r
+                       xMicrelDevice.us_tx_tail = txTail;\r
+                       /* Experiment. */\r
+                       //xMicrelDevice.ul_had_intn_interrupt = 1;\r
+                       if( xTransmitHandle != NULL )\r
+                       {\r
+                               xTaskNotifyGive( xTransmitHandle );\r
+                       }\r
+#warning moved downward\r
+                       /* RX step13: enable INT_RX flag. */\r
+                       ksz8851_reg_write( REG_INT_MASK, INT_RX );\r
+                       /* Prevent the EMAC task from sleeping a single time. */\r
+                       ulISREvents |= EMAC_IF_TX_EVENT;\r
+               }       /* case SPI_PDC_TX_COMPLETE */\r
+               break;\r
+       }       /* switch( xMicrelDevice.ul_spi_pdc_status ) */\r
+}\r
+\r
+/**\r
+ * \brief Set up the RX descriptor ring buffers.\r
+ *\r
+ * This function sets up the descriptor list used for RX packets.\r
+ *\r
+ */\r
+static void ksz8851snl_rx_init()\r
+{\r
+       uint32_t ul_index = 0;\r
+\r
+       /* Init pointer index. */\r
+       xMicrelDevice.us_rx_head = 0;\r
+       xMicrelDevice.us_rx_tail = 0;\r
+\r
+       /* Set up the RX descriptors. */\r
+       for (ul_index = 0; ul_index < MICREL_RX_BUFFERS; ul_index++) {\r
+               xMicrelDevice.rx_buffers[ul_index] = NULL;\r
+               xMicrelDevice.rx_ready[ul_index] = pdFALSE;\r
+       }\r
+\r
+       /* Build RX buffer and descriptors. */\r
+       ksz8851snl_rx_populate_queue();\r
+}\r
+\r
+/**\r
+ * \brief Set up the TX descriptor ring buffers.\r
+ *\r
+ * This function sets up the descriptor list used for TX packets.\r
+ *\r
+ */\r
+static void ksz8851snl_tx_init()\r
+{\r
+       uint32_t ul_index = 0;\r
+\r
+       /* Init TX index pointer. */\r
+       xMicrelDevice.us_tx_head = 0;\r
+       xMicrelDevice.us_tx_tail = 0;\r
+\r
+       /* Set up the TX descriptors */\r
+       for( ul_index = 0; ul_index < MICREL_TX_BUFFERS; ul_index++ )\r
+       {\r
+               xMicrelDevice.tx_busy[ul_index] = pdFALSE;\r
+       }\r
+       xMicrelDevice.tx_space = 6144;\r
+}\r
+\r
+/**\r
+ * \brief Initialize ksz8851snl ethernet controller.\r
+ *\r
+ * \note Called from ethernetif_init().\r
+ *\r
+ * \param netif the lwIP network interface structure for this ethernetif.\r
+ */\r
+static void ksz8851snl_low_level_init( void )\r
+{\r
+       ksz8851snl_rx_init();\r
+       ksz8851snl_tx_init();\r
+\r
+       /* Enable NVIC interrupts. */\r
+       NVIC_SetPriority(SPI_IRQn, INT_PRIORITY_SPI);\r
+       NVIC_EnableIRQ(SPI_IRQn);\r
+\r
+       /* Initialize SPI link. */\r
+       if( ksz8851snl_init() < 0 )\r
+       {\r
+               FreeRTOS_printf( ( "ksz8851snl_low_level_init: failed to initialize the Micrel driver!\n" ) );\r
+               configASSERT(0 == 1);\r
+       }\r
+       memset( xMicrelDevice.pusHashTable, 255, sizeof( xMicrelDevice.pusHashTable ) );\r
+       ksz8851_reg_write( REG_MAC_HASH_0, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 0 ] ) );\r
+       ksz8851_reg_write( REG_MAC_HASH_2, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 1 ] ) );\r
+       ksz8851_reg_write( REG_MAC_HASH_4, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 2 ] ) );\r
+       ksz8851_reg_write( REG_MAC_HASH_6, FreeRTOS_htons( xMicrelDevice.pusHashTable[ 3 ] ) );\r
+\r
+       /* Initialize interrupt line INTN. */\r
+       configure_intn( INTN_Handler );\r
+}\r
+\r
+/**\r
+ * \brief Use pre-allocated pbuf as DMA source and return the incoming packet.\r
+ *\r
+ * \param netif the lwIP network interface structure for this ethernetif.\r
+ *\r
+ * \return a pbuf filled with the received packet (including MAC header).\r
+ * 0 on memory error.\r
+ */\r
+static NetworkBufferDescriptor_t *ksz8851snl_low_level_input( void )\r
+{\r
+NetworkBufferDescriptor_t *pxNetworkBuffer = NULL;\r
+int rxTail = xMicrelDevice.us_rx_tail;\r
+\r
+       /* Check that descriptor is owned by software (ie packet received). */\r
+       if( xMicrelDevice.rx_ready[ rxTail ] != pdFALSE )\r
+       {\r
+\r
+               /* Fetch pre-allocated buffer */\r
+               pxNetworkBuffer = xMicrelDevice.rx_buffers[ rxTail ];\r
+\r
+               /* Remove this pbuf from its descriptor. */\r
+               xMicrelDevice.rx_buffers[ rxTail ] = NULL;\r
+\r
+               /* Clears rx_ready and sets rx_buffers. */\r
+               ksz8851snl_rx_populate_queue();\r
+\r
+               if( ++rxTail == MICREL_RX_BUFFERS )\r
+               {\r
+                       rxTail = 0;\r
+               }\r
+               xMicrelDevice.us_rx_tail = rxTail;\r
+       }\r
+\r
+       return pxNetworkBuffer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static uint32_t prvEMACRxPoll( void )\r
+{\r
+NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+uint32_t ulReturnValue = 0;\r
+\r
+       for( ;; )\r
+       {\r
+       /* Only for logging. */\r
+       int rxTail = xMicrelDevice.us_rx_tail;\r
+       EthernetHeader_t *pxEthernetHeader;\r
+\r
+       pxNetworkBuffer = ksz8851snl_low_level_input();\r
+       \r
+               if( pxNetworkBuffer == NULL )\r
+               {\r
+                       break;\r
+               }\r
+               pxEthernetHeader = ( EthernetHeader_t * ) ( pxNetworkBuffer->pucEthernetBuffer );\r
+\r
+               if( ( pxEthernetHeader->usFrameType != ipIPv4_FRAME_TYPE ) &&\r
+                       ( pxEthernetHeader->usFrameType != ipARP_FRAME_TYPE     ) )\r
+               {\r
+                       FreeRTOS_printf( ( "Frame type %02X received\n", pxEthernetHeader->usFrameType ) );\r
+               }\r
+               ulReturnValue++;\r
+\r
+               xRxEvent.pvData = ( void * )pxNetworkBuffer;\r
+               /* Send the descriptor to the IP task for processing. */\r
+               if( xSendEventStructToIPTask( &xRxEvent, 100UL ) != pdTRUE )\r
+               {\r
+                       vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );\r
+                       iptraceETHERNET_RX_EVENT_LOST();\r
+                       FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) );\r
+               }\r
+       }\r
+\r
+       return ulReturnValue;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvEMACHandlerTask( void *pvParameters )\r
+{\r
+TimeOut_t xPhyTime;\r
+TickType_t xPhyRemTime;\r
+TickType_t xLoggingTime;\r
+UBaseType_t uxLastMinBufferCount = 0;\r
+UBaseType_t uxCurrentCount;\r
+BaseType_t xResult = 0;\r
+uint32_t xStatus;\r
+const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS );\r
+#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+       UBaseType_t uxLastMinQueueSpace = 0;\r
+#endif\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       configASSERT( xEMACTaskHandle );\r
+\r
+       vTaskSetTimeOutState( &xPhyTime );\r
+       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+       xLoggingTime = xTaskGetTickCount();\r
+\r
+       for( ;; )\r
+       {\r
+               uxCurrentCount = uxGetMinimumFreeNetworkBuffers();\r
+               if( uxLastMinBufferCount != uxCurrentCount )\r
+               {\r
+                       /* The logging produced below may be helpful\r
+                       while tuning +TCP: see how many buffers are in use. */\r
+                       uxLastMinBufferCount = uxCurrentCount;\r
+                       FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+                               uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );\r
+               }\r
+\r
+               #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+               {\r
+                       uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+                       if( uxLastMinQueueSpace != uxCurrentCount )\r
+                       {\r
+                               /* The logging produced below may be helpful\r
+                               while tuning +TCP: see how many buffers are in use. */\r
+                               uxLastMinQueueSpace = uxCurrentCount;\r
+                               FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );\r
+                       }\r
+               }\r
+               #endif /* ipconfigCHECK_IP_QUEUE_SPACE */\r
+\r
+               /* Run the state-machine of the ksz8851 driver. */\r
+               ksz8851snl_update();\r
+\r
+               if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )\r
+               {\r
+                       /* No events to process now, wait for the next. */\r
+                       ulTaskNotifyTake( pdTRUE, ulMaxBlockTime );\r
+               }\r
+\r
+               if( ( xTaskGetTickCount() - xLoggingTime ) > 10000 )\r
+               {\r
+                       xLoggingTime += 10000;\r
+                       FreeRTOS_printf( ( "Now Tx/Rx %7d /%7d\n",\r
+                               xMicrelDevice.ul_total_tx, xMicrelDevice.ul_total_rx ) );\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 )\r
+               {\r
+                       ulISREvents &= ~EMAC_IF_RX_EVENT;\r
+\r
+                       /* Wait for the EMAC interrupt to indicate that another packet has been\r
+                       received. */\r
+                       xResult = prvEMACRxPoll();\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )\r
+               {\r
+                       /* Future extension: code to release TX buffers if zero-copy is used. */\r
+                       ulISREvents &= ~EMAC_IF_TX_EVENT;\r
+               }\r
+\r
+               if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )\r
+               {\r
+                       /* Future extension: logging about errors that occurred. */\r
+                       ulISREvents &= ~EMAC_IF_ERR_EVENT;\r
+               }\r
+\r
+               if( xResult > 0 )\r
+               {\r
+                       /* As long as packets are being received, assume that\r
+                       the Link Status is high. */\r
+                       ulPHYLinkStatus |= BMSR_LINK_STATUS;\r
+                       /* A packet was received. No need to check for the PHY status now,\r
+                       but set a timer to check it later on. */\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       xResult = 0;\r
+               }\r
+               else if( ( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) &&\r
+                       ( xMicrelDevice.ul_spi_pdc_status == SPI_PDC_IDLE ) )\r
+               {\r
+                       /* Check the link status again. */\r
+                       xStatus = ulReadMDIO( PHY_REG_01_BMSR );\r
+\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )\r
+                       {\r
+                               ulPHYLinkStatus = xStatus;\r
+                               FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );\r
+                       }\r
+\r
+                       vTaskSetTimeOutState( &xPhyTime );\r
+                       if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );\r
+                       }\r
+                       else\r
+                       {\r
+                               xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );\r
+                       }\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/Common/FreeRTOS_TCP_server.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/Common/FreeRTOS_TCP_server.c
new file mode 100644 (file)
index 0000000..0e7a7af
--- /dev/null
@@ -0,0 +1,382 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_TCP_server.h"\r
+#include "FreeRTOS_server_private.h"\r
+\r
+/* Remove the entire file if TCP is not being used. */\r
+#if( ipconfigUSE_TCP == 1 )\r
+\r
+#if !defined( ARRAY_SIZE )\r
+       #define ARRAY_SIZE(x) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] )\r
+#endif\r
+\r
+\r
+static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket );\r
+static char *strnew( const char *pcString );\r
+/* Remove slashes at the end of a path. */\r
+static void prvRemoveSlash( char *pcDir );\r
+\r
+TCPServer_t *FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG *pxConfigs, BaseType_t xCount )\r
+{\r
+TCPServer_t *pxServer;\r
+SocketSet_t xSocketSet;\r
+\r
+       /* Create a new server.\r
+       xPort / xPortAlt : Make the service available on 1 or 2 public port numbers. */\r
+       xSocketSet = FreeRTOS_CreateSocketSet();\r
+\r
+       if( xSocketSet != NULL )\r
+       {\r
+       BaseType_t xSize;\r
+\r
+               xSize = sizeof( *pxServer ) - sizeof( pxServer->xServers ) + xCount * sizeof( pxServer->xServers[ 0 ] );\r
+\r
+               pxServer = ( TCPServer_t * ) pvPortMallocLarge( xSize );\r
+               if( pxServer != NULL )\r
+               {\r
+               struct freertos_sockaddr xAddress;\r
+               BaseType_t xNoTimeout = 0;\r
+               BaseType_t xIndex;\r
+\r
+                       memset( pxServer, '\0', xSize );\r
+                       pxServer->xServerCount = xCount;\r
+                       pxServer->xSocketSet = xSocketSet;\r
+\r
+                       for( xIndex = 0; xIndex < xCount; xIndex++ )\r
+                       {\r
+                       BaseType_t xPortNumber = pxConfigs[ xIndex ].xPortNumber;\r
+\r
+                               if( xPortNumber > 0 )\r
+                               {\r
+                               Socket_t xSocket;\r
+\r
+                                       xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );\r
+                                       FreeRTOS_printf( ( "TCP socket on port %d\n", ( int )xPortNumber ) );\r
+\r
+                                       if( xSocket != FREERTOS_NO_SOCKET )\r
+                                       {\r
+                                               xAddress.sin_addr = FreeRTOS_GetIPAddress(); // Single NIC, currently not used\r
+                                               xAddress.sin_port = FreeRTOS_htons( xPortNumber );\r
+\r
+                                               FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );\r
+                                               FreeRTOS_listen( xSocket, pxConfigs[ xIndex ].xBackLog );\r
+\r
+                                               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );\r
+                                               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );\r
+\r
+                                               #if( ipconfigHTTP_RX_BUFSIZE > 0 )\r
+                                               {\r
+                                                       if( pxConfigs[ xIndex ].eType == eSERVER_HTTP )\r
+                                                       {\r
+                                                       WinProperties_t xWinProps;\r
+\r
+                                                               memset( &xWinProps, '\0', sizeof( xWinProps ) );\r
+                                                               /* The parent socket itself won't get connected.  The properties below\r
+                                                               will be inherited by each new child socket. */\r
+                                                               xWinProps.lTxBufSize = ipconfigHTTP_TX_BUFSIZE;\r
+                                                               xWinProps.lTxWinSize = ipconfigHTTP_TX_WINSIZE;\r
+                                                               xWinProps.lRxBufSize = ipconfigHTTP_RX_BUFSIZE;\r
+                                                               xWinProps.lRxWinSize = ipconfigHTTP_RX_WINSIZE;\r
+\r
+                                                               /* Set the window and buffer sizes. */\r
+                                                               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps,     sizeof( xWinProps ) );\r
+                                                       }\r
+                                               }\r
+                                               #endif\r
+\r
+                                               FreeRTOS_FD_SET( xSocket, xSocketSet, eSELECT_READ|eSELECT_EXCEPT );\r
+                                               pxServer->xServers[ xIndex ].xSocket = xSocket;\r
+                                               pxServer->xServers[ xIndex ].eType = pxConfigs[ xIndex ].eType;\r
+                                               pxServer->xServers[ xIndex ].pcRootDir = strnew( pxConfigs[ xIndex ].pcRootDir );\r
+                                               prvRemoveSlash( ( char * ) pxServer->xServers[ xIndex ].pcRootDir );\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* Could not allocate the server, delete the socket set */\r
+                       FreeRTOS_DeleteSocketSet( xSocketSet );\r
+               }\r
+       }\r
+       else\r
+       {\r
+               /* Could not create a socket set, return NULL */\r
+               pxServer = NULL;\r
+       }\r
+\r
+       return pxServer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket )\r
+{\r
+TCPClient_t *pxClient = NULL;\r
+BaseType_t xSize = 0;\r
+FTCPWorkFunction fWorkFunc = NULL;\r
+FTCPDeleteFunction fDeleteFunc = NULL;\r
+const char *pcType = "Unknown";\r
+\r
+       /*_RB_ Can the work and delete functions be part of the xSERVER_CONFIG structure\r
+       becomes generic, with no pre-processing required? */\r
+       #if( ipconfigUSE_HTTP != 0 )\r
+       {\r
+               if( pxServer->xServers[ xIndex ].eType == eSERVER_HTTP )\r
+               {\r
+                       xSize = sizeof( HTTPClient_t );\r
+                       fWorkFunc = xHTTPClientWork;\r
+                       fDeleteFunc = vHTTPClientDelete;\r
+                       pcType = "HTTP";\r
+               }\r
+       }\r
+       #endif /* ipconfigUSE_HTTP != 0 */\r
+\r
+       #if( ipconfigUSE_FTP != 0 )\r
+       {\r
+               if( pxServer->xServers[ xIndex ].eType == eSERVER_FTP )\r
+               {\r
+                       xSize = sizeof( FTPClient_t );\r
+                       fWorkFunc = xFTPClientWork;\r
+                       fDeleteFunc = vFTPClientDelete;\r
+                       pcType = "FTP";\r
+               }\r
+       }\r
+       #endif /* ipconfigUSE_FTP != 0 */\r
+\r
+       /* Malloc enough space for a new HTTP-client */\r
+       if( xSize )\r
+       {\r
+               pxClient = ( TCPClient_t* ) pvPortMallocLarge( xSize );\r
+       }\r
+\r
+       if( pxClient != NULL )\r
+       {\r
+               memset( pxClient, '\0', xSize );\r
+\r
+               /* Put the new client in front of the list. */\r
+               pxClient->eType = pxServer->xServers[ xIndex ].eType;\r
+               pxClient->pcRootDir = pxServer->xServers[ xIndex ].pcRootDir;\r
+               pxClient->pxParent = pxServer;\r
+               pxClient->xSocket = xNexSocket;\r
+               pxClient->pxNextClient = pxServer->pxClients;\r
+               pxClient->fWorkFunction = fWorkFunc;\r
+               pxClient->fDeleteFunction = fDeleteFunc;\r
+               pxServer->pxClients = pxClient;\r
+\r
+               FreeRTOS_FD_SET( xNexSocket, pxServer->xSocketSet, eSELECT_READ|eSELECT_EXCEPT );\r
+       }\r
+       else\r
+       {\r
+               pcType = "closed";\r
+               FreeRTOS_closesocket( xNexSocket );\r
+       }\r
+\r
+       FreeRTOS_printf( ( "TPC-server: new %s client\n", pcType ) );\r
+\r
+       /* Remove compiler warnings in case FreeRTOS_printf() is not used. */\r
+       ( void ) pcType;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FreeRTOS_TCPServerWork( TCPServer_t *pxServer, TickType_t xBlockingTime )\r
+{\r
+TCPClient_t **ppxClient;\r
+BaseType_t xIndex;\r
+BaseType_t xRc;\r
+\r
+       /* Let the server do one working cycle */\r
+       xRc = FreeRTOS_select( pxServer->xSocketSet, xBlockingTime );\r
+\r
+       if( xRc != 0 )\r
+       {\r
+               for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )\r
+               {\r
+               struct freertos_sockaddr xAddress;\r
+               Socket_t xNexSocket;\r
+               socklen_t xSocketLength;\r
+\r
+                       if( pxServer->xServers[ xIndex ].xSocket == FREERTOS_NO_SOCKET )\r
+                       {\r
+                               continue;\r
+                       }\r
+\r
+                       xSocketLength = sizeof( xAddress );\r
+                       xNexSocket = FreeRTOS_accept( pxServer->xServers[ xIndex ].xSocket, &xAddress, &xSocketLength);\r
+\r
+                       if( ( xNexSocket != FREERTOS_NO_SOCKET ) && ( xNexSocket != FREERTOS_INVALID_SOCKET ) )\r
+                       {\r
+                               prvReceiveNewClient( pxServer, xIndex, xNexSocket );\r
+                       }\r
+               }\r
+       }\r
+\r
+       ppxClient = &pxServer->pxClients;\r
+\r
+       while( ( * ppxClient ) != NULL )\r
+       {\r
+       TCPClient_t *pxThis = *ppxClient;\r
+\r
+               /* Almost C++ */\r
+               xRc = pxThis->fWorkFunction( pxThis );\r
+\r
+               if (xRc < 0 )\r
+               {\r
+                       *ppxClient = pxThis->pxNextClient;\r
+                       /* Close handles, resources */\r
+                       pxThis->fDeleteFunction( pxThis );\r
+                       /* Free the space */\r
+                       vPortFreeLarge( pxThis );\r
+               }\r
+               else\r
+               {\r
+                       ppxClient = &( pxThis->pxNextClient );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static char *strnew( const char *pcString )\r
+{\r
+BaseType_t xLength;\r
+char *pxBuffer;\r
+\r
+       xLength = strlen( pcString ) + 1;\r
+       pxBuffer = ( char * ) pvPortMalloc( xLength );\r
+       if( pxBuffer != NULL )\r
+       {\r
+               memcpy( pxBuffer, pcString, xLength );\r
+       }\r
+\r
+       return pxBuffer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRemoveSlash( char *pcDir )\r
+{\r
+BaseType_t xLength = strlen( pcDir );\r
+\r
+       while( ( xLength > 0 ) && ( pcDir[ xLength - 1 ] == '/' ) )\r
+       {\r
+               pcDir[ --xLength ] = '\0';\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SIGNALS != 0 )\r
+\r
+       /* FreeRTOS_TCPServerWork() calls select().\r
+       The two functions below provide a possibility to interrupt\r
+       the call to select(). After the interruption, resume\r
+       by calling FreeRTOS_TCPServerWork() again. */\r
+       BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t *pxServer )\r
+       {\r
+       BaseType_t xIndex;\r
+       BaseType_t xResult = pdFALSE;\r
+               for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )\r
+               {\r
+                       if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )\r
+                       {\r
+                               FreeRTOS_SignalSocket( pxServer->xServers[ xIndex ].xSocket );\r
+                               xResult = pdTRUE;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SIGNALS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SIGNALS != 0 )\r
+\r
+       /* Same as above: this function may be called from an ISR,\r
+       for instance a GPIO interrupt. */\r
+       BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t *pxServer, BaseType_t *pxHigherPriorityTaskWoken )\r
+       {\r
+       BaseType_t xIndex;\r
+       BaseType_t xResult = pdFALSE;\r
+               for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )\r
+               {\r
+                       if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )\r
+                       {\r
+                               FreeRTOS_SignalSocketFromISR( pxServer->xServers[ xIndex ].xSocket, pxHigherPriorityTaskWoken );\r
+                               xResult = pdTRUE;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+#endif /* ipconfigSUPPORT_SIGNALS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#endif /* ipconfigUSE_TCP != 1 */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/FTP/FreeRTOS_FTP_commands.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/FTP/FreeRTOS_FTP_commands.c
new file mode 100644 (file)
index 0000000..7e49e83
--- /dev/null
@@ -0,0 +1,106 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_FTP_commands.h"\r
+\r
+const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ] =\r
+{\r
+/* cmdLen cmdName[7]    cmdType  checkLogin checkNullArg */\r
+       { 4, "USER",            ECMD_USER, pdFALSE, pdFALSE },\r
+       { 4, "PASS",            ECMD_PASS, pdFALSE, pdFALSE },\r
+       { 4, "ACCT",            ECMD_ACCT,      pdTRUE, pdFALSE },\r
+       { 3,  "CWD",            ECMD_CWD,       pdTRUE, pdTRUE },\r
+       { 4, "CDUP",            ECMD_CDUP,      pdTRUE, pdFALSE },\r
+       { 4, "SMNT",            ECMD_SMNT,      pdTRUE, pdFALSE },\r
+       { 4, "QUIT",            ECMD_QUIT,      pdTRUE, pdFALSE },\r
+       { 4, "REIN",            ECMD_REIN,      pdTRUE, pdFALSE },\r
+       { 4, "PORT",            ECMD_PORT,      pdTRUE, pdFALSE },\r
+       { 4, "PASV",            ECMD_PASV,      pdTRUE, pdFALSE },\r
+       { 4, "TYPE",            ECMD_TYPE,      pdTRUE, pdFALSE },\r
+       { 4, "STRU",            ECMD_STRU,      pdTRUE, pdFALSE },\r
+       { 4, "MODE",            ECMD_MODE,      pdTRUE, pdFALSE },\r
+       { 4, "RETR",            ECMD_RETR,      pdTRUE, pdTRUE },\r
+       { 4, "STOR",            ECMD_STOR,      pdTRUE, pdTRUE },\r
+       { 4, "STOU",            ECMD_STOU,      pdTRUE, pdFALSE },\r
+       { 4, "APPE",            ECMD_APPE,      pdTRUE, pdFALSE },\r
+       { 4, "ALLO",            ECMD_ALLO,      pdTRUE, pdFALSE },\r
+       { 4, "REST",            ECMD_REST,      pdTRUE, pdFALSE },\r
+       { 4, "RNFR",            ECMD_RNFR,      pdTRUE, pdTRUE },\r
+       { 4, "RNTO",            ECMD_RNTO,      pdTRUE, pdTRUE },\r
+       { 4, "ABOR",            ECMD_ABOR,      pdTRUE, pdFALSE },\r
+       { 4, "SIZE",            ECMD_SIZE,      pdTRUE, pdTRUE },\r
+       { 4, "MDTM",            ECMD_MDTM,      pdTRUE, pdTRUE },\r
+       { 4, "DELE",            ECMD_DELE,      pdTRUE, pdTRUE },\r
+       { 3,  "RMD",            ECMD_RMD,       pdTRUE, pdTRUE },\r
+       { 3,  "MKD",            ECMD_MKD,       pdTRUE, pdTRUE },\r
+       { 3,  "PWD",            ECMD_PWD,       pdTRUE, pdFALSE },\r
+       { 4, "LIST",            ECMD_LIST,      pdTRUE, pdFALSE },\r
+       { 4, "NLST",            ECMD_NLST,      pdTRUE, pdFALSE },\r
+       { 4, "SITE",            ECMD_SITE,      pdTRUE, pdFALSE },\r
+       { 4, "SYST",            ECMD_SYST,      pdFALSE, pdFALSE },\r
+       { 4, "FEAT",            ECMD_FEAT,      pdFALSE, pdFALSE },\r
+       { 4, "STAT",            ECMD_STAT,      pdTRUE, pdFALSE },\r
+       { 4, "HELP",            ECMD_HELP,      pdFALSE, pdFALSE },\r
+       { 4, "NOOP",            ECMD_NOOP,      pdFALSE, pdFALSE },\r
+       { 4, "EMPT",            ECMD_EMPTY,     pdFALSE, pdFALSE },\r
+       { 4, "CLOS",            ECMD_CLOSE,     pdTRUE, pdFALSE },\r
+       { 4, "UNKN",            ECMD_UNKNOWN, pdFALSE, pdFALSE },\r
+};\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/FTP/FreeRTOS_FTP_server.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/FTP/FreeRTOS_FTP_server.c
new file mode 100644 (file)
index 0000000..2e75a63
--- /dev/null
@@ -0,0 +1,2669 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <time.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "portmacro.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_TCP_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_Stream_Buffer.h"\r
+\r
+/* FreeRTOS Protocol includes. */\r
+#include "FreeRTOS_FTP_commands.h"\r
+#include "FreeRTOS_TCP_server.h"\r
+#include "FreeRTOS_server_private.h"\r
+\r
+/* Remove the whole file if FTP is not supported. */\r
+#if( ipconfigUSE_FTP == 1 )\r
+\r
+#ifndef HTTP_SERVER_BACKLOG\r
+       #define HTTP_SERVER_BACKLOG                     ( 12 )\r
+#endif\r
+\r
+#if !defined( ARRAY_SIZE )\r
+       #define ARRAY_SIZE( x ) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] )\r
+#endif\r
+\r
+#if defined(__WIN32__) && !defined(ipconfigFTP_FS_USES_BACKSLAH)\r
+       #define ipconfigFTP_FS_USES_BACKSLAH    1\r
+#endif\r
+\r
+/* Some defines to make the code more readbale */\r
+#define pcCOMMAND_BUFFER       pxClient->pxParent->pcCommandBuffer\r
+#define pcNEW_DIR                      pxClient->pxParent->pcNewDir\r
+#define pcFILE_BUFFER          pxClient->pxParent->pcFileBuffer\r
+\r
+/* This FTP server will only do binary transfers */\r
+#define TMODE_BINARY   1\r
+#define TMODE_ASCII            2\r
+#define TMODE_7BITS            3\r
+#define TMODE_8BITS            4\r
+\r
+/* Ascii character definitions. */\r
+#define ftpASCII_CR    13\r
+#define ftpASCII_LF 10\r
+\r
+#if defined( FTP_WRITES_ALIGNED ) || defined( ipconfigFTP_WRITES_ALIGNED )\r
+       #error Name change : please rename the define to the new name 'ipconfigFTP_ZERO_COPY_ALIGNED_WRITES'\r
+#endif\r
+\r
+/*\r
+ * ipconfigFTP_ZERO_COPY_ALIGNED_WRITES : experimental optimisation option.\r
+ * If non-zero, receiving data will be done with the zero-copy method and also\r
+ * writes to disk will be done with sector-alignment as much as possible.\r
+ */\r
+#ifndef ipconfigFTP_ZERO_COPY_ALIGNED_WRITES\r
+       #define ipconfigFTP_ZERO_COPY_ALIGNED_WRITES                    0\r
+#endif\r
+\r
+/*\r
+ * This module only has 2 public functions:\r
+ */\r
+BaseType_t xFTPClientWork( TCPClient_t *pxClient );\r
+void vFTPClientDelete( TCPClient_t *pxClient );\r
+\r
+/*\r
+ * Process a single command.\r
+ */\r
+static BaseType_t prvProcessCommand( FTPClient_t *pxClient, BaseType_t xIndex, char *pcRestCommand );\r
+\r
+/*\r
+ * Create a socket for a data connection to the FTP client.\r
+ */\r
+static BaseType_t prvTransferConnect( FTPClient_t *pxClient, BaseType_t xDoListen );\r
+\r
+/*\r
+ * Either call listen() or connect() to start the transfer connection.\r
+ */\r
+static BaseType_t prvTransferStart( FTPClient_t *pxClient );\r
+\r
+/*\r
+ * See if the socket has got connected or disconnected. Close the socket if\r
+ * necessary.\r
+ */\r
+static void prvTransferCheck( FTPClient_t *pxClient );\r
+\r
+/*\r
+ * Close the data socket and issue some informative logging.\r
+ */\r
+static void prvTransferCloseSocket( FTPClient_t *pxClient );\r
+\r
+/*\r
+ * Close the file handle (pxReadHandle or pxWriteHandle).\r
+ */\r
+static void prvTransferCloseFile( FTPClient_t *pxClient );\r
+\r
+/*\r
+ * Close a directory (-handle).\r
+ */\r
+static void prvTransferCloseDir( FTPClient_t *pxClient );\r
+\r
+/*\r
+ * Translate a string (indicating a transfer type) to a number.\r
+ */\r
+static BaseType_t prvGetTransferType( const char *pcType );\r
+\r
+#if( ipconfigHAS_PRINTF != 0 )\r
+       /*\r
+        * For nice logging: write an amount (number of bytes), e.g. 3512200 as\r
+        * "3.45 MB"\r
+        */\r
+       static const char *pcMkSize( uint32_t ulAmount, char *pcBuffer, BaseType_t xBufferSize );\r
+#endif\r
+\r
+#if( ipconfigHAS_PRINTF != 0 )\r
+       /*\r
+        * Calculate the average as bytes-per-second, when amount and milliseconds\r
+        * are known.\r
+        */\r
+       static uint32_t ulGetAverage( uint32_t ulAmount, TickType_t xDeltaMs );\r
+#endif\r
+\r
+/*\r
+ * A port command looks like: PORT h1,h2,h3,h4,p1,p2. Parse it and translate it\r
+ * to an IP-address and a port number.\r
+ */\r
+static UBaseType_t prvParsePortData( const char *pcCommand, uint32_t *pulIPAddress );\r
+\r
+/*\r
+ * CWD: Change current working directory.\r
+ */\r
+\r
+static BaseType_t prvChangeDir( FTPClient_t *pxClient, char *pcDirectory );\r
+\r
+/*\r
+ * RNFR: Rename from ...\r
+ */\r
+static BaseType_t prvRenameFrom( FTPClient_t *pxClient, const char *pcFileName );\r
+\r
+/*\r
+ * RNTO: Rename to ...\r
+ */\r
+static BaseType_t prvRenameTo( FTPClient_t *pxClient, const char *pcFileName );\r
+\r
+/*\r
+ * SITE: Change file permissions.\r
+ */\r
+static BaseType_t prvSiteCmd( FTPClient_t *pxClient, char *pcRestCommand );\r
+\r
+/*\r
+ * DELE: Delete a file.\r
+ */\r
+static BaseType_t prvDeleteFile( FTPClient_t *pxClient, char *pcFileName );\r
+\r
+/*\r
+ * SIZE: get the size of a file (xSendDate = 0).\r
+ * MDTM: get data and time properties (xSendDate = 1).\r
+ */\r
+static BaseType_t prvSizeDateFile( FTPClient_t *pxClient, char *pcFileName, BaseType_t xSendDate );\r
+\r
+/*\r
+ * MKD: Make / create a directory (xDoRemove = 0).\r
+ * RMD: Remove a directory (xDoRemove = 1).\r
+ */\r
+static BaseType_t prvMakeRemoveDir( FTPClient_t *pxClient, const char *pcDirectory, BaseType_t xDoRemove );\r
+\r
+/*\r
+ * The next three commands: LIST, RETR and STOR all require a data socket.\r
+ * The data connection is either started with a 'PORT' or a 'PASV' command.\r
+ * Each of the commands has a prepare- (Prep) and a working- (Work) function.\r
+ * The Work function should be called as long as the data socket is open, and\r
+ * there is data to be transmitted.\r
+ */\r
+\r
+/*\r
+ * LIST: Send a directory listing in Unix style.\r
+ */\r
+static BaseType_t prvListSendPrep( FTPClient_t *pxClient );\r
+static BaseType_t prvListSendWork( FTPClient_t *pxClient );\r
+\r
+/*\r
+ * RETR: Send a file to the FTP client.\r
+ */\r
+static BaseType_t prvRetrieveFilePrep( FTPClient_t *pxClient, char *pcFileName );\r
+static BaseType_t prvRetrieveFileWork( FTPClient_t *pxClient );\r
+\r
+/*\r
+ * STOR: Receive a file from the FTP client and store it.\r
+ */\r
+static BaseType_t prvStoreFilePrep( FTPClient_t *pxClient, char *pcFileName );\r
+static BaseType_t prvStoreFileWork( FTPClient_t *pxClient );\r
+\r
+/*\r
+ * Print/format a single directory entry in Unix style.\r
+ */\r
+static BaseType_t prvGetFileInfoStat( FF_DirEnt_t *pxEntry, char *pcLine, BaseType_t xMaxLength );\r
+\r
+/*\r
+ * Send a reply to a socket, either the command- or the data-socket.\r
+ */\r
+static BaseType_t prvSendReply( Socket_t xSocket, const char *pcBuffer, BaseType_t xLength );\r
+\r
+/*\r
+ * Prepend the root directory (if any), plus the current working directory\r
+ * (always), to get an absolute path.\r
+ */\r
+BaseType_t xMakeAbsolute( FTPClient_t *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcPath );\r
+\r
+/*\r
+\r
+####### ##### ######        #     #                ##\r
+ #   ## # # #  #    #       #     #                 #\r
+ #        #    #    #       #     #                 #\r
+ #        #    #    #       #  #  #  ####  ### ##   #    #\r
+ #####    #    #####        #  #  # #    #  # #  #  #   #\r
+ #   #    #    #            #  #  # #    #  ##   #  ####\r
+ #        #    #             ## ##  #    #  #       #   #\r
+ #        #    #             ## ##  #    #  #       #    #\r
+####     #### ####           ## ##   ####  ####    ##   ##\r
+\r
+ *     xFTPClientWork()\r
+ *     will be called by FreeRTOS_TCPServerWork(), after select has expired().\r
+ *     FD_ISSET will not be used.  This work function will always be called at\r
+ *     regular intervals, and also after a select() event has occurred.\r
+ */\r
+BaseType_t xFTPClientWork( TCPClient_t *pxTCPClient )\r
+{\r
+FTPClient_t *pxClient = ( FTPClient_t * ) pxTCPClient;\r
+BaseType_t xRc;\r
+\r
+       if( pxClient->bits.bHelloSent == pdFALSE_UNSIGNED )\r
+       {\r
+       BaseType_t xLength;\r
+\r
+               pxClient->bits.bHelloSent = pdTRUE_UNSIGNED;\r
+\r
+               xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                       "220 Welcome to the FreeRTOS+TCP FTP server\r\n" );\r
+               prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+       }\r
+\r
+       /* Call recv() in a non-blocking way, to see if there is an FTP command\r
+       sent to this server. */\r
+       xRc = FreeRTOS_recv( pxClient->xSocket, ( void * )pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), 0 );\r
+\r
+       if( xRc > 0 )\r
+       {\r
+       BaseType_t xIndex;\r
+       const FTPCommand_t *pxCommand;\r
+       char *pcRestCommand;\r
+\r
+               if( xRc < ( BaseType_t ) sizeof( pcCOMMAND_BUFFER ) )\r
+               {\r
+                       pcCOMMAND_BUFFER[ xRc ] = '\0';\r
+               }\r
+\r
+               while( xRc && ( ( pcCOMMAND_BUFFER[ xRc - 1 ] == ftpASCII_CR ) || ( pcCOMMAND_BUFFER[ xRc - 1 ] == ftpASCII_LF ) ) )\r
+               {\r
+                       pcCOMMAND_BUFFER[ --xRc ] = '\0';\r
+               }\r
+\r
+               /* Now iterate through a list of FTP commands, and look for a match. */\r
+               pxCommand = xFTPCommands;\r
+               pcRestCommand = pcCOMMAND_BUFFER;\r
+               for( xIndex = 0; xIndex < FTP_CMD_COUNT - 1; xIndex++, pxCommand++ )\r
+               {\r
+               BaseType_t xLength;\r
+\r
+                       /* The length of each command is stored as well, just to be a bit\r
+                       quicker here. */\r
+                       xLength = pxCommand->xCommandLength;\r
+\r
+                       if( ( xRc >= xLength ) && ( memcmp( ( const void * ) pxCommand->pcCommandName, ( const void * ) pcCOMMAND_BUFFER, xLength ) == 0 ) )\r
+                       {\r
+                               /* A match with an existing command is found.  Skip any\r
+                               whitespace to get the first parameter. */\r
+                               pcRestCommand += xLength;\r
+                               while( ( *pcRestCommand == ' ' ) || ( *pcRestCommand == '\t' ) )\r
+                               {\r
+                                       pcRestCommand++;\r
+                               }\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               /* If the command received was not recognised, xIndex will point to a\r
+               fake entry called 'ECMD_UNKNOWN'. */\r
+               prvProcessCommand( pxClient, xIndex, pcRestCommand );\r
+       }\r
+       else if( xRc < 0 )\r
+       {\r
+               /* The connection will be closed and the client will be deleted. */\r
+               FreeRTOS_printf( ( "xFTPClientWork: xRc = %ld\n", xRc ) );\r
+       }\r
+\r
+       /* Does it have an open data connection? */\r
+       if( pxClient->xTransferSocket != FREERTOS_NO_SOCKET )\r
+       {\r
+               /* See if the connection has changed. */\r
+               prvTransferCheck( pxClient );\r
+\r
+               /* "pcConnectionAck" contains a string like:\r
+               "Response:      150 Accepted data connection from 192.168.2.3:6789"\r
+               The socket can only be used once this acknowledgement has been sent. */\r
+               if( ( pxClient->xTransferSocket != FREERTOS_NO_SOCKET ) && ( pxClient->pcConnectionAck[ 0 ] == '\0' ) )\r
+               {\r
+               BaseType_t xClientRc = 0;\r
+\r
+                       if( pxClient->bits1.bDirHasEntry )\r
+                       {\r
+                               /* Still listing a directory. */\r
+                               xClientRc = prvListSendWork( pxClient );\r
+                       }\r
+                       else if( pxClient->pxReadHandle != NULL )\r
+                       {\r
+                               /* Sending a file. */\r
+                               xClientRc = prvRetrieveFileWork( pxClient );\r
+                       }\r
+                       else if( pxClient->pxWriteHandle != NULL )\r
+                       {\r
+                               /* Receiving a file. */\r
+                               xClientRc = prvStoreFileWork( pxClient );\r
+                       }\r
+\r
+                       if( xClientRc < 0 )\r
+                       {\r
+                               prvTransferCloseSocket( pxClient );\r
+                               prvTransferCloseFile( pxClient );\r
+                       }\r
+               }\r
+       }\r
+\r
+       return xRc;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTransferCloseDir( FTPClient_t *pxClient )\r
+{\r
+       /* Nothing to close for +FAT. */\r
+       ( void ) pxClient;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vFTPClientDelete( TCPClient_t *pxTCPClient )\r
+{\r
+FTPClient_t *pxClient = ( FTPClient_t * ) pxTCPClient;\r
+\r
+       /* Close any directory-listing-handles (not used by +FAT ). */\r
+       prvTransferCloseDir( pxClient );\r
+       /* Close the data-socket. */\r
+       prvTransferCloseSocket( pxClient );\r
+       /* Close any open file handle. */\r
+       prvTransferCloseFile( pxClient );\r
+\r
+       /* Close the FTP command socket */\r
+       if( pxClient->xSocket != FREERTOS_NO_SOCKET )\r
+       {\r
+               FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_ALL );\r
+               FreeRTOS_closesocket( pxClient->xSocket );\r
+               pxClient->xSocket = FREERTOS_NO_SOCKET;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvProcessCommand( FTPClient_t *pxClient, BaseType_t xIndex, char *pcRestCommand )\r
+{\r
+const FTPCommand_t *pxFTPCommand = &( xFTPCommands[ xIndex ] );\r
+const char *pcMyReply = NULL;\r
+BaseType_t xResult = 0;\r
+\r
+       if( ( pxFTPCommand->ucCommandType != ECMD_PASS ) && ( pxFTPCommand->ucCommandType != ECMD_PORT ) )\r
+       {\r
+               FreeRTOS_printf( ( "       %s %s\n", pxFTPCommand->pcCommandName, pcRestCommand ) );\r
+       }\r
+\r
+       if( ( pxFTPCommand->checkLogin != pdFALSE ) && ( pxClient->bits.bLoggedIn == pdFALSE_UNSIGNED ) )\r
+       {\r
+               pcMyReply = REPL_530; /* Please first log in. */\r
+       }\r
+       else if( ( pxFTPCommand->checkNullArg != pdFALSE ) && ( ( pcRestCommand == NULL ) || ( pcRestCommand[ 0 ] == '\0' ) ) )\r
+       {\r
+               pcMyReply = REPL_501; /* Command needs a parameter. */\r
+       }\r
+\r
+       if( pcMyReply == NULL )\r
+       {\r
+               switch( pxFTPCommand->ucCommandType )\r
+               {\r
+               case ECMD_USER: /* User. */\r
+                       /* User name has been entered, expect password. */\r
+                       pxClient->bits.bStatusUser = pdTRUE_UNSIGNED;\r
+\r
+                       #if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )/*_RB_ Needs defaulting and adding to the web documentation. */\r
+                       {\r
+                               /* Save the user name in 'pcFileName'. */\r
+                               snprintf( pxClient->pcFileName, sizeof( pxClient->pcFileName ), "%s", pcRestCommand );\r
+\r
+                               /* The USER name is presented to the application.  The function\r
+                               may return a const string like "331 Please enter your\r
+                               password\r\n". */\r
+                               pcMyReply = pcApplicationFTPUserHook( pxClient->pcFileName );\r
+                               if( pcMyReply == NULL )\r
+                               {\r
+                                       pcMyReply = REPL_331_ANON;\r
+                               }\r
+                       }\r
+                       #else\r
+                       {\r
+                               /* No password checks, any password will be accepted. */\r
+                               pcMyReply = REPL_331_ANON;\r
+                       }\r
+                       #endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 */\r
+\r
+                       #if( ipconfigFTP_HAS_USER_PROPERTIES_HOOK != 0 )/*_RB_ Needs defaulting and adding to the web documentation. */\r
+                       {\r
+                       FTPUserProperties_t xProperties;\r
+\r
+                               xProperties.pcRootDir = pxClient->pcRootDir;\r
+                               xProperties.xReadOnly = pdFALSE;\r
+                               xProperties.usPortNumber = pxClient->usClientPort;\r
+                               vApplicationFTPUserPropertiesHook( pxClient->pcFileName, &( xProperties ) );\r
+\r
+                               if( xProperties.pcRootDir != NULL )\r
+                               {\r
+                                       pxClient->pcRootDir = xProperties.pcRootDir;\r
+                               }\r
+                               pxClient->bits.bReadOnly = ( xProperties.xReadOnly != pdFALSE_UNSIGNED );\r
+                       }\r
+                       #endif /* ipconfigFTP_HAS_USER_PROPERTIES_HOOK */\r
+                       break;\r
+\r
+               case ECMD_PASS: /* Password. */\r
+                       pxClient->ulRestartOffset = 0;\r
+                       if( pxClient->bits.bStatusUser == pdFALSE_UNSIGNED )\r
+                       {\r
+                               pcMyReply = REPL_503;   /* "503 Bad sequence of commands.\r\n". */\r
+                       }\r
+                       else\r
+                       {\r
+                       BaseType_t xAllow;\r
+\r
+                               pxClient->bits.bStatusUser = pdFALSE_UNSIGNED;\r
+                               #if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )\r
+                               {\r
+                                       xAllow = xApplicationFTPPasswordHook( pxClient->pcFileName, pcRestCommand );\r
+                               }\r
+                               #else\r
+                               {\r
+                                       xAllow = 1;\r
+                               }\r
+                               #endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */\r
+\r
+                               if( xAllow > 0 )\r
+                               {\r
+                                       pxClient->bits.bLoggedIn = pdTRUE_UNSIGNED;  /* Client has now logged in. */\r
+                                       pcMyReply = "230 OK.  Current directory is /\r\n";\r
+                               }\r
+                               else\r
+                               {\r
+                                       pcMyReply = "530 Login incorrect\r\n"; /* 530 Login incorrect. */\r
+                               }\r
+\r
+                               strcpy( pxClient->pcCurrentDir, ( const char * ) "/" );\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_SYST: /* System. */\r
+                       snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), "215 UNIX Type: L8\r\n" );\r
+                       pcMyReply = pcCOMMAND_BUFFER;\r
+                       break;\r
+\r
+               case ECMD_PWD:  /* Get working directory. */\r
+                       xMakeRelative( pxClient, pcFILE_BUFFER, sizeof( pcFILE_BUFFER ), pxClient->pcCurrentDir );\r
+                       snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), REPL_257_PWD, pcFILE_BUFFER );\r
+                       pcMyReply = pcCOMMAND_BUFFER;\r
+                       break;\r
+\r
+               case ECMD_REST:\r
+                       if( pxClient->bits.bReadOnly != pdFALSE_UNSIGNED )\r
+                       {\r
+                               pcMyReply = REPL_553_READ_ONLY;\r
+                       }\r
+                       else\r
+                       {\r
+                       const char *pcPtr = pcRestCommand;\r
+\r
+                               while( *pcPtr == ' ' )\r
+                               {\r
+                                       pcPtr++;\r
+                               }\r
+\r
+                               if( ( *pcPtr >= '0' ) && ( *pcPtr <= '9' ) )\r
+                               {\r
+                                       sscanf( pcPtr, "%lu", &pxClient->ulRestartOffset );\r
+                                       snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                                               "350 Restarting at %lu. Send STORE or RETRIEVE\r\n", pxClient->ulRestartOffset );\r
+                                       pcMyReply = pcCOMMAND_BUFFER;\r
+                               }\r
+                               else\r
+                               {\r
+                                       pcMyReply = REPL_500; /* 500 Syntax error, command unrecognised. */\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_NOOP: /* NOP operation */\r
+                       if( pxClient->xTransferSocket != FREERTOS_NO_SOCKET )\r
+                       {\r
+                               pcMyReply = REPL_200_PROGRESS;\r
+                       }\r
+                       else\r
+                       {\r
+                               pcMyReply = REPL_200;\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_TYPE: /* Ask or set transfer type. */\r
+                       {\r
+                               /* e.g. "TYPE I" for Images (binary). */\r
+                       BaseType_t xType = prvGetTransferType( pcRestCommand );\r
+\r
+                               if( xType < 0 )\r
+                               {\r
+                                       /* TYPE not recognised. */\r
+                                       pcMyReply = REPL_500;\r
+                               }\r
+                               else\r
+                               {\r
+                                       pxClient->xTransType = xType;\r
+                                       pcMyReply = REPL_200;\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_PASV: /* Enter passive mode. */\r
+                       /* Connect passive: Server will listen() and wait for a connection.\r
+                       Start up a new data connection with 'xDoListen' set to true. */\r
+                       if( prvTransferConnect( pxClient, pdTRUE ) == pdFALSE )\r
+                       {\r
+                               pcMyReply = REPL_502;\r
+                       }\r
+                       else\r
+                       {\r
+                       uint32_t ulIP;\r
+                       uint16_t ulPort;\r
+                       struct freertos_sockaddr xLocalAddress;\r
+                       struct freertos_sockaddr xRemoteAddress;\r
+\r
+                               FreeRTOS_GetLocalAddress( pxClient->xTransferSocket, &xLocalAddress );\r
+                               FreeRTOS_GetRemoteAddress( pxClient->xSocket, &xRemoteAddress );\r
+\r
+                               ulIP = FreeRTOS_ntohl( xLocalAddress.sin_addr );\r
+                               pxClient->ulClientIP = FreeRTOS_ntohl( xRemoteAddress.sin_addr );\r
+                               ulPort = FreeRTOS_ntohs( xLocalAddress.sin_port );\r
+\r
+                               pxClient->usClientPort = FreeRTOS_ntohs( xRemoteAddress.sin_port );\r
+\r
+                               /* REPL_227_D "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d). */\r
+                               snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), REPL_227_D,\r
+                                       ( unsigned )ulIP >> 24,\r
+                                       ( unsigned )( ulIP >> 16 ) & 0xFF,\r
+                                       ( unsigned )( ulIP >> 8 ) & 0xFF,\r
+                                       ( unsigned )ulIP & 0xFF,\r
+                                       ( unsigned )ulPort >> 8,\r
+                                       ( unsigned )ulPort & 0xFF );\r
+\r
+                               pcMyReply = pcCOMMAND_BUFFER;\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_PORT: /* Active connection to the client. */\r
+                       /* The client uses this command to tell the server to what\r
+                       client-side port the server should contact; use of this command\r
+                       indicates an active data transfer. e.g. PORT 192,168,1,2,4,19. */\r
+                       {\r
+                       uint32_t ulIPAddress = 0;\r
+                       UBaseType_t uxPort;\r
+\r
+                               uxPort = prvParsePortData( pcRestCommand, &ulIPAddress );\r
+                               FreeRTOS_printf( ("       PORT %lxip:%ld\n", ulIPAddress, uxPort ) );\r
+\r
+                               if( uxPort == 0u )\r
+                               {\r
+                                       pcMyReply = REPL_501;\r
+                               }\r
+                               else if( prvTransferConnect( pxClient, pdFALSE ) == pdFALSE )\r
+                               {\r
+                                       /* Call prvTransferConnect() with 'xDoListen' = false for an\r
+                                       active connect(). */\r
+                                       pcMyReply = REPL_501;\r
+                               }\r
+                               else\r
+                               {\r
+                                       pxClient->usClientPort = ( uint16_t ) uxPort;\r
+                                       pxClient->ulClientIP = ulIPAddress;\r
+                                       FreeRTOS_printf( ("Client address %lxip:%lu\n", ulIPAddress, uxPort ) );\r
+                                       pcMyReply = REPL_200;\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_CWD:  /* Change current working directory. */\r
+                       prvChangeDir( pxClient, pcRestCommand );\r
+                       break;\r
+\r
+               case ECMD_RNFR:\r
+                       if( pxClient->bits.bReadOnly != pdFALSE_UNSIGNED )\r
+                       {\r
+                               pcMyReply = REPL_553_READ_ONLY;\r
+                       }\r
+                       else\r
+                       {\r
+                               prvRenameFrom( pxClient, pcRestCommand );\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_RNTO:\r
+                       if( pxClient->bits.bInRename == pdFALSE_UNSIGNED )\r
+                       {\r
+                               pcMyReply = REPL_503;   /* "503 Bad sequence of commands. */\r
+                       }\r
+                       else\r
+                       {\r
+                               prvRenameTo( pxClient, pcRestCommand );\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_SITE: /* Set file permissions */\r
+                       if( pxClient->bits.bReadOnly != pdFALSE_UNSIGNED )\r
+                       {\r
+                               pcMyReply = REPL_553_READ_ONLY;\r
+                       }\r
+                       else if( prvSiteCmd( pxClient, pcRestCommand ) == pdFALSE )\r
+                       {\r
+                               pcMyReply = REPL_202;\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_DELE:\r
+                       if( pxClient->bits.bReadOnly != pdFALSE_UNSIGNED )\r
+                       {\r
+                               pcMyReply = REPL_553_READ_ONLY;\r
+                       }\r
+                       else\r
+                       {\r
+                               prvDeleteFile( pxClient, pcRestCommand );\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_MDTM:\r
+                       prvSizeDateFile( pxClient, pcRestCommand, pdTRUE );\r
+                       break;\r
+\r
+               case ECMD_SIZE:\r
+                       if( pxClient->pxWriteHandle != NULL )\r
+                       {\r
+                               /* This SIZE query is probably about a file which is now being\r
+                               received.  If so, return the value of pxClient->ulRecvBytes,\r
+                               pcRestCommand points to 'pcCommandBuffer', make it free by\r
+                               copying it to pcNewDir. */\r
+\r
+                               xMakeAbsolute( pxClient, pcNEW_DIR, sizeof( pcNEW_DIR ), pcRestCommand );\r
+\r
+                               if( strcmp( pcNEW_DIR, pcRestCommand ) == 0 )\r
+                               {\r
+                               BaseType_t xCount;\r
+                                       for( xCount = 0; xCount < 3 && pxClient->pxWriteHandle; xCount++ )\r
+                                       {\r
+                                               prvStoreFileWork( pxClient );\r
+                                       }\r
+                                       if( pxClient->pxWriteHandle != NULL )\r
+                                       {\r
+                                               /* File being queried is still open, return number of\r
+                                               bytes received until now. */\r
+                                               snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), "213 %lu\r\n", pxClient->ulRecvBytes );\r
+                                               pcMyReply = pcCOMMAND_BUFFER;\r
+                                       } /* otherwise, do a normal stat(). */\r
+                               }\r
+                               strcpy( pcRestCommand, pcNEW_DIR );\r
+                       }\r
+                       if( pcMyReply == NULL )\r
+                       {\r
+                               prvSizeDateFile( pxClient, pcRestCommand, pdFALSE );\r
+                       }\r
+                       break;\r
+               case ECMD_MKD:\r
+               case ECMD_RMD:\r
+                       if( pxClient->bits.bReadOnly != pdFALSE_UNSIGNED )\r
+                       {\r
+                               pcMyReply = REPL_553_READ_ONLY;\r
+                       }\r
+                       else\r
+                       {\r
+                               prvMakeRemoveDir( pxClient, pcRestCommand, pxFTPCommand->ucCommandType == ECMD_RMD );\r
+                       }\r
+                       break;\r
+               case ECMD_CDUP:\r
+                       prvChangeDir( pxClient, ".." );\r
+                       break;\r
+\r
+               case ECMD_QUIT:\r
+                       prvSendReply( pxClient->xSocket, REPL_221, 0 );\r
+                       pxClient->bits.bLoggedIn = pdFALSE_UNSIGNED;\r
+                       break;\r
+               case ECMD_LIST:\r
+               case ECMD_RETR:\r
+               case ECMD_STOR:\r
+                       if( ( pxClient->xTransferSocket == FREERTOS_NO_SOCKET ) &&\r
+                               ( ( pxFTPCommand->ucCommandType != ECMD_STOR ) ||\r
+                                 ( pxClient->bits1.bEmptyFile == pdFALSE_UNSIGNED ) ) )\r
+                       {\r
+                               /* Sending "425 Can't open data connection." :\r
+                               Before receiving any of these commands, there must have been a\r
+                               PORT or PASV command, which causes the creation of a data socket. */\r
+                               /* There is one exception: a STOR command is received while the\r
+                               data connection has already been closed.  This is tested with the\r
+                               'bEmptyFile' flag. */\r
+                               pcMyReply = REPL_425;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* In case an empty file was received ( bits1.bEmptyFile ), the\r
+                               transfer socket never delivered any data.  Check if the transfer\r
+                               socket is still open: */\r
+                               if( pxClient->xTransferSocket != FREERTOS_NO_SOCKET )\r
+                               {\r
+                                       prvTransferCheck( pxClient );\r
+                               }\r
+                               switch( pxFTPCommand->ucCommandType )\r
+                               {\r
+                               case ECMD_LIST:\r
+                                       prvListSendPrep( pxClient );\r
+                                       break;\r
+                               case ECMD_RETR:\r
+                                       prvRetrieveFilePrep( pxClient, pcRestCommand );\r
+                                       break;\r
+                               case ECMD_STOR:\r
+                                       if( pxClient->bits.bReadOnly != pdFALSE_UNSIGNED )\r
+                                       {\r
+                                               pcMyReply = REPL_553_READ_ONLY;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               prvStoreFilePrep( pxClient, pcRestCommand );\r
+                                               if( pxClient->bits1.bEmptyFile != pdFALSE_UNSIGNED )\r
+                                               {\r
+                                                       /* Although the 'xTransferSocket' is closed already,\r
+                                                       call this function just for the logging. */\r
+                                                       prvTransferCloseSocket( pxClient );\r
+\r
+                                                       /* Close an empty file. */\r
+                                                       prvTransferCloseFile( pxClient );\r
+                                               }\r
+                                       }\r
+                                       break;\r
+                               }\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_FEAT:\r
+                       {\r
+                               static const char pcFeatAnswer[] =\r
+                                       "211-Features:\x0a"\r
+                                       /* The MDTM command is only allowed when\r
+                                       there is support for date&time. */\r
+                               #if( ffconfigTIME_SUPPORT != 0 )\r
+                                       " MDTM\x0a"\r
+                               #endif\r
+                                       " REST STREAM\x0a"\r
+                                       " SIZE\x0d\x0a"\r
+                                       "211 End\x0d\x0a";\r
+                               pcMyReply = pcFeatAnswer;\r
+                       }\r
+                       break;\r
+\r
+               case ECMD_UNKNOWN:\r
+                       FreeRTOS_printf( ("ftp::processCmd: Cmd %s unknown\n", pcRestCommand ) );\r
+                       pcMyReply = REPL_500;\r
+                       break;\r
+               }\r
+       }\r
+       if( pxFTPCommand->ucCommandType != ECMD_RNFR )\r
+       {\r
+               pxClient->bits.bInRename = pdFALSE_UNSIGNED;\r
+       }\r
+\r
+       if( pcMyReply != NULL )\r
+       {\r
+               xResult = prvSendReply( pxClient->xSocket, pcMyReply, strlen( pcMyReply ) );\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvTransferConnect( FTPClient_t *pxClient, BaseType_t xDoListen )\r
+{\r
+Socket_t xSocket;\r
+BaseType_t xResult;\r
+\r
+       /* Open a socket for a data connection with the FTP client.\r
+       Happens after a PORT or a PASV command. */\r
+\r
+       /* Make sure the previous socket is deleted and flags reset */\r
+       prvTransferCloseSocket( pxClient );\r
+\r
+       pxClient->bits1.bEmptyFile = pdFALSE_UNSIGNED;\r
+\r
+       xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );\r
+\r
+       if( ( xSocket != FREERTOS_NO_SOCKET ) && ( xSocket != FREERTOS_INVALID_SOCKET ) )\r
+       {\r
+       BaseType_t xSmallTimeout = pdMS_TO_TICKS( 100 );\r
+       struct freertos_sockaddr xAddress;\r
+\r
+       #if( ipconfigFTP_TX_BUFSIZE > 0 )\r
+               WinProperties_t xWinProps;\r
+       #endif\r
+               xAddress.sin_addr = FreeRTOS_GetIPAddress( );   /* Single NIC, currently not used */\r
+               xAddress.sin_port = FreeRTOS_htons( 0 );                /* Bind to any available port number */\r
+\r
+               FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );\r
+\r
+               #if( ipconfigFTP_TX_BUFSIZE > 0 )\r
+               {\r
+                       /* Fill in the buffer and window sizes that will be used by the\r
+                       socket. */\r
+                       xWinProps.lTxBufSize = ipconfigFTP_TX_BUFSIZE;\r
+                       xWinProps.lTxWinSize = ipconfigFTP_TX_WINSIZE;\r
+                       xWinProps.lRxBufSize = ipconfigFTP_RX_BUFSIZE;\r
+                       xWinProps.lRxWinSize = ipconfigFTP_RX_WINSIZE;\r
+\r
+                       /* Set the window and buffer sizes. */\r
+                       FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps,     sizeof( xWinProps ) );\r
+               }\r
+               #endif\r
+\r
+               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xSmallTimeout, sizeof( BaseType_t ) );\r
+               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xSmallTimeout, sizeof( BaseType_t ) );\r
+\r
+               /* The same instance of the socket will be used for the connection and\r
+               data transport. */\r
+               if( xDoListen != pdFALSE )\r
+               {\r
+               BaseType_t xTrueValue = pdTRUE;\r
+                       FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_REUSE_LISTEN_SOCKET, ( void * ) &xTrueValue, sizeof( xTrueValue ) );\r
+               }\r
+               pxClient->bits1.bIsListen = xDoListen;\r
+               pxClient->xTransferSocket = xSocket;\r
+\r
+               if( xDoListen != pdFALSE )\r
+               {\r
+                       FreeRTOS_FD_SET( xSocket, pxClient->pxParent->xSocketSet, eSELECT_EXCEPT | eSELECT_READ );\r
+                       /* Calling FreeRTOS_listen( ) */\r
+                       xResult = prvTransferStart( pxClient );\r
+                       if( xResult >= 0 )\r
+                       {\r
+                               xResult = pdTRUE;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       FreeRTOS_FD_SET( xSocket, pxClient->pxParent->xSocketSet, eSELECT_EXCEPT | eSELECT_READ | eSELECT_WRITE );\r
+                       xResult = pdTRUE;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               FreeRTOS_printf( ( "FreeRTOS_socket() failed\n" ) );\r
+               xResult = -pdFREERTOS_ERRNO_ENOMEM;\r
+       }\r
+\r
+       /* An active socket (PORT) should connect() later. */\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvTransferStart( FTPClient_t *pxClient )\r
+{\r
+BaseType_t xResult;\r
+\r
+       /* A transfer socket has been opened, now either call listen() for 'PASV'\r
+       or connect() for the 'PORT' command. */\r
+       if( pxClient->bits1.bIsListen != pdFALSE_UNSIGNED )\r
+       {\r
+               xResult = FreeRTOS_listen( pxClient->xTransferSocket, 1 );\r
+       }\r
+       else\r
+       {\r
+       struct freertos_sockaddr xAddress;\r
+\r
+               xAddress.sin_addr = FreeRTOS_htonl( pxClient->ulClientIP );\r
+               xAddress.sin_port = FreeRTOS_htons( pxClient->usClientPort );\r
+               /* Start an active connection for this data socket */\r
+               xResult = FreeRTOS_connect( pxClient->xTransferSocket, &xAddress, sizeof( xAddress ) );\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTransferCheck( FTPClient_t *pxClient )\r
+{\r
+BaseType_t xRxSize;\r
+\r
+       /* A data transfer is busy. Check if there are changes in connectedness. */\r
+       xRxSize = FreeRTOS_rx_size( pxClient->xTransferSocket );\r
+\r
+       if( pxClient->bits1.bClientConnected == pdFALSE_UNSIGNED )\r
+       {\r
+               /* The time to receive a small file can be so short, that we don't even\r
+               see that the socket gets connected and disconnected. Therefore, check\r
+               the sizeof of the RX buffer. */\r
+               {\r
+               struct freertos_sockaddr xAddress;\r
+               Socket_t xNexSocket;\r
+               socklen_t xSocketLength = sizeof( xAddress );\r
+\r
+                       if( pxClient->bits1.bIsListen != pdFALSE_UNSIGNED )\r
+                       {\r
+                               xNexSocket = FreeRTOS_accept( pxClient->xTransferSocket, &xAddress, &xSocketLength);\r
+                               if( ( ( xNexSocket != FREERTOS_NO_SOCKET ) && ( xNexSocket != FREERTOS_INVALID_SOCKET ) ) ||\r
+                                       xRxSize > 0 )\r
+                               {\r
+                                       pxClient->bits1.bClientConnected = pdTRUE_UNSIGNED;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               if( FreeRTOS_issocketconnected( pxClient->xTransferSocket ) > 0 ||\r
+                                       xRxSize > 0 )\r
+                               {\r
+                                       pxClient->bits1.bClientConnected = pdTRUE_UNSIGNED;\r
+                               }\r
+                       }\r
+                       if(     pxClient->bits1.bClientConnected != pdFALSE_UNSIGNED )\r
+                       {\r
+                               pxClient->bits1.bEmptyFile = pdFALSE_UNSIGNED;\r
+                               #if( ipconfigHAS_PRINTF != 0 )\r
+                               {\r
+                                       struct freertos_sockaddr xRemoteAddress, xLocalAddress;\r
+                                       FreeRTOS_GetRemoteAddress( pxClient->xTransferSocket, &xRemoteAddress );\r
+                                       FreeRTOS_GetLocalAddress( pxClient->xTransferSocket, &xLocalAddress );\r
+                                       FreeRTOS_printf( ( "%s Connected from %u to %u\n",\r
+                                               pxClient->bits1.bIsListen != pdFALSE_UNSIGNED ? "PASV" : "PORT",\r
+                                               ( unsigned ) FreeRTOS_ntohs( xLocalAddress.sin_port ),\r
+                                               ( unsigned ) FreeRTOS_ntohs( xRemoteAddress.sin_port ) ) );\r
+                               }\r
+                               #endif /* ipconfigHAS_PRINTF */\r
+                               FreeRTOS_FD_CLR( pxClient->xTransferSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );\r
+                               FreeRTOS_FD_SET( pxClient->xTransferSocket, pxClient->pxParent->xSocketSet, eSELECT_READ|eSELECT_EXCEPT );\r
+                       }\r
+               }\r
+       }\r
+\r
+       if ( pxClient->bits1.bClientConnected != pdFALSE_UNSIGNED )\r
+       {\r
+               if( pxClient->pcConnectionAck[ 0 ] != '\0' )\r
+               {\r
+               BaseType_t xLength;\r
+               BaseType_t xRemotePort;\r
+               struct freertos_sockaddr xRemoteAddress;\r
+\r
+                       FreeRTOS_GetRemoteAddress( pxClient->xTransferSocket, &xRemoteAddress );\r
+                       xRemotePort = FreeRTOS_ntohs( xRemoteAddress.sin_port );\r
+\r
+                       /* Tell on the command port 21 we have a data connection */\r
+                       xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                               pxClient->pcConnectionAck, pxClient->ulClientIP, xRemotePort );\r
+\r
+                       prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+                       pxClient->pcConnectionAck[ 0 ] = '\0';\r
+               }\r
+\r
+               if( ( FreeRTOS_issocketconnected( pxClient->xTransferSocket ) == pdFALSE ) && FreeRTOS_rx_size( pxClient->xTransferSocket ) == 0 )\r
+               {\r
+                       prvTransferCloseSocket( pxClient );\r
+                       prvTransferCloseFile( pxClient );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTransferCloseSocket( FTPClient_t *pxClient )\r
+{\r
+       if( pxClient->xTransferSocket != FREERTOS_NO_SOCKET )\r
+       {\r
+               /* DEBUGGING ONLY */\r
+               BaseType_t xRxSize = FreeRTOS_rx_size( pxClient->xTransferSocket );\r
+               if( xRxSize > 0 )\r
+               {\r
+               BaseType_t xRxSize2;\r
+               BaseType_t xStatus;\r
+                       prvStoreFileWork( pxClient );\r
+                       xStatus = FreeRTOS_connstatus( pxClient->xTransferSocket );\r
+                       xRxSize2 = FreeRTOS_rx_size( pxClient->xTransferSocket );\r
+                       FreeRTOS_printf( ( "FTP: WARNING: %s: RX size = %ld -> %ld (%s)\n",\r
+                               FreeRTOS_GetTCPStateName( xStatus ),\r
+                               xRxSize, xRxSize2, pxClient->pcFileName ) );\r
+                       if( xRxSize2 > 1 )\r
+                       {\r
+                               return;\r
+                       }\r
+\r
+                       /* Remove compiler warnings in case FreeRTOS_printf() is not\r
+                       defined. */\r
+                       ( void ) xStatus;\r
+               }\r
+       }\r
+\r
+       if( ( pxClient->pxWriteHandle != NULL ) || ( pxClient->pxReadHandle != NULL ) )\r
+       {\r
+       BaseType_t xLength;\r
+       char pcStrBuf[ 32 ];\r
+\r
+               if( pxClient->bits1.bHadError == pdFALSE_UNSIGNED )\r
+               {\r
+                       xLength = snprintf( pxClient->pcClientAck, sizeof( pxClient->pcClientAck ),\r
+                                       "226 Closing connection %d bytes transmitted\r\n", ( int ) pxClient->ulRecvBytes );\r
+               }\r
+               else\r
+               {\r
+                       xLength = snprintf( pxClient->pcClientAck, sizeof( pxClient->pcClientAck ),\r
+                                       "451 Requested action aborted after %d bytes\r\n", ( int ) pxClient->ulRecvBytes );\r
+               }\r
+\r
+               /* Tell on the command socket the data connection is now closed. */\r
+               prvSendReply( pxClient->xSocket, pxClient->pcClientAck, xLength );\r
+\r
+               #if( ipconfigHAS_PRINTF != 0 )\r
+               {\r
+               TickType_t xDelta;\r
+               uint32_t ulAverage;\r
+                       xDelta = xTaskGetTickCount( ) - pxClient->xStartTime;\r
+                       ulAverage = ulGetAverage( pxClient->ulRecvBytes, xDelta );\r
+\r
+                       FreeRTOS_printf( ("FTP: %s: '%s' %lu Bytes (%s/sec)\n",\r
+                               pxClient->pxReadHandle ? "sent" : "recv",\r
+                               pxClient->pcFileName,\r
+                               pxClient->ulRecvBytes,\r
+                               pcMkSize( ulAverage, pcStrBuf, sizeof( pcStrBuf ) ) ) );\r
+               }\r
+               #endif\r
+       }\r
+\r
+       if( pxClient->xTransferSocket != FREERTOS_NO_SOCKET )\r
+       {\r
+               FreeRTOS_FD_CLR( pxClient->xTransferSocket, pxClient->pxParent->xSocketSet, eSELECT_ALL );\r
+               FreeRTOS_closesocket( pxClient->xTransferSocket );\r
+               pxClient->xTransferSocket = FREERTOS_NO_SOCKET;\r
+               if( pxClient->ulRecvBytes == 0ul )\r
+               {\r
+                       /* Received zero bytes: an empty file */\r
+                       pxClient->bits1.bEmptyFile = pdTRUE_UNSIGNED;\r
+               }\r
+               else\r
+               {\r
+                       pxClient->bits1.bEmptyFile = pdFALSE_UNSIGNED;\r
+               }\r
+       }\r
+       pxClient->bits1.bIsListen = pdFALSE_UNSIGNED;\r
+       pxClient->bits1.bDirHasEntry = pdFALSE_UNSIGNED;\r
+       pxClient->bits1.bClientConnected = pdFALSE_UNSIGNED;\r
+       pxClient->bits1.bHadError = pdFALSE_UNSIGNED;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTransferCloseFile( FTPClient_t *pxClient )\r
+{\r
+       if( pxClient->pxWriteHandle != NULL )\r
+       {\r
+               ff_fclose( pxClient->pxWriteHandle );\r
+               pxClient->pxWriteHandle = NULL;\r
+               #if( ipconfigFTP_HAS_RECEIVED_HOOK != 0 )\r
+               {\r
+                       vApplicationFTPReceivedHook( pxClient->pcFileName, pxClient->ulRecvBytes, pxClient );\r
+               }\r
+               #endif\r
+\r
+       }\r
+       if( pxClient->pxReadHandle != NULL )\r
+       {\r
+               ff_fclose( pxClient->pxReadHandle );\r
+               pxClient->pxReadHandle = NULL;\r
+       }\r
+       /* These two field are only used for logging / file-statistics */\r
+       pxClient->ulRecvBytes = 0ul;\r
+       pxClient->xStartTime = 0ul;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/**\r
+ * Guess the transfer type, given the client requested type.\r
+ * Actually in unix there is no difference between binary and\r
+ * ascii mode when we work with file descriptors.\r
+ * If #type is not recognized as a valid client request, -1 is returned.\r
+ */\r
+static BaseType_t prvGetTransferType( const char *pcType )\r
+{\r
+BaseType_t xResult = -1;\r
+\r
+       if( pcType != NULL )\r
+       {\r
+               BaseType_t xLength = strlen( pcType );\r
+               if( xLength == 0 )\r
+               {\r
+                       return -1;\r
+               }\r
+               switch( pcType[ 0 ] ) {\r
+               case 'I':\r
+                       xResult = TMODE_BINARY;\r
+                       break;\r
+               case 'A':\r
+                       xResult = TMODE_ASCII;\r
+                       break;\r
+               case 'L':\r
+                       if( xLength >= 3 )\r
+                       {\r
+                               if( pcType[ 2 ] == '7' )\r
+                               {\r
+                                       xResult = TMODE_7BITS;\r
+                               }\r
+                               else if( pcType[ 2 ] == '8' )\r
+                               {\r
+                                       xResult = TMODE_7BITS;\r
+                               }\r
+                       }\r
+                       break;\r
+               }\r
+       }\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigHAS_PRINTF != 0 )\r
+       #define SIZE_1_GB       ( 1024ul * 1024ul * 1024ul )\r
+       #define SIZE_1_MB       ( 1024ul * 1024ul )\r
+       #define SIZE_1_KB       ( 1024ul )\r
+\r
+       static const char *pcMkSize( uint32_t ulAmount, char *pcBuffer, BaseType_t xBufferSize )\r
+       {\r
+       uint32_t ulGB, ulMB, ulKB, ulByte;\r
+\r
+               ulGB = ( ulAmount / SIZE_1_GB );\r
+               ulAmount -= ( ulGB * SIZE_1_GB );\r
+               ulMB = ( ulAmount / SIZE_1_MB );\r
+               ulAmount -= ( ulMB * SIZE_1_MB );\r
+               ulKB = ( ulAmount / SIZE_1_KB );\r
+               ulAmount -= ( ulKB * SIZE_1_KB );\r
+               ulByte = ( ulAmount );\r
+\r
+               if (ulGB != 0ul )\r
+               {\r
+                       snprintf( pcBuffer, xBufferSize, "%lu.%02lu GB", ulGB, (100 * ulMB) / SIZE_1_KB );\r
+               }\r
+               else if( ulMB != 0ul )\r
+               {\r
+                       snprintf( pcBuffer, xBufferSize, "%lu.%02lu MB", ulMB, (100 * ulKB) / SIZE_1_KB );\r
+               }\r
+               else if( ulKB != 0ul )\r
+               {\r
+                       snprintf(pcBuffer, xBufferSize, "%lu.%02lu KB", ulKB, (100 * ulByte) / SIZE_1_KB );\r
+               }\r
+               else\r
+               {\r
+                       snprintf( pcBuffer, xBufferSize, "%lu bytes", ulByte );\r
+               }\r
+\r
+               return pcBuffer;\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+#endif /* ipconfigHAS_PRINTF != 0 */\r
+\r
+#if( ipconfigHAS_PRINTF != 0 )\r
+       static uint32_t ulGetAverage( uint32_t ulAmount, TickType_t xDeltaMs )\r
+       {\r
+       uint32_t ulAverage;\r
+\r
+               /* Get the average amount of bytes per seconds. Ideally this is\r
+               calculated by Multiplying with 1000 and dividing by milliseconds:\r
+                       ulAverage = ( 1000ul * ulAmount ) / xDeltaMs;\r
+               Now get a maximum precision, while avoiding an arithmetic overflow:\r
+               */\r
+               if( xDeltaMs == 0ul )\r
+               {\r
+                       /* Time is zero, there is no average  */\r
+                       ulAverage = 0ul;\r
+               }\r
+               else if( ulAmount >= ( ~0ul / 10ul ) )\r
+               {\r
+                       /* More than 409 MB has been transferred, do not multiply. */\r
+                       ulAverage = ( ulAmount / ( xDeltaMs / 1000ul ) );\r
+               }\r
+               else if( ulAmount >= ( ~0ul / 100ul ) )\r
+               {\r
+                       /* Between 409 and 41 MB has been transferred, can multiply by 10. */\r
+                       ulAverage = ( ( ulAmount * 10ul ) / ( xDeltaMs / 100ul ) );\r
+               }\r
+               else if( ulAmount >= ( ~0ul / 1000ul ) )\r
+               {\r
+                       /* Between 4.1 MB and 41 has been transferred, can multiply by 100. */\r
+                       ulAverage = ( ( ulAmount * 100ul ) / ( xDeltaMs / 10ul ) );\r
+               }\r
+               else\r
+               {\r
+                       /* Less than 4.1 MB: can multiply by 1000. */\r
+                       ulAverage = ( ( ulAmount * 1000ul ) / xDeltaMs );\r
+               }\r
+\r
+               return ulAverage;\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+#endif /* ipconfigHAS_PRINTF != 0 */\r
+\r
+static UBaseType_t prvParsePortData( const char *pcCommand, uint32_t *pulIPAddress )\r
+{\r
+/*_HT_ Using 'unsigned' here because when sscanf() sees '%u', it expects a pointer to 'unsigned'.\r
+Not sure about the sscanf() format for UBaseType_t ? */\r
+unsigned h1, h2, h3, h4, p1, p2;\r
+char sep;\r
+UBaseType_t uxResult;\r
+\r
+       /* Expect PORT h1,h2,h3,h4,p1,p2 */\r
+       if (sscanf (pcCommand, "%u%c%u%c%u%c%u%c%u%c%u", &h1, &sep, &h2, &sep, &h3, &sep, &h4, &sep, &p1, &sep, &p2) != 11)\r
+       {\r
+               uxResult= 0u;\r
+       }\r
+       else\r
+       {\r
+               /* Put in network byte order. */\r
+               *pulIPAddress =\r
+                       ( ( uint32_t ) h1 << 24 ) |\r
+                       ( ( uint32_t ) h2 << 16 ) |\r
+                       ( ( uint32_t ) h3 << 8 ) |\r
+                       ( ( uint32_t ) h4 );\r
+               uxResult = ( p1 << 8 ) | p2;\r
+       }\r
+       return uxResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+\r
+ ####                                  #######   #   ###\r
+#    #   #                              #   ##   #     #\r
+#    #   #                              #    #         #\r
+#      ######  ####  ### ##   ####      #   #  ###     #    ####\r
+ ##      #    #    #  # #  # #    #     #####    #     #   #    #\r
+   ##    #    #    #  ##   # ######     #   #    #     #   ######\r
+#    #   #    #    #  #      #          #        #     #   #\r
+#    #   # ## #    #  #      #   ##     #        #     #   #   ##\r
+ ####     ##   ####  ####     ####     ####    ##### #####  ####\r
+\r
+*/\r
+\r
+static BaseType_t prvStoreFilePrep( FTPClient_t *pxClient, char *pcFileName )\r
+{\r
+BaseType_t xResult;\r
+FF_FILE *pxNewHandle;\r
+size_t uxFileSize = 0ul;\r
+int iErrorNo;\r
+\r
+       /* Close previous handle (if any) and reset file transfer parameters. */\r
+       prvTransferCloseFile( pxClient );\r
+\r
+       xMakeAbsolute( pxClient, pxClient->pcFileName, sizeof( pxClient->pcFileName ), pcFileName );\r
+\r
+       pxNewHandle = NULL;\r
+\r
+       if( pxClient->ulRestartOffset != 0 )\r
+       {\r
+       size_t uxOffset = pxClient->ulRestartOffset;\r
+       int32_t lRc;\r
+\r
+               pxClient->ulRestartOffset = 0ul; /* Only use 1 time. */\r
+               pxNewHandle = ff_fopen( pxClient->pcFileName, "ab" );\r
+\r
+               if( pxNewHandle != NULL )\r
+               {\r
+                       uxFileSize = pxNewHandle->ulFileSize;\r
+\r
+                       if( uxOffset <= uxFileSize )\r
+                       {\r
+                               lRc = ff_fseek( pxNewHandle, uxOffset, FF_SEEK_SET );\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Won't even try to seek after EOF */\r
+                               lRc = -pdFREERTOS_ERRNO_EINVAL;\r
+                       }\r
+                       if( lRc != 0 )\r
+                       {\r
+                       BaseType_t xLength;\r
+\r
+                               xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                                       "450 Seek invalid %u length %u\r\n",\r
+                                       ( unsigned ) uxOffset, ( unsigned ) uxFileSize );\r
+\r
+                               /* "Requested file action not taken". */\r
+                               prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+\r
+                               FreeRTOS_printf( ( "ftp::storeFile: create %s: Seek %u length %u\n",\r
+                                       pxClient->pcFileName, ( unsigned ) uxOffset, ( unsigned ) uxFileSize ) );\r
+\r
+                               ff_fclose( pxNewHandle );\r
+                               pxNewHandle = NULL;\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               pxNewHandle = ff_fopen( pxClient->pcFileName, "wb" );\r
+       }\r
+\r
+       if( pxNewHandle == NULL )\r
+       {\r
+               iErrorNo = stdioGET_ERRNO();\r
+               if( iErrorNo == pdFREERTOS_ERRNO_ENOSPC )\r
+               {\r
+                       prvSendReply( pxClient->xSocket, REPL_552, 0 );\r
+               }\r
+               else\r
+               {\r
+                       /* "Requested file action not taken". */\r
+                       prvSendReply( pxClient->xSocket, REPL_450, 0 );\r
+               }\r
+               FreeRTOS_printf( ( "ftp::storeFile: create %s: %s (errno %d)\n",\r
+                       pxClient->pcFileName,\r
+                       ( const char* ) strerror( iErrorNo ), iErrorNo ) );\r
+\r
+               xResult = pdFALSE;\r
+       }\r
+       else\r
+       {\r
+               if( pxClient->bits1.bIsListen )\r
+               {\r
+                       /* True if PASV is used. */\r
+                       snprintf( pxClient->pcConnectionAck, sizeof( pxClient->pcConnectionAck ),\r
+                               "150 Accepted data connection from %%xip:%%u\r\n" );\r
+                       prvTransferCheck( pxClient );\r
+               }\r
+               else\r
+               {\r
+               BaseType_t xLength;\r
+\r
+                       xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), "150 Opening BIN connection to store file\r\n" );\r
+                       prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+                       pxClient->pcConnectionAck[ 0 ] = '\0';\r
+                       prvTransferStart( pxClient ); /* Now active connect. */\r
+               }\r
+\r
+               pxClient->pxWriteHandle = pxNewHandle;\r
+\r
+               /* To get some statistics about the performance. */\r
+               pxClient->xStartTime = xTaskGetTickCount( );\r
+\r
+               xResult = pdTRUE;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigFTP_ZERO_COPY_ALIGNED_WRITES == 0 )\r
+\r
+       static BaseType_t prvStoreFileWork( FTPClient_t *pxClient )\r
+       {\r
+       BaseType_t xRc, xWritten;\r
+\r
+               /* Read from the data socket until all has been read or until a negative value\r
+               is returned. */\r
+               for( ; ; )\r
+               {\r
+               char *pcBuffer;\r
+\r
+                       /* The "zero-copy" method: */\r
+                       xRc = FreeRTOS_recv( pxClient->xTransferSocket, ( void * ) &pcBuffer,\r
+                               0x20000u, FREERTOS_ZERO_COPY | FREERTOS_MSG_DONTWAIT );\r
+                       if( xRc <= 0 )\r
+                       {\r
+                               break;\r
+                       }\r
+                       pxClient->ulRecvBytes += xRc;\r
+                       xWritten = ff_fwrite( pcBuffer, 1, xRc, pxClient->pxWriteHandle );\r
+                       FreeRTOS_recv( pxClient->xTransferSocket, ( void * ) NULL, xRc, 0 );\r
+                       if( xWritten != xRc )\r
+                       {\r
+                               xRc = -1;\r
+                               /* bHadError: a transfer got aborted because of an error. */\r
+                               pxClient->bits1.bHadError = pdTRUE_UNSIGNED;\r
+                               break;\r
+                       }\r
+               }\r
+               return xRc;\r
+       }\r
+\r
+#else  /* ipconfigFTP_ZERO_COPY_ALIGNED_WRITES != 0 */\r
+\r
+       #if !defined( ipconfigFTP_PREFERRED_WRITE_SIZE )\r
+               /* If you store data on flash, it may be profitable to give 'ipconfigFTP_PREFERRED_WRITE_SIZE'\r
+               the same size as the size of the flash' erase blocks, e.g. 4KB */\r
+               #define ipconfigFTP_PREFERRED_WRITE_SIZE        512ul\r
+       #endif\r
+\r
+       static BaseType_t prvStoreFileWork( FTPClient_t *pxClient )\r
+       {\r
+       BaseType_t xRc, xWritten;\r
+\r
+               /* Read from the data socket until all has been read or until a negative\r
+               value is returned. */\r
+               for( ; ; )\r
+               {\r
+               char *pcBuffer;\r
+               UBaseType_t xStatus;\r
+\r
+                       /* The "zero-copy" method: */\r
+                       xRc = FreeRTOS_recv( pxClient->xTransferSocket, ( void * ) &pcBuffer,\r
+                               0x20000u, FREERTOS_ZERO_COPY | FREERTOS_MSG_DONTWAIT );\r
+\r
+                       if( xRc <= 0 )\r
+                       {\r
+                               /* There are no data or the connection is closed. */\r
+                               break;\r
+                       }\r
+                       xStatus = FreeRTOS_connstatus( pxClient->xTransferSocket );\r
+                       if( xStatus != eESTABLISHED )\r
+                       {\r
+                               /* The connection is not established (any more), therefore\r
+                               accept any amount of bytes, probably the last few bytes. */\r
+                       }\r
+                       else\r
+                       {\r
+                               if( xRc >= ipconfigFTP_PREFERRED_WRITE_SIZE )\r
+                               {\r
+                                       /* More than a sector to write, round down to a multiple of\r
+                                       PREFERRED_WRITE_SIZE bytes. */\r
+                                       xRc = ( xRc / ipconfigFTP_PREFERRED_WRITE_SIZE ) * ipconfigFTP_PREFERRED_WRITE_SIZE;\r
+                               }\r
+                               else\r
+                               {\r
+                               const StreamBuffer_t *pxBuffer = FreeRTOS_get_rx_buf( pxClient->xTransferSocket );\r
+                               size_t uxSpace = pxBuffer->LENGTH - pxBuffer->uxTail;\r
+\r
+                                       if( uxSpace >= ipconfigFTP_PREFERRED_WRITE_SIZE )\r
+                                       {\r
+                                               /* At this moment there are les than PREFERRED_WRITE_SIZE bytes in the RX\r
+                                               buffer, but there is space for more. Just return and\r
+                                               wait for more. */\r
+                                               xRc = 0;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               /* Now reading beyond the end of the circular buffer,\r
+                                               use a normal read. */\r
+                                               pcBuffer = pcFILE_BUFFER;\r
+                                               xRc = FreeRTOS_recvcount( pxClient->xTransferSocket );\r
+                                               xRc = ( xRc / ipconfigFTP_PREFERRED_WRITE_SIZE ) * ipconfigFTP_PREFERRED_WRITE_SIZE;\r
+                                               if( xRc > 0 )\r
+                                               {\r
+                                                       xRc = FreeRTOS_recv( pxClient->xTransferSocket, ( void * ) pcBuffer,\r
+                                                               sizeof( pcFILE_BUFFER ), FREERTOS_MSG_DONTWAIT );\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       if( xRc == 0 )\r
+                       {\r
+                               break;\r
+                       }\r
+                       pxClient->ulRecvBytes += xRc;\r
+\r
+                       xWritten = ff_fwrite( pcBuffer, 1, xRc, pxClient->pxWriteHandle );\r
+                       if( pcBuffer != pcFILE_BUFFER )\r
+                       {\r
+                               FreeRTOS_recv( pxClient->xTransferSocket, ( void * ) NULL, xRc, 0 );\r
+                       }\r
+                       if( xWritten != xRc )\r
+                       {\r
+                               xRc = -1;\r
+                               /* bHadError: a transfer got aborted because of an error. */\r
+                               pxClient->bits1.bHadError = pdTRUE_UNSIGNED;\r
+                               break;\r
+                       }\r
+               }\r
+               return xRc;\r
+       }\r
+\r
+#endif /* ipconfigFTP_ZERO_COPY_ALIGNED_WRITES */\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+######                          #                           #######   #   ###\r
+ #    #          #              #                            #   ##   #     #\r
+ #    #          #                                           #    #         #\r
+ #    #  ####  ###### ### ##  ###    ####  #    #  ####      #   #  ###     #    ####\r
+ ###### #    #   #     # #  #   #   #    # #    # #    #     #####    #     #   #    #\r
+ #  ##  ######   #     ##   #   #   ###### #    # ######     #   #    #     #   ######\r
+ #   #  #        #     #        #   #      #    # #          #        #     #   #\r
+ #    # #   ##   # ##  #        #   #   ##  #  #  #   ##     #        #     #   #   ##\r
+###  ##  ####     ##  ####    #####  ####    ##    ####     ####    ##### #####  ####\r
+*/\r
+static BaseType_t prvRetrieveFilePrep( FTPClient_t *pxClient, char *pcFileName )\r
+{\r
+BaseType_t xResult = pdTRUE;\r
+size_t uxFileSize;\r
+\r
+       /* Close previous handle (if any) and reset file transfer parameters */\r
+       prvTransferCloseFile( pxClient );\r
+\r
+       xMakeAbsolute( pxClient, pxClient->pcFileName, sizeof( pxClient->pcFileName ), pcFileName );\r
+\r
+       pxClient->pxReadHandle = ff_fopen( pxClient->pcFileName, "rb" );\r
+       if( pxClient->pxReadHandle == NULL )\r
+       {\r
+       int iErrno = stdioGET_ERRNO();\r
+               /* "Requested file action not taken". */\r
+               prvSendReply( pxClient->xSocket, REPL_450, 0 );\r
+               FreeRTOS_printf( ("prvRetrieveFilePrep: open '%s': errno %d: %s\n",\r
+                       pxClient->pcFileName, iErrno, ( const char * ) strerror( iErrno ) ) );\r
+               uxFileSize = 0ul;\r
+               xResult = pdFALSE;\r
+       }\r
+       else\r
+       {\r
+               uxFileSize = pxClient->pxReadHandle->ulFileSize;\r
+               pxClient->uxBytesLeft = uxFileSize;\r
+               if( pxClient->ulRestartOffset != 0ul )\r
+               {\r
+               size_t uxOffset = pxClient->ulRestartOffset;\r
+               int32_t iRc;\r
+\r
+                       /* Only use 1 time. */\r
+                       pxClient->ulRestartOffset = 0;\r
+\r
+                       if( uxOffset < uxFileSize )\r
+                       {\r
+                               iRc = ff_fseek( pxClient->pxReadHandle, uxOffset, FF_SEEK_SET );\r
+                       }\r
+                       else\r
+                       {\r
+                               iRc = -pdFREERTOS_ERRNO_EINVAL;\r
+                       }\r
+                       if( iRc != 0 )\r
+                       {\r
+                       BaseType_t xLength;\r
+\r
+                               xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                                       "450 Seek invalid %u length %u\r\n", ( unsigned ) uxOffset, ( unsigned ) uxFileSize );\r
+\r
+                               /* "Requested file action not taken". */\r
+                               prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+\r
+                               FreeRTOS_printf( ( "prvRetrieveFilePrep: create %s: Seek %u length %u\n",\r
+                                       pxClient->pcFileName, ( unsigned ) uxOffset, ( unsigned ) uxFileSize ) );\r
+\r
+                               ff_fclose( pxClient->pxReadHandle );\r
+                               pxClient->pxReadHandle = NULL;\r
+                               xResult = pdFALSE;\r
+                       }\r
+                       else\r
+                       {\r
+                               pxClient->uxBytesLeft = uxFileSize - pxClient->ulRestartOffset;\r
+                       }\r
+               }\r
+       }\r
+       if( xResult != pdFALSE )\r
+       {\r
+               if( pxClient->bits1.bIsListen != pdFALSE_UNSIGNED )\r
+               {\r
+                       /* True if PASV is used. */\r
+                       snprintf( pxClient->pcConnectionAck, sizeof( pxClient->pcConnectionAck ),\r
+                               "150%cAccepted data connection from %%xip:%%u\r\n%s",\r
+                               pxClient->xTransType == TMODE_ASCII ? '-' : ' ',\r
+                               pxClient->xTransType == TMODE_ASCII ? "150 NOTE: ASCII mode requested, but binary mode used\r\n" : "" );\r
+               } else {\r
+               BaseType_t xLength;\r
+\r
+                       xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), "150%cOpening data connection to %lxip:%u\r\n%s",\r
+                               pxClient->xTransType == TMODE_ASCII ? '-' : ' ',\r
+                               pxClient->ulClientIP,\r
+                               pxClient->usClientPort,\r
+                               pxClient->xTransType == TMODE_ASCII ? "150 NOTE: ASCII mode requested, but binary mode used\r\n" : "" );\r
+                       prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+                       pxClient->pcConnectionAck[ 0 ] = '\0';\r
+                       prvTransferStart( pxClient );\r
+               }\r
+\r
+               /* Prepare the ACK which will be sent when all data has been sent. */\r
+               snprintf( pxClient->pcClientAck, sizeof( pxClient->pcClientAck ), "%s", REPL_226 );\r
+\r
+               /* To get some statistics about the performance. */\r
+               pxClient->xStartTime = xTaskGetTickCount( );\r
+               if( uxFileSize == 0ul )\r
+               {\r
+                       FreeRTOS_shutdown( pxClient->xTransferSocket, FREERTOS_SHUT_RDWR );\r
+               }\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvRetrieveFileWork( FTPClient_t *pxClient )\r
+{\r
+size_t uxSpace;\r
+size_t uxCount, uxItemsRead;\r
+BaseType_t xRc = 0;\r
+BaseType_t xSetEvent = pdFALSE;\r
+\r
+       do\r
+       {\r
+       #if( ipconfigFTP_TX_ZERO_COPY != 0 )\r
+               char *pcBuffer;\r
+               BaseType_t xBufferLength;\r
+       #endif /* ipconfigFTP_TX_ZERO_COPY */\r
+\r
+               /* Take the lesser of the two: tx_space (number of bytes that can be\r
+               queued for transmission) and uxBytesLeft (the number of bytes left to\r
+               read from the file) */\r
+               uxSpace = FreeRTOS_tx_space( pxClient->xTransferSocket );\r
+\r
+               if( uxSpace == 0 )\r
+               {\r
+                       FreeRTOS_FD_SET( pxClient->xTransferSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE | eSELECT_EXCEPT );\r
+                       xRc = FreeRTOS_select( pxClient->pxParent->xSocketSet, 200 );\r
+                       uxSpace = FreeRTOS_tx_space( pxClient->xTransferSocket );\r
+               }\r
+\r
+               uxCount = FreeRTOS_min_uint32( pxClient->uxBytesLeft, uxSpace );\r
+\r
+               if( uxCount == 0 )\r
+               {\r
+                       break;\r
+               }\r
+\r
+               #if( ipconfigFTP_TX_ZERO_COPY == 0 )\r
+               {\r
+                       if( uxCount > sizeof( pcFILE_BUFFER ) )\r
+                       {\r
+                               uxCount = sizeof( pcFILE_BUFFER );\r
+                       }\r
+                       uxItemsRead = ff_fread( pcFILE_BUFFER, 1, uxCount, pxClient->pxReadHandle );\r
+                       if( uxItemsRead != uxCount )\r
+                       {\r
+                               FreeRTOS_printf( ( "prvRetrieveFileWork: Got %u Expected %u\n", ( unsigned )uxItemsRead, ( unsigned ) uxCount ) );\r
+                               xRc = FreeRTOS_shutdown( pxClient->xTransferSocket, FREERTOS_SHUT_RDWR );\r
+                               pxClient->uxBytesLeft = 0u;\r
+                               break;\r
+                       }\r
+                       pxClient->uxBytesLeft -= uxCount;\r
+\r
+                       if( pxClient->uxBytesLeft == 0u )\r
+                       {\r
+                       BaseType_t xTrueValue = 1;\r
+\r
+                               FreeRTOS_setsockopt( pxClient->xTransferSocket, 0, FREERTOS_SO_CLOSE_AFTER_SEND, ( void * ) &xTrueValue, sizeof( xTrueValue ) );\r
+                       }\r
+\r
+                       xRc = FreeRTOS_send( pxClient->xTransferSocket, pcFILE_BUFFER, uxCount, 0 );\r
+               }\r
+               #else /* ipconfigFTP_TX_ZERO_COPY != 0 */\r
+               {\r
+                       /* Use zero-copy transmission:\r
+                       FreeRTOS_get_tx_head() returns a direct pointer to the TX stream and\r
+                       set xBufferLength to know how much space there is left. */\r
+                       pcBuffer = ( char * )FreeRTOS_get_tx_head( pxClient->xTransferSocket, &xBufferLength );\r
+                       if( ( pcBuffer != NULL ) && ( xBufferLength >= 512 ) )\r
+                       {\r
+                               /* Will read disk data directly to the TX stream of the socket. */\r
+                               uxCount = FreeRTOS_min_uint32( uxCount, ( uint32_t )xBufferLength );\r
+                               if( uxCount > ( size_t ) 0x40000u )\r
+                               {\r
+                                       uxCount = ( size_t ) 0x40000u;\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Use the normal file i/o buffer. */\r
+                               pcBuffer = pcFILE_BUFFER;\r
+                               if( uxCount > sizeof( pcFILE_BUFFER ) )\r
+                               {\r
+                                       uxCount = sizeof( pcFILE_BUFFER );\r
+                               }\r
+                       }\r
+\r
+                       if ( pxClient->uxBytesLeft >= 1024u )\r
+                       {\r
+                               uxCount &= ~( ( size_t ) 512u - 1u );\r
+                       }\r
+\r
+                       if( uxCount <= 0u )\r
+                       {\r
+                               /* Nothing to send after rounding down to a multiple of a sector size. */\r
+                               break;\r
+                       }\r
+\r
+                       uxItemsRead = ff_fread( pcBuffer, 1, uxCount, pxClient->pxReadHandle );\r
+\r
+                       if( uxCount != uxItemsRead )\r
+                       {\r
+                               FreeRTOS_printf( ( "prvRetrieveFileWork: Got %u Expected %u\n", ( unsigned )uxItemsRead, ( unsigned )uxCount ) );\r
+                               xRc = FreeRTOS_shutdown( pxClient->xTransferSocket, FREERTOS_SHUT_RDWR );\r
+                               pxClient->uxBytesLeft = 0u;\r
+                               break;\r
+                       }\r
+                       pxClient->uxBytesLeft -= uxCount;\r
+\r
+                       if( pxClient->uxBytesLeft == 0u )\r
+                       {\r
+                       BaseType_t xTrueValue = 1;\r
+\r
+                               FreeRTOS_setsockopt( pxClient->xTransferSocket, 0, FREERTOS_SO_CLOSE_AFTER_SEND, ( void * ) &xTrueValue, sizeof( xTrueValue ) );\r
+                       }\r
+                       if( pcBuffer != pcFILE_BUFFER )\r
+                       {\r
+                               pcBuffer = NULL;\r
+                       }\r
+                       xRc = FreeRTOS_send( pxClient->xTransferSocket, pcBuffer, uxCount, 0 );\r
+               }\r
+               #endif /* ipconfigFTP_TX_ZERO_COPY */\r
+\r
+               if( xRc < 0 )\r
+               {\r
+                       break;\r
+               }\r
+\r
+               pxClient->ulRecvBytes += xRc;\r
+               if( pxClient->uxBytesLeft == 0u )\r
+               {\r
+                       break;\r
+               }\r
+       } while( uxCount > 0u );\r
+\r
+       if( xRc < 0 )\r
+       {\r
+               FreeRTOS_printf( ( "prvRetrieveFileWork: already disconnected\n" ) );\r
+       }\r
+       else if( pxClient->uxBytesLeft <= 0u )\r
+       {\r
+       BaseType_t x;\r
+\r
+               for( x = 0; x < 5; x++ )\r
+               {\r
+                       xRc = FreeRTOS_recv( pxClient->xTransferSocket, pcFILE_BUFFER, sizeof( pcFILE_BUFFER ), 0 );\r
+                       if( xRc < 0 )\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+//             FreeRTOS_printf( ( "prvRetrieveFileWork: %s all sent: xRc %ld\n", pxClient->pcFileName, xRc ) );\r
+       }\r
+       else\r
+       {\r
+               FreeRTOS_FD_SET( pxClient->xTransferSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );\r
+               xSetEvent = pdTRUE;\r
+       }\r
+       if( xSetEvent == pdFALSE )\r
+       {\r
+               FreeRTOS_FD_CLR( pxClient->xTransferSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );\r
+       }\r
+       return xRc;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+###     #####  ####  #####\r
+ #        #   #    # # # #\r
+ #        #   #    #   #\r
+ #        #   #        #\r
+ #        #    ##      #\r
+ #    #   #      ##    #\r
+ #    #   #   #    #   #\r
+ #    #   #   #    #   #\r
+####### #####  ####   ####\r
+*/\r
+/* Prepare sending a directory LIST */\r
+static BaseType_t prvListSendPrep( FTPClient_t *pxClient )\r
+{\r
+BaseType_t xFindResult;\r
+int iErrorNo;\r
+\r
+       if( pxClient->bits1.bIsListen != pdFALSE_UNSIGNED )\r
+       {\r
+               /* True if PASV is used */\r
+               snprintf( pxClient->pcConnectionAck, sizeof( pxClient->pcConnectionAck ),\r
+                       "150 Accepted data connection from %%xip:%%u\r\n" );\r
+       }\r
+       else\r
+       {\r
+       BaseType_t xLength;\r
+\r
+               /* Here the FTP server is supposed to connect() */\r
+               xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                       "150 Opening ASCII mode data connection to for /bin/ls \r\n" );\r
+\r
+               prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+               /* Clear the current connection acknowledge message */\r
+               pxClient->pcConnectionAck[ 0 ] = '\0';\r
+               prvTransferStart( pxClient );\r
+       }\r
+\r
+       pxClient->xDirCount = 0;\r
+       xMakeAbsolute( pxClient, pcNEW_DIR, sizeof( pcNEW_DIR ), pxClient->pcCurrentDir );\r
+\r
+       xFindResult = ff_findfirst( pcNEW_DIR, &pxClient->xFindData );\r
+\r
+       pxClient->bits1.bDirHasEntry = ( xFindResult >= 0 );\r
+\r
+       iErrorNo = stdioGET_ERRNO();\r
+       if( ( xFindResult < 0 ) && ( iErrorNo == pdFREERTOS_ERRNO_ENMFILE ) )\r
+       {\r
+               FreeRTOS_printf( ("prvListSendPrep: Empty directory? (%s)\n", pxClient->pcCurrentDir ) );\r
+               prvSendReply( pxClient->xTransferSocket, "total 0\r\n", 0 );\r
+               pxClient->xDirCount++;\r
+       }\r
+       else if( xFindResult < 0 )\r
+       {\r
+               FreeRTOS_printf( ( "prvListSendPrep: rc = %ld iErrorNo = %d\n", xFindResult, iErrorNo ) );\r
+               prvSendReply( pxClient->xSocket, REPL_451, 0 );\r
+       }\r
+       pxClient->pcClientAck[ 0 ] = '\0';\r
+\r
+       return pxClient->xDirCount;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#define        MAX_DIR_LIST_ENTRY_SIZE         256\r
+\r
+static BaseType_t prvListSendWork( FTPClient_t *pxClient )\r
+{\r
+BaseType_t xTxSpace;\r
+\r
+       while( pxClient->bits1.bClientConnected != pdFALSE_UNSIGNED )\r
+       {\r
+       char *pcWritePtr = pcCOMMAND_BUFFER;\r
+       BaseType_t xWriteLength;\r
+\r
+               xTxSpace = FreeRTOS_tx_space( pxClient->xTransferSocket );\r
+\r
+               if( xTxSpace > ( BaseType_t ) sizeof( pcCOMMAND_BUFFER ) )\r
+               {\r
+                       xTxSpace = sizeof( pcCOMMAND_BUFFER );\r
+               }\r
+\r
+               while( ( xTxSpace >= MAX_DIR_LIST_ENTRY_SIZE ) && ( pxClient->bits1.bDirHasEntry != pdFALSE_UNSIGNED ) )\r
+               {\r
+               BaseType_t xLength, xEndOfDir;\r
+               int32_t iRc;\r
+               int iErrorNo;\r
+\r
+                       xLength = prvGetFileInfoStat( &( pxClient->xFindData.xDirectoryEntry ), pcWritePtr, xTxSpace );\r
+\r
+                       pxClient->xDirCount++;\r
+                       pcWritePtr += xLength;\r
+                       xTxSpace -= xLength;\r
+\r
+                       iRc = ff_findnext( &pxClient->xFindData );\r
+                       iErrorNo = stdioGET_ERRNO();\r
+\r
+                       xEndOfDir = ( iRc < 0 ) && ( iErrorNo == pdFREERTOS_ERRNO_ENMFILE );\r
+\r
+                       pxClient->bits1.bDirHasEntry = ( xEndOfDir == pdFALSE ) && ( iRc >= 0 );\r
+\r
+                       if( ( iRc < 0 ) && ( xEndOfDir == pdFALSE ) )\r
+                       {\r
+                               FreeRTOS_printf( ("prvListSendWork: %s (rc %08x)\n",\r
+                                       ( const char * ) strerror( iErrorNo ),\r
+                                       ( unsigned )iRc ) );\r
+                       }\r
+               }\r
+               xWriteLength = ( BaseType_t ) ( pcWritePtr - pcCOMMAND_BUFFER );\r
+\r
+               if( xWriteLength == 0 )\r
+               {\r
+                       break;\r
+               }\r
+\r
+               if( pxClient->bits1.bDirHasEntry == pdFALSE_UNSIGNED )\r
+               {\r
+               uint32_t ulTotalCount;\r
+               uint32_t ulFreeCount;\r
+               uint32_t ulPercentage;\r
+\r
+                       ulTotalCount = 1;\r
+                       ulFreeCount = ff_diskfree( pxClient->pcCurrentDir, &ulTotalCount );\r
+                       ulPercentage = ( uint32_t ) ( ( 100ULL * ulFreeCount + ulTotalCount / 2 ) / ulTotalCount );\r
+\r
+                       /* Prepare the ACK which will be sent when all data has been sent. */\r
+                       snprintf( pxClient->pcClientAck, sizeof( pxClient->pcClientAck ),\r
+                               "226-Options: -l\r\n"\r
+                               "226-%ld matches total\r\n"\r
+                               "226 Total %lu KB (%lu %% free)\r\n",\r
+                               pxClient->xDirCount, ulTotalCount /1024, ulPercentage );\r
+               }\r
+\r
+               if( xWriteLength )\r
+               {\r
+                       if( pxClient->bits1.bDirHasEntry == pdFALSE_UNSIGNED )\r
+                       {\r
+                       BaseType_t xTrueValue = 1;\r
+\r
+                               FreeRTOS_setsockopt( pxClient->xTransferSocket, 0, FREERTOS_SO_CLOSE_AFTER_SEND, ( void * ) &xTrueValue, sizeof( xTrueValue ) );\r
+                       }\r
+\r
+                       prvSendReply( pxClient->xTransferSocket, pcCOMMAND_BUFFER, xWriteLength );\r
+               }\r
+\r
+               if( pxClient->bits1.bDirHasEntry == pdFALSE_UNSIGNED )\r
+               {\r
+                       prvSendReply( pxClient->xSocket, pxClient->pcClientAck, 0 );\r
+                       break;\r
+               }\r
+\r
+       }       /* while( pxClient->bits1.bClientConnected )  */\r
+\r
+       return 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static const char *pcMonthAbbrev( BaseType_t xMonth )\r
+{\r
+static const char pcMonthList[] = "JanFebMarAprMayJunJulAugSepOctNovDec";\r
+\r
+       if( xMonth < 1 || xMonth > 12 )\r
+               xMonth = 12;\r
+\r
+       return pcMonthList + 3 * ( xMonth - 1 );\r
+};\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvGetFileInfoStat( FF_DirEnt_t *pxEntry, char *pcLine, BaseType_t xMaxLength )\r
+{\r
+       char date[ 16 ];\r
+       char mode[ 11 ] = "----------";\r
+       BaseType_t st_nlink = 1;\r
+       const char user[ 9 ] = "freertos";\r
+       const char group[ 8 ] = "plusfat";\r
+\r
+/*\r
+ *     Creates a unix-style listing, understood by most FTP clients:\r
+ *\r
+ * -rw-rw-r--   1 freertos FreeRTOS+FAT 10564588 Sep 01 00:17 03.  Metaharmoniks - Star (Instrumental).mp3\r
+ * -rw-rw-r--   1 freertos FreeRTOS+FAT 19087839 Sep 01 00:17 04.  Simon Le Grec - Dimitri (Wherever U Are) (Cosmos Mix).mp3\r
+ * -rw-rw-r--   1 freertos FreeRTOS+FAT 11100621 Sep 01 00:16 05.  D-Chill - Mistake (feat. Katy Blue).mp3\r
+ */\r
+\r
+       #if ( ffconfigTIME_SUPPORT == 1 )\r
+               const FF_SystemTime_t *pxCreateTime = &( pxEntry->xCreateTime );\r
+       #else\r
+       #warning Do not use this.\r
+               FF_SystemTime_t xCreateTime;\r
+               const FF_SystemTime_t *pxCreateTime = &xCreateTime;\r
+       #endif\r
+       size_t ulSize = ( size_t )pxEntry->ulFileSize;\r
+       const char *pcFileName = pxEntry->pcFileName;\r
+\r
+       mode[ 0 ] = ( ( pxEntry->ucAttrib & FF_FAT_ATTR_DIR ) != 0 ) ? 'd' : '-';\r
+       #if( ffconfigDEV_SUPPORT != 0 )\r
+       {\r
+               if( ( pxEntry->ucAttrib & FF_FAT_ATTR_DIR ) == 0 )\r
+               {\r
+                       switch( pxEntry->ucIsDeviceDir )\r
+                       {\r
+                       case FF_DEV_CHAR_DEV:\r
+                               mode[ 0 ] = 'c';\r
+                               break;\r
+                       case FF_DEV_BLOCK_DEV:\r
+                               mode[ 0 ] = 'b';\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       #endif /* ffconfigDEV_SUPPORT != 0 */\r
+\r
+       mode[ 1 ] = 'r';        /* Owner. */\r
+       mode[ 2 ] = ( ( pxEntry->ucAttrib & FF_FAT_ATTR_READONLY ) != 0 ) ? '-' : 'w';\r
+       mode[ 3 ] = '-';        /* x for executable. */\r
+\r
+       mode[ 4 ] = 'r';        /* group. */\r
+       mode[ 5 ] = ( ( pxEntry->ucAttrib & FF_FAT_ATTR_READONLY ) != 0 ) ? '-' : 'w';\r
+       mode[ 6 ] = '-';        /* x for executable. */\r
+\r
+       mode[ 7 ] = 'r';        /* world. */\r
+       mode[ 8 ] = '-';\r
+       mode[ 9 ] = '-';        /* x for executable. */\r
+\r
+       if( pxCreateTime->Month && pxCreateTime->Day )\r
+       {\r
+               snprintf( date, sizeof( date ), "%-3.3s %02d %02d:%02d",\r
+                       pcMonthAbbrev( pxCreateTime->Month ),\r
+                       pxCreateTime->Day,\r
+                       pxCreateTime->Hour,\r
+                       pxCreateTime->Minute );\r
+       }\r
+       else\r
+       {\r
+               snprintf (date, sizeof( date ), "Jan 01 1970");\r
+       }\r
+       return snprintf( pcLine, xMaxLength, "%s %3ld %-4s %-4s %8d %12s %s\r\n",\r
+               mode, st_nlink, user, group, ( int ) ulSize, date, pcFileName );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+  ####  #     # #####\r
+ #    # #     #  #   #\r
+#     # #     #  #    #\r
+#       #  #  #  #    #\r
+#       #  #  #  #    #\r
+#       #  #  #  #    #\r
+#     #  ## ##   #    #\r
+ #    #  ## ##   #   #\r
+  ####   ## ##  #####\r
+*/\r
+static BaseType_t prvChangeDir( FTPClient_t *pxClient, char *pcDirectory )\r
+{\r
+BaseType_t xResult;\r
+BaseType_t xIsRootDir, xLength, xValid;\r
+BaseType_t xIsDotDir = 0;\r
+\r
+       if( pcDirectory[ 0 ] == '.' )\r
+       {\r
+               if( ( pcDirectory[ 1 ] == '.' ) &&\r
+                       ( pcDirectory[ 2 ] == '\0' ) )\r
+               {\r
+                       xIsDotDir = 2;\r
+               }\r
+               else if( pcDirectory[ 1 ] == '\0' )\r
+               {\r
+                       xIsDotDir = 1;\r
+               }\r
+       }\r
+\r
+       if( xIsDotDir != 0 )\r
+       {\r
+               strcpy( pcFILE_BUFFER, pxClient->pcCurrentDir );\r
+\r
+               if( pcDirectory[ 1 ] == '.' )\r
+               {\r
+                       char *p = strrchr( pcFILE_BUFFER, '/' );\r
+                       if( p != NULL )\r
+                       {\r
+                               if( p == pcFILE_BUFFER )\r
+                               {\r
+                                       p[ 1 ] = '\0';\r
+                               }\r
+                               else\r
+                               {\r
+                                       p[ 0 ] = '\0';\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       else\r
+       {\r
+               if(pcDirectory[ 0 ] != '/' )\r
+               {\r
+               BaseType_t xCurLength;\r
+\r
+                       xCurLength = strlen( pxClient->pcCurrentDir );\r
+                       snprintf( pcFILE_BUFFER, sizeof( pcFILE_BUFFER ), "%s%s%s",\r
+                               pxClient->pcCurrentDir,\r
+                               pxClient->pcCurrentDir[ xCurLength - 1 ] == '/' ? "" : "/",\r
+                               pcDirectory );\r
+               }\r
+               else\r
+               {\r
+                       snprintf( pcFILE_BUFFER, sizeof( pcFILE_BUFFER ), "%s", pcDirectory );\r
+               }\r
+       }\r
+\r
+       xIsRootDir = ( pcFILE_BUFFER[ 0 ] == '/' ) && ( pcFILE_BUFFER[ 1 ] == '\0' );\r
+       xMakeAbsolute( pxClient, pcNEW_DIR, sizeof( pcNEW_DIR ), pcFILE_BUFFER );\r
+\r
+       if( ( ( xIsRootDir == pdFALSE ) || ( FF_FS_Count() == 0 ) ) &&  ( ff_finddir( pcNEW_DIR ) == pdFALSE ) )\r
+       {\r
+               xValid = pdFALSE;\r
+       }\r
+       else\r
+       {\r
+               xValid = pdTRUE;\r
+       }\r
+\r
+       if( xValid == pdFALSE )\r
+       {\r
+               /* Get the directory cluster, if it exists. */\r
+               FreeRTOS_printf( ("FTP: chdir \"%s\": No such dir\n", pcNEW_DIR ) );\r
+               //#define REPL_550 "550 Requested action not taken.\r\n"\r
+               //550 /home/hein/arch/h8300: No such file or directory\r
+               xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                       "550 %s: No such file or directory\r\n",\r
+                       pcNEW_DIR );\r
+               prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+               xResult = pdFALSE;\r
+       }\r
+       else\r
+       {\r
+               memcpy( pxClient->pcCurrentDir, pcNEW_DIR, sizeof( pxClient->pcCurrentDir ) );\r
+\r
+               xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), "250 Changed to %s\r\n", pcNEW_DIR );\r
+               prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+               xResult = pdTRUE;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+######  ##    # ####### ######\r
+ #    # ##    #  #   ##  #    #\r
+ #    # ##    #  #    #  #    #\r
+ #    # ###   #  #   #   #    #\r
+ ###### # ##  #  #####   ######\r
+ #  ##  #  ## #  #   #   #  ##\r
+ #   #  #   ###  #       #   #\r
+ #    # #    ##  #       #    #\r
+###  ## #    ## ####    ###  ##\r
+*/\r
+static BaseType_t prvRenameFrom( FTPClient_t *pxClient, const char *pcFileName )\r
+{\r
+const char *myReply;\r
+FF_FILE *fh;\r
+\r
+       xMakeAbsolute( pxClient, pxClient->pcFileName, sizeof( pxClient->pcFileName ), pcFileName );\r
+\r
+       myReply = NULL;\r
+\r
+       fh = ff_fopen( pxClient->pcFileName, "rb" );\r
+\r
+       if( fh != NULL )\r
+       {\r
+               ff_fclose( fh );\r
+               /* REPL_350; "350 Requested file action pending further information." */\r
+               snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                       "350 Rename '%s' ...\r\n", pxClient->pcFileName );\r
+               myReply = pcCOMMAND_BUFFER;\r
+               pxClient->bits.bInRename = pdTRUE_UNSIGNED;\r
+       }\r
+       else if( stdioGET_ERRNO() == pdFREERTOS_ERRNO_EISDIR )\r
+       {\r
+               snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                       "350 Rename directory '%s' ...\r\n", pxClient->pcFileName );\r
+               myReply = pcCOMMAND_BUFFER;\r
+               pxClient->bits.bInRename = pdTRUE_UNSIGNED;\r
+       }\r
+       else\r
+       {\r
+               FreeRTOS_printf( ("ftp::renameFrom[%s]\n%s\n", pxClient->pcFileName, strerror( stdioGET_ERRNO() ) ) );\r
+               myReply = REPL_451;             /* "451 Requested action aborted. Local error in processing." */\r
+       }\r
+       if( myReply )\r
+       {\r
+               prvSendReply( pxClient->xSocket, myReply, 0 );\r
+       }\r
+\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+######  ##    # #####   ###\r
+ #    # ##    # # # #  ## ##\r
+ #    # ##    #   #   ##   ##\r
+ #    # ###   #   #   #     #\r
+ ###### # ##  #   #   #     #\r
+ #  ##  #  ## #   #   #     #\r
+ #   #  #   ###   #   ##   ##\r
+ #    # #    ##   #    ## ##\r
+###  ## #    ##  ####   ###\r
+*/\r
+static BaseType_t prvRenameTo( FTPClient_t *pxClient, const char *pcFileName )\r
+{\r
+const char *myReply = NULL;\r
+int iResult;\r
+\r
+       xMakeAbsolute( pxClient, pcNEW_DIR, sizeof( pcNEW_DIR ), pcFileName );\r
+\r
+       /* FreeRTOS+FAT rename has an extra parameter: "remove target if already\r
+       exists". */\r
+       iResult = ff_rename( pxClient->pcFileName, pcNEW_DIR, pdFALSE );\r
+\r
+       if( iResult < 0 )\r
+       {\r
+               iResult = stdioGET_ERRNO();\r
+       }\r
+       else\r
+       {\r
+               iResult = 0;\r
+       }\r
+\r
+       switch( iResult )\r
+       {\r
+       case 0:\r
+               FreeRTOS_printf( ( "ftp::renameTo[%s,%s]: Ok\n", pxClient->pcFileName, pcNEW_DIR ) );\r
+               snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                       "250 Rename successful to '%s'\r\n", pcNEW_DIR );\r
+               myReply = pcCOMMAND_BUFFER;\r
+               break;\r
+       case pdFREERTOS_ERRNO_EEXIST:\r
+               /* the destination file already exists.\r
+               "450 Requested file action not taken.\r\n"*/\r
+               snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                       "450 Already exists '%s'\r\n", pcNEW_DIR );\r
+               myReply = pcCOMMAND_BUFFER;\r
+               break;\r
+       case pdFREERTOS_ERRNO_EIO:      /* FF_ERR_FILE_COULD_NOT_CREATE_DIRENT */\r
+               /* if dirent creation failed (fatal error!).\r
+               "553 Requested action not taken.\r\n" */\r
+               FreeRTOS_printf( ("ftp::renameTo[%s,%s]: Error creating DirEnt\n",\r
+                       pxClient->pcFileName, pcNEW_DIR ) );\r
+               myReply = REPL_553;\r
+               break;\r
+       case pdFREERTOS_ERRNO_ENXIO:\r
+       case pdFREERTOS_ERRNO_ENOENT:\r
+               /* if the source file was not found.\r
+               "450 Requested file action not taken.\r\n" */\r
+               snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                       "450 No such file '%s'\r\n", pxClient->pcFileName );\r
+               myReply = pcCOMMAND_BUFFER;\r
+               break;\r
+       default:\r
+               FreeRTOS_printf( ("ftp::renameTo[%s,%s]: %s\n", pxClient->pcFileName, pcNEW_DIR,\r
+                       (const char*)strerror( stdioGET_ERRNO() ) ) );\r
+               myReply = REPL_451;     /* "451 Requested action aborted. Local error in processing." */\r
+               break;\r
+       }\r
+       prvSendReply( pxClient->xSocket, myReply, 0 );\r
+\r
+       return pdTRUE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ ####    #\r
+#    #   #     #\r
+#    #         #\r
+#      ###   ######  ####\r
+ ##      #     #    #    #\r
+   ##    #     #    ######\r
+#    #   #     #    #\r
+#    #   #     # ## #   ##\r
+ ####  #####    ##   ####\r
+*/\r
+static BaseType_t prvSiteCmd( FTPClient_t *pxClient, char *pcRestCommand )\r
+{\r
+       ( void ) pxClient;\r
+       ( void ) pcRestCommand;\r
+\r
+       return 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+#####          ###\r
+ #   #           #            #\r
+ #    #          #            #\r
+ #    #  ####    #    ####  ######  ####\r
+ #    # #    #   #   #    #   #    #    #\r
+ #    # ######   #   ######   #    ######\r
+ #    # #        #   #        #    #\r
+ #   #  #   ##   #   #   ##   # ## #   ##\r
+#####    ####  #####  ####     ##   ####\r
+*/\r
+static BaseType_t prvDeleteFile( FTPClient_t *pxClient, char *pcFileName )\r
+{\r
+BaseType_t xResult, xLength;\r
+int32_t iRc;\r
+int iErrorNo;\r
+\r
+       /* DELE: Delete a file. */\r
+       xMakeAbsolute( pxClient, pxClient->pcFileName, sizeof( pxClient->pcFileName ), pcFileName );\r
+\r
+       iRc = ff_remove( pxClient->pcFileName );\r
+\r
+       if (iRc >= 0 )\r
+       {\r
+               xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                       "250 File \"%s\" removed\r\n", pxClient->pcFileName );\r
+               xResult = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               const char *errMsg = "other error";\r
+\r
+               iErrorNo = stdioGET_ERRNO();\r
+               switch( iErrorNo )\r
+               {                                                                                                                                               /*_RB_ What do these negative numbers relate to? */\r
+                       case pdFREERTOS_ERRNO_ENOENT:   errMsg = "No such file"; break;         /* -31  File was not found. */\r
+                       case pdFREERTOS_ERRNO_EALREADY: errMsg = "File still open"; break;      /* -30  File is in use. */\r
+                       case pdFREERTOS_ERRNO_EISDIR:   errMsg = "Is a dir"; break;                     /* -32  Tried to FF_Open() a Directory. */\r
+                       case pdFREERTOS_ERRNO_EROFS:    errMsg = "Read-only"; break;            /* -33  Tried to FF_Open() a file marked read only. */\r
+                       case pdFREERTOS_ERRNO_ENOTDIR:  errMsg = "Invalid path"; break;         /* -34  The path of the file was not found. */\r
+               }\r
+               FreeRTOS_printf( ( "ftp::delFile: '%s' because %s\n",\r
+                       pxClient->pcFileName, strerror( iErrorNo ) ) );\r
+\r
+               xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                       "521-\"%s\" %s;\r\n"\r
+                       "521 taking no action\r\n",\r
+                       pxClient->pcFileName, errMsg );\r
+\r
+               xResult = pdFALSE;\r
+       }\r
+\r
+       prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ ####    #                       #####\r
+#    #   #                        #   #            #\r
+#    #                            #    #           #\r
+#      ###   ######  ####         #    #  ####   ######  ####\r
+ ##      #   #    # #    #        #    #      #    #    #    #\r
+   ##    #       #  ######        #    #  #####    #    ######\r
+#    #   #     #    #             #    # #    #    #    #\r
+#    #   #    #     #   ##        #   #  #    #    # ## #   ##\r
+ ####  ##### ######  ####        #####    ### ##    ##   ####\r
+*/\r
+static BaseType_t prvSizeDateFile( FTPClient_t *pxClient, char *pcFileName, BaseType_t xSendDate )\r
+{\r
+BaseType_t xResult = pdFALSE;\r
+char *pcPtr;\r
+\r
+       /* SIZE: get the size of a file (xSendDate = 0)\r
+       MDTM: get data and time properties (xSendDate = 1) */\r
+       xMakeAbsolute( pxClient, pxClient->pcFileName, sizeof( pxClient->pcFileName ), pcFileName );\r
+\r
+       pcPtr = strrchr( pxClient->pcFileName, '/' );\r
+\r
+       if( ( pcPtr != NULL ) && ( pcPtr[ 1 ] != '\0' ) )\r
+       {\r
+               FF_Stat_t xStatBuf;\r
+               int32_t iRc = ff_stat( pxClient->pcFileName, &xStatBuf );\r
+               if (iRc < 0 )\r
+                       FreeRTOS_printf( ("In %s: %s\n", pxClient->pcFileName,\r
+                               ( const char* )strerror( stdioGET_ERRNO() ) ) );\r
+\r
+               if( iRc == 0 )\r
+               {\r
+               BaseType_t xLength;\r
+                       /* "YYYYMMDDhhmmss" */\r
+                       if( xSendDate != pdFALSE )\r
+                       {\r
+                               #if( ffconfigTIME_SUPPORT != 0 )\r
+                               {\r
+                                       FF_TimeStruct_t tmStruct;\r
+                                       time_t secs = xStatBuf.st_mtime;\r
+                                       FreeRTOS_gmtime_r( &secs, &tmStruct );\r
+\r
+                                       xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), "213 %04u%02u%02u%02u%02u%02u\r\n",\r
+                                               tmStruct.tm_year + 1900,\r
+                                               tmStruct.tm_mon+1,\r
+                                               tmStruct.tm_mday,\r
+                                               tmStruct.tm_hour,\r
+                                               tmStruct.tm_min,\r
+                                               tmStruct.tm_sec );\r
+                               }\r
+                               #else\r
+                               {\r
+                                       xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), "213 19700101000000\r\n",\r
+                               }\r
+                               #endif\r
+                       }\r
+                       else\r
+                       {\r
+                               xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), "213 %lu\r\n", xStatBuf.st_size );\r
+                       }\r
+                       prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+                       xResult = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       FreeRTOS_printf( ("ftp::sizeDateFile: No such file %s\n", pxClient->pcFileName ) );\r
+               }\r
+       } else {\r
+               FreeRTOS_printf( ("ftp::sizeDateFile: Invalid file name: %s ?\n", pxClient->pcFileName ) );\r
+       }\r
+       if( xResult == pdFALSE )\r
+       {\r
+               prvSendReply( pxClient->xSocket, REPL_450, 0 ); /* "Requested file action not taken". */\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+##   ## ##   ## #####      ######  ##   ## #####\r
+### ###  #    #  #   #      #    # ### ###  #   #\r
+# ### #  #   #   #    #     #    # # ### #  #    #\r
+#  #  #  #   #   #    #     #    # #  #  #  #    #\r
+#  #  #  ####    #    #     ###### #  #  #  #    #\r
+#     #  #   #   #    #     #  ##  #     #  #    #\r
+#     #  #   #   #    #     #   #  #     #  #    #\r
+#     #  #    #  #   #      #    # #     #  #   #\r
+#     # ###  ## #####      ###  ## #     # #####\r
+*/\r
+static BaseType_t prvMakeRemoveDir( FTPClient_t *pxClient, const char *pcDirectory, BaseType_t xDoRemove )\r
+{\r
+BaseType_t xResult;\r
+BaseType_t xLength;\r
+int32_t iRc;\r
+int iErrorNo;\r
+\r
+       /* MKD: Make / create a directory (xDoRemove = 0)\r
+       RMD: Remove a directory (xDoRemove = 1) */\r
+       xMakeAbsolute( pxClient, pxClient->pcFileName, sizeof( pxClient->pcFileName ), pcDirectory );\r
+\r
+       if( xDoRemove )\r
+       {\r
+               iRc = ff_rmdir( pxClient->pcFileName );\r
+       }\r
+       else\r
+       {\r
+               #if( ffconfigMKDIR_RECURSIVE != 0 )\r
+               {\r
+                       iRc = ff_mkdir( pxClient->pcFileName, pdFALSE );\r
+               }\r
+               #else\r
+               {\r
+                       iRc = ff_mkdir( pxClient->pcFileName );\r
+               }\r
+               #endif /* ffconfigMKDIR_RECURSIVE */\r
+       }\r
+       xResult = pdTRUE;\r
+\r
+       if( iRc >= 0 )\r
+       {\r
+               xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), "257 \"%s\" directory %s\r\n",\r
+                       pxClient->pcFileName, xDoRemove ? "removed" : "created" );\r
+       }\r
+       else\r
+       {\r
+       const char *errMsg = "other error";\r
+       BaseType_t xFTPCode = 521;\r
+\r
+               xResult = pdFALSE;\r
+               iErrorNo = stdioGET_ERRNO();\r
+               switch( iErrorNo )\r
+               {\r
+                       case pdFREERTOS_ERRNO_EEXIST:   errMsg = "Directory already exists"; break;\r
+                       case pdFREERTOS_ERRNO_ENOTDIR:  errMsg = "Invalid path"; break;                 /* -34 The path of the file was not found. *//*_RB_ As before, what do these negative numbers relate to? */\r
+                       case pdFREERTOS_ERRNO_ENOTEMPTY:errMsg = "Dir not empty"; break;\r
+                       case pdFREERTOS_ERRNO_EROFS:    errMsg = "Read-only"; break;                    /* -33  Tried to FF_Open() a file marked read only. */\r
+                       default:                                                errMsg = strerror( iErrorNo ); break;\r
+               }\r
+               if( iErrorNo == pdFREERTOS_ERRNO_ENOSPC )\r
+               {\r
+                       xFTPCode = 552;\r
+               }\r
+               xLength = snprintf( pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ),\r
+                       "%ld-\"%s\" %s;\r\n"\r
+                       "%ld taking no action\r\n",\r
+                       xFTPCode, pxClient->pcFileName, errMsg, xFTPCode );\r
+               FreeRTOS_printf( ( "%sdir '%s': %s\n", xDoRemove ? "rm" : "mk", pxClient->pcFileName, errMsg ) );\r
+       }\r
+       prvSendReply( pxClient->xSocket, pcCOMMAND_BUFFER, xLength );\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static portINLINE BaseType_t IsDigit( char cChar )\r
+{\r
+BaseType_t xResult;\r
+\r
+       if( cChar >= '0' && cChar <= '9' )\r
+       {\r
+               xResult = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xResult = pdFALSE;\r
+       }\r
+       return xResult;\r
+}\r
+\r
+static BaseType_t prvSendReply( Socket_t xSocket, const char *pcBuffer, BaseType_t xLength )\r
+{\r
+BaseType_t xResult;\r
+\r
+       if( xLength == 0 )\r
+       {\r
+               xLength = strlen( pcBuffer );\r
+       }\r
+       xResult = FreeRTOS_send( xSocket, ( const void * )pcBuffer, ( size_t ) xLength, 0 );\r
+       if( IsDigit( ( int ) pcBuffer[ 0 ] ) &&\r
+               IsDigit( ( int ) pcBuffer[ 1 ] ) &&\r
+               IsDigit( ( int ) pcBuffer[ 2 ] ) &&\r
+               IsDigit( ( int ) pcBuffer[ 3 ] ) )\r
+       {\r
+               const char *last = pcBuffer + strlen( pcBuffer );\r
+               int iLength;\r
+               while( ( last > pcBuffer ) && ( ( last[ -1 ] == ftpASCII_CR ) || ( last[ -1 ] == ftpASCII_LF ) ) )\r
+               {\r
+                       last--;\r
+               }\r
+               iLength = ( int )( last - pcBuffer );\r
+               FF_PRINTF( "   %-*.*s", iLength, iLength, pcBuffer );\r
+       }\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigFTP_HAS_RECEIVED_HOOK != 0 )\r
+\r
+       /*\r
+        * The following function is called for every file received:\r
+        *     void vApplicationFTPReceivedHook( pcFileName, ulSize, pxFTPClient );\r
+        * This callback function may do a callback to vFTPReplyMessage() to send messages\r
+        * to the FTP client like:\r
+        *      200-Please wait: Received new firmware\r
+        *      200-Please wait: Please wait a few seconds for reboot\r
+        */\r
+       void vFTPReplyMessage( struct xFTP_CLIENT *pxFTPClient, const char *pcMessage )\r
+       {\r
+               if( ( pxFTPClient != NULL ) && ( pxFTPClient->xSocket != NULL ) )\r
+               {\r
+                       prvSendReply( pxFTPClient->xSocket, pcMessage, 0 );\r
+               }\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+#endif /* ipconfigFTP_HAS_RECEIVED_HOOK != 0 */\r
+\r
+/*\r
+ * Some explanation:\r
+ * The FTP client may send: "DELE readme.txt"\r
+ * Here the complete path is constructed consisting of 3 parts:\r
+ *\r
+ * pxClient->pcRootDir  +  pxClient->pcCurrentDir  +  pcFileName\r
+ *\r
+ * 'pcCurrentDir' will not be applied for an absolute path like in "DELE /.htaccess"\r
+ */\r
+BaseType_t xMakeAbsolute( FTPClient_t *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName )\r
+{\r
+BaseType_t xLength = strlen( pxClient->pcRootDir );\r
+\r
+       if( pcFileName[ 0 ] != '/' )\r
+       {\r
+       char *pcNewDirBuffer = pcNEW_DIR;\r
+       BaseType_t xCurLength;\r
+\r
+               xCurLength = strlen( pxClient->pcCurrentDir );\r
+               if( pcBuffer == pcNEW_DIR )\r
+               {\r
+                       /* In one call, the result already goes into pcNEW_DIR.\r
+                       Use pcFILE_BUFFER in that case */\r
+                       pcNewDirBuffer = pcFILE_BUFFER;\r
+               }\r
+               snprintf( pcNewDirBuffer, sizeof( pcNEW_DIR ), "%s%s%s",\r
+                       pxClient->pcCurrentDir,\r
+                       pxClient->pcCurrentDir[ xCurLength - 1 ] == '/' ? "" : "/",\r
+                       pcFileName );\r
+               pcFileName = pcNewDirBuffer;\r
+       }\r
+       if( strncasecmp( pxClient->pcRootDir, pcFileName, xLength ) == 0 )\r
+       {\r
+               xLength = snprintf( pcBuffer, xBufferLength, "%s", pcFileName );\r
+       }\r
+       else\r
+       {\r
+               xLength = snprintf( pcBuffer, xBufferLength, "%s/%s",\r
+                       pxClient->pcRootDir,\r
+                       pcFileName[ 0 ] == '/' ? ( pcFileName + 1 ) : pcFileName );\r
+       }\r
+\r
+       #if( ipconfigFTP_FS_USES_BACKSLAH == 1 )\r
+               for( pcPtr = pcBuffer; *pcPtr; pcPtr++ )\r
+               {\r
+                       if( pcPtr[ 0 ] == '/' )\r
+                       {\r
+                               pcPtr[ 0 ] = '\\';\r
+                       }\r
+               }\r
+       #endif\r
+\r
+       return xLength;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xMakeRelative( FTPClient_t *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName )\r
+{\r
+BaseType_t xLength = strlen( pxClient->pcRootDir );\r
+\r
+       if( strncasecmp ( pxClient->pcRootDir, pcFileName, xLength ) == 0 )\r
+       {\r
+               xLength = snprintf( pcBuffer, xBufferLength, "%s", pcFileName + xLength );\r
+       }\r
+       else\r
+       {\r
+               xLength = snprintf( pcBuffer, xBufferLength, "%s", pcFileName );\r
+       }\r
+\r
+       return xLength;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#endif /* ipconfigUSE_FTP */\r
+\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/HTTP/FreeRTOS_HTTP_commands.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/HTTP/FreeRTOS_HTTP_commands.c
new file mode 100644 (file)
index 0000000..cb9462c
--- /dev/null
@@ -0,0 +1,103 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+\r
+/* Standard includes. */\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+\r
+#include "FreeRTOS_HTTP_commands.h"\r
+\r
+const struct xWEB_COMMAND xWebCommands[ WEB_CMD_COUNT ] =\r
+{\r
+       {       3,     "GET",           ECMD_GET },\r
+       {       4,    "HEAD",           ECMD_HEAD },\r
+       {       4,    "POST",           ECMD_POST },\r
+       {       3,     "PUT",           ECMD_PUT },\r
+       {       6,  "DELETE",           ECMD_DELETE },\r
+       {       5,   "TRACE",           ECMD_TRACE },\r
+       {       7, "OPTIONS",           ECMD_OPTIONS },\r
+       {       7, "CONNECT",           ECMD_CONNECT },\r
+       {       5,   "PATCH",           ECMD_PATCH },\r
+       {       4,    "UNKN",           ECMD_UNK },\r
+};\r
+\r
+const char *webCodename (int aCode)\r
+{\r
+       switch (aCode) {\r
+       case WEB_REPLY_OK:      //  = 200,\r
+               return "OK";\r
+       case WEB_NO_CONTENT:    // 204\r
+               return "No content";\r
+       case WEB_BAD_REQUEST:   //  = 400,\r
+               return "Bad request";\r
+       case WEB_UNAUTHORIZED:  //  = 401,\r
+               return "Authorization Required";\r
+       case WEB_NOT_FOUND:     //  = 404,\r
+               return "Not Found";\r
+       case WEB_GONE:  //  = 410,\r
+               return "Done";\r
+       case WEB_PRECONDITION_FAILED:   //  = 412,\r
+               return "Precondition Failed";\r
+       case WEB_INTERNAL_SERVER_ERROR: //  = 500,\r
+               return "Internal Server Error";\r
+       }\r
+       return "Unknown";\r
+}\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/HTTP/FreeRTOS_HTTP_server.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/HTTP/FreeRTOS_HTTP_server.c
new file mode 100644 (file)
index 0000000..1581f62
--- /dev/null
@@ -0,0 +1,455 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+\r
+/* FreeRTOS Protocol includes. */\r
+#include "FreeRTOS_HTTP_commands.h"\r
+#include "FreeRTOS_TCP_server.h"\r
+#include "FreeRTOS_server_private.h"\r
+\r
+/* FreeRTOS+FAT includes. */\r
+#include "ff_stdio.h"\r
+\r
+#ifndef HTTP_SERVER_BACKLOG\r
+       #define HTTP_SERVER_BACKLOG                     ( 12 )\r
+#endif\r
+\r
+#ifndef USE_HTML_CHUNKS\r
+       #define USE_HTML_CHUNKS                         ( 0 )\r
+#endif\r
+\r
+#if !defined( ARRAY_SIZE )\r
+       #define ARRAY_SIZE(x) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] )\r
+#endif\r
+\r
+/* Some defines to make the code more readbale */\r
+#define pcCOMMAND_BUFFER       pxClient->pxParent->pcCommandBuffer\r
+#define pcNEW_DIR                      pxClient->pxParent->pcNewDir\r
+#define pcFILE_BUFFER          pxClient->pxParent->pcFileBuffer\r
+\r
+#ifndef ipconfigHTTP_REQUEST_CHARACTER\r
+       #define ipconfigHTTP_REQUEST_CHARACTER          '?'\r
+#endif\r
+\r
+/*_RB_ Need comment block, although fairly self evident. */\r
+static void prvFileClose( HTTPClient_t *pxClient );\r
+static BaseType_t prvProcessCmd( HTTPClient_t *pxClient, BaseType_t xIndex );\r
+static const char *pcGetContentsType( const char *apFname );\r
+static BaseType_t prvOpenURL( HTTPClient_t *pxClient );\r
+static BaseType_t prvSendFile( HTTPClient_t *pxClient );\r
+static BaseType_t prvSendReply( HTTPClient_t *pxClient, BaseType_t xCode );\r
+\r
+static const char pcEmptyString[1] = { '\0' };\r
+\r
+typedef struct xTYPE_COUPLE\r
+{\r
+       const char *pcExtension;\r
+       const char *pcType;\r
+} TypeCouple_t;\r
+\r
+static TypeCouple_t pxTypeCouples[ ] =\r
+{\r
+       { "html", "text/html" },\r
+       { "css",  "text/css" },\r
+       { "js",   "text/javascript" },\r
+       { "png",  "image/png" },\r
+       { "jpg",  "image/jpeg" },\r
+       { "gif",  "image/gif" },\r
+       { "txt",  "text/plain" },\r
+       { "mp3",  "audio/mpeg3" },\r
+       { "wav",  "audio/wav" },\r
+       { "flac", "audio/ogg" },\r
+       { "pdf",  "application/pdf" },\r
+       { "ttf",  "application/x-font-ttf" },\r
+       { "ttc",  "application/x-font-ttf" }\r
+};\r
+\r
+void vHTTPClientDelete( TCPClient_t *pxTCPClient )\r
+{\r
+HTTPClient_t *pxClient = ( HTTPClient_t * ) pxTCPClient;\r
+\r
+       /* This HTTP client stops, close / release all resources. */\r
+       if( pxClient->xSocket != FREERTOS_NO_SOCKET )\r
+       {\r
+               FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_ALL );\r
+               FreeRTOS_closesocket( pxClient->xSocket );\r
+               pxClient->xSocket = FREERTOS_NO_SOCKET;\r
+       }\r
+       prvFileClose( pxClient );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvFileClose( HTTPClient_t *pxClient )\r
+{\r
+       if( pxClient->pxFileHandle != NULL )\r
+       {\r
+               FreeRTOS_printf( ( "Closing file: %s\n", pxClient->pcCurrentFilename ) );\r
+               ff_fclose( pxClient->pxFileHandle );\r
+               pxClient->pxFileHandle = NULL;\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvSendReply( HTTPClient_t *pxClient, BaseType_t xCode )\r
+{\r
+struct xTCP_SERVER *pxParent = pxClient->pxParent;\r
+BaseType_t xRc;\r
+\r
+       /* A normal command reply on the main socket (port 21). */\r
+       char *pcBuffer = pxParent->pcFileBuffer;\r
+\r
+       xRc = snprintf( pcBuffer, sizeof( pxParent->pcFileBuffer ),\r
+               "HTTP/1.1 %d %s\r\n"\r
+#if    USE_HTML_CHUNKS\r
+               "Transfer-Encoding: chunked\r\n"\r
+#endif\r
+               "Content-Type: %s\r\n"\r
+               "Connection: keep-alive\r\n"\r
+               "%s\r\n",\r
+               ( int ) xCode,\r
+               webCodename (xCode),\r
+               pxParent->pcContentsType[0] ? pxParent->pcContentsType : "text/html",\r
+               pxParent->pcExtraContents );\r
+\r
+       pxParent->pcContentsType[0] = '\0';\r
+       pxParent->pcExtraContents[0] = '\0';\r
+\r
+       xRc = FreeRTOS_send( pxClient->xSocket, ( const void * ) pcBuffer, xRc, 0 );\r
+       pxClient->bits.bReplySent = pdTRUE_UNSIGNED;\r
+\r
+       return xRc;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvSendFile( HTTPClient_t *pxClient )\r
+{\r
+size_t uxSpace;\r
+size_t uxCount;\r
+BaseType_t xRc = 0;\r
+\r
+       if( pxClient->bits.bReplySent == pdFALSE_UNSIGNED )\r
+       {\r
+               pxClient->bits.bReplySent = pdTRUE_UNSIGNED;\r
+\r
+               strcpy( pxClient->pxParent->pcContentsType, pcGetContentsType( pxClient->pcCurrentFilename ) );\r
+               snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ),\r
+                       "Content-Length: %d\r\n", ( int ) pxClient->uxBytesLeft );\r
+\r
+               /* "Requested file action OK". */\r
+               xRc = prvSendReply( pxClient, WEB_REPLY_OK );\r
+       }\r
+\r
+       if( xRc >= 0 ) do\r
+       {\r
+               uxSpace = FreeRTOS_tx_space( pxClient->xSocket );\r
+\r
+               if( pxClient->uxBytesLeft < uxSpace )\r
+               {\r
+                       uxCount = pxClient->uxBytesLeft;\r
+               }\r
+               else\r
+               {\r
+                       uxCount = uxSpace;\r
+               }\r
+\r
+               if( uxCount > 0u )\r
+               {\r
+                       if( uxCount > sizeof( pxClient->pxParent->pcFileBuffer ) )\r
+                       {\r
+                               uxCount = sizeof( pxClient->pxParent->pcFileBuffer );\r
+                       }\r
+                       ff_fread( pxClient->pxParent->pcFileBuffer, 1, uxCount, pxClient->pxFileHandle );\r
+                       pxClient->uxBytesLeft -= uxCount;\r
+\r
+                       xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pxParent->pcFileBuffer, uxCount, 0 );\r
+                       if( xRc < 0 )\r
+                       {\r
+                               break;\r
+                       }\r
+               }\r
+       } while( uxCount > 0u );\r
+\r
+       if( pxClient->uxBytesLeft == 0u )\r
+       {\r
+               /* Writing is ready, no need for further 'eSELECT_WRITE' events. */\r
+               FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );\r
+               prvFileClose( pxClient );\r
+       }\r
+       else\r
+       {\r
+               /* Wake up the TCP task as soon as this socket may be written to. */\r
+               FreeRTOS_FD_SET( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );\r
+       }\r
+\r
+       return xRc;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvOpenURL( HTTPClient_t *pxClient )\r
+{\r
+BaseType_t xRc;\r
+char pcSlash[ 2 ];\r
+\r
+       pxClient->bits.ulFlags = 0;\r
+\r
+       #if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 )\r
+       {\r
+               if( strchr( pxClient->pcUrlData, ipconfigHTTP_REQUEST_CHARACTER ) != NULL )\r
+               {\r
+               size_t xResult;\r
+\r
+                       xResult = uxApplicationHTTPHandleRequestHook( pxClient->pcUrlData, pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ) );\r
+                       if( xResult > 0 )\r
+                       {\r
+                               strcpy( pxClient->pxParent->pcContentsType, "text/html" );\r
+                               snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ),\r
+                                       "Content-Length: %d\r\n", ( int ) xResult );\r
+                               xRc = prvSendReply( pxClient, WEB_REPLY_OK );   /* "Requested file action OK" */\r
+                               if( xRc > 0 )\r
+                               {\r
+                                       xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pcCurrentFilename, xResult, 0 );\r
+                               }\r
+                               /* Although against the coding standard of FreeRTOS, a return is\r
+                               done here  to simplify this conditional code. */\r
+                               return xRc;\r
+                       }\r
+               }\r
+       }\r
+       #endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */\r
+\r
+       if( pxClient->pcUrlData[ 0 ] != '/' )\r
+       {\r
+               /* Insert a slash before the file name. */\r
+               pcSlash[ 0 ] = '/';\r
+               pcSlash[ 1 ] = '\0';\r
+       }\r
+       else\r
+       {\r
+               /* The browser provided a starting '/' already. */\r
+               pcSlash[ 0 ] = '\0';\r
+       }\r
+       snprintf( pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ), "%s%s%s",\r
+               pxClient->pcRootDir,\r
+               pcSlash,\r
+               pxClient->pcUrlData);\r
+\r
+       pxClient->pxFileHandle = ff_fopen( pxClient->pcCurrentFilename, "rb" );\r
+\r
+       FreeRTOS_printf( ( "Open file '%s': %s\n", pxClient->pcCurrentFilename,\r
+               pxClient->pxFileHandle != NULL ? "Ok" : strerror( stdioGET_ERRNO() ) ) );\r
+\r
+       if( pxClient->pxFileHandle == NULL )\r
+       {\r
+               /* "404 File not found". */\r
+               xRc = prvSendReply( pxClient, WEB_NOT_FOUND );\r
+       }\r
+       else\r
+       {\r
+               pxClient->uxBytesLeft = ( size_t ) pxClient->pxFileHandle->ulFileSize;\r
+               xRc = prvSendFile( pxClient );\r
+       }\r
+\r
+       return xRc;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static BaseType_t prvProcessCmd( HTTPClient_t *pxClient, BaseType_t xIndex )\r
+{\r
+BaseType_t xResult = 0;\r
+\r
+       /* A new command has been received. Process it. */\r
+       switch( xIndex )\r
+       {\r
+       case ECMD_GET:\r
+               xResult = prvOpenURL( pxClient );\r
+               break;\r
+\r
+       case ECMD_HEAD:\r
+       case ECMD_POST:\r
+       case ECMD_PUT:\r
+       case ECMD_DELETE:\r
+       case ECMD_TRACE:\r
+       case ECMD_OPTIONS:\r
+       case ECMD_CONNECT:\r
+       case ECMD_PATCH:\r
+       case ECMD_UNK:\r
+               {\r
+                       FreeRTOS_printf( ( "prvProcessCmd: Not implemented: %s\n",\r
+                               xWebCommands[xIndex].pcCommandName ) );\r
+               }\r
+               break;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xHTTPClientWork( TCPClient_t *pxTCPClient )\r
+{\r
+BaseType_t xRc;\r
+HTTPClient_t *pxClient = ( HTTPClient_t * ) pxTCPClient;\r
+\r
+       if( pxClient->pxFileHandle != NULL )\r
+       {\r
+               prvSendFile( pxClient );\r
+       }\r
+\r
+       xRc = FreeRTOS_recv( pxClient->xSocket, ( void * )pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), 0 );\r
+\r
+       if( xRc > 0 )\r
+       {\r
+       BaseType_t xIndex;\r
+       const char *pcEndOfCmd;\r
+       const struct xWEB_COMMAND *curCmd;\r
+       char *pcBuffer = pcCOMMAND_BUFFER;\r
+\r
+               if( xRc < ( BaseType_t ) sizeof( pcCOMMAND_BUFFER ) )\r
+               {\r
+                       pcBuffer[ xRc ] = '\0';\r
+               }\r
+               while( xRc && ( pcBuffer[ xRc - 1 ] == 13 || pcBuffer[ xRc - 1 ] == 10 ) )\r
+               {\r
+                       pcBuffer[ --xRc ] = '\0';\r
+               }\r
+               pcEndOfCmd = pcBuffer + xRc;\r
+\r
+               curCmd = xWebCommands;\r
+\r
+               /* Pointing to "/index.html HTTP/1.1". */\r
+               pxClient->pcUrlData = pcBuffer;\r
+\r
+               /* Pointing to "HTTP/1.1". */\r
+               pxClient->pcRestData = pcEmptyString;\r
+\r
+               /* Last entry is "ECMD_UNK". */\r
+               for( xIndex = 0; xIndex < WEB_CMD_COUNT - 1; xIndex++, curCmd++ )\r
+               {\r
+               BaseType_t xLength;\r
+\r
+                       xLength = curCmd->xCommandLength;\r
+                       if( ( xRc >= xLength ) && ( memcmp( curCmd->pcCommandName, pcBuffer, xLength ) == 0 ) )\r
+                       {\r
+                       char *pcLastPtr;\r
+\r
+                               pxClient->pcUrlData += xLength + 1;\r
+                               for( pcLastPtr = (char *)pxClient->pcUrlData; pcLastPtr < pcEndOfCmd; pcLastPtr++ )\r
+                               {\r
+                                       char ch = *pcLastPtr;\r
+                                       if( ( ch == '\0' ) || ( strchr( "\n\r \t", ch ) != NULL ) )\r
+                                       {\r
+                                               *pcLastPtr = '\0';\r
+                                               pxClient->pcRestData = pcLastPtr + 1;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if( xIndex < ( WEB_CMD_COUNT - 1 ) )\r
+               {\r
+                       xRc = prvProcessCmd( pxClient, xIndex );\r
+               }\r
+       }\r
+       else if( xRc < 0 )\r
+       {\r
+               /* The connection will be closed and the client will be deleted. */\r
+               FreeRTOS_printf( ( "xHTTPClientWork: rc = %ld\n", xRc ) );\r
+       }\r
+       return xRc;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static const char *pcGetContentsType (const char *apFname)\r
+{\r
+       const char *slash = NULL;\r
+       const char *dot = NULL;\r
+       const char *ptr;\r
+       const char *pcResult = "text/html";\r
+       BaseType_t x;\r
+\r
+       for( ptr = apFname; *ptr; ptr++ )\r
+       {\r
+               if (*ptr == '.') dot = ptr;\r
+               if (*ptr == '/') slash = ptr;\r
+       }\r
+       if( dot > slash )\r
+       {\r
+               dot++;\r
+               for( x = 0; x < ARRAY_SIZE( pxTypeCouples ); x++ )\r
+               {\r
+                       if( strcasecmp( dot, pxTypeCouples[ x ].pcExtension ) == 0 )\r
+                       {\r
+                               pcResult = pxTypeCouples[ x ].pcType;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       return pcResult;\r
+}\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/NTP/NTPDemo.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/NTP/NTPDemo.c
new file mode 100644 (file)
index 0000000..fb3861f
--- /dev/null
@@ -0,0 +1,472 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*\r
+ * NTPDemo.c\r
+ *\r
+ * An example of how to lookup a domain using DNS\r
+ * And also how to send and receive UDP messages to get the NTP time\r
+ *\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <time.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_DNS.h"\r
+#include "FreeRTOS_Stream_Buffer.h"\r
+\r
+/* Use the date & time functions from +FAT. */\r
+#include "ff_time.h"\r
+\r
+#include "NTPDemo.h"\r
+#include "ntpClient.h"\r
+\r
+#include "date_and_time.h"\r
+\r
+enum EStatus {\r
+       EStatusLookup,\r
+       EStatusAsking,\r
+       EStatusPause,\r
+       EStatusFailed,\r
+};\r
+\r
+static struct SNtpPacket xNTPPacket;\r
+\r
+#if( ipconfigUSE_CALLBACKS == 0 )\r
+       static char cRecvBuffer[ sizeof( struct SNtpPacket ) + 64 ];\r
+#endif\r
+\r
+static enum EStatus xStatus = EStatusLookup;\r
+\r
+static const char *pcTimeServers[] = {\r
+       "0.asia.pool.ntp.org",\r
+       "0.europe.pool.ntp.org",\r
+       "0.id.pool.ntp.org",\r
+       "0.south-america.pool.ntp.org",\r
+       "0.oceania.pool.ntp.org",\r
+       "0.north-america.pool.ntp.org"\r
+};\r
+\r
+static SemaphoreHandle_t xNTPWakeupSem = NULL;\r
+static uint32_t ulIPAddressFound;\r
+static Socket_t xUDPSocket = NULL;\r
+static TaskHandle_t xNTPTaskhandle = NULL;\r
+static TickType_t uxSendTime;\r
+\r
+static void prvNTPTask( void *pvParameters );\r
+\r
+static void vSignalTask( void )\r
+{\r
+       #if( ipconfigUSE_CALLBACKS == 0 )\r
+       if( xUDPSocket != NULL )\r
+       {\r
+               /* Send a signal to the socket so that the\r
+               FreeRTOS_recvfrom will get interrupted. */\r
+               FreeRTOS_SignalSocket( xUDPSocket );\r
+       }\r
+       else\r
+       #endif\r
+       if( xNTPWakeupSem != NULL )\r
+       {\r
+               xSemaphoreGive( xNTPWakeupSem );\r
+       }\r
+}\r
+\r
+void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority )\r
+{\r
+       /* The only public function in this module: start a task to contact\r
+       some NTP server. */\r
+\r
+       if( xNTPTaskhandle != NULL )\r
+       {\r
+               switch( xStatus )\r
+               {\r
+               case EStatusPause:\r
+                       xStatus = EStatusAsking;\r
+                       vSignalTask();\r
+                       break;\r
+               case EStatusLookup:\r
+                       FreeRTOS_printf( ( "NTP looking up server\n" ) );\r
+                       break;\r
+               case EStatusAsking:\r
+                       FreeRTOS_printf( ( "NTP still asking\n" ) );\r
+                       break;\r
+               case EStatusFailed:\r
+                       FreeRTOS_printf( ( "NTP failed somehow\n" ) );\r
+                       ulIPAddressFound = 0ul;\r
+                       xStatus = EStatusLookup;\r
+                       vSignalTask();\r
+                       break;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               xUDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
+               if( xUDPSocket != NULL )\r
+               {\r
+               struct freertos_sockaddr xAddress;\r
+               #if( ipconfigUSE_CALLBACKS != 0 )\r
+                       BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 );\r
+               #else\r
+                       BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 );\r
+               #endif\r
+\r
+                       xAddress.sin_addr = 0ul;\r
+                       xAddress.sin_port = FreeRTOS_htons( NTP_PORT );\r
+\r
+                       FreeRTOS_bind( xUDPSocket, &xAddress, sizeof( xAddress ) );\r
+                       FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );\r
+                       xTaskCreate(    prvNTPTask,                                             /* The function that implements the task. */\r
+                                                       ( const char * ) "NTP client",  /* Just a text name for the task to aid debugging. */\r
+                                                       usTaskStackSize,                                /* The stack size is defined in FreeRTOSIPConfig.h. */\r
+                                                       NULL,                                                   /* The task parameter, not used in this case. */\r
+                                                       uxTaskPriority,                                 /* The priority assigned to the task is defined in FreeRTOSConfig.h. */\r
+                                                       &xNTPTaskhandle );                              /* The task handle. */\r
+               }\r
+               else\r
+               {\r
+                       FreeRTOS_printf( ( "Creating socket failed\n" ) );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void vDNS_callback( const char *pcName, void *pvSearchID, uint32_t ulIPAddress )\r
+{\r
+char pcBuf[16];\r
+\r
+       /* The DNS lookup has a result, or it has reached the time-out. */\r
+       FreeRTOS_inet_ntoa( ulIPAddress, pcBuf );\r
+       FreeRTOS_printf( ( "IP address of %s found: %s\n", pcName, pcBuf ) );\r
+       if( ulIPAddressFound == 0ul )\r
+       {\r
+               ulIPAddressFound = ulIPAddress;\r
+       }\r
+       /* For testing: in case DNS doen't respond, still try some NTP server\r
+       with a known IP-address. */\r
+       if( ulIPAddressFound == 0ul )\r
+       {\r
+               ulIPAddressFound = FreeRTOS_inet_addr_quick( 184, 105, 182, 7 );\r
+/*             ulIPAddressFound = FreeRTOS_inet_addr_quick( 103, 242,  70, 4 );        */\r
+       }\r
+       xStatus = EStatusAsking;\r
+\r
+       vSignalTask();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSwapFields( struct SNtpPacket *pxPacket)\r
+{\r
+       /* NTP messages are big-endian */\r
+       pxPacket->rootDelay = FreeRTOS_htonl( pxPacket->rootDelay );\r
+       pxPacket->rootDispersion = FreeRTOS_htonl( pxPacket->rootDispersion );\r
+\r
+       pxPacket->referenceTimestamp.seconds = FreeRTOS_htonl( pxPacket->referenceTimestamp.seconds );\r
+       pxPacket->referenceTimestamp.fraction = FreeRTOS_htonl( pxPacket->referenceTimestamp.fraction );\r
+\r
+       pxPacket->originateTimestamp.seconds = FreeRTOS_htonl( pxPacket->originateTimestamp.seconds );\r
+       pxPacket->originateTimestamp.fraction = FreeRTOS_htonl( pxPacket->originateTimestamp.fraction );\r
+\r
+       pxPacket->receiveTimestamp.seconds = FreeRTOS_htonl( pxPacket->receiveTimestamp.seconds );\r
+       pxPacket->receiveTimestamp.fraction = FreeRTOS_htonl( pxPacket->receiveTimestamp.fraction );\r
+\r
+       pxPacket->transmitTimestamp.seconds = FreeRTOS_htonl( pxPacket->transmitTimestamp.seconds );\r
+       pxPacket->transmitTimestamp.fraction = FreeRTOS_htonl( pxPacket->transmitTimestamp.fraction );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvNTPPacketInit( )\r
+{\r
+       memset (&xNTPPacket, '\0', sizeof( xNTPPacket ) );\r
+\r
+       xNTPPacket.flags = 0xDB;                                /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */\r
+       xNTPPacket.poll = 10;                                   /* 10 means 1 << 10 = 1024 seconds */\r
+       xNTPPacket.precision = 0xFA;                    /* = 250 = 0.015625 seconds */\r
+       xNTPPacket.rootDelay = 0x5D2E;                  /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */\r
+       xNTPPacket.rootDispersion = 0x0008CAC8; /* 0x0008CAC8 = 8.7912  seconds */\r
+\r
+       /* use the recorded NTP time */\r
+       time_t uxSecs = FreeRTOS_time( NULL );/* apTime may be NULL, returns seconds */\r
+\r
+       xNTPPacket.referenceTimestamp.seconds = uxSecs; /* Current time */\r
+       xNTPPacket.transmitTimestamp.seconds = uxSecs + 3;\r
+\r
+       /* Transform the contents of the fields from native to big endian. */\r
+       prvSwapFields( &xNTPPacket );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvReadTime( struct SNtpPacket * pxPacket )\r
+{\r
+       FF_TimeStruct_t xTimeStruct;\r
+       time_t uxPreviousSeconds;\r
+       time_t uxPreviousMS;\r
+\r
+       time_t uxCurrentSeconds;\r
+       time_t uxCurrentMS;\r
+\r
+       const char *pcTimeUnit;\r
+       int32_t ilDiff;\r
+       TickType_t uxTravelTime;\r
+\r
+       uxTravelTime = xTaskGetTickCount() - uxSendTime;\r
+\r
+       /* Transform the contents of the fields from big to native endian. */\r
+       prvSwapFields( pxPacket );\r
+\r
+       uxCurrentSeconds = pxPacket->receiveTimestamp.seconds - TIME1970;\r
+       uxCurrentMS = pxPacket->receiveTimestamp.fraction / 4294967;\r
+       uxCurrentSeconds += uxCurrentMS / 1000;\r
+       uxCurrentMS = uxCurrentMS % 1000;\r
+\r
+       // Get the last time recorded\r
+       uxPreviousSeconds = FreeRTOS_get_secs_msec( &uxPreviousMS );\r
+\r
+       // Set the new time with precision in msec. */\r
+       FreeRTOS_set_secs_msec( &uxCurrentSeconds, &uxCurrentMS );\r
+\r
+       if( uxCurrentSeconds >= uxPreviousSeconds )\r
+       {\r
+               ilDiff = ( int32_t ) ( uxCurrentSeconds - uxPreviousSeconds );\r
+       }\r
+       else\r
+       {\r
+               ilDiff = 0 - ( int32_t ) ( uxPreviousSeconds - uxCurrentSeconds );\r
+       }\r
+\r
+       if( ( ilDiff < -5 ) || ( ilDiff > 5 ) )\r
+       {\r
+               /* More than 5 seconds difference. */\r
+               pcTimeUnit = "sec";\r
+       }\r
+       else\r
+       {\r
+               /* Less than or equal to 5 second difference. */\r
+               pcTimeUnit = "ms";\r
+               uint32_t ulLowest = ( uxCurrentSeconds <= uxPreviousSeconds ) ? uxCurrentSeconds : uxPreviousSeconds;\r
+               int32_t iCurMS = 1000 * ( uxCurrentSeconds - ulLowest ) + uxCurrentMS;\r
+               int32_t iPrevMS = 1000 * ( uxPreviousSeconds - ulLowest ) + uxPreviousMS;\r
+               ilDiff = iCurMS - iPrevMS;\r
+       }\r
+       uxCurrentSeconds -= iTimeZone;\r
+\r
+       FreeRTOS_gmtime_r( &uxCurrentSeconds, &xTimeStruct );\r
+\r
+       /*\r
+               378.067 [NTP client] NTP time: 9/11/2015 16:11:19.559 Diff -20 ms (289 ms)\r
+               379.441 [NTP client] NTP time: 9/11/2015 16:11:20.933 Diff 0 ms (263 ms)\r
+       */\r
+\r
+       FreeRTOS_printf( ("NTP time: %d/%d/%02d %2d:%02d:%02d.%03u Diff %d %s (%lu ms)\n",\r
+               xTimeStruct.tm_mday,\r
+               xTimeStruct.tm_mon + 1,\r
+               xTimeStruct.tm_year + 1900,\r
+               xTimeStruct.tm_hour,\r
+               xTimeStruct.tm_min,\r
+               xTimeStruct.tm_sec,\r
+               ( unsigned )uxCurrentMS,\r
+               ( unsigned )ilDiff,\r
+               pcTimeUnit,\r
+               uxTravelTime ) );\r
+\r
+       /* Remove compiler warnings in case FreeRTOS_printf() is not used. */\r
+       ( void ) pcTimeUnit;\r
+       ( void ) uxTravelTime;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigUSE_CALLBACKS != 0 )\r
+\r
+       static BaseType_t xOnUDPReceive( Socket_t xSocket, void * pvData, size_t xLength,\r
+               const struct freertos_sockaddr *pxFrom, const struct freertos_sockaddr *pxDest )\r
+       {\r
+               if( xLength >= sizeof( xNTPPacket ) )\r
+               {\r
+                       prvReadTime( ( struct SNtpPacket *)pvData );\r
+                       if( xStatus != EStatusPause )\r
+                       {\r
+                               xStatus = EStatusPause;\r
+                       }\r
+               }\r
+               vSignalTask();\r
+               /* Tell the driver not to store the RX data */\r
+               return 1;\r
+       }\r
+       /*-----------------------------------------------------------*/\r
+\r
+#endif /* ipconfigUSE_CALLBACKS != 0 */\r
+\r
+static void prvNTPTask( void *pvParameters )\r
+{\r
+BaseType_t xServerIndex = 3;\r
+struct freertos_sockaddr xAddress;\r
+#if( ipconfigUSE_CALLBACKS != 0 )\r
+       F_TCP_UDP_Handler_t xHandler;\r
+#endif /* ipconfigUSE_CALLBACKS != 0 */\r
+\r
+       xStatus = EStatusLookup;\r
+       #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) || ( ipconfigUSE_CALLBACKS != 0 )\r
+       {\r
+               xNTPWakeupSem = xSemaphoreCreateBinary();\r
+       }\r
+       #endif\r
+\r
+       #if( ipconfigUSE_CALLBACKS != 0 )\r
+       {\r
+               memset( &xHandler, '\0', sizeof( xHandler ) );\r
+               xHandler.pxOnUDPReceive = xOnUDPReceive;\r
+               FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) );\r
+       }\r
+       #endif\r
+       #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )\r
+       {\r
+               FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_SET_SEMAPHORE, ( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) );\r
+       }\r
+       #endif\r
+       for( ; ; )\r
+       {\r
+               switch( xStatus )\r
+               {\r
+               case EStatusLookup:\r
+                       if( ( ulIPAddressFound == 0ul ) || ( ulIPAddressFound == ~0ul ) )\r
+                       {\r
+                               if( ++xServerIndex == sizeof( pcTimeServers ) / sizeof( pcTimeServers[ 0 ] ) )\r
+                               {\r
+                                       xServerIndex = 0;\r
+                               }\r
+                               FreeRTOS_printf( ( "Looking up server '%s'\n", pcTimeServers[ xServerIndex ] ) );\r
+                               FreeRTOS_gethostbyname_a( pcTimeServers[ xServerIndex ], vDNS_callback, (void *)NULL, 1200 );\r
+                       }\r
+                       else\r
+                       {\r
+                               xStatus = EStatusAsking;\r
+                       }\r
+                       break;\r
+\r
+               case EStatusAsking:\r
+                       {\r
+                       char pcBuf[16];\r
+\r
+                               prvNTPPacketInit( );\r
+                               xAddress.sin_addr = ulIPAddressFound;\r
+                               xAddress.sin_port = FreeRTOS_htons( NTP_PORT );\r
+\r
+                               FreeRTOS_inet_ntoa( xAddress.sin_addr, pcBuf );\r
+                               FreeRTOS_printf( ( "Sending UDP message to %s:%u\n",\r
+                                       pcBuf,\r
+                                       FreeRTOS_ntohs( xAddress.sin_port ) ) );\r
+\r
+                               uxSendTime = xTaskGetTickCount( );\r
+                               FreeRTOS_sendto( xUDPSocket, ( void * )&xNTPPacket, sizeof( xNTPPacket ), 0, &xAddress, sizeof( xAddress ) );\r
+                       }\r
+                       break;\r
+\r
+               case EStatusPause:\r
+                       break;\r
+\r
+               case EStatusFailed:\r
+                       break;\r
+               }\r
+\r
+               #if( ipconfigUSE_CALLBACKS != 0 )\r
+               {\r
+                       xSemaphoreTake( xNTPWakeupSem, 5000 );\r
+               }\r
+               #else\r
+               {\r
+               uint32_t xAddressSize;\r
+               BaseType_t xReturned;\r
+\r
+                       xAddressSize = sizeof( xAddress );\r
+                       xReturned = FreeRTOS_recvfrom( xUDPSocket, ( void * ) cRecvBuffer, sizeof( cRecvBuffer ), 0, &xAddress, &xAddressSize );\r
+                       switch( xReturned )\r
+                       {\r
+                       case 0:\r
+                       case -pdFREERTOS_ERRNO_EAGAIN:\r
+                       case -pdFREERTOS_ERRNO_EINTR:\r
+                               break;\r
+                       default:\r
+                               if( xReturned < sizeof( xNTPPacket ) )\r
+                               {\r
+                                       FreeRTOS_printf( ( "FreeRTOS_recvfrom: returns %ld\n", xReturned ) );\r
+                               }\r
+                               else\r
+                               {\r
+                                       prvReadTime( ( struct SNtpPacket *)cRecvBuffer );\r
+                                       if( xStatus != EStatusPause )\r
+                                       {\r
+                                               xStatus = EStatusPause;\r
+                                       }\r
+                               }\r
+                               break;\r
+                       }\r
+               }\r
+               #endif\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_FTP_commands.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_FTP_commands.h
new file mode 100644 (file)
index 0000000..f11675f
--- /dev/null
@@ -0,0 +1,165 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+#ifndef        __FTPCMD_H__\r
+\r
+#define        __FTPCMD_H__\r
+\r
+#define REPL_110 "110 Restart marker reply.\r\n"\r
+#define REPL_120 "120 Try again in 2 minutes.\r\n"\r
+#define REPL_125 "125 Data connection already open; transfer starting.\r\n"\r
+#define REPL_150 "150 File status okay; about to open data connection.\r\n"\r
+#define REPL_200 "200 NOOP command successful.\r\n"\r
+#define REPL_200_PROGRESS "200 NOOP: data transfer in progress.\r\n"\r
+#define REPL_202 "202 Command not implemented, superfluous at this site.\r\n"\r
+#define REPL_211 "221 System status, or system help reply.\r\n"\r
+#define REPL_211_STATUS "221-status of %s.\r\n"\r
+#define REPL_211_END "221 End of status.\r\n"\r
+#define REPL_212 "212 Directory status.\r\n"\r
+#define REPL_213 "213 File status.\r\n"\r
+#define REPL_214 "214 Help message.\r\n"\r
+#define REPL_214_END "214 End Help message.\r\n"\r
+#define REPL_215 "215 %s system type.\r\n"\r
+#define REPL_220 "220 Service ready for new user.\r\n"\r
+#define REPL_221 "221 Service closing control connection.\r\n"\r
+#define REPL_225 "225 Data connection open; no transfer in progress.\r\n"\r
+#define REPL_226 "226 Closing data connection.\r\n"\r
+#define REPL_227 "227 Entering Passive Mode (%s,%s,%s,%s,%s,%s).\r\n"\r
+#define REPL_227_D "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n"\r
+#define REPL_230 "230 User logged in, proceed.\r\n"\r
+#define REPL_250 "250 Requested file action okay, completed.\r\n"\r
+#define REPL_257 "257 %s created.\r\n"\r
+//     #define REPL_257_PWD "257 \"%s\" is current working dir.\r\n"\r
+#define REPL_257_PWD "257 \"%s\"\r\n"\r
+#define REPL_331 "331 Only anonymous user is accepted.\r\n"\r
+#define REPL_331_ANON "331 Anonymous login okay\r\n"\r
+#define REPL_332 "332 Need account for login.\r\n"\r
+#define REPL_350 "350 Requested file action pending further information.\r\n"\r
+#define REPL_421 "421 Service not available, closing control connection.\r\n"\r
+#define REPL_425 "425 Can't open data connection.\r\n"\r
+#define REPL_426 "426 Connection closed; transfer aborted.\r\n"\r
+#define REPL_450 "450 Requested file action not taken.\r\n"\r
+#define REPL_451 "451 Requested action aborted. Local error in processing.\r\n"\r
+#define REPL_452 "452 Requested action not taken.\r\n"\r
+#define REPL_500 "500 Syntax error, command unrecognized.\r\n"\r
+#define REPL_501 "501 Syntax error in parameters or arguments.\r\n"\r
+#define REPL_502 "502 Command not implemented.\r\n"\r
+#define REPL_503 "503 Bad sequence of commands.\r\n"\r
+#define REPL_504 "504 Command not implemented for that parameter.\r\n"\r
+#define REPL_530 "530 Not logged in.\r\n"\r
+#define REPL_532 "532 Need account for storing files.\r\n"\r
+#define REPL_550 "550 Requested action not taken.\r\n"\r
+#define REPL_551 "551 Requested action aborted. Page type unknown.\r\n"\r
+#define REPL_552 "552 Requested file action aborted.\r\n"\r
+#define REPL_553 "553 Requested action not taken.\r\n"\r
+#define REPL_553_READ_ONLY "553 Read-only file-system.\r\n"\r
+\r
+enum EFTPCommand {\r
+       ECMD_USER,\r
+       ECMD_PASS,\r
+       ECMD_ACCT,\r
+       ECMD_CWD,\r
+       ECMD_CDUP,\r
+       ECMD_SMNT,\r
+       ECMD_QUIT,\r
+       ECMD_REIN,\r
+       ECMD_PORT,\r
+       ECMD_PASV,\r
+       ECMD_TYPE,\r
+       ECMD_STRU,\r
+       ECMD_MODE,\r
+       ECMD_RETR,\r
+       ECMD_STOR,\r
+       ECMD_STOU,\r
+       ECMD_APPE,\r
+       ECMD_ALLO,\r
+       ECMD_REST,\r
+       ECMD_RNFR,\r
+       ECMD_RNTO,\r
+       ECMD_ABOR,\r
+       ECMD_SIZE,\r
+       ECMD_MDTM,\r
+       ECMD_DELE,\r
+       ECMD_RMD,\r
+       ECMD_MKD,\r
+       ECMD_PWD,\r
+       ECMD_LIST,\r
+       ECMD_NLST,\r
+       ECMD_SITE,\r
+       ECMD_SYST,\r
+       ECMD_FEAT,\r
+       ECMD_STAT,\r
+       ECMD_HELP,\r
+       ECMD_NOOP,\r
+       ECMD_EMPTY,\r
+       ECMD_CLOSE,\r
+       ECMD_UNKNOWN,\r
+};\r
+\r
+typedef struct xFTP_COMMAND {\r
+       BaseType_t xCommandLength;\r
+       const char pcCommandName[7];\r
+       const unsigned char ucCommandType;\r
+       const unsigned char checkLogin;\r
+       const unsigned char checkNullArg;\r
+} FTPCommand_t;\r
+\r
+#define        FTP_CMD_COUNT   (ECMD_UNKNOWN+1)\r
+\r
+extern const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ];\r
+\r
+#endif // __FTPCMD_H__\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_HTTP_commands.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_HTTP_commands.h
new file mode 100644 (file)
index 0000000..e8f6567
--- /dev/null
@@ -0,0 +1,99 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+#ifndef FREERTOS_HTTP_COMMANDS_H\r
+#define        FREERTOS_HTTP_COMMANDS_H\r
+\r
+enum {\r
+       WEB_REPLY_OK = 200,\r
+       WEB_NO_CONTENT = 204,\r
+       WEB_BAD_REQUEST = 400,\r
+       WEB_UNAUTHORIZED = 401,\r
+       WEB_NOT_FOUND = 404,\r
+       WEB_GONE = 410,\r
+       WEB_PRECONDITION_FAILED = 412,\r
+       WEB_INTERNAL_SERVER_ERROR = 500,\r
+};\r
+\r
+enum EWebCommand {\r
+       ECMD_GET,\r
+       ECMD_HEAD,\r
+       ECMD_POST,\r
+       ECMD_PUT,\r
+       ECMD_DELETE,\r
+       ECMD_TRACE,\r
+       ECMD_OPTIONS,\r
+       ECMD_CONNECT,\r
+       ECMD_PATCH,\r
+       ECMD_UNK,\r
+};\r
+\r
+struct xWEB_COMMAND\r
+{\r
+       BaseType_t xCommandLength;\r
+       const char *pcCommandName;\r
+       const unsigned char ucCommandType;\r
+};\r
+\r
+#define        WEB_CMD_COUNT   (ECMD_UNK+1)\r
+\r
+extern const struct xWEB_COMMAND xWebCommands[WEB_CMD_COUNT];\r
+\r
+extern const char *webCodename (int aCode);\r
+\r
+#endif /* FREERTOS_HTTP_COMMANDS_H */\r
+\r
+\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_TCP_server.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_TCP_server.h
new file mode 100644 (file)
index 0000000..13a7f75
--- /dev/null
@@ -0,0 +1,157 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+/*\r
+       Some code which is common to TCP servers like HTTP en FTP\r
+*/\r
+\r
+#ifndef FREERTOS_TCP_SERVER_H\r
+#define        FREERTOS_TCP_SERVER_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+#ifndef        FTP_SERVER_USES_RELATIVE_DIRECTORY\r
+       #define FTP_SERVER_USES_RELATIVE_DIRECTORY              0\r
+#endif\r
+\r
+enum eSERVER_TYPE\r
+{\r
+       eSERVER_NONE,\r
+       eSERVER_HTTP,\r
+       eSERVER_FTP,\r
+};\r
+\r
+struct xFTP_CLIENT;\r
+\r
+#if( ipconfigFTP_HAS_RECEIVED_HOOK != 0 )\r
+       extern void vApplicationFTPReceivedHook( const char *pcFileName, uint32_t ulSize, struct xFTP_CLIENT *pxFTPClient );\r
+       extern void vFTPReplyMessage( struct xFTP_CLIENT *pxFTPClient, const char *pcMessage );\r
+#endif /* ipconfigFTP_HAS_RECEIVED_HOOK != 0 */\r
+\r
+#if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )\r
+       /*\r
+        * Function is called when a user name has been submitted.\r
+        * The function may return a string such as: "331 Please enter your password"\r
+        * or return NULL to use the default reply.\r
+        */\r
+       extern const char *pcApplicationFTPUserHook( const char *pcUserName );\r
+#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */\r
+\r
+#if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )\r
+       /*\r
+        * Function is called when a password was received.\r
+        * Return positive value to allow the user\r
+        */\r
+       extern BaseType_t xApplicationFTPPasswordHook( const char *pcUserName, const char *pcPassword );\r
+#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */\r
+\r
+#if( ipconfigFTP_HAS_USER_PROPERTIES_HOOK != 0 )\r
+       /*\r
+        * The FTP server is asking for user-specific properties\r
+        */\r
+       typedef struct\r
+       {\r
+               uint16_t usPortNumber;  /* For reference only. Host-endian. */\r
+               const char *pcRootDir;\r
+               BaseType_t xReadOnly;\r
+       }\r
+       FTPUserProperties_t;\r
+       extern void vApplicationFTPUserPropertiesHook( const char *pcUserName, FTPUserProperties_t *pxProperties );\r
+#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */\r
+\r
+#if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 )\r
+       /*\r
+        * A GET request is received containing a special character,\r
+        * usually a question mark.\r
+        * const char *pcURLData;       // A request, e.g. "/request?limit=75"\r
+        * char *pcBuffer;                      // Here the answer can be written\r
+        * size_t uxBufferLength;       // Size of the buffer\r
+        *\r
+        */\r
+       extern size_t uxApplicationHTTPHandleRequestHook( const char *pcURLData, char *pcBuffer, size_t uxBufferLength );\r
+#endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */\r
+\r
+struct xSERVER_CONFIG\r
+{\r
+       enum eSERVER_TYPE eType;                /* eSERVER_HTTP | eSERVER_FTP */\r
+       BaseType_t xPortNumber;                 /* e.g. 80, 8080, 21 */\r
+       BaseType_t xBackLog;                    /* e.g. 10, maximum number of connected TCP clients */\r
+       const char * const pcRootDir;   /* Treat this directory as the root directory */\r
+};\r
+\r
+struct xTCP_SERVER;\r
+typedef struct xTCP_SERVER TCPServer_t;\r
+\r
+TCPServer_t *FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG *pxConfigs, BaseType_t xCount );\r
+void FreeRTOS_TCPServerWork( TCPServer_t *pxServer, TickType_t xBlockingTime );\r
+\r
+#if( ipconfigSUPPORT_SIGNALS != 0 )\r
+       /* FreeRTOS_TCPServerWork() calls select().\r
+       The two functions below provide a possibility to interrupt\r
+       the call to select(). After the interruption, resume\r
+       by calling FreeRTOS_TCPServerWork() again. */\r
+       BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t *pxServer );\r
+       BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t *pxServer, BaseType_t *pxHigherPriorityTaskWoken );\r
+#endif\r
+\r
+#ifdef __cplusplus\r
+} /* extern "C" */\r
+#endif\r
+\r
+#endif /* FREERTOS_TCP_SERVER_H */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_server_private.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/FreeRTOS_server_private.h
new file mode 100644 (file)
index 0000000..355aded
--- /dev/null
@@ -0,0 +1,217 @@
+/*\r
+ * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
+ * Authors include Hein Tibosch and Richard Barry\r
+ *\r
+ *******************************************************************************\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
+ ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
+ ***   download):                                                            ***\r
+ ***                                                                         ***\r
+ ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
+ ***   for some time.  Be aware however that we are still refining its       ***\r
+ ***   design, the source code does not yet quite conform to the strict      ***\r
+ ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
+ ***   the documentation and testing is not necessarily complete.            ***\r
+ ***                                                                         ***\r
+ ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
+ ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
+ ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
+ ***   under a license other than that described below.                      ***\r
+ ***                                                                         ***\r
+ ***                                                                         ***\r
+ ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
+ *******************************************************************************\r
+ *\r
+ * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
+ * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
+ * executed, as follows:\r
+ *\r
+ * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
+ * License Arrangements heading of the FreeRTOS+TCP license information web\r
+ * page, then it can be used under the terms of the FreeRTOS Open Source\r
+ * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
+ * under the terms of the GNU General Public License V2.  Links to the relevant\r
+ * licenses follow:\r
+ *\r
+ * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
+ * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
+ * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
+ *\r
+ * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
+ * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
+ * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
+ * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+ * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
+ * implied, expressed, or statutory.\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://www.FreeRTOS.org/plus\r
+ * http://www.FreeRTOS.org/labs\r
+ *\r
+ */\r
+\r
+ /*\r
+       Some code which is common to TCP servers like HTTP and FTP\r
+*/\r
+\r
+#ifndef FREERTOS_SERVER_PRIVATE_H\r
+#define        FREERTOS_SERVER_PRIVATE_H\r
+\r
+#define FREERTOS_NO_SOCKET             NULL\r
+\r
+/* FreeRTOS+FAT */\r
+#include "ff_stdio.h"\r
+\r
+/* Each HTTP server has 1, at most 2 sockets */\r
+#define        HTTP_SOCKET_COUNT       2\r
+\r
+/*\r
+ * ipconfigTCP_COMMAND_BUFFER_SIZE sets the size of:\r
+ *     pcCommandBuffer': a buffer to receive and send TCP commands\r
+ *\r
+ * ipconfigTCP_FILE_BUFFER_SIZE sets the size of:\r
+ *     pcFileBuffer'   : a buffer to access the file system: read or write data.\r
+ *\r
+ * The buffers are both used for FTP as well as HTTP.\r
+ */\r
+\r
+#ifndef ipconfigTCP_COMMAND_BUFFER_SIZE\r
+       #define ipconfigTCP_COMMAND_BUFFER_SIZE ( 2048 )\r
+#endif\r
+\r
+#ifndef ipconfigTCP_FILE_BUFFER_SIZE\r
+       #define ipconfigTCP_FILE_BUFFER_SIZE    ( 2048 )\r
+#endif\r
+\r
+struct xTCP_CLIENT;\r
+\r
+typedef BaseType_t ( * FTCPWorkFunction ) ( struct xTCP_CLIENT * /* pxClient */ );\r
+typedef void ( * FTCPDeleteFunction ) ( struct xTCP_CLIENT * /* pxClient */ );\r
+\r
+#define        TCP_CLIENT_FIELDS \\r
+       enum eSERVER_TYPE eType; \\r
+       struct xTCP_SERVER *pxParent; \\r
+       Socket_t xSocket; \\r
+       const char *pcRootDir; \\r
+       FTCPWorkFunction fWorkFunction; \\r
+       FTCPDeleteFunction fDeleteFunction; \\r
+       struct xTCP_CLIENT *pxNextClient\r
+\r
+typedef struct xTCP_CLIENT\r
+{\r
+       /* This define contains fields which must come first within each of the client structs */\r
+       TCP_CLIENT_FIELDS;\r
+       /* --- Keep at the top  --- */\r
+\r
+} TCPClient_t;\r
+\r
+struct xHTTP_CLIENT\r
+{\r
+       /* This define contains fields which must come first within each of the client structs */\r
+       TCP_CLIENT_FIELDS;\r
+       /* --- Keep at the top  --- */\r
+\r
+       const char *pcUrlData;\r
+       const char *pcRestData;\r
+       char pcCurrentFilename[ ffconfigMAX_FILENAME ];\r
+       size_t uxBytesLeft;\r
+       FF_FILE *pxFileHandle;\r
+       union {\r
+               struct {\r
+                       uint32_t\r
+                               bReplySent : 1;\r
+               };\r
+               uint32_t ulFlags;\r
+       } bits;\r
+};\r
+\r
+typedef struct xHTTP_CLIENT HTTPClient_t;\r
+\r
+struct xFTP_CLIENT\r
+{\r
+       /* This define contains fields which must come first within each of the client structs */\r
+       TCP_CLIENT_FIELDS;\r
+       /* --- Keep at the top  --- */\r
+\r
+       uint32_t ulRestartOffset;\r
+       uint32_t ulRecvBytes;\r
+       size_t uxBytesLeft;     /* Bytes left to send */\r
+       uint32_t ulClientIP;\r
+       TickType_t xStartTime;\r
+       uint16_t usClientPort;\r
+       Socket_t xTransferSocket;\r
+       BaseType_t xTransType;\r
+       BaseType_t xDirCount;\r
+       FF_FindData_t xFindData;\r
+       FF_FILE *pxReadHandle;\r
+       FF_FILE *pxWriteHandle;\r
+       char pcCurrentDir[ ffconfigMAX_FILENAME ];\r
+       char pcFileName[ ffconfigMAX_FILENAME ];\r
+       char pcConnectionAck[ 128 ];\r
+       char pcClientAck[ 128 ];\r
+       union {\r
+               struct {\r
+                       uint32_t\r
+                               bHelloSent : 1,\r
+                               bLoggedIn : 1,\r
+                               bStatusUser : 1,\r
+                               bInRename : 1,\r
+                               bReadOnly : 1;\r
+               };\r
+               uint32_t ulFTPFlags;\r
+       } bits;\r
+       union {\r
+               struct {\r
+                       uint32_t\r
+                               bIsListen : 1,                  /* pdTRUE for passive data connections (using list()). */\r
+                               bDirHasEntry : 1,               /* pdTRUE if ff_findfirst() was successful. */\r
+                               bClientConnected : 1,   /* pdTRUE after connect() or accept() has succeeded. */\r
+                               bEmptyFile : 1,                 /* pdTRUE if a connection-without-data was received. */\r
+                               bHadError : 1;                  /* pdTRUE if a transfer got aborted because of an error. */\r
+               };\r
+               uint32_t ulConnFlags;\r
+       } bits1;\r
+};\r
+\r
+typedef struct xFTP_CLIENT FTPClient_t;\r
+\r
+BaseType_t xHTTPClientWork( TCPClient_t *pxClient );\r
+BaseType_t xFTPClientWork( TCPClient_t *pxClient );\r
+\r
+void vHTTPClientDelete( TCPClient_t *pxClient );\r
+void vFTPClientDelete( TCPClient_t *pxClient );\r
+\r
+BaseType_t xMakeAbsolute( struct xFTP_CLIENT *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName );\r
+BaseType_t xMakeRelative( FTPClient_t *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName );\r
+\r
+struct xTCP_SERVER\r
+{\r
+       SocketSet_t xSocketSet;\r
+       /* A buffer to receive and send TCP commands, either HTTP of FTP. */\r
+       char pcCommandBuffer[ ipconfigTCP_COMMAND_BUFFER_SIZE ];\r
+       /* A buffer to access the file system: read or write data. */\r
+       char pcFileBuffer[ ipconfigTCP_FILE_BUFFER_SIZE ];\r
+\r
+       #if( ipconfigUSE_FTP != 0 )\r
+               char pcNewDir[ ffconfigMAX_FILENAME ];\r
+       #endif\r
+       #if( ipconfigUSE_HTTP != 0 )\r
+               char pcContentsType[40];        /* Space for the msg: "text/javascript" */\r
+               char pcExtraContents[40];       /* Space for the msg: "Content-Length: 346500" */\r
+       #endif\r
+       BaseType_t xServerCount;\r
+       TCPClient_t *pxClients;\r
+       struct xSERVER\r
+       {\r
+               enum eSERVER_TYPE eType;                /* eSERVER_HTTP | eSERVER_FTP */\r
+               const char *pcRootDir;\r
+               Socket_t xSocket;\r
+       } xServers[ 1 ];\r
+};\r
+\r
+#endif /* FREERTOS_SERVER_PRIVATE_H */\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/NTPClient.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/NTPClient.h
new file mode 100644 (file)
index 0000000..813539e
--- /dev/null
@@ -0,0 +1,71 @@
+//\r
+//     ntpClient.h\r
+//\r
+\r
+#ifndef        __NTPCLIENT_H__\r
+\r
+#define __NTPCLIENT_H__\r
+\r
+#define NTP_PORT       123\r
+\r
+typedef uint32_t quint32;\r
+typedef int32_t qint32;\r
+typedef uint8_t quint8;\r
+typedef int8_t qint8;\r
+\r
+typedef union _SNtpFlags  SNtpFlags;\r
+\r
+/**\r
+ * 64-bit NTP timestamp.\r
+ */\r
+struct __attribute__ ((__packed__)) _SNtpTimestamp {\r
+  /** Number of seconds passed since Jan 1 1900, in big-endian format. */\r
+  quint32 seconds;\r
+\r
+  /** Fractional time part, in <tt>1/0xFFFFFFFF</tt>s of a second. */\r
+  quint32 fraction;\r
+};\r
+\r
+typedef struct _SNtpTimestamp SNtpTimestamp;\r
+/**\r
+ * Mandatory part of an NTP packet\r
+ */\r
+struct SNtpPacket {\r
+  /** Flags. */\r
+  unsigned char flags;  // value 0xDB : mode 3 (client), version 3, leap indicator unknown 3\r
+\r
+  /** Stratum of the clock. */\r
+  quint8 stratum;  // value 0 : unspecified\r
+\r
+  /** Maximum interval between successive messages, in log2 seconds. Note that the value is signed. */\r
+  qint8 poll;  // 10 means 1 << 10 = 1024 seconds\r
+\r
+  /** Precision of the clock, in log2 seconds. Note that the value is signed. */\r
+  qint8 precision; // 0xFA = 250 = 0.015625 seconds\r
+\r
+  /** Round trip time to the primary reference source, in NTP short format. */\r
+  qint32 rootDelay; // 0x5D2E = 23854 or (23854/65535)= 0.3640 sec\r
+\r
+  /** Nominal error relative to the primary reference source. */\r
+  qint32 rootDispersion; // 0x0008 CAC8 = 8.7912  seconds\r
+\r
+  /** Reference identifier (either a 4 character string or an IP address). */\r
+  qint8 referenceID[4]; // or just 0000\r
+\r
+  /** The time at which the clock was last set or corrected. */\r
+  SNtpTimestamp referenceTimestamp; // Current time\r
+\r
+  /** The time at which the request departed the client for the server. */\r
+  SNtpTimestamp originateTimestamp; // Keep 0\r
+\r
+  /** The time at which the request arrived at the server. */\r
+  SNtpTimestamp receiveTimestamp; // Keep 0\r
+\r
+  /** The time at which the reply departed the server for client. */\r
+  SNtpTimestamp transmitTimestamp;\r
+};\r
+\r
+/* Add this number to get secs since 1-1-1900 */\r
+#define TIME1970 2208988800UL\r
+\r
+#endif // __NTPCLIENT_H__\r
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/NTPDemo.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/protocols/include/NTPDemo.h
new file mode 100644 (file)
index 0000000..e75fb76
--- /dev/null
@@ -0,0 +1,11 @@
+/*\r
+ * A simple demo for NTP using FreeRTOS+TCP\r
+ */\r
+\r
+#ifndef NTPDEMO_H\r
+\r
+#define NTPDEMO_H\r
+\r
+void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority );\r
+\r
+#endif
\ No newline at end of file
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/readme.txt b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/readme.txt
new file mode 100644 (file)
index 0000000..a90fb9e
--- /dev/null
@@ -0,0 +1,18 @@
+Contains the files that implement FreeRTOS+TCP.\r
+\r
+User documentation, including an API reference is available on:\r
+http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/\r
+\r
+A description of the source code organisation is available on:\r
+http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_Networking_Tutorial.html\r
+\r
+The porting guide is available on:\r
+http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/FreeRTOS_TCP_Porting.html\r
+\r
+License information is available on:\r
+http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/FreeRTOS_Plus_TCP_License.html\r
+\r
+At this time it is recommended to use BufferAllocation_2.c in which case it is\r
+essential to use the heap_4.c memory allocation scheme:\r
+http://www.FreeRTOS.org/a00111.html\r
+\r