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