xref: /FreeRTOS-Plus-TCP-v4.0.0/source/portable/NetworkInterface/esp32/NetworkInterface.c (revision 2d3f4daa567ffe71aeda2e0f6d0bc02850db0627)
1 /* Copyright 2018 Espressif Systems (Shanghai) PTE LTD */
2 /* */
3 /* Licensed under the Apache License, Version 2.0 (the "License"); */
4 /* you may not use this file except in compliance with the License. */
5 /* You may obtain a copy of the License at */
6 /* */
7 /*     http://www.apache.org/licenses/LICENSE-2.0 */
8 /* */
9 /* Unless required by applicable law or agreed to in writing, software */
10 /* distributed under the License is distributed on an "AS IS" BASIS, */
11 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
12 /* See the License for the specific language governing permissions and */
13 /* limitations under the License. */
14 
15 /* Standard includes. */
16 #include <stdint.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 
20 /* FreeRTOS includes. */
21 #include "FreeRTOS.h"
22 #include "task.h"
23 #include "queue.h"
24 #include "semphr.h"
25 
26 /* FreeRTOS+TCP includes. */
27 #include "FreeRTOS_IP.h"
28 #include "FreeRTOS_Sockets.h"
29 #include "FreeRTOS_IP_Private.h"
30 #include "FreeRTOS_DNS.h"
31 #include "NetworkBufferManagement.h"
32 #include "NetworkInterface.h"
33 
34 #include "esp_log.h"
35 #include "esp_wifi.h"
36 #include "esp_wifi_internal.h"
37 #include "tcpip_adapter.h"
38 
39 enum if_state_t
40 {
41     INTERFACE_DOWN = 0,
42     INTERFACE_UP,
43 };
44 
45 static const char * TAG = "NetInterface";
46 volatile static uint32_t xInterfaceState = INTERFACE_DOWN;
47 
48 static NetworkInterface_t * pxMyInterface;
49 
50 static BaseType_t xESP32_Eth_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface );
51 
52 static BaseType_t xESP32_Eth_NetworkInterfaceOutput( NetworkInterface_t * pxInterface,
53                                                      NetworkBufferDescriptor_t * const pxDescriptor,
54                                                      BaseType_t xReleaseAfterSend );
55 
56 static BaseType_t xESP32_Eth_GetPhyLinkStatus( NetworkInterface_t * pxInterface );
57 
58 NetworkInterface_t * pxESP32_Eth_FillInterfaceDescriptor( BaseType_t xEMACIndex,
59                                                           NetworkInterface_t * pxInterface );
60 
61 /*-----------------------------------------------------------*/
62 
63 #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 1 )
64 
65 /* Do not call the following function directly. It is there for downward compatibility.
66  * The function FreeRTOS_IPInit() will call it to initialice the interface and end-point
67  * objects.  See the description in FreeRTOS_Routing.h. */
pxFillInterfaceDescriptor(BaseType_t xEMACIndex,NetworkInterface_t * pxInterface)68     NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex,
69                                                     NetworkInterface_t * pxInterface )
70     {
71         pxESP32_Eth_FillInterfaceDescriptor( xEMACIndex, pxInterface );
72     }
73 
74 #endif
75 /*-----------------------------------------------------------*/
76 
77 
pxESP32_Eth_FillInterfaceDescriptor(BaseType_t xEMACIndex,NetworkInterface_t * pxInterface)78 NetworkInterface_t * pxESP32_Eth_FillInterfaceDescriptor( BaseType_t xEMACIndex,
79                                                           NetworkInterface_t * pxInterface )
80 {
81     static char pcName[ 8 ];
82 
83 /* This function pxESP32_Eth_FillInterfaceDescriptor() adds a network-interface.
84  * Make sure that the object pointed to by 'pxInterface'
85  * is declared static or global, and that it will remain to exist. */
86 
87     snprintf( pcName, sizeof( pcName ), "eth%ld", xEMACIndex );
88 
89     memset( pxInterface, '\0', sizeof( *pxInterface ) );
90     pxInterface->pcName = pcName;                    /* Just for logging, debugging. */
91     pxInterface->pvArgument = ( void * ) xEMACIndex; /* Has only meaning for the driver functions. */
92     pxInterface->pfInitialise = xESP32_Eth_NetworkInterfaceInitialise;
93     pxInterface->pfOutput = xESP32_Eth_NetworkInterfaceOutput;
94     pxInterface->pfGetPhyLinkStatus = xESP32_Eth_GetPhyLinkStatus;
95 
96     FreeRTOS_AddNetworkInterface( pxInterface );
97     pxMyInterface = pxInterface;
98 
99     return pxInterface;
100 }
101 /*-----------------------------------------------------------*/
102 
xESP32_Eth_NetworkInterfaceInitialise(NetworkInterface_t * pxInterface)103 static BaseType_t xESP32_Eth_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface )
104 {
105     static BaseType_t xMACAdrInitialized = pdFALSE;
106     uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ];
107 
108     if( xInterfaceState == INTERFACE_UP )
109     {
110         if( xMACAdrInitialized == pdFALSE )
111         {
112             esp_wifi_get_mac( ESP_IF_WIFI_STA, ucMACAddress );
113             FreeRTOS_UpdateMACAddress( ucMACAddress );
114             xMACAdrInitialized = pdTRUE;
115         }
116 
117         return pdTRUE;
118     }
119 
120     return pdFALSE;
121 }
122 
xESP32_Eth_GetPhyLinkStatus(NetworkInterface_t * pxInterface)123 static BaseType_t xESP32_Eth_GetPhyLinkStatus( NetworkInterface_t * pxInterface )
124 {
125     BaseType_t xResult = pdFALSE;
126 
127     if( xInterfaceState == INTERFACE_UP )
128     {
129         xResult = pdTRUE;
130     }
131 
132     return xResult;
133 }
134 
xESP32_Eth_NetworkInterfaceOutput(NetworkInterface_t * pxInterface,NetworkBufferDescriptor_t * const pxDescriptor,BaseType_t xReleaseAfterSend)135 static BaseType_t xESP32_Eth_NetworkInterfaceOutput( NetworkInterface_t * pxInterface,
136                                                      NetworkBufferDescriptor_t * const pxDescriptor,
137                                                      BaseType_t xReleaseAfterSend )
138 {
139     if( ( pxNetworkBuffer == NULL ) || ( pxNetworkBuffer->pucEthernetBuffer == NULL ) || ( pxNetworkBuffer->xDataLength == 0 ) )
140     {
141         ESP_LOGE( TAG, "Invalid params" );
142         return pdFALSE;
143     }
144 
145     esp_err_t ret;
146 
147     if( xInterfaceState == INTERFACE_DOWN )
148     {
149         ESP_LOGD( TAG, "Interface down" );
150         ret = ESP_FAIL;
151     }
152     else
153     {
154         ret = esp_wifi_internal_tx( ESP_IF_WIFI_STA, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
155 
156         if( ret != ESP_OK )
157         {
158             ESP_LOGE( TAG, "Failed to tx buffer %p, len %d, err %d", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret );
159         }
160     }
161 
162     #if ( ipconfigHAS_PRINTF != 0 )
163         {
164             /* Call a function that monitors resources: the amount of free network
165              * buffers and the amount of free space on the heap.  See FreeRTOS_IP.c
166              * for more detailed comments. */
167             vPrintResourceStats();
168         }
169     #endif /* ( ipconfigHAS_PRINTF != 0 ) */
170 
171     if( xReleaseAfterSend == pdTRUE )
172     {
173         vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
174     }
175 
176     return ret == ESP_OK ? pdTRUE : pdFALSE;
177 }
178 
vNetworkNotifyIFDown()179 void vNetworkNotifyIFDown()
180 {
181     IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };
182 
183     if( xInterfaceState != INTERFACE_DOWN )
184     {
185         xInterfaceState = INTERFACE_DOWN;
186         xSendEventStructToIPTask( &xRxEvent, 0 );
187     }
188 }
189 
vNetworkNotifyIFUp()190 void vNetworkNotifyIFUp()
191 {
192     xInterfaceState = INTERFACE_UP;
193 }
194 
wlanif_input(void * netif,void * buffer,uint16_t len,void * eb)195 esp_err_t wlanif_input( void * netif,
196                         void * buffer,
197                         uint16_t len,
198                         void * eb )
199 {
200     NetworkBufferDescriptor_t * pxNetworkBuffer;
201     IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
202     const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
203 
204     #if ( ipconfigHAS_PRINTF != 0 )
205         {
206             vPrintResourceStats();
207         }
208     #endif /* ( ipconfigHAS_PRINTF != 0 ) */
209 
210     if( eConsiderFrameForProcessing( buffer ) != eProcessBuffer )
211     {
212         ESP_LOGD( TAG, "Dropping packet" );
213         esp_wifi_internal_free_rx_buffer( eb );
214         return ESP_OK;
215     }
216 
217     pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( len, xDescriptorWaitTime );
218 
219     if( pxNetworkBuffer != NULL )
220     {
221         /* Set the packet size, in case a larger buffer was returned. */
222         pxNetworkBuffer->xDataLength = len;
223         pxNetworkBuffer->pxInterface = pxMyInterface;
224         pxNetworkBuffer->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pcBuffer );
225 
226         /* Copy the packet data. */
227         memcpy( pxNetworkBuffer->pucEthernetBuffer, buffer, len );
228         xRxEvent.pvData = ( void * ) pxNetworkBuffer;
229 
230         if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFAIL )
231         {
232             ESP_LOGE( TAG, "Failed to enqueue packet to network stack %p, len %d", buffer, len );
233             vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
234             return ESP_FAIL;
235         }
236 
237         esp_wifi_internal_free_rx_buffer( eb );
238         return ESP_OK;
239     }
240     else
241     {
242         ESP_LOGE( TAG, "Failed to get buffer descriptor" );
243         return ESP_FAIL;
244     }
245 }
246