/* | |
FreeRTOS+TCP V2.0.11 | |
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. | |
Permission is hereby granted, free of charge, to any person obtaining a copy of | |
this software and associated documentation files (the "Software"), to deal in | |
the Software without restriction, including without limitation the rights to | |
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | |
the Software, and to permit persons to whom the Software is furnished to do so, | |
subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in all | |
copies or substantial portions of the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | |
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | |
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | |
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
http://aws.amazon.com/freertos | |
http://www.FreeRTOS.org | |
*/ | |
/* FreeRTOS includes. */ | |
#include "FreeRTOS.h" | |
#include "list.h" | |
/* FreeRTOS+TCP includes. */ | |
#include "FreeRTOS_IP.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 "wifi-decl.h" | |
#include "wmerrno.h" | |
#include "wifi.h" | |
#include <wmlog.h> | |
#define net_e(...) \ | |
wmlog_e("freertos_tcp", ##__VA_ARGS__) | |
#define net_w(...) \ | |
wmlog_w("freertos_tcp", ##__VA_ARGS__) | |
#define net_d(...) \ | |
wmlog("freertos_tcp", ##__VA_ARGS__) | |
#if 0 //this is lwip structure. | |
#define MAX_INTERFACES_SUPPORTED 3 | |
static struct netif *netif_arr[MAX_INTERFACES_SUPPORTED]; | |
#endif | |
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet | |
driver will filter incoming packets and only pass the stack those packets it | |
considers need processing. */ | |
#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) | |
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer | |
#else | |
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) | |
#endif | |
#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any) | |
#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast) | |
/** 255.255.255.255 */ | |
#define IPADDR_NONE ((u32_t)0xffffffffUL) | |
/** 127.0.0.1 */ | |
#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) | |
/** 0.0.0.0 */ | |
#define IPADDR_ANY ((u32_t)0x00000000UL) | |
/** 255.255.255.255 */ | |
#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) | |
/** 255.255.255.255 */ | |
#define INADDR_NONE IPADDR_NONE | |
/** 127.0.0.1 */ | |
#define INADDR_LOOPBACK IPADDR_LOOPBACK | |
/** 0.0.0.0 */ | |
#define INADDR_ANY IPADDR_ANY | |
/** 255.255.255.255 */ | |
#define INADDR_BROADCAST IPADDR_BROADCAST | |
enum if_state_t { | |
INTERFACE_DOWN = 0, | |
INTERFACE_UP, | |
}; | |
struct ip_addr { | |
u32_t addr; | |
}; | |
#define MLAN_BSS_TYPE_STA 0 | |
extern uint8_t outbuf[2048]; | |
extern bool mlan_is_amsdu(const t_u8 *rcvdata); | |
extern t_u8 *mlan_get_payload(const t_u8 *rcvdata, t_u16 *payload_len, int *interface); | |
extern int wrapper_wlan_handle_amsdu_rx_packet(const t_u8 *rcvdata, const t_u16 datalen); | |
extern int wrapper_wlan_handle_rx_packet(const t_u16 datalen, const t_u8 *rcvdata, NetworkBufferDescriptor_t *pxNetworkBuffer); | |
static volatile uint32_t xInterfaceState = INTERFACE_DOWN; | |
static int process_data_packet(const t_u8 *databuf, const t_u16 datalen) | |
{ | |
int interface = BSS_TYPE_STA; | |
t_u8 *payload = NULL; | |
t_u16 payload_len = 0; | |
const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 ); | |
NetworkBufferDescriptor_t *pxNetworkBuffer; | |
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; | |
payload = (t_u8 *)mlan_get_payload(databuf, &payload_len, &interface); | |
if( eConsiderFrameForProcessing( payload ) != eProcessBuffer ) { | |
net_d("Dropping packet\r\n"); | |
return WM_SUCCESS; | |
} | |
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(/*payload_len*/datalen, xDescriptorWaitTime); | |
if (pxNetworkBuffer != NULL) { | |
/* Set the packet size, in case a larger buffer was returned. */ | |
pxNetworkBuffer->xDataLength = payload_len; | |
/* Copy the packet data. */ | |
memcpy(pxNetworkBuffer->pucEthernetBuffer, payload, payload_len); | |
xRxEvent.pvData = (void *) pxNetworkBuffer; | |
if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) { | |
wmprintf("Failed to enqueue packet to network stack %p, len %d", payload, payload_len); | |
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer); | |
return WM_FAIL; | |
} | |
} | |
return WM_SUCCESS; | |
} | |
/* Callback function called from the wifi module */ | |
void handle_data_packet(const t_u8 interface, const t_u8 *rcvdata, | |
const t_u16 datalen) | |
{ | |
if (interface == BSS_TYPE_STA) | |
process_data_packet(rcvdata, datalen); | |
} | |
BaseType_t xNetworkInterfaceInitialise( void ) | |
{ | |
uint8_t ret; | |
mac_addr_t mac_addr; | |
ret = wifi_get_device_mac_addr(&mac_addr); | |
if (ret != WM_SUCCESS) { | |
net_d("Failed to get mac address"); | |
} | |
FreeRTOS_UpdateMACAddress(mac_addr.mac); | |
return ( xInterfaceState == INTERFACE_UP && ret == WM_SUCCESS ) ? pdTRUE : pdFALSE; | |
} | |
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) | |
{ | |
/* FIX ME. */ | |
} | |
BaseType_t xGetPhyLinkStatus( void ) | |
{ | |
/* FIX ME. */ | |
return pdFALSE; | |
} | |
void vNetworkNotifyIFDown() | |
{ | |
IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL }; | |
xInterfaceState = INTERFACE_DOWN; | |
if( xSendEventStructToIPTask( &xRxEvent, 0 ) != pdPASS ) { | |
/* Could not send the message, so it is still pending. */ | |
net_e("Could not send network down event"); | |
} | |
else { | |
/* Message was sent so it is not pending. */ | |
net_d("Sent network down event"); | |
} | |
} | |
void vNetworkNotifyIFUp() | |
{ | |
xInterfaceState = INTERFACE_UP; | |
} | |
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend ) | |
{ | |
uint8_t pkt_len; | |
if (pxNetworkBuffer == NULL || | |
pxNetworkBuffer->pucEthernetBuffer == NULL || | |
pxNetworkBuffer->xDataLength == 0) { | |
net_d("Incorrect params"); | |
return pdFALSE; | |
} | |
memset(outbuf, 0x00, sizeof(outbuf)); | |
pkt_len = 22 + 4; /* sizeof(TxPD) + INTF_HEADER_LEN */ | |
memcpy((u8_t *) outbuf + pkt_len, (u8_t *) pxNetworkBuffer->pucEthernetBuffer, | |
pxNetworkBuffer->xDataLength); | |
int ret = wifi_low_level_output(BSS_TYPE_STA, outbuf + pkt_len, pxNetworkBuffer->xDataLength); | |
if (ret != WM_SUCCESS) { | |
net_e("Failed output %p, length %d, error %d \r\n", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret); | |
} | |
if (xReleaseAfterSend != pdFALSE) { | |
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer); | |
} | |
return ret == WM_SUCCESS ? pdTRUE : pdFALSE; | |
} |