| /* |
| 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; |
| } |