--- /dev/null
+// Copyright 2018 Espressif Systems (Shanghai) PTE LTD\r
+//\r
+// Licensed under the Apache License, Version 2.0 (the "License");\r
+// you may not use this file except in compliance with the License.\r
+// You may obtain a copy of the License at\r
+//\r
+// http://www.apache.org/licenses/LICENSE-2.0\r
+//\r
+// Unless required by applicable law or agreed to in writing, software\r
+// distributed under the License is distributed on an "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+// See the License for the specific language governing permissions and\r
+// limitations under the License.\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
+#include "esp_log.h"\r
+#include "esp_wifi.h"\r
+#include "esp_wifi_internal.h"\r
+#include "tcpip_adapter.h"\r
+\r
+enum if_state_t {\r
+ INTERFACE_DOWN = 0,\r
+ INTERFACE_UP,\r
+};\r
+\r
+static const char *TAG = "NetInterface";\r
+volatile static uint32_t xInterfaceState = INTERFACE_DOWN;\r
+\r
+#if ( ipconfigHAS_PRINTF != 0 )\r
+ static void prvMonitorResources();\r
+#endif\r
+\r
+BaseType_t xNetworkInterfaceInitialise( void )\r
+{\r
+ static BaseType_t xMACAdrInitialized = pdFALSE;\r
+ uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ];\r
+\r
+ if (xInterfaceState == INTERFACE_UP) {\r
+ if (xMACAdrInitialized == pdFALSE) {\r
+ esp_wifi_get_mac(ESP_IF_WIFI_STA, ucMACAddress);\r
+ FreeRTOS_UpdateMACAddress(ucMACAddress);\r
+ xMACAdrInitialized = pdTRUE;\r
+ }\r
+ return pdTRUE;\r
+ }\r
+ return pdFALSE;\r
+}\r
+\r
+BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend )\r
+{\r
+ if (pxNetworkBuffer == NULL || pxNetworkBuffer->pucEthernetBuffer == NULL || pxNetworkBuffer->xDataLength == 0) {\r
+ ESP_LOGE(TAG, "Invalid params");\r
+ return pdFALSE;\r
+ }\r
+\r
+ esp_err_t ret;\r
+ if (xInterfaceState == INTERFACE_DOWN) {\r
+ ESP_LOGD(TAG, "Interface down");\r
+ ret = ESP_FAIL;\r
+ } else {\r
+ ret = esp_wifi_internal_tx(ESP_IF_WIFI_STA, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength);\r
+ if (ret != ESP_OK) {\r
+ ESP_LOGE(TAG, "Failed to tx buffer %p, len %d, err %d", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret);\r
+ }\r
+ }\r
+\r
+#if ( ipconfigHAS_PRINTF != 0 )\r
+ prvMonitorResources();\r
+#endif\r
+ if (xReleaseAfterSend == pdTRUE) {\r
+ vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);\r
+ }\r
+\r
+ return ret == ESP_OK ? pdTRUE : pdFALSE;\r
+}\r
+\r
+void vNetworkNotifyIFDown()\r
+{\r
+ IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };\r
+ if (xInterfaceState != INTERFACE_DOWN) {\r
+ xInterfaceState = INTERFACE_DOWN;\r
+ xSendEventStructToIPTask( &xRxEvent, 0 );\r
+ }\r
+}\r
+\r
+void vNetworkNotifyIFUp()\r
+{\r
+ xInterfaceState = INTERFACE_UP;\r
+}\r
+\r
+esp_err_t wlanif_input(void *netif, void *buffer, uint16_t len, void *eb)\r
+{\r
+ NetworkBufferDescriptor_t *pxNetworkBuffer;\r
+ IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };\r
+ const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );\r
+\r
+#if ( ipconfigHAS_PRINTF != 0 )\r
+ prvMonitorResources();\r
+#endif\r
+\r
+ if( eConsiderFrameForProcessing( buffer ) != eProcessBuffer ) {\r
+ ESP_LOGD(TAG, "Dropping packet");\r
+ esp_wifi_internal_free_rx_buffer(eb);\r
+ return ESP_OK;\r
+ }\r
+\r
+ pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(len, xDescriptorWaitTime);\r
+ if (pxNetworkBuffer != NULL) {\r
+\r
+ /* Set the packet size, in case a larger buffer was returned. */\r
+ pxNetworkBuffer->xDataLength = len;\r
+\r
+ /* Copy the packet data. */\r
+ memcpy(pxNetworkBuffer->pucEthernetBuffer, buffer, len);\r
+ xRxEvent.pvData = (void *) pxNetworkBuffer;\r
+\r
+ if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) {\r
+ ESP_LOGE(TAG, "Failed to enqueue packet to network stack %p, len %d", buffer, len);\r
+ vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);\r
+ return ESP_FAIL;\r
+ }\r
+ esp_wifi_internal_free_rx_buffer(eb);\r
+ return ESP_OK;\r
+ } else {\r
+ ESP_LOGE(TAG, "Failed to get buffer descriptor");\r
+ return ESP_FAIL;\r
+ }\r
+}\r
+\r
+#if ( ipconfigHAS_PRINTF != 0 )\r
+ static void prvMonitorResources()\r
+ {\r
+ static UBaseType_t uxLastMinBufferCount = 0u;\r
+ static UBaseType_t uxCurrentBufferCount = 0u;\r
+ static size_t uxMinLastSize = 0uL;\r
+ size_t uxMinSize;\r
+\r
+ uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers();\r
+\r
+ if( uxLastMinBufferCount != uxCurrentBufferCount )\r
+ {\r
+ /* The logging produced below may be helpful\r
+ * while tuning +TCP: see how many buffers are in use. */\r
+ uxLastMinBufferCount = uxCurrentBufferCount;\r
+ FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",\r
+ uxGetNumberOfFreeNetworkBuffers(), uxCurrentBufferCount ) );\r
+ }\r
+\r
+ uxMinSize = xPortGetMinimumEverFreeHeapSize();\r
+\r
+ if( uxMinLastSize != uxMinSize )\r
+ {\r
+ uxMinLastSize = uxMinSize;\r
+ FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", xPortGetFreeHeapSize(), uxMinSize ) );\r
+ }\r
+\r
+ #if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )\r
+ {\r
+ static UBaseType_t uxLastMinQueueSpace = 0;\r
+ UBaseType_t uxCurrentCount = 0u;\r
+\r
+ uxCurrentCount = uxGetMinimumIPQueueSpace();\r
+\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
+#endif /* ( ipconfigHAS_PRINTF != 0 ) */\r
+/*-----------------------------------------------------------*/\r