/* * FreeRTOS+TCP * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * SPDX-License-Identifier: MIT * * 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 #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; }