blob: 96503f457a504e1a60728826b19f0e18edc0d2fe [file] [log] [blame]
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DNS.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_wifi_internal.h"
#include "tcpip_adapter.h"
enum if_state_t {
INTERFACE_DOWN = 0,
INTERFACE_UP,
};
static const char *TAG = "NetInterface";
volatile static uint32_t xInterfaceState = INTERFACE_DOWN;
BaseType_t xNetworkInterfaceInitialise( void )
{
static BaseType_t xMACAdrInitialized = pdFALSE;
uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ];
if (xInterfaceState == INTERFACE_UP) {
if (xMACAdrInitialized == pdFALSE) {
esp_wifi_get_mac(ESP_IF_WIFI_STA, ucMACAddress);
FreeRTOS_UpdateMACAddress(ucMACAddress);
xMACAdrInitialized = pdTRUE;
}
return pdTRUE;
}
return pdFALSE;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
if (pxNetworkBuffer == NULL || pxNetworkBuffer->pucEthernetBuffer == NULL || pxNetworkBuffer->xDataLength == 0) {
ESP_LOGE(TAG, "Invalid params");
return pdFALSE;
}
esp_err_t ret;
if (xInterfaceState == INTERFACE_DOWN) {
ESP_LOGD(TAG, "Interface down");
ret = ESP_FAIL;
} else {
ret = esp_wifi_internal_tx(ESP_IF_WIFI_STA, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to tx buffer %p, len %d, err %d", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret);
}
}
if (xReleaseAfterSend == pdTRUE) {
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
}
return ret == ESP_OK ? pdTRUE : pdFALSE;
}
void vNetworkNotifyIFDown()
{
IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };
if (xInterfaceState != INTERFACE_DOWN) {
xInterfaceState = INTERFACE_DOWN;
xSendEventStructToIPTask( &xRxEvent, 0 );
}
}
void vNetworkNotifyIFUp()
{
xInterfaceState = INTERFACE_UP;
}
esp_err_t wlanif_input(void *netif, void *buffer, uint16_t len, void *eb)
{
NetworkBufferDescriptor_t *pxNetworkBuffer;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
if( eConsiderFrameForProcessing( buffer ) != eProcessBuffer ) {
ESP_LOGD(TAG, "Dropping packet");
esp_wifi_internal_free_rx_buffer(eb);
return ESP_OK;
}
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(len, xDescriptorWaitTime);
if (pxNetworkBuffer != NULL) {
/* Set the packet size, in case a larger buffer was returned. */
pxNetworkBuffer->xDataLength = len;
/* Copy the packet data. */
memcpy(pxNetworkBuffer->pucEthernetBuffer, buffer, len);
xRxEvent.pvData = (void *) pxNetworkBuffer;
if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) {
ESP_LOGE(TAG, "Failed to enqueue packet to network stack %p, len %d", buffer, len);
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
return ESP_FAIL;
}
esp_wifi_internal_free_rx_buffer(eb);
return ESP_OK;
} else {
ESP_LOGE(TAG, "Failed to get buffer descriptor");
return ESP_FAIL;
}
}