xref: /FreeRTOS-Plus-TCP-v3.1.0/source/portable/NetworkInterface/esp32/NetworkInterface.c (revision a4124602cc584fa0658448c229f48a459a84fbb1)
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 
xNetworkInterfaceInitialise(void)48 BaseType_t xNetworkInterfaceInitialise( void )
49 {
50     static BaseType_t xMACAdrInitialized = pdFALSE;
51     uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ];
52 
53     if( xInterfaceState == INTERFACE_UP )
54     {
55         if( xMACAdrInitialized == pdFALSE )
56         {
57             esp_wifi_get_mac( ESP_IF_WIFI_STA, ucMACAddress );
58             FreeRTOS_UpdateMACAddress( ucMACAddress );
59             xMACAdrInitialized = pdTRUE;
60         }
61 
62         return pdTRUE;
63     }
64 
65     return pdFALSE;
66 }
67 
xNetworkInterfaceOutput(NetworkBufferDescriptor_t * const pxNetworkBuffer,BaseType_t xReleaseAfterSend)68 BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer,
69                                     BaseType_t xReleaseAfterSend )
70 {
71     if( ( pxNetworkBuffer == NULL ) || ( pxNetworkBuffer->pucEthernetBuffer == NULL ) || ( pxNetworkBuffer->xDataLength == 0 ) )
72     {
73         ESP_LOGE( TAG, "Invalid params" );
74         return pdFALSE;
75     }
76 
77     esp_err_t ret;
78 
79     if( xInterfaceState == INTERFACE_DOWN )
80     {
81         ESP_LOGD( TAG, "Interface down" );
82         ret = ESP_FAIL;
83     }
84     else
85     {
86         ret = esp_wifi_internal_tx( ESP_IF_WIFI_STA, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
87 
88         if( ret != ESP_OK )
89         {
90             ESP_LOGE( TAG, "Failed to tx buffer %p, len %d, err %d", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret );
91         }
92     }
93 
94     #if ( ipconfigHAS_PRINTF != 0 )
95         {
96             /* Call a function that monitors resources: the amount of free network
97              * buffers and the amount of free space on the heap.  See FreeRTOS_IP.c
98              * for more detailed comments. */
99             vPrintResourceStats();
100         }
101     #endif /* ( ipconfigHAS_PRINTF != 0 ) */
102 
103     if( xReleaseAfterSend == pdTRUE )
104     {
105         vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
106     }
107 
108     return ret == ESP_OK ? pdTRUE : pdFALSE;
109 }
110 
vNetworkNotifyIFDown()111 void vNetworkNotifyIFDown()
112 {
113     IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };
114 
115     if( xInterfaceState != INTERFACE_DOWN )
116     {
117         xInterfaceState = INTERFACE_DOWN;
118         xSendEventStructToIPTask( &xRxEvent, 0 );
119     }
120 }
121 
vNetworkNotifyIFUp()122 void vNetworkNotifyIFUp()
123 {
124     xInterfaceState = INTERFACE_UP;
125 }
126 
wlanif_input(void * netif,void * buffer,uint16_t len,void * eb)127 esp_err_t wlanif_input( void * netif,
128                         void * buffer,
129                         uint16_t len,
130                         void * eb )
131 {
132     NetworkBufferDescriptor_t * pxNetworkBuffer;
133     IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
134     const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
135 
136     #if ( ipconfigHAS_PRINTF != 0 )
137         {
138             vPrintResourceStats();
139         }
140     #endif /* ( ipconfigHAS_PRINTF != 0 ) */
141 
142     if( eConsiderFrameForProcessing( buffer ) != eProcessBuffer )
143     {
144         ESP_LOGD( TAG, "Dropping packet" );
145         esp_wifi_internal_free_rx_buffer( eb );
146         return ESP_OK;
147     }
148 
149     pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( len, xDescriptorWaitTime );
150 
151     if( pxNetworkBuffer != NULL )
152     {
153         /* Set the packet size, in case a larger buffer was returned. */
154         pxNetworkBuffer->xDataLength = len;
155 
156         /* Copy the packet data. */
157         memcpy( pxNetworkBuffer->pucEthernetBuffer, buffer, len );
158         xRxEvent.pvData = ( void * ) pxNetworkBuffer;
159 
160         if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFAIL )
161         {
162             ESP_LOGE( TAG, "Failed to enqueue packet to network stack %p, len %d", buffer, len );
163             vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
164             return ESP_FAIL;
165         }
166 
167         esp_wifi_internal_free_rx_buffer( eb );
168         return ESP_OK;
169     }
170     else
171     {
172         ESP_LOGE( TAG, "Failed to get buffer descriptor" );
173         return ESP_FAIL;
174     }
175 }
176