--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+\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
--- /dev/null
+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
--- /dev/null
+[{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
--- /dev/null
+<?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
--- /dev/null
+<?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
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*\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
--- /dev/null
+/*-
+ * 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>
--- /dev/null
+/*
+ * 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>
--- /dev/null
+/*\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
--- /dev/null
+/*
+ * 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>
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*-
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/* -*- 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
--- /dev/null
+/*-
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*-
+ * 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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
<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
<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="&Heap:Default;Post Data;Default&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><?xml version="1.0" encoding="UTF-8"?> \r
<TargetConfig> \r
-<Properties property_0="" property_2="LPC1850A_4350A_SPIFI.cfx" property_3="NXP" property_4="LPC1830" property_count="5" version="70200"/> \r
+<Properties property_2="LPC1850A_4350A_SPIFI.cfx" property_3="NXP" property_4="LPC1830" property_count="5" version="70200"/> \r
<infoList vendor="NXP"><info chip="LPC1830" match_id="0x0" name="LPC1830" resetscript="LPC18LPC43ExternalFLASHBootResetscript.scp" stub="crt_emu_lpc18_43_nxp"><chip><name>LPC1830</name> \r
<family>LPC18xx</family> \r
<vendor>NXP (formerly Philips)</vendor> \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
\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
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
\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
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
\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
#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
-/*******************************************************************************\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
--- /dev/null
+/*******************************************************************************\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+[{000214A0-0000-0000-C000-000000000046}]\r
+Prop3=19,2\r
+[InternetShortcut]\r
+URL=http://www.freertos.org/tcp\r
+IDList=\r
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/**\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
--- /dev/null
+ /**\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
--- /dev/null
+/**\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
--- /dev/null
+ /**\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
--- /dev/null
+ /**\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
--- /dev/null
+ /**\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+#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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+//\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
--- /dev/null
+/*\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
--- /dev/null
+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