mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-11-06 11:42:31 -05:00
This commit is contained in:
parent
a869e61be6
commit
2bac2cf6c6
6215 changed files with 2146988 additions and 0 deletions
File diff suppressed because it is too large
Load diff
173
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/AT91SAM7_Startup.s
Normal file
173
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/AT91SAM7_Startup.s
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*****************************************************************************
|
||||
Exception handlers and startup code for ATMEL AT91SAM7.
|
||||
|
||||
Copyright (c) 2004 Rowley Associates Limited.
|
||||
|
||||
This file may be distributed under the terms of the License Agreement
|
||||
provided with this software.
|
||||
|
||||
THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*****************************************************************************/
|
||||
|
||||
#define REG_BASE 0xFFFFF000
|
||||
#define CKGR_MOR_OFFSET 0xC20
|
||||
#define CKGR_PLLR_OFFSET 0xC2C
|
||||
#define PMC_MCKR_OFFSET 0xC30
|
||||
#define PMC_SR_OFFSET 0xC68
|
||||
#define WDT_MR_OFFSET 0xD44
|
||||
#define MC_RCR_OFFSET 0xF00
|
||||
#define MC_FMR_OFFSET 0xF60
|
||||
|
||||
#define CKGR_MOR_MOSCEN (1 << 0)
|
||||
#define CKGR_MOR_OSCBYPASS (1 << 1)
|
||||
#define CKGR_MOR_OSCOUNT_BIT_OFFSET (8)
|
||||
|
||||
#define CKGR_PLLR_DIV_BIT_OFFSET (0)
|
||||
#define CKGR_PLLR_PLLCOUNT_BIT_OFFSET (8)
|
||||
#define CKGR_PLLR_OUT_BIT_OFFSET (14)
|
||||
#define CKGR_PLLR_MUL_BIT_OFFSET (16)
|
||||
#define CKGR_PLLR_USBDIV_BIT_OFFSET (28)
|
||||
|
||||
#define PMC_MCKR_CSS_MAIN_CLOCK (0x1)
|
||||
#define PMC_MCKR_CSS_PLL_CLOCK (0x3)
|
||||
#define PMC_MCKR_PRES_CLK (0)
|
||||
#define PMC_MCKR_PRES_CLK_2 (1 << 2)
|
||||
#define PMC_MCKR_PRES_CLK_4 (2 << 2)
|
||||
#define PMC_MCKR_PRES_CLK_8 (3 << 2)
|
||||
#define PMC_MCKR_PRES_CLK_16 (4 << 2)
|
||||
#define PMC_MCKR_PRES_CLK_32 (5 << 2)
|
||||
#define PMC_MCKR_PRES_CLK_64 (6 << 2)
|
||||
|
||||
#define PMC_SR_MOSCS (1 << 0)
|
||||
#define PMC_SR_LOCK (1 << 2)
|
||||
#define PMC_SR_MCKRDY (1 << 3)
|
||||
#define PMC_SR_PCKRDY0 (1 << 8)
|
||||
#define PMC_SR_PCKRDY1 (1 << 9)
|
||||
#define PMC_SR_PCKRDY2 (1 << 10)
|
||||
|
||||
#define MC_RCR_RCB (1 << 0)
|
||||
|
||||
#define MC_FMR_FWS_0FWS (0)
|
||||
#define MC_FMR_FWS_1FWS (1 << 8)
|
||||
#define MC_FMR_FWS_2FWS (2 << 8)
|
||||
#define MC_FMR_FWS_3FWS (3 << 8)
|
||||
#define MC_FMR_FMCN_BIT_OFFSET 16
|
||||
|
||||
#define WDT_MR_WDDIS (1 << 15)
|
||||
|
||||
.section .vectors, "ax"
|
||||
.code 32
|
||||
.align 0
|
||||
|
||||
/*****************************************************************************
|
||||
Exception Vectors
|
||||
*****************************************************************************/
|
||||
_vectors:
|
||||
ldr pc, [pc, #reset_handler_address - . - 8] /* reset */
|
||||
ldr pc, [pc, #undef_handler_address - . - 8] /* undefined instruction */
|
||||
ldr pc, [pc, #swi_handler_address - . - 8] /* swi handler */
|
||||
ldr pc, [pc, #pabort_handler_address - . - 8] /* abort prefetch */
|
||||
ldr pc, [pc, #dabort_handler_address - . - 8] /* abort data */
|
||||
nop
|
||||
ldr pc, [PC, #-0xF20] /* irq */
|
||||
ldr pc, [pc, #fiq_handler_address - . - 8] /* fiq */
|
||||
|
||||
reset_handler_address:
|
||||
.word reset_handler
|
||||
undef_handler_address:
|
||||
.word undef_handler
|
||||
swi_handler_address:
|
||||
.word swi_handler
|
||||
pabort_handler_address:
|
||||
.word pabort_handler
|
||||
dabort_handler_address:
|
||||
.word dabort_handler
|
||||
irq_handler_address:
|
||||
.word irq_handler
|
||||
fiq_handler_address:
|
||||
.word fiq_handler
|
||||
|
||||
.section .init, "ax"
|
||||
.code 32
|
||||
.align 0
|
||||
|
||||
/******************************************************************************
|
||||
Reset handler
|
||||
******************************************************************************/
|
||||
reset_handler:
|
||||
|
||||
|
||||
ldr r10, =REG_BASE
|
||||
|
||||
/* Set up FLASH wait state */
|
||||
ldr r0, =(50 << MC_FMR_FMCN_BIT_OFFSET) | MC_FMR_FWS_1FWS
|
||||
str r0, [r10, #MC_FMR_OFFSET]
|
||||
|
||||
/* Disable Watchdog */
|
||||
ldr r0, =WDT_MR_WDDIS
|
||||
str r0, [r10, #WDT_MR_OFFSET]
|
||||
|
||||
/* Enable the main oscillator */
|
||||
ldr r0, =(6 << CKGR_MOR_OSCOUNT_BIT_OFFSET) | CKGR_MOR_MOSCEN
|
||||
str r0, [r10, #CKGR_MOR_OFFSET]
|
||||
|
||||
1:/* Wait for main oscillator to stabilize */
|
||||
ldr r0, [r10, #PMC_SR_OFFSET]
|
||||
tst r0, #PMC_SR_MOSCS
|
||||
beq 1b
|
||||
|
||||
/* Set up the PLL */
|
||||
ldr r0, =(5 << CKGR_PLLR_DIV_BIT_OFFSET) | (28 << CKGR_PLLR_PLLCOUNT_BIT_OFFSET) | (25 << CKGR_PLLR_MUL_BIT_OFFSET)
|
||||
str r0, [r10, #CKGR_PLLR_OFFSET]
|
||||
|
||||
1:/* Wait for PLL to lock */
|
||||
ldr r0, [r10, #PMC_SR_OFFSET]
|
||||
tst r0, #PMC_SR_LOCK
|
||||
beq 1b
|
||||
|
||||
/* Select PLL as clock source */
|
||||
ldr r0, =(PMC_MCKR_CSS_PLL_CLOCK | PMC_MCKR_PRES_CLK_2)
|
||||
str r0, [r10, #PMC_MCKR_OFFSET]
|
||||
|
||||
#ifdef __FLASH_BUILD
|
||||
/* Copy exception vectors into Internal SRAM */
|
||||
mov r8, #0x00200000
|
||||
ldr r9, =_vectors
|
||||
ldmia r9!, {r0-r7}
|
||||
stmia r8!, {r0-r7}
|
||||
ldmia r9!, {r0-r6}
|
||||
stmia r8!, {r0-r6}
|
||||
|
||||
/* Remap Internal SRAM to 0x00000000 */
|
||||
ldr r0, =MC_RCR_RCB
|
||||
strb r0, [r10, #MC_RCR_OFFSET]
|
||||
#endif
|
||||
|
||||
|
||||
/* Jump to the default C runtime startup code. */
|
||||
b _start
|
||||
|
||||
/******************************************************************************
|
||||
Default exception handlers
|
||||
(These are declared weak symbols so they can be redefined in user code)
|
||||
******************************************************************************/
|
||||
undef_handler:
|
||||
b undef_handler
|
||||
|
||||
swi_handler:
|
||||
b swi_handler
|
||||
|
||||
pabort_handler:
|
||||
b pabort_handler
|
||||
|
||||
dabort_handler:
|
||||
b dabort_handler
|
||||
|
||||
irq_handler:
|
||||
b irq_handler
|
||||
|
||||
fiq_handler:
|
||||
b fiq_handler
|
||||
|
||||
.weak undef_handler, swi_handler, pabort_handler, dabort_handler, irq_handler, fiq_handler
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/******************************************************************************
|
||||
Target Script for ATMEL AT91SAM7.
|
||||
|
||||
Copyright (c) 2004 Rowley Associates Limited.
|
||||
|
||||
This file may be distributed under the terms of the License Agreement
|
||||
provided with this software.
|
||||
|
||||
THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
******************************************************************************/
|
||||
|
||||
function Reset()
|
||||
{
|
||||
/* Reset and stop target */
|
||||
TargetInterface.pokeWord(0xFFFFFD00, 0xA500000D); // RSTC_CR
|
||||
TargetInterface.waitForDebugState(1000);
|
||||
/* Configure Clock */
|
||||
TargetInterface.pokeWord(0xFFFFFC20, 0x00000601); // CKGR_MOR
|
||||
TargetInterface.delay(10);
|
||||
TargetInterface.pokeWord(0xFFFFFC2C, 0x00191C05); // CKGR_PLLR
|
||||
TargetInterface.delay(10);
|
||||
TargetInterface.pokeWord(0xFFFFFC30, 0x00000007); // CKGR_MCKR
|
||||
TargetInterface.delay(10);
|
||||
}
|
||||
|
||||
function RAMReset()
|
||||
{
|
||||
Reset();
|
||||
/* Remap SRAM to 0x00000000 */
|
||||
TargetInterface.pokeWord(0xFFFFFF00, 1); // MC_RCR
|
||||
}
|
||||
|
||||
function FLASHReset()
|
||||
{
|
||||
Reset();
|
||||
|
||||
// Mask All interrupt pAic->AIC_IDCR = 0xFFFFFFFF;
|
||||
|
||||
TargetInterface.pokeWord(0xffffffff,0xFFFFF124);
|
||||
TargetInterface.pokeWord(0xffffffff,0xFFFFF128);
|
||||
// disable peripheral clock Peripheral Clock Disable Register
|
||||
TargetInterface.pokeWord(0xffffffff,0xFFFFFC14);
|
||||
|
||||
// #define AT91C_TC0_SR ((AT91_REG *) 0xFFFA0020) // (TC0) Status Register
|
||||
// #define AT91C_TC1_SR ((AT91_REG *) 0xFFFA0060) // (TC1) Status Register
|
||||
// #define AT91C_TC2_SR ((AT91_REG *) 0xFFFA00A0) // (TC2) Status Register
|
||||
TargetInterface.peekWord(0xFFFA0020);
|
||||
TargetInterface.peekWord(0xFFFA0060);
|
||||
TargetInterface.peekWord(0xFFFA00A0);
|
||||
|
||||
// for (__mac_i=0;__mac_i < 8; __mac_i++)
|
||||
// {
|
||||
// AT91C_BASE_AIC->AIC_EOICR
|
||||
// __mac_pt = TargetInterface.peekWord(0xFFFFF130);
|
||||
|
||||
// }
|
||||
// __message "------------------------------- AIC 2 INIT ---------------------------------------------";
|
||||
|
||||
}
|
||||
|
||||
241
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/BasicWEB.c
Normal file
241
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/BasicWEB.c
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
/*
|
||||
Implements a simplistic WEB server. Every time a connection is made and
|
||||
data is received a dynamic page that shows the current TCP/IP statistics
|
||||
is generated and returned. The connection is then closed.
|
||||
|
||||
This file was adapted from a FreeRTOS lwIP slip demo supplied by a third
|
||||
party.
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.2
|
||||
|
||||
+ Changed the page returned by the lwIP WEB server demo to display the
|
||||
task status table rather than the TCP/IP statistics.
|
||||
*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* Demo includes. */
|
||||
#include "BasicWEB.h"
|
||||
#include "SAM7_EMAC.h"
|
||||
|
||||
/* lwIP includes. */
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "netif/loopif.h"
|
||||
|
||||
/* The size of the buffer in which the dynamic WEB page is created. */
|
||||
#define webMAX_PAGE_SIZE 2048
|
||||
|
||||
/* Standard GET response. */
|
||||
#define webHTTP_OK "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n"
|
||||
|
||||
/* The port on which we listen. */
|
||||
#define webHTTP_PORT ( 80 )
|
||||
|
||||
/* Delay on close error. */
|
||||
#define webSHORT_DELAY ( 10 )
|
||||
|
||||
/* Format of the dynamic page that is returned on each connection. */
|
||||
#define webHTML_START \
|
||||
"<html>\
|
||||
<head>\
|
||||
</head>\
|
||||
<BODY onLoad=\"window.setTimeout("location.href='index.html'",1000)\"bgcolor=\"#CCCCff\">\
|
||||
\r\nPage Hits = "
|
||||
|
||||
#define webHTML_END \
|
||||
"\r\n</pre>\
|
||||
\r\n</BODY>\
|
||||
</html>"
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Process an incoming connection on port 80.
|
||||
*
|
||||
* This simply checks to see if the incoming data contains a GET request, and
|
||||
* if so sends back a single dynamically created page. The connection is then
|
||||
* closed. A more complete implementation could create a task for each
|
||||
* connection.
|
||||
*/
|
||||
static void vProcessConnection( struct netconn *pxNetCon );
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
static void vProcessConnection( struct netconn *pxNetCon )
|
||||
{
|
||||
static char cDynamicPage[ webMAX_PAGE_SIZE ], cPageHits[ 11 ];
|
||||
struct netbuf *pxRxBuffer;
|
||||
char *pcRxString;
|
||||
unsigned short usLength;
|
||||
static unsigned long ulPageHits = 0;
|
||||
|
||||
/* We expect to immediately get data. */
|
||||
pxRxBuffer = netconn_recv( pxNetCon );
|
||||
|
||||
if( pxRxBuffer != NULL )
|
||||
{
|
||||
/* Where is the data? */
|
||||
netbuf_data( pxRxBuffer, ( void * ) &pcRxString, &usLength );
|
||||
|
||||
/* Is this a GET? We don't handle anything else. */
|
||||
if( !strncmp( pcRxString, "GET", 3 ) )
|
||||
{
|
||||
pcRxString = cDynamicPage;
|
||||
|
||||
/* Update the hit count. */
|
||||
ulPageHits++;
|
||||
sprintf( cPageHits, "%lu", ulPageHits );
|
||||
|
||||
/* Write out the HTTP OK header. */
|
||||
netconn_write(pxNetCon, webHTTP_OK, (u16_t)strlen( webHTTP_OK ), NETCONN_COPY );
|
||||
|
||||
/* Generate the dynamic page...
|
||||
|
||||
... First the page header. */
|
||||
strcpy( cDynamicPage, webHTML_START );
|
||||
/* ... Then the hit count... */
|
||||
strcat( cDynamicPage, cPageHits );
|
||||
strcat( cDynamicPage, "<p><pre>Task State Priority Stack #<br>************************************************<br>" );
|
||||
/* ... Then the list of tasks and their status... */
|
||||
vTaskList( ( signed char * ) cDynamicPage + strlen( cDynamicPage ) );
|
||||
/* ... Finally the page footer. */
|
||||
strcat( cDynamicPage, webHTML_END );
|
||||
|
||||
/* Write out the dynamically generated page. */
|
||||
netconn_write(pxNetCon, cDynamicPage, (u16_t)strlen( cDynamicPage ), NETCONN_COPY );
|
||||
}
|
||||
|
||||
netbuf_delete( pxRxBuffer );
|
||||
}
|
||||
|
||||
netconn_close( pxNetCon );
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void vlwIPInit( void )
|
||||
{
|
||||
/* Initialize lwIP and its interface layer. */
|
||||
sys_init();
|
||||
mem_init();
|
||||
memp_init();
|
||||
pbuf_init();
|
||||
netif_init();
|
||||
ip_init();
|
||||
tcpip_init( NULL, NULL );
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void vBasicWEBServer( void *pvParameters )
|
||||
{
|
||||
struct netconn *pxHTTPListener, *pxNewConnection;
|
||||
struct ip_addr xIpAddr, xNetMast, xGateway;
|
||||
extern err_t ethernetif_init( struct netif *netif );
|
||||
static struct netif EMAC_if;
|
||||
|
||||
/* Parameters are not used - suppress compiler error. */
|
||||
( void ) pvParameters;
|
||||
|
||||
|
||||
/* Create and configure the EMAC interface. */
|
||||
IP4_ADDR(&xIpAddr,emacIPADDR0,emacIPADDR1,emacIPADDR2,emacIPADDR3);
|
||||
IP4_ADDR(&xNetMast,emacNET_MASK0,emacNET_MASK1,emacNET_MASK2,emacNET_MASK3);
|
||||
IP4_ADDR(&xGateway,emacGATEWAY_ADDR0,emacGATEWAY_ADDR1,emacGATEWAY_ADDR2,emacGATEWAY_ADDR3);
|
||||
netif_add(&EMAC_if, &xIpAddr, &xNetMast, &xGateway, NULL, ethernetif_init, tcpip_input);
|
||||
|
||||
/* make it the default interface */
|
||||
netif_set_default(&EMAC_if);
|
||||
|
||||
/* bring it up */
|
||||
netif_set_up(&EMAC_if);
|
||||
|
||||
/* Create a new tcp connection handle */
|
||||
|
||||
pxHTTPListener = netconn_new( NETCONN_TCP );
|
||||
netconn_bind(pxHTTPListener, NULL, webHTTP_PORT );
|
||||
netconn_listen( pxHTTPListener );
|
||||
|
||||
/* Loop forever */
|
||||
for( ;; )
|
||||
{
|
||||
/* Wait for connection. */
|
||||
pxNewConnection = netconn_accept(pxHTTPListener);
|
||||
|
||||
if(pxNewConnection != NULL)
|
||||
{
|
||||
/* Service connection. */
|
||||
vProcessConnection( pxNewConnection );
|
||||
while( netconn_delete( pxNewConnection ) != ERR_OK )
|
||||
{
|
||||
vTaskDelay( webSHORT_DELAY );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
64
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/BasicWEB.h
Normal file
64
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/BasicWEB.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
#ifndef BASIC_WEB_SERVER_H
|
||||
#define BASIC_WEB_SERVER_H
|
||||
|
||||
/* The function that implements the WEB server task. */
|
||||
void vBasicWEBServer( void *pvParameters );
|
||||
|
||||
/* Initialisation required by lwIP. */
|
||||
void vlwIPInit( void );
|
||||
|
||||
#endif
|
||||
|
||||
68
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/Board.h
Normal file
68
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/Board.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support - ROUSSET -
|
||||
*----------------------------------------------------------------------------
|
||||
* The software is delivered "AS IS" without warranty or condition of any
|
||||
* kind, either express, implied or statutory. This includes without
|
||||
* limitation any warranty or condition with respect to merchantability or
|
||||
* fitness for any particular purpose, or against the infringements of
|
||||
* intellectual property rights of others.
|
||||
*----------------------------------------------------------------------------
|
||||
* File Name : Board.h
|
||||
* Object : AT91SAM7X Evaluation Board Features Definition File.
|
||||
*
|
||||
* Creation : JG 20/Jun/2005
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef Board_h
|
||||
#define Board_h
|
||||
|
||||
#include "AT91SAM7X256.h"
|
||||
#include "ioat91sam7x256.h"
|
||||
|
||||
#define true -1
|
||||
#define false 0
|
||||
|
||||
/*-------------------------------*/
|
||||
/* SAM7Board Memories Definition */
|
||||
/*-------------------------------*/
|
||||
// The AT91SAM7X128 embeds a 32-Kbyte SRAM bank, and 128K-Byte Flash
|
||||
|
||||
#define FLASH_PAGE_NB 256
|
||||
#define FLASH_PAGE_SIZE 128
|
||||
|
||||
/*-----------------*/
|
||||
/* Leds Definition */
|
||||
/*-----------------*/
|
||||
#define LED1 (1<<19) // PB19
|
||||
#define LED2 (1<<20) // PB20
|
||||
#define LED3 (1<<21) // PB21
|
||||
#define LED4 (1<<22) // PB22
|
||||
#define NB_LED 4
|
||||
|
||||
#define LED_MASK (LED1|LED2|LED3|LED4)
|
||||
|
||||
/*-------------------------*/
|
||||
/* Push Buttons Definition */
|
||||
/*-------------------------*/
|
||||
|
||||
#define SW1_MASK (1<<21) // PA21
|
||||
#define SW2_MASK (1<<22) // PA22
|
||||
#define SW3_MASK (1<<23) // PA23
|
||||
#define SW4_MASK (1<<24) // PA24
|
||||
#define SW_MASK (SW1_MASK|SW2_MASK|SW3_MASK|SW4_MASK)
|
||||
|
||||
|
||||
#define SW1 (1<<21) // PA21
|
||||
#define SW2 (1<<22) // PA22
|
||||
#define SW3 (1<<23) // PA23
|
||||
#define SW4 (1<<24) // PA24
|
||||
|
||||
/*--------------*/
|
||||
/* Master Clock */
|
||||
/*--------------*/
|
||||
|
||||
#define EXT_OC 18432000 // Exetrnal ocilator MAINCK
|
||||
#define MCK 47923200 // MCK (PLLRC div by 2)
|
||||
#define MCKKHz (MCK/1000) //
|
||||
|
||||
#endif /* Board_h */
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
//*----------------------------------------------------------------------------
|
||||
//* ATMEL Microcontroller Software Support - ROUSSET -
|
||||
//*----------------------------------------------------------------------------
|
||||
//* The software is delivered "AS IS" without warranty or condition of any
|
||||
//* kind, either express, implied or statutory. This includes without
|
||||
//* limitation any warranty or condition with respect to merchantability or
|
||||
//* fitness for any particular purpose, or against the infringements of
|
||||
//* intellectual property rights of others.
|
||||
//*----------------------------------------------------------------------------
|
||||
//* File Name : Cstartup_SAM7.c
|
||||
//* Object : Low level initializations written in C for IAR
|
||||
//* tools
|
||||
//* 1.0 08/Sep/04 JPP : Creation
|
||||
//* 1.10 10/Sep/04 JPP : Update AT91C_CKGR_PLLCOUNT filed
|
||||
//*----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Include the board file description
|
||||
#include "Board.h"
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_LowLevelInit
|
||||
//* \brief This function performs very low level HW initialization
|
||||
//* this function can be use a Stack, depending the compilation
|
||||
//* optimization mode
|
||||
//*----------------------------------------------------------------------------
|
||||
void AT91F_LowLevelInit( void);
|
||||
void AT91F_LowLevelInit( void )
|
||||
{
|
||||
AT91PS_PMC pPMC = AT91C_BASE_PMC;
|
||||
|
||||
//* Set Flash Waite sate
|
||||
// Single Cycle Access at Up to 30 MHz, or 40
|
||||
// if MCK = 47923200 I have 50 Cycle for 1 useconde ( flied MC_FMR->FMCN
|
||||
AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN)&(75 <<16)) | AT91C_MC_FWS_1FWS ;
|
||||
|
||||
//* Watchdog Disable
|
||||
AT91C_BASE_WDTC->WDTC_WDMR= AT91C_WDTC_WDDIS;
|
||||
|
||||
//* Set MCK at 47 923 200
|
||||
// 1 Enabling the Main Oscillator:
|
||||
// SCK = 1/32768 = 30.51 uSeconde
|
||||
// Start up time = 8 * 6 / SCK = 56 * 30.51 = 1,46484375 ms
|
||||
pPMC->PMC_MOR = ((( AT91C_CKGR_OSCOUNT & (0x06 <<8)) | AT91C_CKGR_MOSCEN ));
|
||||
// Wait the startup time
|
||||
while(!(pPMC->PMC_SR & AT91C_PMC_MOSCS));
|
||||
// 2 Checking the Main Oscillator Frequency (Optional)
|
||||
// 3 Setting PLL and divider:
|
||||
// - div by 5 Fin = 3,6864 =(18,432 / 5)
|
||||
// - Mul 25+1: Fout = 95,8464 =(3,6864 *26)
|
||||
// for 96 MHz the erroe is 0.16%
|
||||
//eld out NOT USED = 0 Fi
|
||||
pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 5) |
|
||||
(AT91C_CKGR_PLLCOUNT & (28<<8)) |
|
||||
(AT91C_CKGR_MUL & (25<<16)));
|
||||
|
||||
// Wait the startup time
|
||||
while(!(pPMC->PMC_SR & AT91C_PMC_LOCK));
|
||||
// 4. Selection of Master Clock and Processor Clock
|
||||
// select the PLL clock divided by 2
|
||||
pPMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 ;
|
||||
while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
|
||||
|
||||
pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ;
|
||||
while(!(pPMC->PMC_SR & AT91C_PMC_MCKRDY));
|
||||
}
|
||||
|
||||
|
||||
|
||||
117
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/EMAC/Emac.h
Normal file
117
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/EMAC/Emac.h
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
//*----------------------------------------------------------------------------
|
||||
//* ATMEL Microcontroller Software Support - ROUSSET -
|
||||
//*----------------------------------------------------------------------------
|
||||
//* The software is delivered "AS IS" without warranty or condition of any
|
||||
//* kind, either express, implied or statutory. This includes without
|
||||
//* limitation any warranty or condition with respect to merchantability or
|
||||
//* fitness for any particular purpose, or against the infringements of
|
||||
//* intellectual property rights of others.
|
||||
//*----------------------------------------------------------------------------
|
||||
//* File Name : Emac.h
|
||||
//* Object : Emac header file
|
||||
//* Creation : Hi 11/18/2002
|
||||
//*
|
||||
//*----------------------------------------------------------------------------
|
||||
#ifndef AT91C_EMAC_H
|
||||
#define AT91C_EMAC_H
|
||||
|
||||
#include "lwipopts.h"
|
||||
|
||||
|
||||
/* Number of receive buffers */
|
||||
#define NB_RX_BUFFERS 20
|
||||
|
||||
/* Size of each receive buffer - DO NOT CHANGE. */
|
||||
#define ETH_RX_BUFFER_SIZE 128
|
||||
|
||||
/* Number of Transmit buffers */
|
||||
#define NB_TX_BUFFERS ( MEMP_NUM_PBUF / 2 )
|
||||
|
||||
/* Size of each Transmit buffer. */
|
||||
#define ETH_TX_BUFFER_SIZE ( PBUF_POOL_BUFSIZE )
|
||||
|
||||
/* Receive Transfer descriptor structure */
|
||||
typedef struct _AT91S_RxTdDescriptor {
|
||||
unsigned int addr;
|
||||
union
|
||||
{
|
||||
unsigned int status;
|
||||
struct {
|
||||
unsigned int Length:11;
|
||||
unsigned int Res0:1;
|
||||
unsigned int Rxbuf_off:2;
|
||||
unsigned int StartOfFrame:1;
|
||||
unsigned int EndOfFrame:1;
|
||||
unsigned int Cfi:1;
|
||||
unsigned int VlanPriority:3;
|
||||
unsigned int PriorityTag:1;
|
||||
unsigned int VlanTag:1;
|
||||
unsigned int TypeID:1;
|
||||
unsigned int Sa4Match:1;
|
||||
unsigned int Sa3Match:1;
|
||||
unsigned int Sa2Match:1;
|
||||
unsigned int Sa1Match:1;
|
||||
unsigned int Res1:1;
|
||||
unsigned int ExternalAdd:1;
|
||||
unsigned int UniCast:1;
|
||||
unsigned int MultiCast:1;
|
||||
unsigned int BroadCast:1;
|
||||
}S_Status;
|
||||
}U_Status;
|
||||
}AT91S_RxTdDescriptor, *AT91PS_RxTdDescriptor;
|
||||
|
||||
|
||||
/* Transmit Transfer descriptor structure */
|
||||
typedef struct _AT91S_TxTdDescriptor {
|
||||
unsigned int addr;
|
||||
union
|
||||
{
|
||||
unsigned int status;
|
||||
struct {
|
||||
unsigned int Length:11;
|
||||
unsigned int Res0:4;
|
||||
unsigned int LastBuff:1;
|
||||
unsigned int NoCrc:1;
|
||||
unsigned int Res1:10;
|
||||
unsigned int BufExhausted:1;
|
||||
unsigned int TransmitUnderrun:1;
|
||||
unsigned int TransmitError:1;
|
||||
unsigned int Wrap:1;
|
||||
unsigned int BuffUsed:1;
|
||||
}S_Status;
|
||||
}U_Status;
|
||||
}AT91S_TxTdDescriptor, *AT91PS_TxTdDescriptor;
|
||||
|
||||
#define AT91C_OWNERSHIP_BIT 0x00000001
|
||||
|
||||
/* Receive status defintion */
|
||||
#define AT91C_BROADCAST_ADDR ((unsigned int) (1 << 31)) //* Broadcat address detected
|
||||
#define AT91C_MULTICAST_HASH ((unsigned int) (1 << 30)) //* MultiCast hash match
|
||||
#define AT91C_UNICAST_HASH ((unsigned int) (1 << 29)) //* UniCast hash match
|
||||
#define AT91C_EXTERNAL_ADDR ((unsigned int) (1 << 28)) //* External Address match
|
||||
#define AT91C_SA1_ADDR ((unsigned int) (1 << 26)) //* Specific address 1 match
|
||||
#define AT91C_SA2_ADDR ((unsigned int) (1 << 25)) //* Specific address 2 match
|
||||
#define AT91C_SA3_ADDR ((unsigned int) (1 << 24)) //* Specific address 3 match
|
||||
#define AT91C_SA4_ADDR ((unsigned int) (1 << 23)) //* Specific address 4 match
|
||||
#define AT91C_TYPE_ID ((unsigned int) (1 << 22)) //* Type ID match
|
||||
#define AT91C_VLAN_TAG ((unsigned int) (1 << 21)) //* VLAN tag detected
|
||||
#define AT91C_PRIORITY_TAG ((unsigned int) (1 << 20)) //* PRIORITY tag detected
|
||||
#define AT91C_VLAN_PRIORITY ((unsigned int) (7 << 17)) //* PRIORITY Mask
|
||||
#define AT91C_CFI_IND ((unsigned int) (1 << 16)) //* CFI indicator
|
||||
#define AT91C_EOF ((unsigned int) (1 << 15)) //* EOF
|
||||
#define AT91C_SOF ((unsigned int) (1 << 14)) //* SOF
|
||||
#define AT91C_RBF_OFFSET ((unsigned int) (3 << 12)) //* Receive Buffer Offset Mask
|
||||
#define AT91C_LENGTH_FRAME ((unsigned int) 0x07FF) //* Length of frame
|
||||
|
||||
/* Transmit Status definition */
|
||||
#define AT91C_TRANSMIT_OK ((unsigned int) (1 << 31)) //*
|
||||
#define AT91C_TRANSMIT_WRAP ((unsigned int) (1 << 30)) //* Wrap bit: mark the last descriptor
|
||||
#define AT91C_TRANSMIT_ERR ((unsigned int) (1 << 29)) //* RLE:transmit error
|
||||
#define AT91C_TRANSMIT_UND ((unsigned int) (1 << 28)) //* Transmit Underrun
|
||||
#define AT91C_BUF_EX ((unsigned int) (1 << 27)) //* Buffers exhausted in mid frame
|
||||
#define AT91C_TRANSMIT_NO_CRC ((unsigned int) (1 << 16)) //* No CRC will be appended to the current frame
|
||||
#define AT91C_LAST_BUFFER ((unsigned int) (1 << 15)) //*
|
||||
|
||||
#define AT91C_EMAC_CLKEN 0x2
|
||||
|
||||
#endif //* AT91C_EMAC_H
|
||||
882
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC.c
Normal file
882
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC.c
Normal file
|
|
@ -0,0 +1,882 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Interrupt driven driver for the EMAC peripheral. This driver is not
|
||||
* reentrant, re-entrancy is handled by a semaphore at the network interface
|
||||
* level.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Changes from V3.2.2
|
||||
|
||||
+ Corrected the byte order when writing the MAC address to the MAC.
|
||||
+ Support added for MII interfaces. Previously only RMII was supported.
|
||||
|
||||
Changes from V3.2.3
|
||||
|
||||
+ The MII interface is now the default.
|
||||
+ Modified the initialisation sequence slightly to allow auto init more
|
||||
time to complete.
|
||||
|
||||
Changes from V4.0.1
|
||||
|
||||
+ Made the function vClearEMACTxBuffer() more robust by moving the index
|
||||
manipulation into the if() statement. This allows the tx interrupt to
|
||||
execute even when there is no data to handle.
|
||||
|
||||
Changes from V4.0.4
|
||||
|
||||
+ Corrected the Rx frame length mask when obtaining the length from the
|
||||
rx descriptor.
|
||||
*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <string.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Demo app includes. */
|
||||
#include "SAM7_EMAC.h"
|
||||
|
||||
/* Hardware specific includes. */
|
||||
#include "Emac.h"
|
||||
#include "mii.h"
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
|
||||
/* USE_RMII_INTERFACE must be defined as 1 to use an RMII interface, or 0
|
||||
to use an MII interface. */
|
||||
#define USE_RMII_INTERFACE 0
|
||||
|
||||
|
||||
/* The buffer addresses written into the descriptors must be aligned so the
|
||||
last few bits are zero. These bits have special meaning for the EMAC
|
||||
peripheral and cannot be used as part of the address. */
|
||||
#define emacADDRESS_MASK ( ( unsigned long ) 0xFFFFFFFC )
|
||||
|
||||
/* Bit used within the address stored in the descriptor to mark the last
|
||||
descriptor in the array. */
|
||||
#define emacRX_WRAP_BIT ( ( unsigned long ) 0x02 )
|
||||
|
||||
/* Bit used within the Tx descriptor status to indicate whether the
|
||||
descriptor is under the control of the EMAC or the software. */
|
||||
#define emacTX_BUF_USED ( ( unsigned long ) 0x80000000 )
|
||||
|
||||
/* A short delay is used to wait for a buffer to become available, should
|
||||
one not be immediately available when trying to transmit a frame. */
|
||||
#define emacBUFFER_WAIT_DELAY ( 2 )
|
||||
#define emacMAX_WAIT_CYCLES ( ( portBASE_TYPE ) ( configTICK_RATE_HZ / 40 ) )
|
||||
|
||||
/* The time to block waiting for input. */
|
||||
#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 )
|
||||
|
||||
/* Peripheral setup for the EMAC. */
|
||||
#define emacPERIPHERAL_A_SETUP ( ( unsigned long ) AT91C_PB2_ETX0 ) | \
|
||||
( ( unsigned long ) AT91C_PB12_ETXER ) | \
|
||||
( ( unsigned long ) AT91C_PB16_ECOL ) | \
|
||||
( ( unsigned long ) AT91C_PB11_ETX3 ) | \
|
||||
( ( unsigned long ) AT91C_PB6_ERX1 ) | \
|
||||
( ( unsigned long ) AT91C_PB15_ERXDV ) | \
|
||||
( ( unsigned long ) AT91C_PB13_ERX2 ) | \
|
||||
( ( unsigned long ) AT91C_PB3_ETX1 ) | \
|
||||
( ( unsigned long ) AT91C_PB8_EMDC ) | \
|
||||
( ( unsigned long ) AT91C_PB5_ERX0 ) | \
|
||||
( ( unsigned long ) AT91C_PB14_ERX3 ) | \
|
||||
( ( unsigned long ) AT91C_PB4_ECRS_ECRSDV ) | \
|
||||
( ( unsigned long ) AT91C_PB1_ETXEN ) | \
|
||||
( ( unsigned long ) AT91C_PB10_ETX2 ) | \
|
||||
( ( unsigned long ) AT91C_PB0_ETXCK_EREFCK ) | \
|
||||
( ( unsigned long ) AT91C_PB9_EMDIO ) | \
|
||||
( ( unsigned long ) AT91C_PB7_ERXER ) | \
|
||||
( ( unsigned long ) AT91C_PB17_ERXCK );
|
||||
|
||||
/* Misc defines. */
|
||||
#define emacINTERRUPT_LEVEL ( 5 )
|
||||
#define emacNO_DELAY ( 0 )
|
||||
#define emacTOTAL_FRAME_HEADER_SIZE ( 54 )
|
||||
#define emacPHY_INIT_DELAY ( 5000 / portTICK_RATE_MS )
|
||||
#define emacRESET_KEY ( ( unsigned long ) 0xA5000000 )
|
||||
#define emacRESET_LENGTH ( ( unsigned long ) ( 0x01 << 8 ) )
|
||||
|
||||
/* The Atmel header file only defines the TX frame length mask. */
|
||||
#define emacRX_LENGTH_FRAME ( 0xfff )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Buffer written to by the EMAC DMA. Must be aligned as described by the
|
||||
comment above the emacADDRESS_MASK definition. */
|
||||
static volatile char pcRxBuffer[ NB_RX_BUFFERS * ETH_RX_BUFFER_SIZE ] __attribute__ ((aligned (8)));
|
||||
|
||||
/* Buffer read by the EMAC DMA. Must be aligned as described by the comment
|
||||
above the emacADDRESS_MASK definition. */
|
||||
static char pcTxBuffer[ NB_TX_BUFFERS * ETH_TX_BUFFER_SIZE ] __attribute__ ((aligned (8)));
|
||||
|
||||
/* Descriptors used to communicate between the program and the EMAC peripheral.
|
||||
These descriptors hold the locations and state of the Rx and Tx buffers. */
|
||||
static volatile AT91S_TxTdDescriptor xTxDescriptors[ NB_TX_BUFFERS ];
|
||||
static volatile AT91S_RxTdDescriptor xRxDescriptors[ NB_RX_BUFFERS ];
|
||||
|
||||
/* The IP and Ethernet addresses are read from the header files. */
|
||||
const char cMACAddress[ 6 ] = { emacETHADDR0, emacETHADDR1, emacETHADDR2, emacETHADDR3, emacETHADDR4, emacETHADDR5 };
|
||||
const unsigned char ucIPAddress[ 4 ] = { emacIPADDR0, emacIPADDR1, emacIPADDR2, emacIPADDR3 };
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* See the header file for descriptions of public functions. */
|
||||
|
||||
/*
|
||||
* Prototype for the EMAC interrupt function.
|
||||
*/
|
||||
void vEMACISR_Wrapper( void ) __attribute__ ((naked));
|
||||
|
||||
/*
|
||||
* Initialise both the Tx and Rx descriptors used by the EMAC.
|
||||
*/
|
||||
static void prvSetupDescriptors(void);
|
||||
|
||||
/*
|
||||
* Write our MAC address into the EMAC.
|
||||
*/
|
||||
static void prvSetupMACAddress( void );
|
||||
|
||||
/*
|
||||
* Configure the EMAC and AIC for EMAC interrupts.
|
||||
*/
|
||||
static void prvSetupEMACInterrupt( void );
|
||||
|
||||
/*
|
||||
* Some initialisation functions taken from the Atmel EMAC sample code.
|
||||
*/
|
||||
static void vReadPHY( unsigned char ucPHYAddress, unsigned char ucAddress, unsigned long *pulValue );
|
||||
static portBASE_TYPE xGetLinkSpeed( void );
|
||||
static portBASE_TYPE prvProbePHY( void );
|
||||
#if USE_RMII_INTERFACE != 1
|
||||
static void vWritePHY( unsigned char ucPHYAddress, unsigned char ucAddress, unsigned long ulValue);
|
||||
#endif
|
||||
|
||||
|
||||
/* The semaphore used by the EMAC ISR to wake the EMAC task. */
|
||||
static xSemaphoreHandle xSemaphore = NULL;
|
||||
|
||||
/* Holds the index to the next buffer from which data will be read. */
|
||||
static volatile unsigned long ulNextRxBuffer = 0;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* See the header file for descriptions of public functions. */
|
||||
long lEMACSend( char *pcFrom, unsigned long ulLength, long lEndOfFrame )
|
||||
{
|
||||
static unsigned portBASE_TYPE uxTxBufferIndex = 0;
|
||||
portBASE_TYPE xWaitCycles = 0;
|
||||
long lReturn = pdPASS;
|
||||
char *pcBuffer;
|
||||
unsigned long ulLastBuffer, ulDataBuffered = 0, ulDataRemainingToSend, ulLengthToSend;
|
||||
|
||||
/* If the length of data to be transmitted is greater than each individual
|
||||
transmit buffer then the data will be split into more than one buffer.
|
||||
Loop until the entire length has been buffered. */
|
||||
while( ulDataBuffered < ulLength )
|
||||
{
|
||||
/* Is a buffer available? */
|
||||
while( !( xTxDescriptors[ uxTxBufferIndex ].U_Status.status & AT91C_TRANSMIT_OK ) )
|
||||
{
|
||||
/* There is no room to write the Tx data to the Tx buffer. Wait a
|
||||
short while, then try again. */
|
||||
xWaitCycles++;
|
||||
if( xWaitCycles > emacMAX_WAIT_CYCLES )
|
||||
{
|
||||
/* Give up. */
|
||||
lReturn = pdFAIL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
vTaskDelay( emacBUFFER_WAIT_DELAY );
|
||||
}
|
||||
}
|
||||
|
||||
/* lReturn will only be pdPASS if a buffer is available. */
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* Get the address of the buffer from the descriptor, then copy
|
||||
the data into the buffer. */
|
||||
pcBuffer = ( char * ) xTxDescriptors[ uxTxBufferIndex ].addr;
|
||||
|
||||
/* How much can we write to the buffer? */
|
||||
ulDataRemainingToSend = ulLength - ulDataBuffered;
|
||||
if( ulDataRemainingToSend <= ETH_TX_BUFFER_SIZE )
|
||||
{
|
||||
/* We can write all the remaining bytes. */
|
||||
ulLengthToSend = ulDataRemainingToSend;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We can not write more than ETH_TX_BUFFER_SIZE in one go. */
|
||||
ulLengthToSend = ETH_TX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/* Copy the data into the buffer. */
|
||||
memcpy( ( void * ) pcBuffer, ( void * ) &( pcFrom[ ulDataBuffered ] ), ulLengthToSend );
|
||||
ulDataBuffered += ulLengthToSend;
|
||||
|
||||
/* Is this the last data for the frame? */
|
||||
if( lEndOfFrame && ( ulDataBuffered >= ulLength ) )
|
||||
{
|
||||
/* No more data remains for this frame so we can start the
|
||||
transmission. */
|
||||
ulLastBuffer = AT91C_LAST_BUFFER;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* More data to come for this frame. */
|
||||
ulLastBuffer = 0;
|
||||
}
|
||||
|
||||
/* Fill out the necessary in the descriptor to get the data sent,
|
||||
then move to the next descriptor, wrapping if necessary. */
|
||||
if( uxTxBufferIndex >= ( NB_TX_BUFFERS - 1 ) )
|
||||
{
|
||||
xTxDescriptors[ uxTxBufferIndex ].U_Status.status = ( ulLengthToSend & ( unsigned long ) AT91C_LENGTH_FRAME )
|
||||
| ulLastBuffer
|
||||
| AT91C_TRANSMIT_WRAP;
|
||||
uxTxBufferIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xTxDescriptors[ uxTxBufferIndex ].U_Status.status = ( ulLengthToSend & ( unsigned long ) AT91C_LENGTH_FRAME )
|
||||
| ulLastBuffer;
|
||||
uxTxBufferIndex++;
|
||||
}
|
||||
|
||||
/* If this is the last buffer to be sent for this frame we can
|
||||
start the transmission. */
|
||||
if( ulLastBuffer )
|
||||
{
|
||||
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* See the header file for descriptions of public functions. */
|
||||
unsigned long ulEMACInputLength( void )
|
||||
{
|
||||
register unsigned long ulIndex, ulLength = 0;
|
||||
|
||||
/* Skip any fragments. We are looking for the first buffer that contains
|
||||
data and has the SOF (start of frame) bit set. */
|
||||
while( ( xRxDescriptors[ ulNextRxBuffer ].addr & AT91C_OWNERSHIP_BIT ) && !( xRxDescriptors[ ulNextRxBuffer ].U_Status.status & AT91C_SOF ) )
|
||||
{
|
||||
/* Ignoring this buffer. Mark it as free again. */
|
||||
xRxDescriptors[ ulNextRxBuffer ].addr &= ~( AT91C_OWNERSHIP_BIT );
|
||||
ulNextRxBuffer++;
|
||||
if( ulNextRxBuffer >= NB_RX_BUFFERS )
|
||||
{
|
||||
ulNextRxBuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* We are going to walk through the descriptors that make up this frame,
|
||||
but don't want to alter ulNextRxBuffer as this would prevent vEMACRead()
|
||||
from finding the data. Therefore use a copy of ulNextRxBuffer instead. */
|
||||
ulIndex = ulNextRxBuffer;
|
||||
|
||||
/* Walk through the descriptors until we find the last buffer for this
|
||||
frame. The last buffer will give us the length of the entire frame. */
|
||||
while( ( xRxDescriptors[ ulIndex ].addr & AT91C_OWNERSHIP_BIT ) && !ulLength )
|
||||
{
|
||||
ulLength = xRxDescriptors[ ulIndex ].U_Status.status & emacRX_LENGTH_FRAME;
|
||||
|
||||
/* Increment to the next buffer, wrapping if necessary. */
|
||||
ulIndex++;
|
||||
if( ulIndex >= NB_RX_BUFFERS )
|
||||
{
|
||||
ulIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ulLength;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* See the header file for descriptions of public functions. */
|
||||
void vEMACRead( char *pcTo, unsigned long ulSectionLength, unsigned long ulTotalFrameLength )
|
||||
{
|
||||
static unsigned long ulSectionBytesReadSoFar = 0, ulBufferPosition = 0, ulFameBytesReadSoFar = 0;
|
||||
static char *pcSource;
|
||||
register unsigned long ulBytesRemainingInBuffer, ulRemainingSectionBytes;
|
||||
|
||||
/* Read ulSectionLength bytes from the Rx buffers. This is not necessarily any
|
||||
correspondence between the length of our Rx buffers, and the length of the
|
||||
data we are returning or the length of the data being requested. Therefore,
|
||||
between calls we have to remember not only which buffer we are currently
|
||||
processing, but our position within that buffer. This would be greatly
|
||||
simplified if PBUF_POOL_BUFSIZE could be guaranteed to be greater than
|
||||
the size of each Rx buffer, and that memory fragmentation did not occur.
|
||||
|
||||
This function should only be called after a call to ulEMACInputLength().
|
||||
This will ensure ulNextRxBuffer is set to the correct buffer. */
|
||||
|
||||
|
||||
|
||||
/* vEMACRead is called with pcTo set to NULL to indicate that we are about
|
||||
to read a new frame. Any fragments remaining in the frame we were
|
||||
processing during the last call should be dropped. */
|
||||
if( pcTo == NULL )
|
||||
{
|
||||
/* How many bytes are indicated as being in this buffer? If none then
|
||||
the buffer is completely full and the frame is contained within more
|
||||
than one buffer. */
|
||||
|
||||
/* Reset our state variables ready for the next read from this buffer. */
|
||||
pcSource = ( char * )( xRxDescriptors[ ulNextRxBuffer ].addr & emacADDRESS_MASK );
|
||||
ulFameBytesReadSoFar = ( unsigned long ) 0;
|
||||
ulBufferPosition = ( unsigned long ) 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Loop until we have obtained the required amount of data. */
|
||||
ulSectionBytesReadSoFar = 0;
|
||||
while( ulSectionBytesReadSoFar < ulSectionLength )
|
||||
{
|
||||
/* We may have already read some data from this buffer. How much
|
||||
data remains in the buffer? */
|
||||
ulBytesRemainingInBuffer = ( ETH_RX_BUFFER_SIZE - ulBufferPosition );
|
||||
|
||||
/* How many more bytes do we need to read before we have the
|
||||
required amount of data? */
|
||||
ulRemainingSectionBytes = ulSectionLength - ulSectionBytesReadSoFar;
|
||||
|
||||
/* Do we want more data than remains in the buffer? */
|
||||
if( ulRemainingSectionBytes > ulBytesRemainingInBuffer )
|
||||
{
|
||||
/* We want more data than remains in the buffer so we can
|
||||
write the remains of the buffer to the destination, then move
|
||||
onto the next buffer to get the rest. */
|
||||
memcpy( &( pcTo[ ulSectionBytesReadSoFar ] ), &( pcSource[ ulBufferPosition ] ), ulBytesRemainingInBuffer );
|
||||
ulSectionBytesReadSoFar += ulBytesRemainingInBuffer;
|
||||
ulFameBytesReadSoFar += ulBytesRemainingInBuffer;
|
||||
|
||||
/* Mark the buffer as free again. */
|
||||
xRxDescriptors[ ulNextRxBuffer ].addr &= ~( AT91C_OWNERSHIP_BIT );
|
||||
|
||||
/* Move onto the next buffer. */
|
||||
ulNextRxBuffer++;
|
||||
if( ulNextRxBuffer >= NB_RX_BUFFERS )
|
||||
{
|
||||
ulNextRxBuffer = ( unsigned long ) 0;
|
||||
}
|
||||
|
||||
/* Reset the variables for the new buffer. */
|
||||
pcSource = ( char * )( xRxDescriptors[ ulNextRxBuffer ].addr & emacADDRESS_MASK );
|
||||
ulBufferPosition = ( unsigned long ) 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have enough data in this buffer to send back. Read out
|
||||
enough data and remember how far we read up to. */
|
||||
memcpy( &( pcTo[ ulSectionBytesReadSoFar ] ), &( pcSource[ ulBufferPosition ] ), ulRemainingSectionBytes );
|
||||
|
||||
/* There may be more data in this buffer yet. Increment our
|
||||
position in this buffer past the data we have just read. */
|
||||
ulBufferPosition += ulRemainingSectionBytes;
|
||||
ulSectionBytesReadSoFar += ulRemainingSectionBytes;
|
||||
ulFameBytesReadSoFar += ulRemainingSectionBytes;
|
||||
|
||||
/* Have we now finished with this buffer? */
|
||||
if( ( ulBufferPosition >= ETH_RX_BUFFER_SIZE ) || ( ulFameBytesReadSoFar >= ulTotalFrameLength ) )
|
||||
{
|
||||
/* Mark the buffer as free again. */
|
||||
xRxDescriptors[ ulNextRxBuffer ].addr &= ~( AT91C_OWNERSHIP_BIT );
|
||||
|
||||
/* Move onto the next buffer. */
|
||||
ulNextRxBuffer++;
|
||||
if( ulNextRxBuffer >= NB_RX_BUFFERS )
|
||||
{
|
||||
ulNextRxBuffer = 0;
|
||||
}
|
||||
|
||||
pcSource = ( char * )( xRxDescriptors[ ulNextRxBuffer ].addr & emacADDRESS_MASK );
|
||||
ulBufferPosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* See the header file for descriptions of public functions. */
|
||||
xSemaphoreHandle xEMACInit( void )
|
||||
{
|
||||
/* Code supplied by Atmel -------------------------------*/
|
||||
|
||||
/* Disable pull up on RXDV => PHY normal mode (not in test mode),
|
||||
PHY has internal pull down. */
|
||||
AT91C_BASE_PIOB->PIO_PPUDR = 1 << 15;
|
||||
|
||||
#if USE_RMII_INTERFACE != 1
|
||||
/* PHY has internal pull down : set MII mode. */
|
||||
AT91C_BASE_PIOB->PIO_PPUDR = 1 << 16;
|
||||
#endif
|
||||
|
||||
/* Clear PB18 <=> PHY powerdown. */
|
||||
AT91C_BASE_PIOB->PIO_PER = 1 << 18;
|
||||
AT91C_BASE_PIOB->PIO_OER = 1 << 18;
|
||||
AT91C_BASE_PIOB->PIO_CODR = 1 << 18;
|
||||
|
||||
/* After PHY power up, hardware reset. */
|
||||
AT91C_BASE_RSTC->RSTC_RMR = emacRESET_KEY | emacRESET_LENGTH;
|
||||
AT91C_BASE_RSTC->RSTC_RCR = emacRESET_KEY | AT91C_RSTC_EXTRST;
|
||||
|
||||
/* Wait for hardware reset end. */
|
||||
while( !( AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL ) )
|
||||
{
|
||||
__asm volatile ( "NOP" );
|
||||
}
|
||||
__asm volatile ( "NOP" );
|
||||
|
||||
/* Setup the pins. */
|
||||
AT91C_BASE_PIOB->PIO_ASR = emacPERIPHERAL_A_SETUP;
|
||||
AT91C_BASE_PIOB->PIO_PDR = emacPERIPHERAL_A_SETUP;
|
||||
|
||||
/* Enable com between EMAC PHY.
|
||||
|
||||
Enable management port. */
|
||||
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE;
|
||||
|
||||
/* MDC = MCK/32. */
|
||||
AT91C_BASE_EMAC->EMAC_NCFGR |= ( 2 ) << 10;
|
||||
|
||||
/* Wait for PHY auto init end (rather crude delay!). */
|
||||
vTaskDelay( emacPHY_INIT_DELAY );
|
||||
|
||||
/* PHY configuration. */
|
||||
#if USE_RMII_INTERFACE != 1
|
||||
{
|
||||
unsigned long ulControl;
|
||||
|
||||
/* PHY has internal pull down : disable MII isolate. */
|
||||
vReadPHY( AT91C_PHY_ADDR, MII_BMCR, &ulControl );
|
||||
vReadPHY( AT91C_PHY_ADDR, MII_BMCR, &ulControl );
|
||||
ulControl &= ~BMCR_ISOLATE;
|
||||
vWritePHY( AT91C_PHY_ADDR, MII_BMCR, ulControl );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Disable management port again. */
|
||||
AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
|
||||
|
||||
#if USE_RMII_INTERFACE != 1
|
||||
/* Enable EMAC in MII mode, enable clock ERXCK and ETXCK. */
|
||||
AT91C_BASE_EMAC->EMAC_USRIO = AT91C_EMAC_CLKEN ;
|
||||
#else
|
||||
/* Enable EMAC in RMII mode, enable RMII clock (50MHz from oscillator
|
||||
on ERFCK). */
|
||||
AT91C_BASE_EMAC->EMAC_USRIO = AT91C_EMAC_RMII | AT91C_EMAC_CLKEN ;
|
||||
#endif
|
||||
|
||||
/* End of code supplied by Atmel ------------------------*/
|
||||
|
||||
/* Setup the buffers and descriptors. */
|
||||
prvSetupDescriptors();
|
||||
|
||||
/* Load our MAC address into the EMAC. */
|
||||
prvSetupMACAddress();
|
||||
|
||||
/* Are we connected? */
|
||||
if( prvProbePHY() )
|
||||
{
|
||||
/* Enable the interrupt! */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
prvSetupEMACInterrupt();
|
||||
vPassEMACSemaphore( xSemaphore );
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
return xSemaphore;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* See the header file for descriptions of public functions. */
|
||||
void vClearEMACTxBuffer( void )
|
||||
{
|
||||
static unsigned portBASE_TYPE uxNextBufferToClear = 0;
|
||||
|
||||
/* Called on Tx interrupt events to reset the AT91C_TRANSMIT_OK bit in each
|
||||
Tx buffer within the frame just transmitted. This marks all the buffers
|
||||
as available again.
|
||||
|
||||
The first buffer in the frame should have the bit set automatically. */
|
||||
if( xTxDescriptors[ uxNextBufferToClear ].U_Status.status & AT91C_TRANSMIT_OK )
|
||||
{
|
||||
/* Loop through the other buffers in the frame. */
|
||||
while( !( xTxDescriptors[ uxNextBufferToClear ].U_Status.status & AT91C_LAST_BUFFER ) )
|
||||
{
|
||||
uxNextBufferToClear++;
|
||||
|
||||
if( uxNextBufferToClear >= NB_TX_BUFFERS )
|
||||
{
|
||||
uxNextBufferToClear = 0;
|
||||
}
|
||||
|
||||
xTxDescriptors[ uxNextBufferToClear ].U_Status.status |= AT91C_TRANSMIT_OK;
|
||||
}
|
||||
|
||||
/* Start with the next buffer the next time a Tx interrupt is called. */
|
||||
uxNextBufferToClear++;
|
||||
|
||||
/* Do we need to wrap back to the first buffer? */
|
||||
if( uxNextBufferToClear >= NB_TX_BUFFERS )
|
||||
{
|
||||
uxNextBufferToClear = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupDescriptors(void)
|
||||
{
|
||||
unsigned portBASE_TYPE xIndex;
|
||||
unsigned long ulAddress;
|
||||
|
||||
/* Initialise xRxDescriptors descriptor. */
|
||||
for( xIndex = 0; xIndex < NB_RX_BUFFERS; ++xIndex )
|
||||
{
|
||||
/* Calculate the address of the nth buffer within the array. */
|
||||
ulAddress = ( unsigned long )( pcRxBuffer + ( xIndex * ETH_RX_BUFFER_SIZE ) );
|
||||
|
||||
/* Write the buffer address into the descriptor. The DMA will place
|
||||
the data at this address when this descriptor is being used. Mask off
|
||||
the bottom bits of the address as these have special meaning. */
|
||||
xRxDescriptors[ xIndex ].addr = ulAddress & emacADDRESS_MASK;
|
||||
}
|
||||
|
||||
/* The last buffer has the wrap bit set so the EMAC knows to wrap back
|
||||
to the first buffer. */
|
||||
xRxDescriptors[ NB_RX_BUFFERS - 1 ].addr |= emacRX_WRAP_BIT;
|
||||
|
||||
/* Initialise xTxDescriptors. */
|
||||
for( xIndex = 0; xIndex < NB_TX_BUFFERS; ++xIndex )
|
||||
{
|
||||
/* Calculate the address of the nth buffer within the array. */
|
||||
ulAddress = ( unsigned long )( pcTxBuffer + ( xIndex * ETH_TX_BUFFER_SIZE ) );
|
||||
|
||||
/* Write the buffer address into the descriptor. The DMA will read
|
||||
data from here when the descriptor is being used. */
|
||||
xTxDescriptors[ xIndex ].addr = ulAddress & emacADDRESS_MASK;
|
||||
xTxDescriptors[ xIndex ].U_Status.status = AT91C_TRANSMIT_OK;
|
||||
}
|
||||
|
||||
/* The last buffer has the wrap bit set so the EMAC knows to wrap back
|
||||
to the first buffer. */
|
||||
xTxDescriptors[ NB_TX_BUFFERS - 1 ].U_Status.status = AT91C_TRANSMIT_WRAP | AT91C_TRANSMIT_OK;
|
||||
|
||||
/* Tell the EMAC where to find the descriptors. */
|
||||
AT91C_BASE_EMAC->EMAC_RBQP = ( unsigned long ) xRxDescriptors;
|
||||
AT91C_BASE_EMAC->EMAC_TBQP = ( unsigned long ) xTxDescriptors;
|
||||
|
||||
/* Clear all the bits in the receive status register. */
|
||||
AT91C_BASE_EMAC->EMAC_RSR = ( AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA );
|
||||
|
||||
/* Enable the copy of data into the buffers, ignore broadcasts,
|
||||
and don't copy FCS. */
|
||||
AT91C_BASE_EMAC->EMAC_NCFGR |= ( AT91C_EMAC_CAF | AT91C_EMAC_NBC | AT91C_EMAC_DRFCS);
|
||||
|
||||
/* Enable Rx and Tx, plus the stats register. */
|
||||
AT91C_BASE_EMAC->EMAC_NCR |= ( AT91C_EMAC_TE | AT91C_EMAC_RE | AT91C_EMAC_WESTAT );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupMACAddress( void )
|
||||
{
|
||||
/* Must be written SA1L then SA1H. */
|
||||
AT91C_BASE_EMAC->EMAC_SA1L = ( ( unsigned long ) cMACAddress[ 3 ] << 24 ) |
|
||||
( ( unsigned long ) cMACAddress[ 2 ] << 16 ) |
|
||||
( ( unsigned long ) cMACAddress[ 1 ] << 8 ) |
|
||||
cMACAddress[ 0 ];
|
||||
|
||||
AT91C_BASE_EMAC->EMAC_SA1H = ( ( unsigned long ) cMACAddress[ 5 ] << 8 ) |
|
||||
cMACAddress[ 4 ];
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupEMACInterrupt( void )
|
||||
{
|
||||
/* Create the semaphore used to trigger the EMAC task. */
|
||||
vSemaphoreCreateBinary( xSemaphore );
|
||||
if( xSemaphore )
|
||||
{
|
||||
/* We start by 'taking' the semaphore so the ISR can 'give' it when the
|
||||
first interrupt occurs. */
|
||||
xSemaphoreTake( xSemaphore, emacNO_DELAY );
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* We want to interrupt on Rx and Tx events. */
|
||||
AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP;
|
||||
|
||||
/* Enable the interrupts in the AIC. */
|
||||
AT91F_AIC_ConfigureIt( AT91C_ID_EMAC, emacINTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vEMACISR_Wrapper );
|
||||
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_EMAC;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The following functions are initialisation functions taken from the Atmel
|
||||
* EMAC sample code.
|
||||
*/
|
||||
|
||||
|
||||
static portBASE_TYPE prvProbePHY( void )
|
||||
{
|
||||
unsigned long ulPHYId1, ulPHYId2, ulStatus;
|
||||
portBASE_TYPE xReturn = pdPASS;
|
||||
|
||||
/* Code supplied by Atmel (reformatted) -----------------*/
|
||||
|
||||
/* Enable management port */
|
||||
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE;
|
||||
AT91C_BASE_EMAC->EMAC_NCFGR |= ( 2 ) << 10;
|
||||
|
||||
/* Read the PHY ID. */
|
||||
vReadPHY( AT91C_PHY_ADDR, MII_PHYSID1, &ulPHYId1 );
|
||||
vReadPHY(AT91C_PHY_ADDR, MII_PHYSID2, &ulPHYId2 );
|
||||
|
||||
/* AMD AM79C875:
|
||||
PHY_ID1 = 0x0022
|
||||
PHY_ID2 = 0x5541
|
||||
Bits 3:0 Revision Number Four bit manufacturer?s revision number.
|
||||
0001 stands for Rev. A, etc.
|
||||
*/
|
||||
if( ( ( ulPHYId1 << 16 ) | ( ulPHYId2 & 0xfff0 ) ) != MII_DM9161_ID )
|
||||
{
|
||||
/* Did not expect this ID. */
|
||||
xReturn = pdFAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulStatus = xGetLinkSpeed();
|
||||
|
||||
if( ulStatus != pdPASS )
|
||||
{
|
||||
xReturn = pdFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable management port */
|
||||
AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
|
||||
|
||||
/* End of code supplied by Atmel ------------------------*/
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vReadPHY( unsigned char ucPHYAddress, unsigned char ucAddress, unsigned long *pulValue )
|
||||
{
|
||||
/* Code supplied by Atmel (reformatted) ----------------------*/
|
||||
|
||||
AT91C_BASE_EMAC->EMAC_MAN = (AT91C_EMAC_SOF & (0x01<<30))
|
||||
| (2 << 16) | (2 << 28)
|
||||
| ((ucPHYAddress & 0x1f) << 23)
|
||||
| (ucAddress << 18);
|
||||
|
||||
/* Wait until IDLE bit in Network Status register is cleared. */
|
||||
while( !( AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE ) )
|
||||
{
|
||||
__asm( "NOP" );
|
||||
}
|
||||
|
||||
*pulValue = ( AT91C_BASE_EMAC->EMAC_MAN & 0x0000ffff );
|
||||
|
||||
/* End of code supplied by Atmel ------------------------*/
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if USE_RMII_INTERFACE != 1
|
||||
static void vWritePHY( unsigned char ucPHYAddress, unsigned char ucAddress, unsigned long ulValue )
|
||||
{
|
||||
/* Code supplied by Atmel (reformatted) ----------------------*/
|
||||
|
||||
AT91C_BASE_EMAC->EMAC_MAN = (( AT91C_EMAC_SOF & (0x01<<30))
|
||||
| (2 << 16) | (1 << 28)
|
||||
| ((ucPHYAddress & 0x1f) << 23)
|
||||
| (ucAddress << 18))
|
||||
| (ulValue & 0xffff);
|
||||
|
||||
/* Wait until IDLE bit in Network Status register is cleared */
|
||||
while( !( AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE ) )
|
||||
{
|
||||
__asm( "NOP" );
|
||||
};
|
||||
|
||||
/* End of code supplied by Atmel ------------------------*/
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static portBASE_TYPE xGetLinkSpeed( void )
|
||||
{
|
||||
unsigned long ulBMSR, ulBMCR, ulLPA, ulMACCfg, ulSpeed, ulDuplex;
|
||||
|
||||
/* Code supplied by Atmel (reformatted) -----------------*/
|
||||
|
||||
/* Link status is latched, so read twice to get current value */
|
||||
vReadPHY(AT91C_PHY_ADDR, MII_BMSR, &ulBMSR);
|
||||
vReadPHY(AT91C_PHY_ADDR, MII_BMSR, &ulBMSR);
|
||||
|
||||
if( !( ulBMSR & BMSR_LSTATUS ) )
|
||||
{
|
||||
/* No Link. */
|
||||
return pdFAIL;
|
||||
}
|
||||
|
||||
vReadPHY(AT91C_PHY_ADDR, MII_BMCR, &ulBMCR);
|
||||
if (ulBMCR & BMCR_ANENABLE)
|
||||
{
|
||||
/* AutoNegotiation is enabled. */
|
||||
if (!(ulBMSR & BMSR_ANEGCOMPLETE))
|
||||
{
|
||||
/* Auto-negotitation in progress. */
|
||||
return pdFAIL;
|
||||
}
|
||||
|
||||
vReadPHY(AT91C_PHY_ADDR, MII_LPA, &ulLPA);
|
||||
if( ( ulLPA & LPA_100FULL ) || ( ulLPA & LPA_100HALF ) )
|
||||
{
|
||||
ulSpeed = SPEED_100;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulSpeed = SPEED_10;
|
||||
}
|
||||
|
||||
if( ( ulLPA & LPA_100FULL ) || ( ulLPA & LPA_10FULL ) )
|
||||
{
|
||||
ulDuplex = DUPLEX_FULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulDuplex = DUPLEX_HALF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ulSpeed = ( ulBMCR & BMCR_SPEED100 ) ? SPEED_100 : SPEED_10;
|
||||
ulDuplex = ( ulBMCR & BMCR_FULLDPLX ) ? DUPLEX_FULL : DUPLEX_HALF;
|
||||
}
|
||||
|
||||
/* Update the MAC */
|
||||
ulMACCfg = AT91C_BASE_EMAC->EMAC_NCFGR & ~( AT91C_EMAC_SPD | AT91C_EMAC_FD );
|
||||
if( ulSpeed == SPEED_100 )
|
||||
{
|
||||
if( ulDuplex == DUPLEX_FULL )
|
||||
{
|
||||
/* 100 Full Duplex */
|
||||
AT91C_BASE_EMAC->EMAC_NCFGR = ulMACCfg | AT91C_EMAC_SPD | AT91C_EMAC_FD;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 100 Half Duplex */
|
||||
AT91C_BASE_EMAC->EMAC_NCFGR = ulMACCfg | AT91C_EMAC_SPD;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ulDuplex == DUPLEX_FULL)
|
||||
{
|
||||
/* 10 Full Duplex */
|
||||
AT91C_BASE_EMAC->EMAC_NCFGR = ulMACCfg | AT91C_EMAC_FD;
|
||||
}
|
||||
else
|
||||
{ /* 10 Half Duplex */
|
||||
AT91C_BASE_EMAC->EMAC_NCFGR = ulMACCfg;
|
||||
}
|
||||
}
|
||||
|
||||
/* End of code supplied by Atmel ------------------------*/
|
||||
|
||||
return pdPASS;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vEMACWaitForInput( void )
|
||||
{
|
||||
/* Just wait until we are signled from an ISR that data is available, or
|
||||
we simply time out. */
|
||||
xSemaphoreTake( xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT );
|
||||
}
|
||||
141
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC.h
Normal file
141
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC.h
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.4
|
||||
|
||||
+ Modified the default MAC address as the one used previously was not liked
|
||||
by some routers.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SAM_7_EMAC_H
|
||||
#define SAM_7_EMAC_H
|
||||
|
||||
/* MAC address definition. The MAC address must be unique on the network. */
|
||||
#define emacETHADDR0 0
|
||||
#define emacETHADDR1 0xbd
|
||||
#define emacETHADDR2 0x33
|
||||
#define emacETHADDR3 0x06
|
||||
#define emacETHADDR4 0x68
|
||||
#define emacETHADDR5 0x22
|
||||
|
||||
/* The IP address being used. */
|
||||
#define emacIPADDR0 172
|
||||
#define emacIPADDR1 25
|
||||
#define emacIPADDR2 218
|
||||
#define emacIPADDR3 205
|
||||
|
||||
/* The gateway address being used. */
|
||||
#define emacGATEWAY_ADDR0 172
|
||||
#define emacGATEWAY_ADDR1 25
|
||||
#define emacGATEWAY_ADDR2 218
|
||||
#define emacGATEWAY_ADDR3 3
|
||||
|
||||
/* The network mask being used. */
|
||||
#define emacNET_MASK0 255
|
||||
#define emacNET_MASK1 255
|
||||
#define emacNET_MASK2 0
|
||||
#define emacNET_MASK3 0
|
||||
|
||||
/*
|
||||
* Initialise the EMAC driver. If successful a semaphore is returned that
|
||||
* is used by the EMAC ISR to indicate that Rx packets have been received.
|
||||
* If the initialisation fails then NULL is returned.
|
||||
*/
|
||||
xSemaphoreHandle xEMACInit( void );
|
||||
|
||||
/*
|
||||
* Send ulLength bytes from pcFrom. This copies the buffer to one of the
|
||||
* EMAC Tx buffers, then indicates to the EMAC that the buffer is ready.
|
||||
* If lEndOfFrame is true then the data being copied is the end of the frame
|
||||
* and the frame can be transmitted.
|
||||
*/
|
||||
long lEMACSend( char *pcFrom, unsigned long ulLength, long lEndOfFrame );
|
||||
|
||||
/*
|
||||
* Frames can be read from the EMAC in multiple sections.
|
||||
* Read ulSectionLength bytes from the EMAC receive buffers to pcTo.
|
||||
* ulTotalFrameLength is the size of the entire frame. Generally vEMACRead
|
||||
* will be repetedly called until the sum of all the ulSectionLenths totals
|
||||
* the value of ulTotalFrameLength.
|
||||
*/
|
||||
void vEMACRead( char *pcTo, unsigned long ulSectionLength, unsigned long ulTotalFrameLength );
|
||||
|
||||
/*
|
||||
* The EMAC driver and interrupt service routines are defined in different
|
||||
* files as the driver is compiled to THUMB, and the ISR to ARM. This function
|
||||
* simply passes the semaphore used to communicate between the two.
|
||||
*/
|
||||
void vPassEMACSemaphore( xSemaphoreHandle xCreatedSemaphore );
|
||||
|
||||
/*
|
||||
* Called by the Tx interrupt, this function traverses the buffers used to
|
||||
* hold the frame that has just completed transmission and marks each as
|
||||
* free again.
|
||||
*/
|
||||
void vClearEMACTxBuffer( void );
|
||||
|
||||
/*
|
||||
* Suspend on a semaphore waiting either for the semaphore to be obtained
|
||||
* or a timeout. The semaphore is used by the EMAC ISR to indicate that
|
||||
* data has been received and is ready for processing.
|
||||
*/
|
||||
void vEMACWaitForInput( void );
|
||||
|
||||
/*
|
||||
* Return the length of the next frame in the receive buffers.
|
||||
*/
|
||||
unsigned long ulEMACInputLength( void );
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
#include "SAM7_EMAC.h"
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The semaphore used to signal the arrival of new data to the interface
|
||||
task. */
|
||||
static xSemaphoreHandle xSemaphore = NULL;
|
||||
|
||||
/* The interrupt entry point is naked so we can control the context saving. */
|
||||
void vEMACISR_Wrapper( void ) __attribute__((naked));
|
||||
|
||||
/* The interrupt handler function must be separate from the entry function
|
||||
to ensure the correct stack frame is set up. */
|
||||
void vEMACISR_Handler( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* The EMAC ISR. Handles both Tx and Rx complete interrupts.
|
||||
*/
|
||||
void vEMACISR_Handler( void )
|
||||
{
|
||||
volatile unsigned long ulIntStatus, ulEventStatus;
|
||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||||
extern void vClearEMACTxBuffer( void );
|
||||
|
||||
/* Find the cause of the interrupt. */
|
||||
ulIntStatus = AT91C_BASE_EMAC->EMAC_ISR;
|
||||
ulEventStatus = AT91C_BASE_EMAC->EMAC_RSR;
|
||||
|
||||
if( ( ulIntStatus & AT91C_EMAC_RCOMP ) || ( ulEventStatus & AT91C_EMAC_REC ) )
|
||||
{
|
||||
/* A frame has been received, signal the lwIP task so it can process
|
||||
the Rx descriptors. */
|
||||
xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
|
||||
AT91C_BASE_EMAC->EMAC_RSR = AT91C_EMAC_REC;
|
||||
}
|
||||
|
||||
if( ulIntStatus & AT91C_EMAC_TCOMP )
|
||||
{
|
||||
/* A frame has been transmitted. Mark all the buffers used by the
|
||||
frame just transmitted as free again. */
|
||||
vClearEMACTxBuffer();
|
||||
AT91C_BASE_EMAC->EMAC_TSR = AT91C_EMAC_COMP;
|
||||
}
|
||||
|
||||
/* Clear the interrupt. */
|
||||
AT91C_BASE_AIC->AIC_EOICR = 0;
|
||||
|
||||
/* If a task was woken by either a frame being received then we may need to
|
||||
switch to another task. If the unblocked task was of higher priority then
|
||||
the interrupted task it will then execute immediately that the ISR
|
||||
completes. */
|
||||
if( xHigherPriorityTaskWoken )
|
||||
{
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vEMACISR_Wrapper( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Call the handler to do the work. This must be a separate
|
||||
function to ensure the stack frame is set up correctly. */
|
||||
vEMACISR_Handler();
|
||||
|
||||
/* Restore the context of whichever task will execute next. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPassEMACSemaphore( xSemaphoreHandle xCreatedSemaphore )
|
||||
{
|
||||
/* Simply store the semaphore that should be used by the ISR. */
|
||||
xSemaphore = xCreatedSemaphore;
|
||||
}
|
||||
|
||||
105
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/EMAC/mii.h
Normal file
105
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/EMAC/mii.h
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/* Generic MII registers. */
|
||||
|
||||
#define MII_BMCR 0x00 /* Basic mode control register */
|
||||
#define MII_BMSR 0x01 /* Basic mode status register */
|
||||
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
|
||||
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
|
||||
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
|
||||
#define MII_LPA 0x05 /* Link partner ability reg */
|
||||
#define MII_EXPANSION 0x06 /* Expansion register */
|
||||
#define MII_DCOUNTER 0x12 /* Disconnect counter */
|
||||
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
|
||||
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
|
||||
#define MII_RERRCOUNTER 0x15 /* Receive error counter */
|
||||
#define MII_SREVISION 0x16 /* Silicon revision */
|
||||
#define MII_RESV1 0x17 /* Reserved... */
|
||||
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
|
||||
#define MII_PHYADDR 0x19 /* PHY address */
|
||||
#define MII_RESV2 0x1a /* Reserved... */
|
||||
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
|
||||
#define MII_NCONFIG 0x1c /* Network interface config */
|
||||
|
||||
/* Basic mode control register. */
|
||||
#define BMCR_RESV 0x007f /* Unused... */
|
||||
#define BMCR_CTST 0x0080 /* Collision test */
|
||||
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
|
||||
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
|
||||
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
|
||||
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
|
||||
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
|
||||
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
|
||||
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
|
||||
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
|
||||
|
||||
/* Basic mode status register. */
|
||||
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
|
||||
#define BMSR_JCD 0x0002 /* Jabber detected */
|
||||
#define BMSR_LSTATUS 0x0004 /* Link status */
|
||||
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
|
||||
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
|
||||
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
|
||||
#define BMSR_RESV 0x07c0 /* Unused... */
|
||||
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
|
||||
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
|
||||
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
|
||||
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
|
||||
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
|
||||
|
||||
/* Advertisement control register. */
|
||||
#define ADVERTISE_SLCT 0x001f /* Selector bits */
|
||||
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
|
||||
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
|
||||
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
|
||||
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
|
||||
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
|
||||
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
|
||||
#define ADVERTISE_RESV 0x1c00 /* Unused... */
|
||||
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
|
||||
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
|
||||
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
|
||||
|
||||
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
|
||||
ADVERTISE_CSMA)
|
||||
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
|
||||
ADVERTISE_100HALF | ADVERTISE_100FULL)
|
||||
|
||||
/* Link partner ability register. */
|
||||
#define LPA_SLCT 0x001f /* Same as advertise selector */
|
||||
#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
|
||||
#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
|
||||
#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
|
||||
#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
|
||||
#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
|
||||
#define LPA_RESV 0x1c00 /* Unused... */
|
||||
#define LPA_RFAULT 0x2000 /* Link partner faulted */
|
||||
#define LPA_LPACK 0x4000 /* Link partner acked us */
|
||||
#define LPA_NPAGE 0x8000 /* Next page bit */
|
||||
|
||||
#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
|
||||
#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
|
||||
|
||||
/* Expansion register for auto-negotiation. */
|
||||
#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
|
||||
#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
|
||||
#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
|
||||
#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
|
||||
#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
|
||||
#define EXPANSION_RESV 0xffe0 /* Unused... */
|
||||
|
||||
/* N-way test register. */
|
||||
#define NWAYTEST_RESV1 0x00ff /* Unused... */
|
||||
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
|
||||
#define NWAYTEST_RESV2 0xfe00 /* Unused... */
|
||||
|
||||
#define SPEED_10 10
|
||||
#define SPEED_100 100
|
||||
|
||||
/* Duplex, half or full. */
|
||||
#define DUPLEX_HALF 0x00
|
||||
#define DUPLEX_FULL 0x01
|
||||
|
||||
/* PHY ID */
|
||||
#define MII_DM9161_ID 0x0181b8a0
|
||||
#define MII_AM79C875_ID 0x00225540 /* 0x00225541 */
|
||||
|
||||
#define AT91C_PHY_ADDR 31
|
||||
102
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/FreeRTOSConfig.h
Normal file
102
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/FreeRTOSConfig.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_CONFIG_H
|
||||
#define FREERTOS_CONFIG_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Application specific definitions.
|
||||
*
|
||||
* These definitions should be adjusted for your particular hardware and
|
||||
* application requirements.
|
||||
*
|
||||
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
|
||||
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
|
||||
*
|
||||
* See http://www.freertos.org/a00110.html.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* The SWI is used by the scheduler. */
|
||||
#define vPortYieldProcessor swi_handler
|
||||
|
||||
|
||||
#define configUSE_PREEMPTION 1
|
||||
#define configUSE_IDLE_HOOK 1
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configCPU_CLOCK_HZ ( ( unsigned long ) 47923200 )
|
||||
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
|
||||
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
|
||||
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 110 )
|
||||
#define configTOTAL_HEAP_SIZE ( ( size_t ) 22000 )
|
||||
#define configMAX_TASK_NAME_LEN ( 16 )
|
||||
#define configUSE_TRACE_FACILITY 1
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configIDLE_SHOULD_YIELD 1
|
||||
|
||||
/* Co-routine definitions. */
|
||||
#define configUSE_CO_ROUTINES 0
|
||||
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
|
||||
|
||||
/* Set the following definitions to 1 to include the API function, or zero
|
||||
to exclude the API function. */
|
||||
|
||||
#define INCLUDE_vTaskPrioritySet 1
|
||||
#define INCLUDE_uxTaskPriorityGet 1
|
||||
#define INCLUDE_vTaskDelete 1
|
||||
#define INCLUDE_vTaskCleanUpResources 0
|
||||
#define INCLUDE_vTaskSuspend 1
|
||||
#define INCLUDE_vTaskDelayUntil 1
|
||||
#define INCLUDE_vTaskDelay 1
|
||||
#define INCLUDE_xTaskGetCurrentTaskHandle 1
|
||||
|
||||
#endif /* FREERTOS_CONFIG_H */
|
||||
107
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/ParTest/ParTest.c
Normal file
107
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/ParTest/ParTest.c
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* Demo application includes. */
|
||||
#include "partest.h"
|
||||
|
||||
/* Hardware specific includes. */
|
||||
#include "Board.h"
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Simple parallel port IO routines for the LED's. LED's can be set, cleared
|
||||
* or toggled.
|
||||
*-----------------------------------------------------------*/
|
||||
const unsigned long ulLED_MASK[ NB_LED ]= { LED1, LED2, LED3, LED4 };
|
||||
|
||||
void vParTestInitialise( void )
|
||||
{
|
||||
/* Start with all LED's off. */
|
||||
AT91C_BASE_PIOB->PIO_SODR = LED_MASK;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue )
|
||||
{
|
||||
if( uxLED < ( portBASE_TYPE ) NB_LED )
|
||||
{
|
||||
if( xValue )
|
||||
{
|
||||
AT91C_BASE_PIOB->PIO_SODR = ulLED_MASK[ uxLED ];
|
||||
}
|
||||
else
|
||||
{
|
||||
AT91C_BASE_PIOB->PIO_CODR = ulLED_MASK[ uxLED ];
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vParTestToggleLED( unsigned portBASE_TYPE uxLED )
|
||||
{
|
||||
if( uxLED < ( portBASE_TYPE ) NB_LED )
|
||||
{
|
||||
if( AT91C_BASE_PIOB->PIO_PDSR & ulLED_MASK[ uxLED ] )
|
||||
{
|
||||
AT91C_BASE_PIOB->PIO_CODR = ulLED_MASK[ uxLED ];
|
||||
}
|
||||
else
|
||||
{
|
||||
AT91C_BASE_PIOB->PIO_SODR = ulLED_MASK[ uxLED ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
[Version]
|
||||
Signature="$Windows NT$"
|
||||
Class=Ports
|
||||
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
|
||||
Provider=%ATMEL%
|
||||
LayoutFile=layout.inf
|
||||
DriverVer=10/15/1999,5.0.2153.1
|
||||
|
||||
[MANUFACTURER]
|
||||
%FreeRTOS%=FreeRTOS
|
||||
|
||||
[FreeRTOS]
|
||||
%FreeRTOS_CDC%=Reader,USB\VID_EB03&PID_0920
|
||||
|
||||
[Reader_Install.NTx86]
|
||||
;Windows2000
|
||||
|
||||
[DestinationDirs]
|
||||
DefaultDestDir=12
|
||||
Reader.NT.Copy=12
|
||||
|
||||
[Reader.NT]
|
||||
CopyFiles=Reader.NT.Copy
|
||||
AddReg=Reader.NT.AddReg
|
||||
|
||||
[Reader.NT.Copy]
|
||||
usbser.sys
|
||||
|
||||
[Reader.NT.AddReg]
|
||||
HKR,,NTMPDriver,,*ntkern
|
||||
HKR,,NTMPDriver,,usbser.sys
|
||||
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
|
||||
[Reader.NT.Services]
|
||||
AddService = usbser, 0x00000002,Service_Inst
|
||||
|
||||
[Service_Inst]
|
||||
DisplayName = %Serial.SvcDesc%
|
||||
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
|
||||
StartType = 3 ; SERVICE_DEMAND_START
|
||||
ErrorControl = 1 ;SERVICE_ERROR_NORMAL
|
||||
ServiceBinary = %12%\usbser.sys
|
||||
LoadOrderGroup = Base
|
||||
|
||||
[Strings]
|
||||
FreeRTOS = "FreeRTOS"
|
||||
FreeRTOS_CDC = "FreeRTOS CDC Demo"
|
||||
Serial.SvcDesc = "USB Serial emulation driver"
|
||||
|
||||
884
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/USB/USB-CDC.c
Normal file
884
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/USB/USB-CDC.c
Normal file
|
|
@ -0,0 +1,884 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
/*
|
||||
USB Communications Device Class driver.
|
||||
Implements task vUSBCDCTask and provides an Abstract Control Model serial
|
||||
interface. Control is through endpoint 0, device-to-host notification is
|
||||
provided by interrupt-in endpoint 3, and raw data is transferred through
|
||||
bulk endpoints 1 and 2.
|
||||
|
||||
- developed from original FreeRTOS HID example by Scott Miller
|
||||
- modified to support 3.2 GCC by najay
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Demo board includes. */
|
||||
#include "Board.h"
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* Demo app includes. */
|
||||
#include "USB-CDC.h"
|
||||
#include "descriptors.h"
|
||||
|
||||
#define usbNO_BLOCK ( ( portTickType ) 0 )
|
||||
|
||||
/* Reset all endpoints */
|
||||
static void prvResetEndPoints( void );
|
||||
|
||||
/* Clear pull up resistor to detach device from host */
|
||||
static void vDetachUSBInterface( void );
|
||||
|
||||
/* Set up interface and initialize variables */
|
||||
static void vInitUSBInterface( void );
|
||||
|
||||
/* Handle control endpoint events. */
|
||||
static void prvProcessEndPoint0Interrupt( xISRStatus *pxMessage );
|
||||
|
||||
/* Handle standard device requests. */
|
||||
static void prvHandleStandardDeviceRequest( xUSB_REQUEST *pxRequest );
|
||||
|
||||
/* Handle standard interface requests. */
|
||||
static void prvHandleStandardInterfaceRequest( xUSB_REQUEST *pxRequest );
|
||||
|
||||
/* Handle endpoint requests. */
|
||||
static void prvHandleStandardEndPointRequest( xUSB_REQUEST *pxRequest );
|
||||
|
||||
/* Handle class interface requests. */
|
||||
static void prvHandleClassInterfaceRequest( xUSB_REQUEST *pxRequest );
|
||||
|
||||
/* Prepare control data transfer. prvSendNextSegment starts transfer. */
|
||||
static void prvSendControlData( unsigned char *pucData, unsigned short usRequestedLength, unsigned long ulLengthLeftToSend, long lSendingDescriptor );
|
||||
|
||||
/* Send next segment of data for the control transfer */
|
||||
static void prvSendNextSegment( void );
|
||||
|
||||
/* Send stall - used to respond to unsupported requests */
|
||||
static void prvSendStall( void );
|
||||
|
||||
/* Send a zero-length (null) packet */
|
||||
static void prvSendZLP( void );
|
||||
|
||||
/* Handle requests for standard interface descriptors */
|
||||
static void prvGetStandardInterfaceDescriptor( xUSB_REQUEST *pxRequest );
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
/* File scope static variables */
|
||||
static unsigned char ucUSBConfig = ( unsigned char ) 0;
|
||||
static unsigned long ulReceivedAddress = ( unsigned long ) 0;
|
||||
static eDRIVER_STATE eDriverState = eNOTHING;
|
||||
|
||||
/* Incoming and outgoing control data structures */
|
||||
static xCONTROL_MESSAGE pxControlTx;
|
||||
static xCONTROL_MESSAGE pxControlRx;
|
||||
|
||||
/* Queue holding pointers to pending messages */
|
||||
xQueueHandle xUSBInterruptQueue;
|
||||
|
||||
/* Queues used to hold received characters, and characters waiting to be
|
||||
transmitted. Rx queue must be larger than FIFO size. */
|
||||
static xQueueHandle xRxCDC;
|
||||
static xQueueHandle xTxCDC;
|
||||
|
||||
/* Line coding - 115,200 baud, N-8-1 */
|
||||
static const unsigned char pxLineCoding[] = { 0x00, 0xC2, 0x01, 0x00, 0x00, 0x00, 0x08 };
|
||||
|
||||
/* Status variables. */
|
||||
static unsigned char ucControlState;
|
||||
static unsigned int uiCurrentBank;
|
||||
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
|
||||
void vUSBCDCTask( void *pvParameters )
|
||||
{
|
||||
xISRStatus *pxMessage;
|
||||
unsigned long ulStatus;
|
||||
unsigned long ulRxBytes;
|
||||
unsigned char ucByte;
|
||||
portBASE_TYPE xByte;
|
||||
|
||||
( void ) pvParameters;
|
||||
|
||||
/* Disconnect USB device from hub. For debugging - causes host to register reset */
|
||||
portENTER_CRITICAL();
|
||||
vDetachUSBInterface();
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
vTaskDelay( portTICK_RATE_MS * 60 );
|
||||
|
||||
/* Init USB interface */
|
||||
portENTER_CRITICAL();
|
||||
vInitUSBInterface();
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
/* Main task loop. Process incoming endpoint 0 interrupts, handle data transfers. */
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* Look for data coming from the ISR. */
|
||||
if( xQueueReceive( xUSBInterruptQueue, &pxMessage, usbSHORTEST_DELAY ) )
|
||||
{
|
||||
if( pxMessage->ulISR & AT91C_UDP_EPINT0 )
|
||||
{
|
||||
/* All endpoint 0 interrupts are handled here. */
|
||||
prvProcessEndPoint0Interrupt( pxMessage );
|
||||
}
|
||||
|
||||
if( pxMessage->ulISR & AT91C_UDP_ENDBUSRES )
|
||||
{
|
||||
/* End of bus reset - reset the endpoints and de-configure. */
|
||||
prvResetEndPoints();
|
||||
}
|
||||
}
|
||||
|
||||
/* See if we're ready to send and receive data. */
|
||||
if( eDriverState == eREADY_TO_SEND && ucControlState )
|
||||
{
|
||||
if( ( !(AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] & AT91C_UDP_TXPKTRDY) ) && uxQueueMessagesWaiting( xTxCDC ) )
|
||||
{
|
||||
for( xByte = 0; xByte < 64; xByte++ )
|
||||
{
|
||||
if( !xQueueReceive( xTxCDC, &ucByte, 0 ) )
|
||||
{
|
||||
/* No data buffered to transmit. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Got a byte to transmit. */
|
||||
AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_2 ] = ucByte;
|
||||
}
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] |= AT91C_UDP_TXPKTRDY;
|
||||
}
|
||||
|
||||
/* Check for incoming data (host-to-device) on endpoint 1. */
|
||||
while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1) )
|
||||
{
|
||||
ulRxBytes = (AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] >> 16) & usbRX_COUNT_MASK;
|
||||
|
||||
/* Only process FIFO if there's room to store it in the queue */
|
||||
if( ulRxBytes < ( USB_CDC_QUEUE_SIZE - uxQueueMessagesWaiting( xRxCDC ) ) )
|
||||
{
|
||||
while( ulRxBytes-- )
|
||||
{
|
||||
ucByte = AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ];
|
||||
xQueueSend( xRxCDC, &ucByte, 0 );
|
||||
}
|
||||
|
||||
/* Release the FIFO */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];
|
||||
usbCSR_CLEAR_BIT( &ulStatus, uiCurrentBank );
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulStatus;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
/* Re-enable endpoint 1's interrupts */
|
||||
AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
|
||||
|
||||
/* Update the current bank in use */
|
||||
if( uiCurrentBank == AT91C_UDP_RX_DATA_BK0 )
|
||||
{
|
||||
uiCurrentBank = AT91C_UDP_RX_DATA_BK1;
|
||||
}
|
||||
else
|
||||
{
|
||||
uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
void vUSBSendByte( char cByte )
|
||||
{
|
||||
/* Queue the byte to be sent. The USB task will send it. */
|
||||
xQueueSend( xTxCDC, &cByte, usbNO_BLOCK );
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
static void prvSendZLP( void )
|
||||
{
|
||||
unsigned long ulStatus;
|
||||
|
||||
/* Wait until the FIFO is free - even though we are not going to use it.
|
||||
THERE IS NO TIMEOUT HERE! */
|
||||
while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_TXPKTRDY )
|
||||
{
|
||||
vTaskDelay( usbSHORTEST_DELAY );
|
||||
}
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* Cancel any further pending data */
|
||||
pxControlTx.ulTotalDataLength = pxControlTx.ulNextCharIndex;
|
||||
|
||||
/* Set the TXPKTRDY bit to cause a transmission with no data. */
|
||||
ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
|
||||
usbCSR_SET_BIT( &ulStatus, AT91C_UDP_TXPKTRDY );
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
static void prvSendStall( void )
|
||||
{
|
||||
unsigned long ulStatus;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* Force a stall by simply setting the FORCESTALL bit in the CSR. */
|
||||
ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
|
||||
usbCSR_SET_BIT( &ulStatus, AT91C_UDP_FORCESTALL );
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
static void prvResetEndPoints( void )
|
||||
{
|
||||
unsigned long ulTemp;
|
||||
|
||||
eDriverState = eJUST_RESET;
|
||||
ucControlState = 0;
|
||||
|
||||
/* Reset all the end points. */
|
||||
AT91C_BASE_UDP->UDP_RSTEP = usbEND_POINT_RESET_MASK;
|
||||
AT91C_BASE_UDP->UDP_RSTEP = ( unsigned long ) 0x00;
|
||||
|
||||
/* Enable data to be sent and received. */
|
||||
AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
|
||||
|
||||
/* Repair the configuration end point. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
|
||||
usbCSR_SET_BIT( &ulTemp, ( ( unsigned long ) ( AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL ) ) );
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulTemp;
|
||||
AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT0;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
static void prvProcessEndPoint0Interrupt( xISRStatus *pxMessage )
|
||||
{
|
||||
static xUSB_REQUEST xRequest;
|
||||
unsigned long ulRxBytes;
|
||||
|
||||
/* Get number of bytes received, if any */
|
||||
ulRxBytes = pxMessage->ulCSR0 >> 16;
|
||||
ulRxBytes &= usbRX_COUNT_MASK;
|
||||
|
||||
if( pxMessage->ulCSR0 & AT91C_UDP_TXCOMP )
|
||||
{
|
||||
/* We received a TX complete interrupt. What we do depends on
|
||||
what we sent to get this interrupt. */
|
||||
|
||||
if( eDriverState == eJUST_GOT_CONFIG )
|
||||
{
|
||||
/* We sent an acknowledgement of a SET_CONFIG request. We
|
||||
are now at the end of the enumeration.
|
||||
|
||||
TODO: Config 0 sets unconfigured state, should enter Address state.
|
||||
Request for unsupported config should stall. */
|
||||
AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG;
|
||||
|
||||
/* Set up endpoints */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
unsigned long ulTemp;
|
||||
|
||||
/* Set endpoint 1 to bulk-out */
|
||||
ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];
|
||||
usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT );
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulTemp;
|
||||
AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
|
||||
/* Set endpoint 2 to bulk-in */
|
||||
ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ];
|
||||
usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN );
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] = ulTemp;
|
||||
AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT2;
|
||||
/* Set endpoint 3 to interrupt-in, enable it, and enable interrupts */
|
||||
ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_3 ];
|
||||
usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN );
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_3 ] = ulTemp;
|
||||
/*AT91F_UDP_EnableIt( AT91C_BASE_UDP, AT91C_UDP_EPINT3 ); */
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
eDriverState = eREADY_TO_SEND;
|
||||
}
|
||||
else if( eDriverState == eJUST_GOT_ADDRESS )
|
||||
{
|
||||
/* We sent an acknowledgement of a SET_ADDRESS request. Move
|
||||
to the addressed state. */
|
||||
if( ulReceivedAddress != ( unsigned long ) 0 )
|
||||
{
|
||||
AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
AT91C_BASE_UDP->UDP_GLBSTATE = 0;
|
||||
}
|
||||
|
||||
AT91C_BASE_UDP->UDP_FADDR = ( AT91C_UDP_FEN | ulReceivedAddress );
|
||||
eDriverState = eNOTHING;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The TXCOMP was not for any special type of transmission. See
|
||||
if there is any more data to send. */
|
||||
prvSendNextSegment();
|
||||
}
|
||||
}
|
||||
|
||||
if( pxMessage->ulCSR0 & AT91C_UDP_RX_DATA_BK0 )
|
||||
{
|
||||
/* Received a control data packet. May be a 0-length ACK or a data stage. */
|
||||
unsigned char ucBytesToGet;
|
||||
|
||||
/* Got data. Cancel any outgoing data. */
|
||||
pxControlTx.ulNextCharIndex = pxControlTx.ulTotalDataLength;
|
||||
|
||||
/* Determine how many bytes we need to receive. */
|
||||
ucBytesToGet = pxControlRx.ulTotalDataLength - pxControlRx.ulNextCharIndex;
|
||||
if( ucBytesToGet > ulRxBytes )
|
||||
{
|
||||
ucBytesToGet = ulRxBytes;
|
||||
}
|
||||
|
||||
/* If we're not expecting any data, it's an ack - just quit now. */
|
||||
if( !ucBytesToGet )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the required data and update the index. */
|
||||
memcpy( pxControlRx.ucBuffer, pxMessage->ucFifoData, ucBytesToGet );
|
||||
pxControlRx.ulNextCharIndex += ucBytesToGet;
|
||||
}
|
||||
|
||||
if( pxMessage->ulCSR0 & AT91C_UDP_RXSETUP )
|
||||
{
|
||||
/* Received a SETUP packet. May be followed by data packets. */
|
||||
|
||||
if( ulRxBytes >= usbEXPECTED_NUMBER_OF_BYTES )
|
||||
{
|
||||
/* Create an xUSB_REQUEST variable from the raw bytes array. */
|
||||
|
||||
xRequest.ucReqType = pxMessage->ucFifoData[ usbREQUEST_TYPE_INDEX ];
|
||||
xRequest.ucRequest = pxMessage->ucFifoData[ usbREQUEST_INDEX ];
|
||||
|
||||
xRequest.usValue = pxMessage->ucFifoData[ usbVALUE_HIGH_BYTE ];
|
||||
xRequest.usValue <<= 8;
|
||||
xRequest.usValue |= pxMessage->ucFifoData[ usbVALUE_LOW_BYTE ];
|
||||
|
||||
xRequest.usIndex = pxMessage->ucFifoData[ usbINDEX_HIGH_BYTE ];
|
||||
xRequest.usIndex <<= 8;
|
||||
xRequest.usIndex |= pxMessage->ucFifoData[ usbINDEX_LOW_BYTE ];
|
||||
|
||||
xRequest.usLength = pxMessage->ucFifoData[ usbLENGTH_HIGH_BYTE ];
|
||||
xRequest.usLength <<= 8;
|
||||
xRequest.usLength |= pxMessage->ucFifoData[ usbLENGTH_LOW_BYTE ];
|
||||
|
||||
pxControlRx.ulNextCharIndex = 0;
|
||||
if( ! (xRequest.ucReqType & 0x80) ) /* Host-to-Device transfer, may need to get data first */
|
||||
{
|
||||
if( xRequest.usLength > usbMAX_CONTROL_MESSAGE_SIZE )
|
||||
{
|
||||
/* Too big! No space for control data, stall and abort. */
|
||||
prvSendStall();
|
||||
return;
|
||||
}
|
||||
|
||||
pxControlRx.ulTotalDataLength = xRequest.usLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We're sending the data, don't wait for any. */
|
||||
pxControlRx.ulTotalDataLength = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* See if we've got a pending request and all its associated data ready */
|
||||
if( ( pxMessage->ulCSR0 & ( AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RXSETUP ) )
|
||||
&& ( pxControlRx.ulNextCharIndex >= pxControlRx.ulTotalDataLength ) )
|
||||
{
|
||||
unsigned char ucRequest;
|
||||
|
||||
/* Manipulate the ucRequestType and the ucRequest parameters to
|
||||
generate a zero based request selection. This is just done to
|
||||
break up the requests into subsections for clarity. The
|
||||
alternative would be to have more huge switch statement that would
|
||||
be difficult to optimise. */
|
||||
ucRequest = ( ( xRequest.ucReqType & 0x60 ) >> 3 );
|
||||
ucRequest |= ( xRequest.ucReqType & 0x03 );
|
||||
|
||||
switch( ucRequest )
|
||||
{
|
||||
case usbSTANDARD_DEVICE_REQUEST:
|
||||
/* Standard Device request */
|
||||
prvHandleStandardDeviceRequest( &xRequest );
|
||||
break;
|
||||
|
||||
case usbSTANDARD_INTERFACE_REQUEST:
|
||||
/* Standard Interface request */
|
||||
prvHandleStandardInterfaceRequest( &xRequest );
|
||||
break;
|
||||
|
||||
case usbSTANDARD_END_POINT_REQUEST:
|
||||
/* Standard Endpoint request */
|
||||
prvHandleStandardEndPointRequest( &xRequest );
|
||||
break;
|
||||
|
||||
case usbCLASS_INTERFACE_REQUEST:
|
||||
/* Class Interface request */
|
||||
prvHandleClassInterfaceRequest( &xRequest );
|
||||
break;
|
||||
|
||||
default: /* This is not something we want to respond to. */
|
||||
prvSendStall();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
static void prvGetStandardDeviceDescriptor( xUSB_REQUEST *pxRequest )
|
||||
{
|
||||
/* The type is in the high byte. Return whatever has been requested. */
|
||||
switch( ( pxRequest->usValue & 0xff00 ) >> 8 )
|
||||
{
|
||||
case usbDESCRIPTOR_TYPE_DEVICE:
|
||||
prvSendControlData( ( unsigned char * ) &pxDeviceDescriptor, pxRequest->usLength, sizeof( pxDeviceDescriptor ), pdTRUE );
|
||||
break;
|
||||
|
||||
case usbDESCRIPTOR_TYPE_CONFIGURATION:
|
||||
prvSendControlData( ( unsigned char * ) &( pxConfigDescriptor ), pxRequest->usLength, sizeof( pxConfigDescriptor ), pdTRUE );
|
||||
break;
|
||||
|
||||
case usbDESCRIPTOR_TYPE_STRING:
|
||||
|
||||
/* The index to the string descriptor is the lower byte. */
|
||||
switch( pxRequest->usValue & 0xff )
|
||||
{
|
||||
case usbLANGUAGE_STRING:
|
||||
prvSendControlData( ( unsigned char * ) &pxLanguageStringDescriptor, pxRequest->usLength, sizeof(pxLanguageStringDescriptor), pdTRUE );
|
||||
break;
|
||||
|
||||
case usbMANUFACTURER_STRING:
|
||||
prvSendControlData( ( unsigned char * ) &pxManufacturerStringDescriptor, pxRequest->usLength, sizeof( pxManufacturerStringDescriptor ), pdTRUE );
|
||||
break;
|
||||
|
||||
case usbPRODUCT_STRING:
|
||||
prvSendControlData( ( unsigned char * ) &pxProductStringDescriptor, pxRequest->usLength, sizeof( pxProductStringDescriptor ), pdTRUE );
|
||||
break;
|
||||
|
||||
case usbCONFIGURATION_STRING:
|
||||
prvSendControlData( ( unsigned char * ) &pxConfigurationStringDescriptor, pxRequest->usLength, sizeof( pxConfigurationStringDescriptor ), pdTRUE );
|
||||
break;
|
||||
|
||||
case usbINTERFACE_STRING:
|
||||
prvSendControlData( ( unsigned char * ) &pxInterfaceStringDescriptor, pxRequest->usLength, sizeof( pxInterfaceStringDescriptor ), pdTRUE );
|
||||
break;
|
||||
|
||||
default:
|
||||
prvSendStall();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
prvSendStall();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
static void prvHandleStandardDeviceRequest( xUSB_REQUEST *pxRequest )
|
||||
{
|
||||
unsigned short usStatus = 0;
|
||||
|
||||
switch( pxRequest->ucRequest )
|
||||
{
|
||||
case usbGET_STATUS_REQUEST:
|
||||
/* Just send two byte dummy status. */
|
||||
prvSendControlData( ( unsigned char * ) &usStatus, sizeof( usStatus ), sizeof( usStatus ), pdFALSE );
|
||||
break;
|
||||
|
||||
case usbGET_DESCRIPTOR_REQUEST:
|
||||
/* Send device descriptor */
|
||||
prvGetStandardDeviceDescriptor( pxRequest );
|
||||
break;
|
||||
|
||||
case usbGET_CONFIGURATION_REQUEST:
|
||||
/* Send selected device configuration */
|
||||
prvSendControlData( ( unsigned char * ) &ucUSBConfig, sizeof( ucUSBConfig ), sizeof( ucUSBConfig ), pdFALSE );
|
||||
break;
|
||||
|
||||
case usbSET_FEATURE_REQUEST:
|
||||
prvSendZLP();
|
||||
break;
|
||||
|
||||
case usbSET_ADDRESS_REQUEST:
|
||||
/* Get assigned address and send ack, but don't implement new address until we get a TXCOMP */
|
||||
prvSendZLP();
|
||||
eDriverState = eJUST_GOT_ADDRESS;
|
||||
ulReceivedAddress = ( unsigned long ) pxRequest->usValue;
|
||||
break;
|
||||
|
||||
case usbSET_CONFIGURATION_REQUEST:
|
||||
/* Ack SET_CONFIGURATION request, but don't implement until TXCOMP */
|
||||
ucUSBConfig = ( unsigned char ) ( pxRequest->usValue & 0xff );
|
||||
eDriverState = eJUST_GOT_CONFIG;
|
||||
prvSendZLP();
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Any unsupported request results in a STALL response. */
|
||||
prvSendStall();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
static void prvHandleClassInterfaceRequest( xUSB_REQUEST *pxRequest )
|
||||
{
|
||||
switch( pxRequest->ucRequest )
|
||||
{
|
||||
case usbSEND_ENCAPSULATED_COMMAND:
|
||||
prvSendStall();
|
||||
break;
|
||||
|
||||
case usbGET_ENCAPSULATED_RESPONSE:
|
||||
prvSendStall();
|
||||
break;
|
||||
|
||||
case usbSET_LINE_CODING:
|
||||
/* Set line coding - baud rate, data bits, parity, stop bits */
|
||||
prvSendZLP();
|
||||
memcpy( ( void * ) pxLineCoding, pxControlRx.ucBuffer, sizeof( pxLineCoding ) );
|
||||
break;
|
||||
|
||||
case usbGET_LINE_CODING:
|
||||
/* Get line coding */
|
||||
prvSendControlData( (unsigned char *) &pxLineCoding, pxRequest->usLength, sizeof( pxLineCoding ), pdFALSE );
|
||||
break;
|
||||
|
||||
case usbSET_CONTROL_LINE_STATE:
|
||||
/* D0: 1=DTR, 0=No DTR, D1: 1=Activate Carrier, 0=Deactivate carrier (RTS, half-duplex) */
|
||||
prvSendZLP();
|
||||
ucControlState = pxRequest->usValue;
|
||||
break;
|
||||
|
||||
default:
|
||||
prvSendStall();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
static void prvGetStandardInterfaceDescriptor( xUSB_REQUEST *pxRequest )
|
||||
{
|
||||
switch( ( pxRequest->usValue & ( unsigned short ) 0xff00 ) >> 8 )
|
||||
{
|
||||
default:
|
||||
prvSendStall();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHandleStandardInterfaceRequest( xUSB_REQUEST *pxRequest )
|
||||
{
|
||||
unsigned short usStatus = 0;
|
||||
|
||||
switch( pxRequest->ucRequest )
|
||||
{
|
||||
case usbGET_STATUS_REQUEST:
|
||||
/* Send dummy 2 bytes. */
|
||||
prvSendControlData( ( unsigned char * ) &usStatus, sizeof( usStatus ), sizeof( usStatus ), pdFALSE );
|
||||
break;
|
||||
|
||||
case usbGET_DESCRIPTOR_REQUEST:
|
||||
prvGetStandardInterfaceDescriptor( pxRequest );
|
||||
break;
|
||||
|
||||
/* This minimal implementation does not respond to these. */
|
||||
case usbGET_INTERFACE_REQUEST:
|
||||
case usbSET_FEATURE_REQUEST:
|
||||
case usbSET_INTERFACE_REQUEST:
|
||||
|
||||
default:
|
||||
prvSendStall();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHandleStandardEndPointRequest( xUSB_REQUEST *pxRequest )
|
||||
{
|
||||
switch( pxRequest->ucRequest )
|
||||
{
|
||||
/* This minimal implementation does not expect to respond to these. */
|
||||
case usbGET_STATUS_REQUEST:
|
||||
case usbCLEAR_FEATURE_REQUEST:
|
||||
case usbSET_FEATURE_REQUEST:
|
||||
|
||||
default:
|
||||
prvSendStall();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vDetachUSBInterface( void)
|
||||
{
|
||||
/* Setup the PIO for the USB pull up resistor. */
|
||||
AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16;
|
||||
AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16;
|
||||
|
||||
|
||||
/* Disable pull up */
|
||||
AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA16;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vInitUSBInterface( void )
|
||||
{
|
||||
extern void ( vUSB_ISR_Wrapper )( void );
|
||||
|
||||
/* Create the queue used to communicate between the USB ISR and task. */
|
||||
xUSBInterruptQueue = xQueueCreate( usbQUEUE_LENGTH + 1, sizeof( xISRStatus * ) );
|
||||
|
||||
/* Create the queues used to hold Rx and Tx characters. */
|
||||
xRxCDC = xQueueCreate( USB_CDC_QUEUE_SIZE, ( unsigned char ) sizeof( signed char ) );
|
||||
xTxCDC = xQueueCreate( USB_CDC_QUEUE_SIZE + 1, ( unsigned char ) sizeof( signed char ) );
|
||||
|
||||
if( (!xUSBInterruptQueue) || (!xRxCDC) || (!xTxCDC) )
|
||||
{
|
||||
/* Not enough RAM to create queues!. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialise a few state variables. */
|
||||
pxControlTx.ulNextCharIndex = ( unsigned long ) 0;
|
||||
pxControlRx.ulNextCharIndex = ( unsigned long ) 0;
|
||||
ucUSBConfig = ( unsigned char ) 0;
|
||||
eDriverState = eNOTHING;
|
||||
ucControlState = 0;
|
||||
uiCurrentBank = AT91C_UDP_RX_DATA_BK0;
|
||||
|
||||
|
||||
/* HARDWARE SETUP */
|
||||
|
||||
/* Set the PLL USB Divider */
|
||||
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1;
|
||||
|
||||
/* Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock. */
|
||||
AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
|
||||
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
|
||||
|
||||
/* Setup the PIO for the USB pull up resistor. */
|
||||
AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16;
|
||||
AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16;
|
||||
|
||||
|
||||
/* Start without the pullup - this will get set at the end of this
|
||||
function. */
|
||||
AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA16;
|
||||
|
||||
|
||||
/* When using the USB debugger the peripheral registers do not always get
|
||||
set to the correct default values. To make sure set the relevant registers
|
||||
manually here. */
|
||||
AT91C_BASE_UDP->UDP_IDR = ( unsigned long ) 0xffffffff;
|
||||
AT91C_BASE_UDP->UDP_ICR = ( unsigned long ) 0xffffffff;
|
||||
AT91C_BASE_UDP->UDP_CSR[ 0 ] = ( unsigned long ) 0x00;
|
||||
AT91C_BASE_UDP->UDP_CSR[ 1 ] = ( unsigned long ) 0x00;
|
||||
AT91C_BASE_UDP->UDP_CSR[ 2 ] = ( unsigned long ) 0x00;
|
||||
AT91C_BASE_UDP->UDP_CSR[ 3 ] = ( unsigned long ) 0x00;
|
||||
AT91C_BASE_UDP->UDP_GLBSTATE = 0;
|
||||
AT91C_BASE_UDP->UDP_FADDR = 0;
|
||||
|
||||
/* Enable the transceiver. */
|
||||
AT91C_UDP_TRANSCEIVER_ENABLE = 0;
|
||||
|
||||
/* Enable the USB interrupts - other interrupts get enabled as the
|
||||
enumeration process progresses. */
|
||||
AT91F_AIC_ConfigureIt( AT91C_ID_UDP, usbINTERRUPT_PRIORITY, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vUSB_ISR_Wrapper );
|
||||
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_UDP;
|
||||
|
||||
|
||||
/* Wait a short while before making our presence known. */
|
||||
vTaskDelay( usbINIT_DELAY );
|
||||
AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA16;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSendControlData( unsigned char *pucData, unsigned short usRequestedLength, unsigned long ulLengthToSend, long lSendingDescriptor )
|
||||
{
|
||||
if( ( ( unsigned long ) usRequestedLength < ulLengthToSend ) )
|
||||
{
|
||||
/* Cap the data length to that requested. */
|
||||
ulLengthToSend = ( unsigned short ) usRequestedLength;
|
||||
}
|
||||
else if( ( ulLengthToSend < ( unsigned long ) usRequestedLength ) && lSendingDescriptor )
|
||||
{
|
||||
/* We are sending a descriptor. If the descriptor is an exact
|
||||
multiple of the FIFO length then it will have to be terminated
|
||||
with a NULL packet. Set the state to indicate this if
|
||||
necessary. */
|
||||
if( ( ulLengthToSend % usbFIFO_LENGTH ) == 0 )
|
||||
{
|
||||
eDriverState = eSENDING_EVEN_DESCRIPTOR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Here we assume that the previous message has been sent. THERE IS NO
|
||||
BUFFER OVERFLOW PROTECTION HERE.
|
||||
|
||||
Copy the data to send into the buffer as we cannot send it all at once
|
||||
(if it is greater than 8 bytes in length). */
|
||||
memcpy( pxControlTx.ucBuffer, pucData, ulLengthToSend );
|
||||
|
||||
/* Reinitialise the buffer index so we start sending from the start of
|
||||
the data. */
|
||||
pxControlTx.ulTotalDataLength = ulLengthToSend;
|
||||
pxControlTx.ulNextCharIndex = ( unsigned long ) 0;
|
||||
|
||||
/* Send the first 8 bytes now. The rest will get sent in response to
|
||||
TXCOMP interrupts. */
|
||||
prvSendNextSegment();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSendNextSegment( void )
|
||||
{
|
||||
volatile unsigned long ulNextLength, ulStatus, ulLengthLeftToSend;
|
||||
|
||||
/* Is there any data to send? */
|
||||
if( pxControlTx.ulTotalDataLength > pxControlTx.ulNextCharIndex )
|
||||
{
|
||||
ulLengthLeftToSend = pxControlTx.ulTotalDataLength - pxControlTx.ulNextCharIndex;
|
||||
|
||||
/* We can only send 8 bytes to the fifo at a time. */
|
||||
if( ulLengthLeftToSend > usbFIFO_LENGTH )
|
||||
{
|
||||
ulNextLength = usbFIFO_LENGTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulNextLength = ulLengthLeftToSend;
|
||||
}
|
||||
|
||||
/* Wait until we can place data in the fifo. THERE IS NO TIMEOUT
|
||||
HERE! */
|
||||
while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_TXPKTRDY )
|
||||
{
|
||||
vTaskDelay( usbSHORTEST_DELAY );
|
||||
}
|
||||
|
||||
/* Write the data to the FIFO. */
|
||||
while( ulNextLength > ( unsigned long ) 0 )
|
||||
{
|
||||
AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_0 ] = pxControlTx.ucBuffer[ pxControlTx.ulNextCharIndex ];
|
||||
|
||||
ulNextLength--;
|
||||
pxControlTx.ulNextCharIndex++;
|
||||
}
|
||||
|
||||
/* Start the transmission. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
|
||||
usbCSR_SET_BIT( &ulStatus, ( ( unsigned long ) 0x10 ) );
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There is no data to send. If we were sending a descriptor and the
|
||||
descriptor was an exact multiple of the max packet size then we need
|
||||
to send a null to terminate the transmission. */
|
||||
if( eDriverState == eSENDING_EVEN_DESCRIPTOR )
|
||||
{
|
||||
prvSendZLP();
|
||||
eDriverState = eNOTHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
107
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/USB/USB-CDC.h
Normal file
107
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/USB/USB-CDC.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
#ifndef USB_CDC_H
|
||||
#define USB_CDC_H
|
||||
|
||||
#include "usb.h"
|
||||
|
||||
#define USB_CDC_QUEUE_SIZE 200
|
||||
|
||||
/* Structure used to take a snapshot of the USB status from within the ISR. */
|
||||
typedef struct X_ISR_STATUS
|
||||
{
|
||||
unsigned long ulISR;
|
||||
unsigned long ulCSR0;
|
||||
unsigned char ucFifoData[ 8 ];
|
||||
} xISRStatus;
|
||||
|
||||
/* Structure used to hold the received requests. */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char ucReqType;
|
||||
unsigned char ucRequest;
|
||||
unsigned short usValue;
|
||||
unsigned short usIndex;
|
||||
unsigned short usLength;
|
||||
} xUSB_REQUEST;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eNOTHING,
|
||||
eJUST_RESET,
|
||||
eJUST_GOT_CONFIG,
|
||||
eJUST_GOT_ADDRESS,
|
||||
eSENDING_EVEN_DESCRIPTOR,
|
||||
eREADY_TO_SEND
|
||||
} eDRIVER_STATE;
|
||||
|
||||
/* Structure used to control the data being sent to the host. */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char ucBuffer[ usbMAX_CONTROL_MESSAGE_SIZE ];
|
||||
unsigned long ulNextCharIndex;
|
||||
unsigned long ulTotalDataLength;
|
||||
} xCONTROL_MESSAGE;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
void vUSBCDCTask( void *pvParameters );
|
||||
|
||||
/* Send cByte down the USB port. Characters are simply buffered and not
|
||||
sent unless the port is connected. */
|
||||
void vUSBSendByte( char cByte );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
198
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/USB/USBIsr.c
Normal file
198
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/USB/USBIsr.c
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
BASIC INTERRUPT DRIVEN DRIVER FOR USB.
|
||||
|
||||
This file contains all the usb components that must be compiled
|
||||
to ARM mode. The components that can be compiled to either ARM or THUMB
|
||||
mode are contained in USB-CDC.c.
|
||||
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
|
||||
/* Demo application includes. */
|
||||
#include "Board.h"
|
||||
#include "usb.h"
|
||||
#include "USB-CDC.h"
|
||||
|
||||
#define usbINT_CLEAR_MASK (AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP | AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Messages and queue used to communicate between the ISR and the USB task. */
|
||||
static xISRStatus xISRMessages[ usbQUEUE_LENGTH + 1 ];
|
||||
extern xQueueHandle xUSBInterruptQueue;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The ISR can cause a context switch so is declared naked. */
|
||||
void vUSB_ISR_Wrapper( void ) __attribute__ ((naked));
|
||||
|
||||
/* The function that actually performs the ISR work. This must be separate
|
||||
from the wrapper function to ensure the correct stack frame gets set up. */
|
||||
void vUSB_ISR_Handler( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vUSB_ISR_Handler( void )
|
||||
{
|
||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||||
static volatile unsigned long ulNextMessage = 0;
|
||||
xISRStatus *pxMessage;
|
||||
unsigned long ulRxBytes;
|
||||
unsigned char ucFifoIndex;
|
||||
|
||||
/* Use the next message from the array. */
|
||||
pxMessage = &( xISRMessages[ ( ulNextMessage & usbQUEUE_LENGTH ) ] );
|
||||
ulNextMessage++;
|
||||
|
||||
/* Save UDP ISR state for task-level processing. */
|
||||
pxMessage->ulISR = AT91C_BASE_UDP->UDP_ISR;
|
||||
pxMessage->ulCSR0 = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
|
||||
|
||||
/* Clear interrupts from ICR. */
|
||||
AT91C_BASE_UDP->UDP_ICR = AT91C_BASE_UDP->UDP_IMR | AT91C_UDP_ENDBUSRES;
|
||||
|
||||
|
||||
/* Process incoming FIFO data. Must set DIR (if needed) and clear RXSETUP
|
||||
before exit. */
|
||||
|
||||
/* Read CSR and get incoming byte count. */
|
||||
ulRxBytes = ( pxMessage->ulCSR0 >> 16 ) & usbRX_COUNT_MASK;
|
||||
|
||||
/* Receive control transfers on endpoint 0. */
|
||||
if( pxMessage->ulCSR0 & ( AT91C_UDP_RXSETUP | AT91C_UDP_RX_DATA_BK0 ) )
|
||||
{
|
||||
/* Save FIFO data buffer for either a SETUP or DATA stage */
|
||||
for( ucFifoIndex = 0; ucFifoIndex < ulRxBytes; ucFifoIndex++ )
|
||||
{
|
||||
pxMessage->ucFifoData[ ucFifoIndex ] = AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_0 ];
|
||||
}
|
||||
|
||||
/* Set direction for data stage. Must be done before RXSETUP is
|
||||
cleared. */
|
||||
if( ( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_RXSETUP ) )
|
||||
{
|
||||
if( ulRxBytes && ( pxMessage->ucFifoData[ usbREQUEST_TYPE_INDEX ] & 0x80 ) )
|
||||
{
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] |= AT91C_UDP_DIR;
|
||||
|
||||
/* Might not be wise in an ISR! */
|
||||
while( !(AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_DIR) );
|
||||
}
|
||||
|
||||
/* Clear RXSETUP */
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] &= ~AT91C_UDP_RXSETUP;
|
||||
|
||||
/* Might not be wise in an ISR! */
|
||||
while ( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_RXSETUP );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear RX_DATA_BK0 */
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] &= ~AT91C_UDP_RX_DATA_BK0;
|
||||
|
||||
/* Might not be wise in an ISR! */
|
||||
while ( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_RX_DATA_BK0 );
|
||||
}
|
||||
}
|
||||
|
||||
/* If we received data on endpoint 1, disable its interrupts until it is
|
||||
processed in the main loop */
|
||||
if( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] & ( AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 ) )
|
||||
{
|
||||
AT91C_BASE_UDP->UDP_IDR = AT91C_UDP_EPINT1;
|
||||
}
|
||||
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] &= ~( AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT );
|
||||
|
||||
/* Clear interrupts for the other endpoints, retain data flags for endpoint
|
||||
1. */
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] &= ~( AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP );
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_2 ] &= ~usbINT_CLEAR_MASK;
|
||||
AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_3 ] &= ~usbINT_CLEAR_MASK;
|
||||
|
||||
/* Post ISR data to queue for task-level processing */
|
||||
xQueueSendFromISR( xUSBInterruptQueue, &pxMessage, &xHigherPriorityTaskWoken );
|
||||
|
||||
/* Clear AIC to complete ISR processing */
|
||||
AT91C_BASE_AIC->AIC_EOICR = 0;
|
||||
|
||||
/* Do a task switch if needed */
|
||||
if( xHigherPriorityTaskWoken )
|
||||
{
|
||||
/* This call will ensure that the unblocked task will be executed
|
||||
immediately upon completion of the ISR if it has a priority higher
|
||||
than the interrupted task. */
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vUSB_ISR_Wrapper( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Call the handler to do the work. This must be a separate
|
||||
function to ensure the stack frame is set up correctly. */
|
||||
vUSB_ISR_Handler();
|
||||
|
||||
/* Restore the context of whichever task will execute next. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
|
||||
224
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/USB/descriptors.h
Normal file
224
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/USB/descriptors.h
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
/*
|
||||
- DESCRIPTOR DEFINITIONS -
|
||||
*/
|
||||
|
||||
/* String descriptors used during the enumeration process.
|
||||
These take the form:
|
||||
|
||||
{
|
||||
Length of descriptor,
|
||||
Descriptor type,
|
||||
Data
|
||||
}
|
||||
*/
|
||||
|
||||
const char pxLanguageStringDescriptor[] =
|
||||
{
|
||||
4,
|
||||
usbDESCRIPTOR_TYPE_STRING,
|
||||
0x09, 0x04
|
||||
};
|
||||
|
||||
const char pxManufacturerStringDescriptor[] =
|
||||
{
|
||||
18,
|
||||
usbDESCRIPTOR_TYPE_STRING,
|
||||
|
||||
'F', 0x00, 'r', 0x00, 'e', 0x00, 'e', 0x00, 'R', 0x00, 'T', 0x00, 'O', 0x00, 'S', 0x00
|
||||
};
|
||||
|
||||
const char pxProductStringDescriptor[] =
|
||||
{
|
||||
36,
|
||||
usbDESCRIPTOR_TYPE_STRING,
|
||||
|
||||
'F', 0x00, 'r', 0x00, 'e', 0x00, 'e', 0x00, 'R', 0x00, 'T', 0x00, 'O', 0x00, 'S', 0x00, ' ', 0x00, 'C', 0x00, 'D', 0x00,
|
||||
'C', 0x00, ' ', 0x00, 'D', 0x00, 'E', 0x00, 'M', 0x00, 'O', 0x00
|
||||
};
|
||||
|
||||
const char pxConfigurationStringDescriptor[] =
|
||||
{
|
||||
38,
|
||||
usbDESCRIPTOR_TYPE_STRING,
|
||||
|
||||
'C', 0x00, 'o', 0x00, 'n', 0x00, 'f', 0x00, 'i', 0x00, 'g', 0x00, 'u', 0x00, 'r', 0x00, 'a', 0x00, 't', 0x00, 'i', 0x00,
|
||||
'o', 0x00, 'n', 0x00, ' ', 0x00, 'N', 0x00, 'a', 0x00, 'm', 0x00, 'e', 0x00
|
||||
};
|
||||
|
||||
const char pxInterfaceStringDescriptor[] =
|
||||
{
|
||||
30,
|
||||
usbDESCRIPTOR_TYPE_STRING,
|
||||
|
||||
'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, ' ', 0x00, 'N', 0x00,
|
||||
'a', 0x00, 'm', 0x00, 'e', 0x00
|
||||
};
|
||||
|
||||
/* Device should properly be 0x134A:0x9001, using 0x05F9:0xFFFF for Linux testing */
|
||||
const char pxDeviceDescriptor[] =
|
||||
{
|
||||
/* Device descriptor */
|
||||
0x12, /* bLength */
|
||||
0x01, /* bDescriptorType */
|
||||
0x10, 0x01, /* bcdUSBL */
|
||||
0x02, /* bDeviceClass: */
|
||||
0x00, /* bDeviceSubclass: */
|
||||
0x00, /* bDeviceProtocol: */
|
||||
0x08, /* bMaxPacketSize0 */
|
||||
0x03, 0xEB, /* idVendorL */
|
||||
0x20, 0x09, /* idProductL */
|
||||
0x10, 0x01, /* bcdDeviceL */
|
||||
usbMANUFACTURER_STRING, /* iManufacturer */
|
||||
usbPRODUCT_STRING, /* iProduct */
|
||||
0x00, /* SerialNumber */
|
||||
0x01 /* bNumConfigs */
|
||||
};
|
||||
|
||||
const char pxConfigDescriptor[] = {
|
||||
|
||||
/* Configuration 1 descriptor
|
||||
Here we define two interfaces (0 and 1) and a total of 3 endpoints.
|
||||
Interface 0 is a CDC Abstract Control Model interface with one interrupt-in endpoint.
|
||||
Interface 1 is a CDC Data Interface class, with a bulk-in and bulk-out endpoint.
|
||||
Endpoint 0 gets used as the CDC management element.
|
||||
*/
|
||||
0x09, /* CbLength */
|
||||
0x02, /* CbDescriptorType */
|
||||
0x43, 0x00, /* CwTotalLength 2 EP + Control ? */
|
||||
0x02, /* CbNumInterfaces */
|
||||
0x01, /* CbConfigurationValue */
|
||||
usbCONFIGURATION_STRING,/* CiConfiguration */
|
||||
usbBUS_POWERED, /* CbmAttributes Bus powered + Remote Wakeup*/
|
||||
0x32, /* CMaxPower: 100mA */
|
||||
|
||||
/* Communication Class Interface Descriptor Requirement */
|
||||
0x09, /* bLength */
|
||||
0x04, /* bDescriptorType */
|
||||
0x00, /* bInterfaceNumber */
|
||||
0x00, /* bAlternateSetting */
|
||||
0x01, /* bNumEndpoints */
|
||||
0x02, /* bInterfaceClass: Comm Interface Class */
|
||||
0x02, /* bInterfaceSubclass: Abstract Control Model*/
|
||||
0x00, /* bInterfaceProtocol */
|
||||
usbINTERFACE_STRING,/* iInterface */
|
||||
|
||||
/* Header Functional Descriptor */
|
||||
0x05, /* bLength */
|
||||
0x24, /* bDescriptor type: CS_INTERFACE */
|
||||
0x00, /* bDescriptor subtype: Header Func Desc*/
|
||||
0x10, 0x01, /* bcdCDC:1.1 */
|
||||
|
||||
/* ACM Functional Descriptor */
|
||||
0x04, /* bFunctionLength */
|
||||
0x24, /* bDescriptor type: CS_INTERFACE */
|
||||
0x02, /* bDescriptor subtype: ACM Func Desc */
|
||||
0x00, /* bmCapabilities: We don't support squat*/
|
||||
|
||||
/* Union Functional Descriptor */
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptor type: CS_INTERFACE */
|
||||
0x06, /* bDescriptor subtype: Union Func Desc */
|
||||
0x00, /* bMasterInterface: CDC Interface */
|
||||
0x01, /* bSlaveInterface0: Data Class Interface*/
|
||||
|
||||
/* Call Management Functional Descriptor
|
||||
0 in D1 and D0 indicates that device does not handle call management*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptor type: CS_INTERFACE */
|
||||
0x01, /* bDescriptor subtype: Call Management Func*/
|
||||
0x01, /* bmCapabilities: D1 + D0 */
|
||||
0x01, /* bDataInterface: Data Class Interface 1*/
|
||||
|
||||
/* CDC Control - Endpoint 3 descriptor
|
||||
This endpoint serves as a notification element. */
|
||||
|
||||
0x07, /* bLength */
|
||||
0x05, /* bDescriptorType */
|
||||
0x83, /* bEndpointAddress, Endpoint 03 - IN */
|
||||
0x03, /* bmAttributes INT */
|
||||
0x08, 0x00, /* wMaxPacketSize: 8 bytes */
|
||||
0xFF, /* bInterval */
|
||||
|
||||
/* Data Class Interface Descriptor Requirement */
|
||||
0x09, /* bLength */
|
||||
0x04, /* bDescriptorType */
|
||||
0x01, /* bInterfaceNumber */
|
||||
0x00, /* bAlternateSetting */
|
||||
0x02, /* bNumEndPoints */
|
||||
0x0A, /* bInterfaceClass */
|
||||
0x00, /* bInterfaceSubclass */
|
||||
0x00, /* bInterfaceProtocol */
|
||||
0x00, /* iInterface */
|
||||
|
||||
/* CDC Data - Endpoint 1 descriptor */
|
||||
0x07, /* bLenght */
|
||||
0x05, /* bDescriptorType */
|
||||
0x01, /* bEndPointAddress, Endpoint 01 - OUT */
|
||||
0x02, /* bmAttributes BULK */
|
||||
64, /* wMaxPacketSize */
|
||||
0x00,
|
||||
0x00, /* bInterval */
|
||||
|
||||
/* CDC Data - Endpoint 2 descriptor */
|
||||
0x07, /* bLength */
|
||||
0x05, /* bDescriptorType */
|
||||
0x82, /* bEndPointAddress, Endpoint 02 - IN */
|
||||
0x02, /* bmAttributes BULK */
|
||||
64, /* wMaxPacketSize */
|
||||
0x00,
|
||||
0x00 /* bInterval */
|
||||
};
|
||||
|
||||
165
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/USB/usb.h
Normal file
165
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/USB/usb.h
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
FreeRTOS V7.1.0 - Copyright (C) 2011 Real Time Engineers Ltd.
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS tutorial books are available in pdf and paperback. *
|
||||
* Complete, revised, and edited pdf reference manuals are also *
|
||||
* available. *
|
||||
* *
|
||||
* Purchasing FreeRTOS documentation will not only help you, by *
|
||||
* ensuring you get running as quickly as possible and with an *
|
||||
* in-depth knowledge of how to use FreeRTOS, it will also help *
|
||||
* the FreeRTOS project to continue with its mission of providing *
|
||||
* professional grade, cross platform, de facto standard solutions *
|
||||
* for microcontrollers - completely free of charge! *
|
||||
* *
|
||||
* >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
|
||||
* *
|
||||
* Thank you for using FreeRTOS, and thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
>>>NOTE<<< The modification to the GPL is included to allow you to
|
||||
distribute a combined work that includes FreeRTOS without being obliged to
|
||||
provide the source code for proprietary components outside of the FreeRTOS
|
||||
kernel. FreeRTOS is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
/* Descriptor type definitions. */
|
||||
#define usbDESCRIPTOR_TYPE_DEVICE ( 0x01 )
|
||||
#define usbDESCRIPTOR_TYPE_CONFIGURATION ( 0x02 )
|
||||
#define usbDESCRIPTOR_TYPE_STRING ( 0x03 )
|
||||
|
||||
/* USB request type definitions. */
|
||||
#define usbGET_REPORT_REQUEST ( 0x01 )
|
||||
#define usbGET_IDLE_REQUEST ( 0x02 )
|
||||
#define usbGET_PROTOCOL_REQUEST ( 0x03 )
|
||||
#define usbSET_REPORT_REQUEST ( 0x09 )
|
||||
#define usbSET_IDLE_REQUEST ( 0x0A )
|
||||
#define usbSET_PROTOCOL_REQUEST ( 0x0B )
|
||||
#define usbGET_CONFIGURATION_REQUEST ( 0x08 )
|
||||
#define usbGET_STATUS_REQUEST ( 0x00 )
|
||||
#define usbCLEAR_FEATURE_REQUEST ( 0x01 )
|
||||
#define usbSET_FEATURE_REQUEST ( 0x03 )
|
||||
#define usbSET_ADDRESS_REQUEST ( 0x05 )
|
||||
#define usbGET_DESCRIPTOR_REQUEST ( 0x06 )
|
||||
#define usbSET_CONFIGURATION_REQUEST ( 0x09 )
|
||||
#define usbGET_INTERFACE_REQUEST ( 0x0A )
|
||||
#define usbSET_INTERFACE_REQUEST ( 0x0B )
|
||||
|
||||
/* ACM Requests */
|
||||
#define usbSEND_ENCAPSULATED_COMMAND ( 0x00 )
|
||||
#define usbGET_ENCAPSULATED_RESPONSE ( 0x01 )
|
||||
#define usbSET_LINE_CODING ( 0x20 )
|
||||
#define usbGET_LINE_CODING ( 0x21 )
|
||||
#define usbSET_CONTROL_LINE_STATE ( 0x22 )
|
||||
|
||||
/* Misc USB definitions. */
|
||||
#define usbDEVICE_CLASS_VENDOR_SPECIFIC ( 0xFF )
|
||||
#define usbBUS_POWERED ( 0x80 )
|
||||
#define usbHID_REPORT_DESCRIPTOR ( 0x22 )
|
||||
#define AT91C_UDP_TRANSCEIVER_ENABLE ( *( ( unsigned long * ) 0xfffb0074 ) )
|
||||
|
||||
/* Index to the various string. */
|
||||
#define usbLANGUAGE_STRING ( 0 )
|
||||
#define usbMANUFACTURER_STRING ( 1 )
|
||||
#define usbPRODUCT_STRING ( 2 )
|
||||
#define usbCONFIGURATION_STRING ( 3 )
|
||||
#define usbINTERFACE_STRING ( 4 )
|
||||
|
||||
/* Defines fields of standard SETUP request. Now in normal order. */
|
||||
#define usbREQUEST_TYPE_INDEX ( 0 )
|
||||
#define usbREQUEST_INDEX ( 1 )
|
||||
#define usbVALUE_HIGH_BYTE ( 3 )
|
||||
#define usbVALUE_LOW_BYTE ( 2 )
|
||||
#define usbINDEX_HIGH_BYTE ( 5 )
|
||||
#define usbINDEX_LOW_BYTE ( 4 )
|
||||
#define usbLENGTH_HIGH_BYTE ( 7 )
|
||||
#define usbLENGTH_LOW_BYTE ( 6 )
|
||||
|
||||
/* Misc application definitions. */
|
||||
#define usbINTERRUPT_PRIORITY ( 3 )
|
||||
#define usbQUEUE_LENGTH ( 0x3 ) /* Must have all bits set! */
|
||||
#define usbFIFO_LENGTH ( ( unsigned long ) 8 )
|
||||
#define usbEND_POINT_0 ( 0 )
|
||||
#define usbEND_POINT_1 ( 1 )
|
||||
#define usbEND_POINT_2 ( 2 )
|
||||
#define usbEND_POINT_3 ( 3 )
|
||||
#define usbMAX_CONTROL_MESSAGE_SIZE ( 128 )
|
||||
#define usbRX_COUNT_MASK ( ( unsigned long ) 0x7ff )
|
||||
#define AT91C_UDP_STALLSENT AT91C_UDP_ISOERROR
|
||||
#define usbSHORTEST_DELAY ( ( portTickType ) 1 )
|
||||
#define usbINIT_DELAY ( ( portTickType ) 1000 / portTICK_RATE_MS )
|
||||
#define usbSHORT_DELAY ( ( portTickType ) 50 / portTICK_RATE_MS )
|
||||
#define usbEND_POINT_RESET_MASK ( ( unsigned long ) 0x0f )
|
||||
#define usbDATA_INC ( ( char ) 5 )
|
||||
#define usbEXPECTED_NUMBER_OF_BYTES ( ( unsigned long ) 8 )
|
||||
|
||||
/* Control request types. */
|
||||
#define usbSTANDARD_DEVICE_REQUEST ( 0 )
|
||||
#define usbSTANDARD_INTERFACE_REQUEST ( 1 )
|
||||
#define usbSTANDARD_END_POINT_REQUEST ( 2 )
|
||||
#define usbCLASS_INTERFACE_REQUEST ( 5 )
|
||||
|
||||
|
||||
/* Macros to manipulate the control and status registers. These registers
|
||||
cannot be accessed using a direct read modify write operation outside of the
|
||||
ISR as some bits are left unchanged by writing with a 0, and some are left
|
||||
unchanged by writing with a 1. */
|
||||
|
||||
|
||||
#define usbCSR_SET_BIT( pulValueNow, ulBit ) \
|
||||
{ \
|
||||
/* Set TXCOMP, RX_DATA_BK0, RXSETUP, */ \
|
||||
/* STALLSENT and RX_DATA_BK1 to 1 so the */ \
|
||||
/* write has no effect. */ \
|
||||
( * ( ( unsigned long * ) pulValueNow ) ) |= ( unsigned long ) 0x4f; \
|
||||
\
|
||||
/* Clear the FORCE_STALL and TXPKTRDY bits */ \
|
||||
/* so the write has no effect. */ \
|
||||
( * ( ( unsigned long * ) pulValueNow ) ) &= ( unsigned long ) 0xffffffcf; \
|
||||
\
|
||||
/* Set whichever bit we want set. */ \
|
||||
( * ( ( unsigned long * ) pulValueNow ) ) |= ( ulBit ); \
|
||||
}
|
||||
|
||||
#define usbCSR_CLEAR_BIT( pulValueNow, ulBit ) \
|
||||
{ \
|
||||
/* Set TXCOMP, RX_DATA_BK0, RXSETUP, */ \
|
||||
/* STALLSENT and RX_DATA_BK1 to 1 so the */ \
|
||||
/* write has no effect. */ \
|
||||
( * ( ( unsigned long * ) pulValueNow ) ) |= ( unsigned long ) 0x4f; \
|
||||
\
|
||||
/* Clear the FORCE_STALL and TXPKTRDY bits */ \
|
||||
/* so the write has no effect. */ \
|
||||
( * ( ( unsigned long * ) pulValueNow ) ) &= ( unsigned long ) 0xffffffcf; \
|
||||
\
|
||||
/* Clear whichever bit we want clear. */ \
|
||||
( * ( ( unsigned long * ) pulValueNow ) ) &= ( ~ulBit ); \
|
||||
}
|
||||
49
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/atmel-rom.ld
Normal file
49
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/atmel-rom.ld
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
MEMORY
|
||||
{
|
||||
flash : ORIGIN = 0x00100000, LENGTH = 256K
|
||||
ram : ORIGIN = 0x00200000, LENGTH = 64K
|
||||
}
|
||||
|
||||
__stack_end__ = 0x00200000 + 64K - 4;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0;
|
||||
startup : { *(.startup)} >flash
|
||||
|
||||
prog :
|
||||
{
|
||||
*(.text)
|
||||
*(.rodata)
|
||||
*(.rodata*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
} >flash
|
||||
|
||||
__end_of_text__ = .;
|
||||
|
||||
.data :
|
||||
{
|
||||
__data_beg__ = .;
|
||||
__data_beg_src__ = __end_of_text__;
|
||||
*(.data)
|
||||
__data_end__ = .;
|
||||
} >ram AT>flash
|
||||
|
||||
.bss :
|
||||
{
|
||||
__bss_beg__ = .;
|
||||
*(.bss)
|
||||
} >ram
|
||||
|
||||
/* Align here to ensure that the .bss section occupies space up to
|
||||
_end. Align after .bss to ensure correct alignment even if the
|
||||
.bss section disappears because there are no input sections. */
|
||||
. = ALIGN(32 / 8);
|
||||
}
|
||||
. = ALIGN(32 / 8);
|
||||
_end = .;
|
||||
_bss_end__ = . ; __bss_end__ = . ; __end__ = . ;
|
||||
PROVIDE (end = .);
|
||||
|
||||
|
||||
161
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/boot.s
Normal file
161
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/boot.s
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
/* Sample initialization file */
|
||||
|
||||
.extern main
|
||||
.extern exit
|
||||
.extern AT91F_LowLevelInit
|
||||
|
||||
.text
|
||||
.code 32
|
||||
|
||||
|
||||
.align 0
|
||||
|
||||
.extern __stack_end__
|
||||
.extern __bss_beg__
|
||||
.extern __bss_end__
|
||||
.extern __data_beg__
|
||||
.extern __data_end__
|
||||
.extern __data+beg_src__
|
||||
|
||||
.global start
|
||||
.global endless_loop
|
||||
|
||||
/* Stack Sizes */
|
||||
.set UND_STACK_SIZE, 0x00000004
|
||||
.set ABT_STACK_SIZE, 0x00000004
|
||||
.set FIQ_STACK_SIZE, 0x00000004
|
||||
.set IRQ_STACK_SIZE, 0X00000400
|
||||
.set SVC_STACK_SIZE, 0x00000400
|
||||
|
||||
/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */
|
||||
.set MODE_USR, 0x10 /* User Mode */
|
||||
.set MODE_FIQ, 0x11 /* FIQ Mode */
|
||||
.set MODE_IRQ, 0x12 /* IRQ Mode */
|
||||
.set MODE_SVC, 0x13 /* Supervisor Mode */
|
||||
.set MODE_ABT, 0x17 /* Abort Mode */
|
||||
.set MODE_UND, 0x1B /* Undefined Mode */
|
||||
.set MODE_SYS, 0x1F /* System Mode */
|
||||
|
||||
.equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */
|
||||
.equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */
|
||||
|
||||
|
||||
start:
|
||||
_start:
|
||||
_mainCRTStartup:
|
||||
|
||||
/* Setup a stack for each mode - note that this only sets up a usable stack
|
||||
for system/user, SWI and IRQ modes. Also each mode is setup with
|
||||
interrupts initially disabled. */
|
||||
ldr r0, .LC6
|
||||
msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */
|
||||
mov sp, r0
|
||||
sub r0, r0, #UND_STACK_SIZE
|
||||
msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */
|
||||
mov sp, r0
|
||||
sub r0, r0, #ABT_STACK_SIZE
|
||||
msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */
|
||||
mov sp, r0
|
||||
sub r0, r0, #FIQ_STACK_SIZE
|
||||
msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */
|
||||
mov sp, r0
|
||||
sub r0, r0, #IRQ_STACK_SIZE
|
||||
msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */
|
||||
mov sp, r0
|
||||
sub r0, r0, #SVC_STACK_SIZE
|
||||
msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* System Mode */
|
||||
mov sp, r0
|
||||
|
||||
/* We want to start in supervisor mode. Operation will switch to system
|
||||
mode when the first task starts. */
|
||||
msr CPSR_c, #MODE_SVC|I_BIT|F_BIT
|
||||
|
||||
bl AT91F_LowLevelInit
|
||||
|
||||
/* Clear BSS. */
|
||||
|
||||
mov a2, #0 /* Fill value */
|
||||
mov fp, a2 /* Null frame pointer */
|
||||
mov r7, a2 /* Null frame pointer for Thumb */
|
||||
|
||||
ldr r1, .LC1 /* Start of memory block */
|
||||
ldr r3, .LC2 /* End of memory block */
|
||||
subs r3, r3, r1 /* Length of block */
|
||||
beq .end_clear_loop
|
||||
mov r2, #0
|
||||
|
||||
.clear_loop:
|
||||
strb r2, [r1], #1
|
||||
subs r3, r3, #1
|
||||
bgt .clear_loop
|
||||
|
||||
.end_clear_loop:
|
||||
|
||||
/* Initialise data. */
|
||||
|
||||
ldr r1, .LC3 /* Start of memory block */
|
||||
ldr r2, .LC4 /* End of memory block */
|
||||
ldr r3, .LC5
|
||||
subs r3, r3, r1 /* Length of block */
|
||||
beq .end_set_loop
|
||||
|
||||
.set_loop:
|
||||
ldrb r4, [r2], #1
|
||||
strb r4, [r1], #1
|
||||
subs r3, r3, #1
|
||||
bgt .set_loop
|
||||
|
||||
.end_set_loop:
|
||||
|
||||
mov r0, #0 /* no arguments */
|
||||
mov r1, #0 /* no argv either */
|
||||
|
||||
ldr lr, =main
|
||||
bx lr
|
||||
|
||||
endless_loop:
|
||||
b endless_loop
|
||||
|
||||
|
||||
.align 0
|
||||
|
||||
.LC1:
|
||||
.word __bss_beg__
|
||||
.LC2:
|
||||
.word __bss_end__
|
||||
.LC3:
|
||||
.word __data_beg__
|
||||
.LC4:
|
||||
.word __data_beg_src__
|
||||
.LC5:
|
||||
.word __data_end__
|
||||
.LC6:
|
||||
.word __stack_end__
|
||||
|
||||
|
||||
/* Setup vector table. Note that undf, pabt, dabt, fiq just execute
|
||||
a null loop. */
|
||||
|
||||
.section .startup,"ax"
|
||||
.code 32
|
||||
.align 0
|
||||
|
||||
b _start /* reset - _start */
|
||||
ldr pc, _undf /* undefined - _undf */
|
||||
ldr pc, _swi /* SWI - _swi */
|
||||
ldr pc, _pabt /* program abort - _pabt */
|
||||
ldr pc, _dabt /* data abort - _dabt */
|
||||
nop /* reserved */
|
||||
ldr pc, [pc,#-0xF20] /* IRQ - read the AIC */
|
||||
ldr pc, _fiq /* FIQ - _fiq */
|
||||
|
||||
_undf: .word __undf /* undefined */
|
||||
_swi: .word swi_handler /* SWI */
|
||||
_pabt: .word __pabt /* program abort */
|
||||
_dabt: .word __dabt /* data abort */
|
||||
_fiq: .word __fiq /* FIQ */
|
||||
|
||||
__undf: b . /* undefined */
|
||||
__pabt: b . /* program abort */
|
||||
__dabt: b . /* data abort */
|
||||
__fiq: b . /* FIQ */
|
||||
265
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/crt0.s
Normal file
265
20120401V7.1.1-RC1/Demo/lwIP_Demo_Rowley_ARM7/crt0.s
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2001, 2002 Rowley Associates Limited. *
|
||||
* *
|
||||
* This file may be distributed under the terms of the License Agreement *
|
||||
* provided with this software. *
|
||||
* *
|
||||
* THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE *
|
||||
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
*****************************************************************************/
|
||||
.section .init, "ax"
|
||||
.code 32
|
||||
.align 0
|
||||
|
||||
.weak _start
|
||||
.global __start
|
||||
.global __gccmain
|
||||
.extern main
|
||||
.extern exit
|
||||
|
||||
/*****************************************************************************
|
||||
* Function : _start *
|
||||
* Description : Main entry point and startup code for C system. *
|
||||
*****************************************************************************/
|
||||
_start:
|
||||
__start:
|
||||
mrs r0, cpsr
|
||||
bic r0, r0, #0x1F
|
||||
|
||||
/* Setup stacks */
|
||||
orr r1, r0, #0x1B /* Undefined mode */
|
||||
msr cpsr_cxsf, r1
|
||||
ldr sp, =__stack_und_end__
|
||||
|
||||
orr r1, r0, #0x17 /* Abort mode */
|
||||
msr cpsr_cxsf, r1
|
||||
ldr sp, =__stack_abt_end__
|
||||
|
||||
orr r1, r0, #0x12 /* IRQ mode */
|
||||
msr cpsr_cxsf, r1
|
||||
ldr sp, =__stack_irq_end__
|
||||
|
||||
orr r1, r0, #0x11 /* FIQ mode */
|
||||
msr cpsr_cxsf, r1
|
||||
ldr sp, =__stack_fiq_end__
|
||||
|
||||
orr r1, r0, #0x13 /* Supervisor mode */
|
||||
msr cpsr_cxsf, r1
|
||||
ldr sp, =__stack_svc_end__
|
||||
#ifdef SUPERVISOR_START
|
||||
/* Start application in supervisor mode */
|
||||
ldr r1, =__stack_end__ /* Setup user/system mode stack */
|
||||
mov r2, sp
|
||||
stmfd r2!, {r1}
|
||||
ldmfd r2, {sp}^
|
||||
#else
|
||||
/* Start application in system mode */
|
||||
orr r1, r0, #0x1F /* System mode */
|
||||
msr cpsr_cxsf, r1
|
||||
ldr sp, =__stack_end__
|
||||
#endif
|
||||
|
||||
/* Copy from initialised data section to data section (if necessary). */
|
||||
ldr r0, =__data_load_start__
|
||||
ldr r1, =__data_start__
|
||||
cmp r0, r1
|
||||
beq copy_data_end
|
||||
|
||||
ldr r2, =__data_end__
|
||||
subs r2, r2, r1
|
||||
beq copy_data_end
|
||||
|
||||
copy_data_loop:
|
||||
ldrb r3, [r0], #+1
|
||||
strb r3, [r1], #+1
|
||||
subs r2, r2, #1
|
||||
bne copy_data_loop
|
||||
copy_data_end:
|
||||
|
||||
/* Copy from initialised text section to text section (if necessary). */
|
||||
ldr r0, =__text_load_start__
|
||||
ldr r1, =__text_start__
|
||||
cmp r0, r1
|
||||
beq copy_text_end
|
||||
|
||||
ldr r2, =__text_end__
|
||||
subs r2, r2, r1
|
||||
beq copy_text_end
|
||||
|
||||
copy_text_loop:
|
||||
ldrb r3, [r0], #+1
|
||||
strb r3, [r1], #+1
|
||||
subs r2, r2, #1
|
||||
bne copy_text_loop
|
||||
copy_text_end:
|
||||
|
||||
/* Copy from initialised fast_text section to fast_text section (if necessary). */
|
||||
ldr r0, =__fast_load_start__
|
||||
ldr r1, =__fast_start__
|
||||
cmp r0, r1
|
||||
beq copy_fast_end
|
||||
|
||||
ldr r2, =__fast_end__
|
||||
subs r2, r2, r1
|
||||
beq copy_fast_end
|
||||
|
||||
copy_fast_loop:
|
||||
ldrb r3, [r0], #+1
|
||||
strb r3, [r1], #+1
|
||||
subs r2, r2, #1
|
||||
bne copy_fast_loop
|
||||
copy_fast_end:
|
||||
|
||||
/* Zero the bss. */
|
||||
ldr r0, =__bss_start__
|
||||
ldr r1, =__bss_end__
|
||||
mov r2, #0
|
||||
zero_bss_loop:
|
||||
cmp r0, r1
|
||||
beq zero_bss_end
|
||||
strb r2, [r0], #+1
|
||||
b zero_bss_loop
|
||||
zero_bss_end:
|
||||
|
||||
#ifdef CHECK
|
||||
/* Check data */
|
||||
ldr r0, =__data_load_start__
|
||||
ldr r1, =__data_start__
|
||||
cmp r0, r1
|
||||
beq check_data_end
|
||||
ldr r2, =__data_end__
|
||||
subs r2, r2, r1
|
||||
beq check_data_end
|
||||
|
||||
check_data_loop:
|
||||
ldrb r3, [r0], #+1
|
||||
ldrb r4, [r1], #+1
|
||||
cmp r3, r4
|
||||
bne data_error_loop
|
||||
subs r2, r2, #1
|
||||
bne check_data_loop
|
||||
check_data_end:
|
||||
|
||||
/* Check text */
|
||||
ldr r0, =__text_load_start__
|
||||
ldr r1, =__text_start__
|
||||
cmp r0, r1
|
||||
beq check_text_end
|
||||
ldr r2, =__text_end__
|
||||
subs r2, r2, r1
|
||||
beq check_text_end
|
||||
|
||||
check_text_loop:
|
||||
ldrb r3, [r0], #+1
|
||||
ldrb r4, [r1], #+1
|
||||
cmp r3, r4
|
||||
bne text_error_loop
|
||||
subs r2, r2, #1
|
||||
bne check_text_loop
|
||||
check_text_end:
|
||||
|
||||
/* Check fast */
|
||||
ldr r0, =__fast_load_start__
|
||||
ldr r1, =__fast_start__
|
||||
cmp r0, r1
|
||||
beq check_fast_end
|
||||
ldr r2, =__fast_end__
|
||||
subs r2, r2, r1
|
||||
beq check_fast_end
|
||||
|
||||
check_fast_loop:
|
||||
ldrb r3, [r0], #+1
|
||||
ldrb r4, [r1], #+1
|
||||
cmp r3, r4
|
||||
bne fast_error_loop
|
||||
subs r2, r2, #1
|
||||
bne check_fast_loop
|
||||
check_fast_end:
|
||||
|
||||
/* Check bss */
|
||||
ldr r0, =__bss_start__
|
||||
ldr r1, =__bss_end__
|
||||
mov r2, #0
|
||||
check_bss_loop:
|
||||
cmp r0, r1
|
||||
beq check_bss_end
|
||||
ldrb r2, [r0], #+1
|
||||
cmp r2, #0
|
||||
bne bss_error_loop
|
||||
b check_bss_loop
|
||||
check_bss_end:
|
||||
#endif
|
||||
|
||||
/* Initialise the heap */
|
||||
ldr r0, = __heap_start__
|
||||
ldr r1, = __heap_end__
|
||||
sub r1, r1, r0 /* r1 = r1-r0 */
|
||||
mov r2, #0
|
||||
str r2, [r0], #+4 /* *r0++ = 0 */
|
||||
str r1, [r0] /* *r0 = __heap_end__ - __heap_start__ */
|
||||
|
||||
/* Call constructors */
|
||||
ldr r0, =__ctors_start__
|
||||
ldr r1, =__ctors_end__
|
||||
ctor_loop:
|
||||
cmp r0, r1
|
||||
beq ctor_end
|
||||
ldr r2, [r0], #+4
|
||||
stmfd sp!, {r0-r1}
|
||||
mov lr, pc
|
||||
mov pc, r2
|
||||
ldmfd sp!, {r0-r1}
|
||||
b ctor_loop
|
||||
ctor_end:
|
||||
|
||||
/* Setup initial call frame */
|
||||
mov lr, #4
|
||||
mov r12, sp
|
||||
stmfd sp!, {r11-r12, lr-pc}
|
||||
sub r11, r12, #0x00000004
|
||||
|
||||
start:
|
||||
/* Jump to main entry point */
|
||||
mov r0, #0
|
||||
mov r1, #0
|
||||
ldr r2, =main
|
||||
mov lr, pc
|
||||
#ifdef __ARM_ARCH_3__
|
||||
mov pc, r2
|
||||
#else
|
||||
bx r2
|
||||
#endif
|
||||
|
||||
/* Call destructors */
|
||||
ldr r0, =__dtors_start__
|
||||
ldr r1, =__dtors_end__
|
||||
dtor_loop:
|
||||
cmp r0, r1
|
||||
beq dtor_end
|
||||
ldr r2, [r0], #+4
|
||||
stmfd sp!, {r0-r1}
|
||||
mov lr, pc
|
||||
mov pc, r2
|
||||
ldmfd sp!, {r0-r1}
|
||||
b dtor_loop
|
||||
dtor_end:
|
||||
|
||||
/* Return from main, loop forever. */
|
||||
exit_loop:
|
||||
b exit_loop
|
||||
|
||||
#ifdef CHECK
|
||||
data_error_loop:
|
||||
b data_error_loop
|
||||
|
||||
text_error_loop:
|
||||
b text_error_loop
|
||||
|
||||
fast_error_loop:
|
||||
b fast_error_loop
|
||||
|
||||
bss_error_loop:
|
||||
b bss_error_loop
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE Linker_Placement_File>
|
||||
<Root name="Flash Section Placement" >
|
||||
<MemorySegment name="FLASH" >
|
||||
<ProgramSection load="Yes" inputsections="*(.vectors .vectors.*)" name=".vectors" />
|
||||
<ProgramSection alignment="4" load="Yes" inputsections="*(.init .init.*)" name=".init" />
|
||||
<ProgramSection alignment="4" load="No" name=".text_load" />
|
||||
<ProgramSection alignment="4" load="Yes" inputsections="*(.text .text.* .glue_7t .glue_7 .gnu.linkonce.t.*)" name=".text" />
|
||||
<ProgramSection alignment="4" load="Yes" inputsections="KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors))" name=".dtors" />
|
||||
<ProgramSection alignment="4" load="Yes" inputsections="KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors))" name=".ctors" />
|
||||
<ProgramSection alignment="4" load="Yes" inputsections="*(.rodata .rodata.* .gnu.linkonce.r.*)" name=".rodata" />
|
||||
<ProgramSection alignment="4" load="Yes" runin=".fast_run" inputsections="*(.fast .fast.*)" name=".fast" />
|
||||
<ProgramSection alignment="4" load="Yes" runin=".data_run" inputsections="*(.data .data.* .gnu.linkonce.d.*)" name=".data" />
|
||||
</MemorySegment>
|
||||
<MemorySegment name="External SRAM;SRAM;SDRAM;DRAM" >
|
||||
<ProgramSection alignment="4" load="No" name=".data_run" />
|
||||
<ProgramSection alignment="4" load="No" inputsections="*(.bss .bss.* .gnu.linkonce.b.*) *(COMMON)" name=".bss" />
|
||||
<ProgramSection alignment="4" size="__HEAPSIZE__" load="No" name=".heap" />
|
||||
<ProgramSection alignment="4" size="__STACKSIZE__" load="No" name=".stack" />
|
||||
<ProgramSection alignment="4" size="0x190" load="No" name=".stack_irq" />
|
||||
<ProgramSection alignment="4" size="0x0" load="No" name=".stack_fiq" />
|
||||
<ProgramSection alignment="4" size="0x190" load="No" name=".stack_svc" />
|
||||
<ProgramSection alignment="4" size="0x0" load="No" name=".stack_abt" />
|
||||
<ProgramSection alignment="4" size="0x0" load="No" name=".stack_und" />
|
||||
</MemorySegment>
|
||||
<MemorySegment name="Internal SRAM;SRAM;SDRAM;DRAM" >
|
||||
<ProgramSection size="0x3C" load="No" name=".vectors_ram" />
|
||||
<ProgramSection alignment="4" load="No" name=".fast_run" />
|
||||
</MemorySegment>
|
||||
</Root>
|
||||
|
|
@ -0,0 +1,536 @@
|
|||
FUTURE
|
||||
|
||||
* TODO: The lwIP source code makes some invalid assumptions on processor
|
||||
word-length, storage sizes and alignment. See the mailing lists for
|
||||
problems with exoteric (/DSP) architectures showing these problems.
|
||||
We still have to fix some of these issues neatly.
|
||||
|
||||
* TODO: the ARP layer is not protected against concurrent access. If
|
||||
you run from a multitasking OS, serialize access to ARP (called from
|
||||
your network device driver and from a timeout thread.)
|
||||
|
||||
HISTORY
|
||||
|
||||
(HEAD)
|
||||
|
||||
2004-12-28 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* etharp.*: Disabled multiple packets on the ARP queue.
|
||||
This clashes with TCP queueing.
|
||||
|
||||
2004-11-28 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* etharp.*: Fixed race condition from ARP request to ARP timeout.
|
||||
Halved the ARP period, doubled the period counts.
|
||||
ETHARP_MAX_PENDING now should be at least 2. This prevents
|
||||
the counter from reaching 0 right away (which would allow
|
||||
too little time for ARP responses to be received).
|
||||
|
||||
2004-11-25 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* dhcp.c: Decline messages were not multicast but unicast.
|
||||
* etharp.c: ETHARP_CREATE is renamed to ETHARP_TRY_HARD.
|
||||
Do not try hard to insert arbitrary packet's source address,
|
||||
etharp_ip_input() now calls etharp_update() without ETHARP_TRY_HARD.
|
||||
etharp_query() now always DOES call ETHARP_TRY_HARD so that users
|
||||
querying an address will see it appear in the cache (DHCP could
|
||||
suffer from this when a server invalidly gave an in-use address.)
|
||||
* ipv4/ip_addr.h: Renamed ip_addr_maskcmp() to _netcmp() as we are
|
||||
comparing network addresses (identifiers), not the network masks
|
||||
themselves.
|
||||
* ipv4/ip_addr.c: ip_addr_isbroadcast() now checks that the given
|
||||
IP address actually belongs to the network of the given interface.
|
||||
|
||||
2004-11-24 Kieran Mansley <kjm25@cam.ac.uk>
|
||||
* tcp.c: Increment pcb->snd_buf when ACK is received in SYN_SENT state.
|
||||
|
||||
(STABLE-1_1_0-RC1)
|
||||
|
||||
2004-10-16 Kieran Mansley <kjm25@cam.ac.uk>
|
||||
* tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately,
|
||||
even if one is already pending, if the rcv_wnd is above a threshold
|
||||
(currently TCP_WND/2). This avoids waiting for a timer to expire to send a
|
||||
delayed ACK in order to open the window if the stack is only receiving data.
|
||||
|
||||
2004-09-12 Kieran Mansley <kjm25@cam.ac.uk>
|
||||
* tcp*.*: Retransmit time-out handling improvement by Sam Jansen.
|
||||
|
||||
2004-08-20 Tony Mountifield <tony@softins.co.uk>
|
||||
* etharp.c: Make sure the first pbuf queued on an ARP entry
|
||||
is properly ref counted.
|
||||
|
||||
2004-07-27 Tony Mountifield <tony@softins.co.uk>
|
||||
* debug.h: Added (int) cast in LWIP_DEBUGF() to avoid compiler
|
||||
warnings about comparison.
|
||||
* pbuf.c: Stopped compiler complaining of empty if statement
|
||||
when LWIP_DEBUGF() empty. Closed an unclosed comment.
|
||||
* tcp.c: Stopped compiler complaining of empty if statement
|
||||
when LWIP_DEBUGF() empty.
|
||||
* ip.h Corrected IPH_TOS() macro: returns a byte, so doesn't need htons().
|
||||
* inet.c: Added a couple of casts to quiet the compiler.
|
||||
No need to test isascii(c) before isdigit(c) or isxdigit(c).
|
||||
|
||||
2004-07-22 Tony Mountifield <tony@softins.co.uk>
|
||||
* inet.c: Made data types consistent in inet_ntoa().
|
||||
Added casts for return values of checksum routines, to pacify compiler.
|
||||
* ip_frag.c, tcp_out.c, sockets.c, pbuf.c
|
||||
Small corrections to some debugging statements, to pacify compiler.
|
||||
|
||||
2004-07-21 Tony Mountifield <tony@softins.co.uk>
|
||||
* etharp.c: Removed spurious semicolon and added missing end-of-comment.
|
||||
* ethernetif.c Updated low_level_output() to match prototype for
|
||||
netif->linkoutput and changed low_level_input() similarly for consistency.
|
||||
* api_msg.c: Changed recv_raw() from int to u8_t, to match prototype
|
||||
of raw_recv() in raw.h and so avoid compiler error.
|
||||
* sockets.c: Added trivial (int) cast to keep compiler happier.
|
||||
* ip.c, netif.c Changed debug statements to use the tidier ip4_addrN() macros.
|
||||
|
||||
(STABLE-1_0_0)
|
||||
|
||||
++ Changes:
|
||||
|
||||
2004-07-05 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* sockets.*: Restructured LWIP_PRIVATE_TIMEVAL. Make sure
|
||||
your cc.h file defines this either 1 or 0. If non-defined,
|
||||
defaults to 1.
|
||||
* .c: Added <string.h> and <errno.h> includes where used.
|
||||
* etharp.c: Made some array indices unsigned.
|
||||
|
||||
2004-06-27 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* netif.*: Added netif_set_up()/down().
|
||||
* dhcp.c: Changes to restart program flow.
|
||||
|
||||
2004-05-07 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* etharp.c: In find_entry(), instead of a list traversal per candidate, do a
|
||||
single-pass lookup for different candidates. Should exploit locality.
|
||||
|
||||
2004-04-29 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* tcp*.c: Cleaned up source comment documentation for Doxygen processing.
|
||||
* opt.h: ETHARP_ALWAYS_INSERT option removed to comply with ARP RFC.
|
||||
* etharp.c: update_arp_entry() only adds new ARP entries when adviced to by
|
||||
the caller. This deprecates the ETHARP_ALWAYS_INSERT overrule option.
|
||||
|
||||
++ Bug fixes:
|
||||
|
||||
2004-04-27 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* etharp.c: Applied patch of bug #8708 by Toni Mountifield with a solution
|
||||
suggested by Timmy Brolin. Fix for 32-bit processors that cannot access
|
||||
non-aligned 32-bit words, such as soms 32-bit TCP/IP header fields. Fix
|
||||
is to prefix the 14-bit Ethernet headers with two padding bytes.
|
||||
|
||||
2004-04-23 Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
* ip_addr.c: Fix in the ip_addr_isbroadcast() check.
|
||||
* etharp.c: Fixed the case where the packet that initiates the ARP request
|
||||
is not queued, and gets lost. Fixed the case where the packets destination
|
||||
address is already known; we now always queue the packet and perform an ARP
|
||||
request.
|
||||
|
||||
(STABLE-0_7_0)
|
||||
|
||||
++ Bug fixes:
|
||||
|
||||
* Fixed TCP bug for SYN_SENT to ESTABLISHED state transition.
|
||||
* Fixed TCP bug in dequeueing of FIN from out of order segment queue.
|
||||
* Fixed two possible NULL references in rare cases.
|
||||
|
||||
(STABLE-0_6_6)
|
||||
|
||||
++ Bug fixes:
|
||||
|
||||
* Fixed DHCP which did not include the IP address in DECLINE messages.
|
||||
|
||||
++ Changes:
|
||||
|
||||
* etharp.c has been hauled over a bit.
|
||||
|
||||
(STABLE-0_6_5)
|
||||
|
||||
++ Bug fixes:
|
||||
|
||||
* Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic.
|
||||
* Packets sent from ARP queue had invalid source hardware address.
|
||||
|
||||
++ Changes:
|
||||
|
||||
* Pass-by ARP requests do now update the cache.
|
||||
|
||||
++ New features:
|
||||
|
||||
* No longer dependent on ctype.h.
|
||||
* New socket options.
|
||||
* Raw IP pcb support.
|
||||
|
||||
(STABLE-0_6_4)
|
||||
|
||||
++ Bug fixes:
|
||||
|
||||
* Some debug formatters and casts fixed.
|
||||
* Numereous fixes in PPP.
|
||||
|
||||
++ Changes:
|
||||
|
||||
* DEBUGF now is LWIP_DEBUGF
|
||||
* pbuf_dechain() has been re-enabled.
|
||||
* Mentioned the changed use of CVS branches in README.
|
||||
|
||||
(STABLE-0_6_3)
|
||||
|
||||
++ Bug fixes:
|
||||
|
||||
* Fixed pool pbuf memory leak in pbuf_alloc().
|
||||
Occured if not enough PBUF_POOL pbufs for a packet pbuf chain.
|
||||
Reported by Savin Zlobec.
|
||||
|
||||
* PBUF_POOL chains had their tot_len field not set for non-first
|
||||
pbufs. Fixed in pbuf_alloc().
|
||||
|
||||
++ New features:
|
||||
|
||||
* Added PPP stack contributed by Marc Boucher
|
||||
|
||||
++ Changes:
|
||||
|
||||
* Now drops short packets for ICMP/UDP/TCP protocols. More robust.
|
||||
|
||||
* ARP queueuing now queues the latest packet instead of the first.
|
||||
This is the RFC recommended behaviour, but can be overridden in
|
||||
lwipopts.h.
|
||||
|
||||
(0.6.2)
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
* TCP has been fixed to deal with the new use of the pbuf->ref
|
||||
counter.
|
||||
|
||||
* DHCP dhcp_inform() crash bug fixed.
|
||||
|
||||
++ Changes:
|
||||
|
||||
* Removed pbuf_pool_free_cache and pbuf_pool_alloc_cache. Also removed
|
||||
pbuf_refresh(). This has sped up pbuf pool operations considerably.
|
||||
Implemented by David Haas.
|
||||
|
||||
(0.6.1)
|
||||
|
||||
++ New features:
|
||||
|
||||
* The packet buffer implementation has been enhanced to support
|
||||
zero-copy and copy-on-demand for packet buffers which have their
|
||||
payloads in application-managed memory.
|
||||
Implemented by David Haas.
|
||||
|
||||
Use PBUF_REF to make a pbuf refer to RAM. lwIP will use zero-copy
|
||||
if an outgoing packet can be directly sent on the link, or perform
|
||||
a copy-on-demand when necessary.
|
||||
|
||||
The application can safely assume the packet is sent, and the RAM
|
||||
is available to the application directly after calling udp_send()
|
||||
or similar function.
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
* ARP_QUEUEING should now correctly work for all cases, including
|
||||
PBUF_REF.
|
||||
Implemented by Leon Woestenberg.
|
||||
|
||||
++ Changes:
|
||||
|
||||
* IP_ADDR_ANY is no longer a NULL pointer. Instead, it is a pointer
|
||||
to a '0.0.0.0' IP address.
|
||||
|
||||
* The packet buffer implementation is changed. The pbuf->ref counter
|
||||
meaning has changed, and several pbuf functions have been
|
||||
adapted accordingly.
|
||||
|
||||
* netif drivers have to be changed to set the hardware address length field
|
||||
that must be initialized correctly by the driver (hint: 6 for Ethernet MAC).
|
||||
See the contrib/ports/c16x cs8900 driver as a driver example.
|
||||
|
||||
* netif's have a dhcp field that must be initialized to NULL by the driver.
|
||||
See the contrib/ports/c16x cs8900 driver as a driver example.
|
||||
|
||||
(0.5.x) This file has been unmaintained up to 0.6.1. All changes are
|
||||
logged in CVS but have not been explained here.
|
||||
|
||||
(0.5.3) Changes since version 0.5.2
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
* memp_malloc(MEMP_API_MSG) could fail with multiple application
|
||||
threads because it wasn't protected by semaphores.
|
||||
|
||||
++ Other changes:
|
||||
|
||||
* struct ip_addr now packed.
|
||||
|
||||
* The name of the time variable in arp.c has been changed to ctime
|
||||
to avoid conflicts with the time() function.
|
||||
|
||||
(0.5.2) Changes since version 0.5.1
|
||||
|
||||
++ New features:
|
||||
|
||||
* A new TCP function, tcp_tmr(), now handles both TCP timers.
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
* A bug in tcp_parseopt() could cause the stack to hang because of a
|
||||
malformed TCP option.
|
||||
|
||||
* The address of new connections in the accept() function in the BSD
|
||||
socket library was not handled correctly.
|
||||
|
||||
* pbuf_dechain() did not update the ->tot_len field of the tail.
|
||||
|
||||
* Aborted TCP connections were not handled correctly in all
|
||||
situations.
|
||||
|
||||
++ Other changes:
|
||||
|
||||
* All protocol header structs are now packed.
|
||||
|
||||
* The ->len field in the tcp_seg structure now counts the actual
|
||||
amount of data, and does not add one for SYN and FIN segments.
|
||||
|
||||
(0.5.1) Changes since version 0.5.0
|
||||
|
||||
++ New features:
|
||||
|
||||
* Possible to run as a user process under Linux.
|
||||
|
||||
* Preliminary support for cross platform packed structs.
|
||||
|
||||
* ARP timer now implemented.
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
* TCP output queue length was badly initialized when opening
|
||||
connections.
|
||||
|
||||
* TCP delayed ACKs were not sent correctly.
|
||||
|
||||
* Explicit initialization of BSS segment variables.
|
||||
|
||||
* read() in BSD socket library could drop data.
|
||||
|
||||
* Problems with memory alignment.
|
||||
|
||||
* Situations when all TCP buffers were used could lead to
|
||||
starvation.
|
||||
|
||||
* TCP MSS option wasn't parsed correctly.
|
||||
|
||||
* Problems with UDP checksum calculation.
|
||||
|
||||
* IP multicast address tests had endianess problems.
|
||||
|
||||
* ARP requests had wrong destination hardware address.
|
||||
|
||||
++ Other changes:
|
||||
|
||||
* struct eth_addr changed from u16_t[3] array to u8_t[6].
|
||||
|
||||
* A ->linkoutput() member was added to struct netif.
|
||||
|
||||
* TCP and UDP ->dest_* struct members where changed to ->remote_*.
|
||||
|
||||
* ntoh* macros are now null definitions for big endian CPUs.
|
||||
|
||||
(0.5.0) Changes since version 0.4.2
|
||||
|
||||
++ New features:
|
||||
|
||||
* Redesigned operating system emulation layer to make porting easier.
|
||||
|
||||
* Better control over TCP output buffers.
|
||||
|
||||
* Documenation added.
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
* Locking issues in buffer management.
|
||||
|
||||
* Bugfixes in the sequential API.
|
||||
|
||||
* IP forwarding could cause memory leakage. This has been fixed.
|
||||
|
||||
++ Other changes:
|
||||
|
||||
* Directory structure somewhat changed; the core/ tree has been
|
||||
collapsed.
|
||||
|
||||
(0.4.2) Changes since version 0.4.1
|
||||
|
||||
++ New features:
|
||||
|
||||
* Experimental ARP implementation added.
|
||||
|
||||
* Skeleton Ethernet driver added.
|
||||
|
||||
* Experimental BSD socket API library added.
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
* In very intense situations, memory leakage could occur. This has
|
||||
been fixed.
|
||||
|
||||
++ Other changes:
|
||||
|
||||
* Variables named "data" and "code" have been renamed in order to
|
||||
avoid name conflicts in certain compilers.
|
||||
|
||||
* Variable++ have in appliciable cases been translated to ++variable
|
||||
since some compilers generate better code in the latter case.
|
||||
|
||||
(0.4.1) Changes since version 0.4
|
||||
|
||||
++ New features:
|
||||
|
||||
* TCP: Connection attempts time out earlier than data
|
||||
transmissions. Nagle algorithm implemented. Push flag set on the
|
||||
last segment in a burst.
|
||||
|
||||
* UDP: experimental support for UDP-Lite extensions.
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
* TCP: out of order segments were in some cases handled incorrectly,
|
||||
and this has now been fixed. Delayed acknowledgements was broken
|
||||
in 0.4, has now been fixed. Binding to an address that is in use
|
||||
now results in an error. Reset connections sometimes hung an
|
||||
application; this has been fixed.
|
||||
|
||||
* Checksum calculation sometimes failed for chained pbufs with odd
|
||||
lengths. This has been fixed.
|
||||
|
||||
* API: a lot of bug fixes in the API. The UDP API has been improved
|
||||
and tested. Error reporting and handling has been
|
||||
improved. Logical flaws and race conditions for incoming TCP
|
||||
connections has been found and removed.
|
||||
|
||||
* Memory manager: alignment issues. Reallocating memory sometimes
|
||||
failed, this has been fixed.
|
||||
|
||||
* Generic library: bcopy was flawed and has been fixed.
|
||||
|
||||
++ Other changes:
|
||||
|
||||
* API: all datatypes has been changed from generic ones such as
|
||||
ints, to specified ones such as u16_t. Functions that return
|
||||
errors now have the correct type (err_t).
|
||||
|
||||
* General: A lot of code cleaned up and debugging code removed. Many
|
||||
portability issues have been fixed.
|
||||
|
||||
* The license was changed; the advertising clause was removed.
|
||||
|
||||
* C64 port added.
|
||||
|
||||
* Thanks: Huge thanks go to Dagan Galarneau, Horst Garnetzke, Petri
|
||||
Kosunen, Mikael Caleres, and Frits Wilmink for reporting and
|
||||
fixing bugs!
|
||||
|
||||
(0.4) Changes since version 0.3.1
|
||||
|
||||
* Memory management has been radically changed; instead of
|
||||
allocating memory from a shared heap, memory for objects that are
|
||||
rapidly allocated and deallocated is now kept in pools. Allocation
|
||||
and deallocation from those memory pools is very fast. The shared
|
||||
heap is still present but is used less frequently.
|
||||
|
||||
* The memory, memory pool, and packet buffer subsystems now support
|
||||
4-, 2-, or 1-byte alignment.
|
||||
|
||||
* "Out of memory" situations are handled in a more robust way.
|
||||
|
||||
* Stack usage has been reduced.
|
||||
|
||||
* Easier configuration of lwIP parameters such as memory usage,
|
||||
TTLs, statistics gathering, etc. All configuration parameters are
|
||||
now kept in a single header file "lwipopts.h".
|
||||
|
||||
* The directory structure has been changed slightly so that all
|
||||
architecture specific files are kept under the src/arch
|
||||
hierarchy.
|
||||
|
||||
* Error propagation has been improved, both in the protocol modules
|
||||
and in the API.
|
||||
|
||||
* The code for the RTXC architecture has been implemented, tested
|
||||
and put to use.
|
||||
|
||||
* Bugs have been found and corrected in the TCP, UDP, IP, API, and
|
||||
the Internet checksum modules.
|
||||
|
||||
* Bugs related to porting between a 32-bit and a 16-bit architecture
|
||||
have been found and corrected.
|
||||
|
||||
* The license has been changed slightly to conform more with the
|
||||
original BSD license, including the advertisement clause.
|
||||
|
||||
(0.3.1) Changes since version 0.3
|
||||
|
||||
* Fix of a fatal bug in the buffer management. Pbufs with allocated
|
||||
RAM never returned the RAM when the pbuf was deallocated.
|
||||
|
||||
* TCP congestion control, window updates and retransmissions did not
|
||||
work correctly. This has now been fixed.
|
||||
|
||||
* Bugfixes in the API.
|
||||
|
||||
(0.3) Changes since version 0.2
|
||||
|
||||
* New and improved directory structure. All include files are now
|
||||
kept in a dedicated include/ directory.
|
||||
|
||||
* The API now has proper error handling. A new function,
|
||||
netconn_err(), now returns an error code for the connection in
|
||||
case of errors.
|
||||
|
||||
* Improvements in the memory management subsystem. The system now
|
||||
keeps a pointer to the lowest free memory block. A new function,
|
||||
mem_malloc2() tries to allocate memory once, and if it fails tries
|
||||
to free some memory and retry the allocation.
|
||||
|
||||
* Much testing has been done with limited memory
|
||||
configurations. lwIP now does a better job when overloaded.
|
||||
|
||||
* Some bugfixes and improvements to the buffer (pbuf) subsystem.
|
||||
|
||||
* Many bugfixes in the TCP code:
|
||||
|
||||
- Fixed a bug in tcp_close().
|
||||
|
||||
- The TCP receive window was incorrectly closed when out of
|
||||
sequence segments was received. This has been fixed.
|
||||
|
||||
- Connections are now timed-out of the FIN-WAIT-2 state.
|
||||
|
||||
- The initial congestion window could in some cases be too
|
||||
large. This has been fixed.
|
||||
|
||||
- The retransmission queue could in some cases be screwed up. This
|
||||
has been fixed.
|
||||
|
||||
- TCP RST flag now handled correctly.
|
||||
|
||||
- Out of sequence data was in some cases never delivered to the
|
||||
application. This has been fixed.
|
||||
|
||||
- Retransmitted segments now contain the correct acknowledgment
|
||||
number and advertised window.
|
||||
|
||||
- TCP retransmission timeout backoffs are not correctly computed
|
||||
(ala BSD). After a number of retransmissions, TCP now gives up
|
||||
the connection.
|
||||
|
||||
* TCP connections now are kept on three lists, one for active
|
||||
connections, one for listening connections, and one for
|
||||
connections that are in TIME-WAIT. This greatly speeds up the fast
|
||||
timeout processing for sending delayed ACKs.
|
||||
|
||||
* TCP now provides proper feedback to the application when a
|
||||
connection has been successfully set up.
|
||||
|
||||
* More comments have been added to the code. The code has also been
|
||||
somewhat cleaned up.
|
||||
|
||||
(0.2) Initial public release.
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
src/ - The source code for the lwIP TCP/IP stack.
|
||||
doc/ - The documentation for lwIP.
|
||||
|
||||
See also the FILES file in each subdirectory.
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
INTRODUCTION
|
||||
|
||||
lwIP is a small independent implementation of the TCP/IP protocol
|
||||
suite that has been developed by Adam Dunkels at the Computer and
|
||||
Networks Architectures (CNA) lab at the Swedish Institute of Computer
|
||||
Science (SICS).
|
||||
|
||||
The focus of the lwIP TCP/IP implementation is to reduce the RAM usage
|
||||
while still having a full scale TCP. This making lwIP suitable for use
|
||||
in embedded systems with tenths of kilobytes of free RAM and room for
|
||||
around 40 kilobytes of code ROM.
|
||||
|
||||
FEATURES
|
||||
|
||||
* IP (Internet Protocol) including packet forwarding over multiple
|
||||
network interfaces
|
||||
* ICMP (Internet Control Message Protocol) for network maintenance
|
||||
and debugging
|
||||
* UDP (User Datagram Protocol) including experimental UDP-lite
|
||||
extensions
|
||||
* TCP (Transmission Control Protocol) with congestion control, RTT
|
||||
estimation and fast recovery/fast retransmit
|
||||
* Specialized API for enhanced performance
|
||||
* Optional Berkeley socket API
|
||||
|
||||
LICENSE
|
||||
|
||||
lwIP is freely available under a BSD license.
|
||||
|
||||
DEVELOPMENT
|
||||
|
||||
lwIP has grown into an excellent TCP/IP stack for embedded devices,
|
||||
and developers using the stack often submit bug fixes, improvements,
|
||||
and additions to the stack to further increase its usefulness.
|
||||
|
||||
Development of lwIP is hosted on Savannah, a central point for
|
||||
software development, maintenance and distribution. Everyone can
|
||||
help improve lwIP by use of Savannah's interface, CVS and the
|
||||
mailing list. A core team of developers will commit changes to the
|
||||
CVS source tree.
|
||||
|
||||
The lwIP TCP/IP stack is maintained in the 'lwip' CVS module and
|
||||
contributions (such as platform ports) are in the 'contrib' module.
|
||||
|
||||
The CVS main trunk is the stable branch, which contains bug fixes and
|
||||
tested features. The latest stable branch can be checked out by doing:
|
||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co lwip
|
||||
|
||||
The 'STABLE' tag in the stable branch will represent the most stable
|
||||
revision (which may be somewhat older to protect us from errors
|
||||
introduced by merges). This 'STABLE' tagged version can be checked out
|
||||
by doing:
|
||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co -r STABLE lwip
|
||||
|
||||
The 'DEVEL' branch is the active development branch, which contains
|
||||
bleeding edge changes, and may be instable. It can be checkout by doing:
|
||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co -r DEVEL lwip
|
||||
|
||||
The current contrib CVS tree can be checked out by doing:
|
||||
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
|
||||
cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip co contrib
|
||||
|
||||
Last night's CVS tar ball can be downloaded from:
|
||||
http://savannah.gnu.org/cvs.backups/lwip.tar.gz
|
||||
|
||||
The current CVS trees are web-browsable:
|
||||
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/lwip/
|
||||
http://savannah.nongnu.org/cgi-bin/viewcvs/lwip/contrib/
|
||||
|
||||
Submit patches and bugs via the lwIP project page:
|
||||
http://savannah.nongnu.org/projects/lwip/
|
||||
|
||||
|
||||
DOCUMENTATION
|
||||
|
||||
The original out-dated homepage of lwIP and Adam Dunkels' papers on
|
||||
lwIP are at the official lwIP home page:
|
||||
http://www.sics.se/~adam/lwip/
|
||||
|
||||
Self documentation of the source code is regularly extracted from the
|
||||
current CVS sources and is available from this web page:
|
||||
http://www.nongnu.org/lwip/
|
||||
|
||||
Reading Adam's papers, the files in docs/, browsing the source code
|
||||
documentation and browsing the mailing list archives is a good way to
|
||||
become familiar with the design of lwIP.
|
||||
|
||||
Adam Dunkels <adam@sics.se>
|
||||
Leon Woestenberg <leon.woestenberg@gmx.net>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __CC_H__
|
||||
#define __CC_H__
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
typedef unsigned char u8_t;
|
||||
typedef signed char s8_t;
|
||||
typedef unsigned short u16_t;
|
||||
typedef signed short s16_t;
|
||||
typedef unsigned long u32_t;
|
||||
typedef signed long s32_t;
|
||||
typedef u32_t mem_ptr_t;
|
||||
typedef int sys_prot_t;
|
||||
|
||||
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
|
||||
#define PACK_STRUCT_END
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
|
||||
#endif /* __CC_H__ */
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __CPU_H__
|
||||
#define __CPU_H__
|
||||
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
#endif /* __CPU_H__ */
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __ARCH_INIT_H__
|
||||
#define __ARCH_INIT_H__
|
||||
|
||||
#define TCPIP_INIT_DONE(arg) tcpip_init_done(arg)
|
||||
|
||||
void tcpip_init_done(void *);
|
||||
int wait_for_tcpip_init(void);
|
||||
|
||||
#endif /* __ARCH_INIT_H__ */
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LIB_H__
|
||||
#define __LIB_H__
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#endif /* __LIB_H__ */
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __PERF_H__
|
||||
#define __PERF_H__
|
||||
|
||||
#define PERF_START /* null definition */
|
||||
#define PERF_STOP(x) /* null definition */
|
||||
|
||||
#endif /* __PERF_H__ */
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __SYS_RTXC_H__
|
||||
#define __SYS_RTXC_H__
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#define SYS_MBOX_NULL (xQueueHandle)0
|
||||
#define SYS_SEM_NULL (xSemaphoreHandle)0
|
||||
|
||||
typedef xSemaphoreHandle sys_sem_t;
|
||||
typedef xQueueHandle sys_mbox_t;
|
||||
typedef xTaskHandle sys_thread_t;
|
||||
|
||||
#endif /* __SYS_RTXC_H__ */
|
||||
|
||||
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/* lwIP includes. */
|
||||
#include "lwip/debug.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/mem.h"
|
||||
|
||||
/* Message queue constants. */
|
||||
#define archMESG_QUEUE_LENGTH ( 6 )
|
||||
#define archPOST_BLOCK_TIME_MS ( ( unsigned long ) 10000 )
|
||||
|
||||
struct timeoutlist
|
||||
{
|
||||
struct sys_timeouts timeouts;
|
||||
xTaskHandle pid;
|
||||
};
|
||||
|
||||
/* This is the number of threads that can be started with sys_thread_new() */
|
||||
#define SYS_THREAD_MAX 4
|
||||
|
||||
#define lwipTCP_STACK_SIZE 600
|
||||
#define lwipBASIC_SERVER_STACK_SIZE 250
|
||||
|
||||
static struct timeoutlist timeoutlist[SYS_THREAD_MAX];
|
||||
static u16_t nextthread = 0;
|
||||
int intlevel = 0;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// Creates an empty mailbox.
|
||||
sys_mbox_t
|
||||
sys_mbox_new(void)
|
||||
{
|
||||
xQueueHandle mbox;
|
||||
|
||||
mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) );
|
||||
|
||||
return mbox;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*
|
||||
Deallocates a mailbox. If there are messages still present in the
|
||||
mailbox when the mailbox is deallocated, it is an indication of a
|
||||
programming error in lwIP and the developer should be notified.
|
||||
*/
|
||||
void
|
||||
sys_mbox_free(sys_mbox_t mbox)
|
||||
{
|
||||
if( uxQueueMessagesWaiting( mbox ) )
|
||||
{
|
||||
/* Line for breakpoint. Should never break here! */
|
||||
__asm volatile ( "NOP" );
|
||||
}
|
||||
|
||||
vQueueDelete( mbox );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// Posts the "msg" to the mailbox.
|
||||
void
|
||||
sys_mbox_post(sys_mbox_t mbox, void *data)
|
||||
{
|
||||
xQueueSend( mbox, &data, ( portTickType ) ( archPOST_BLOCK_TIME_MS / portTICK_RATE_MS ) );
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*
|
||||
Blocks the thread until a message arrives in the mailbox, but does
|
||||
not block the thread longer than "timeout" milliseconds (similar to
|
||||
the sys_arch_sem_wait() function). The "msg" argument is a result
|
||||
parameter that is set by the function (i.e., by doing "*msg =
|
||||
ptr"). The "msg" parameter maybe NULL to indicate that the message
|
||||
should be dropped.
|
||||
|
||||
The return values are the same as for the sys_arch_sem_wait() function:
|
||||
Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
|
||||
timeout.
|
||||
|
||||
Note that a function with a similar name, sys_mbox_fetch(), is
|
||||
implemented by lwIP.
|
||||
*/
|
||||
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
|
||||
{
|
||||
void *dummyptr;
|
||||
portTickType StartTime, EndTime, Elapsed;
|
||||
|
||||
StartTime = xTaskGetTickCount();
|
||||
|
||||
if( msg == NULL )
|
||||
{
|
||||
msg = &dummyptr;
|
||||
}
|
||||
|
||||
if( timeout != 0 )
|
||||
{
|
||||
if(pdTRUE == xQueueReceive( mbox, &(*msg), timeout ) )
|
||||
{
|
||||
EndTime = xTaskGetTickCount();
|
||||
Elapsed = EndTime - StartTime;
|
||||
if( Elapsed == 0 )
|
||||
{
|
||||
Elapsed = 1;
|
||||
}
|
||||
return ( Elapsed );
|
||||
}
|
||||
else // timed out blocking for message
|
||||
{
|
||||
*msg = NULL;
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
}
|
||||
else // block forever for a message.
|
||||
{
|
||||
while( pdTRUE != xQueueReceive( mbox, &(*msg), 10000 ) ) // time is arbitrary
|
||||
{
|
||||
;
|
||||
}
|
||||
EndTime = xTaskGetTickCount();
|
||||
Elapsed = EndTime - StartTime;
|
||||
if( Elapsed == 0 )
|
||||
{
|
||||
Elapsed = 1;
|
||||
}
|
||||
return ( Elapsed ); // return time blocked TBD test
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// Creates and returns a new semaphore. The "count" argument specifies
|
||||
// the initial state of the semaphore. TBD finish and test
|
||||
sys_sem_t
|
||||
sys_sem_new(u8_t count)
|
||||
{
|
||||
xSemaphoreHandle xSemaphore;
|
||||
|
||||
portENTER_CRITICAL();
|
||||
vSemaphoreCreateBinary( xSemaphore );
|
||||
if(count == 0) // Means it can't be taken
|
||||
{
|
||||
xSemaphoreTake(xSemaphore,1);
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
if( xSemaphore == NULL )
|
||||
{
|
||||
return NULL; // TBD need assert
|
||||
}
|
||||
else
|
||||
{
|
||||
return xSemaphore;
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*
|
||||
Blocks the thread while waiting for the semaphore to be
|
||||
signaled. If the "timeout" argument is non-zero, the thread should
|
||||
only be blocked for the specified time (measured in
|
||||
milliseconds).
|
||||
|
||||
If the timeout argument is non-zero, the return value is the number of
|
||||
milliseconds spent waiting for the semaphore to be signaled. If the
|
||||
semaphore wasn't signaled within the specified time, the return value is
|
||||
SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
|
||||
(i.e., it was already signaled), the function may return zero.
|
||||
|
||||
Notice that lwIP implements a function with a similar name,
|
||||
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
|
||||
*/
|
||||
u32_t
|
||||
sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
|
||||
{
|
||||
portTickType StartTime, EndTime, Elapsed;
|
||||
|
||||
StartTime = xTaskGetTickCount();
|
||||
|
||||
if( timeout != 0)
|
||||
{
|
||||
if( xSemaphoreTake( sem, timeout ) == pdTRUE )
|
||||
{
|
||||
EndTime = xTaskGetTickCount();
|
||||
Elapsed = EndTime - StartTime;
|
||||
if( Elapsed == 0 )
|
||||
{
|
||||
Elapsed = 1;
|
||||
}
|
||||
return (Elapsed); // return time blocked TBD test
|
||||
}
|
||||
else
|
||||
{
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
}
|
||||
else // must block without a timeout
|
||||
{
|
||||
while( xSemaphoreTake( sem, 10000 ) != pdTRUE )
|
||||
{
|
||||
;
|
||||
}
|
||||
EndTime = xTaskGetTickCount();
|
||||
Elapsed = EndTime - StartTime;
|
||||
if( Elapsed == 0 )
|
||||
{
|
||||
Elapsed = 1;
|
||||
}
|
||||
|
||||
return ( Elapsed ); // return time blocked
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// Signals a semaphore
|
||||
void
|
||||
sys_sem_signal(sys_sem_t sem)
|
||||
{
|
||||
xSemaphoreGive( sem );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// Deallocates a semaphore
|
||||
void
|
||||
sys_sem_free(sys_sem_t sem)
|
||||
{
|
||||
vQueueDelete( sem );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// Initialize sys arch
|
||||
void
|
||||
sys_init(void)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
// Initialize the the per-thread sys_timeouts structures
|
||||
// make sure there are no valid pids in the list
|
||||
for(i = 0; i < SYS_THREAD_MAX; i++)
|
||||
{
|
||||
timeoutlist[i].pid = 0;
|
||||
}
|
||||
|
||||
// keep track of how many threads have been created
|
||||
nextthread = 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*
|
||||
Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
|
||||
each thread has a list of timeouts which is represented as a linked
|
||||
list of sys_timeout structures. The sys_timeouts structure holds a
|
||||
pointer to a linked list of timeouts. This function is called by
|
||||
the lwIP timeout scheduler and must not return a NULL value.
|
||||
|
||||
In a single threaded sys_arch implementation, this function will
|
||||
simply return a pointer to a global sys_timeouts variable stored in
|
||||
the sys_arch module.
|
||||
*/
|
||||
struct sys_timeouts *
|
||||
sys_arch_timeouts(void)
|
||||
{
|
||||
int i;
|
||||
xTaskHandle pid;
|
||||
struct timeoutlist *tl;
|
||||
|
||||
pid = xTaskGetCurrentTaskHandle( );
|
||||
|
||||
for(i = 0; i < nextthread; i++)
|
||||
{
|
||||
tl = &timeoutlist[i];
|
||||
if(tl->pid == pid)
|
||||
{
|
||||
return &(tl->timeouts);
|
||||
}
|
||||
}
|
||||
|
||||
// Error
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
// TBD
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*
|
||||
Starts a new thread with priority "prio" that will begin its execution in the
|
||||
function "thread()". The "arg" argument will be passed as an argument to the
|
||||
thread() function. The id of the new thread is returned. Both the id and
|
||||
the priority are system dependent.
|
||||
*/
|
||||
sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio)
|
||||
{
|
||||
xTaskHandle CreatedTask;
|
||||
int result;
|
||||
static int iCall = 0;
|
||||
|
||||
if( iCall == 0 )
|
||||
{
|
||||
/* The first time this is called we are creating the lwIP handler. */
|
||||
result = xTaskCreate( thread, ( signed char * ) "lwIP", lwipTCP_STACK_SIZE, arg, prio, &CreatedTask );
|
||||
iCall++;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = xTaskCreate( thread, ( signed char * ) "WEBSvr", lwipBASIC_SERVER_STACK_SIZE, arg, prio, &CreatedTask );
|
||||
}
|
||||
|
||||
// For each task created, store the task handle (pid) in the timers array.
|
||||
// This scheme doesn't allow for threads to be deleted
|
||||
timeoutlist[nextthread++].pid = CreatedTask;
|
||||
|
||||
if(result == pdPASS)
|
||||
{
|
||||
return CreatedTask;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This optional function does a "fast" critical region protection and returns
|
||||
the previous protection level. This function is only called during very short
|
||||
critical regions. An embedded system which supports ISR-based drivers might
|
||||
want to implement this function by disabling interrupts. Task-based systems
|
||||
might want to implement this by using a mutex or disabling tasking. This
|
||||
function should support recursive calls from the same task or interrupt. In
|
||||
other words, sys_arch_protect() could be called while already protected. In
|
||||
that case the return value indicates that it is already protected.
|
||||
|
||||
sys_arch_protect() is only required if your port is supporting an operating
|
||||
system.
|
||||
*/
|
||||
sys_prot_t sys_arch_protect(void)
|
||||
{
|
||||
vPortEnterCritical();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
This optional function does a "fast" set of critical region protection to the
|
||||
value specified by pval. See the documentation for sys_arch_protect() for
|
||||
more information. This function is only required if your port is supporting
|
||||
an operating system.
|
||||
*/
|
||||
void sys_arch_unprotect(sys_prot_t pval)
|
||||
{
|
||||
( void ) pval;
|
||||
vPortExitCritical();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
1 Introduction
|
||||
|
||||
This document describes some guidelines for people participating
|
||||
in lwIP development.
|
||||
|
||||
2 How to contribute to lwIP
|
||||
|
||||
Here is a short list of suggestions to anybody working with lwIP and
|
||||
trying to contribute bug reports, fixes, enhancements, platform ports etc.
|
||||
First of all as you may already know lwIP is a volunteer project so feedback
|
||||
to fixes or questions might often come late. Hopefully the bug and patch tracking
|
||||
features of Savannah help us not lose users' input.
|
||||
|
||||
2.1 Source code style:
|
||||
|
||||
1. do not use tabs.
|
||||
2. indentation is two spaces per level (i.e. per tab).
|
||||
3. end debug messages with a trailing newline (\n).
|
||||
4. one space between keyword and opening bracket.
|
||||
5. no space between function and opening bracket.
|
||||
6. one space and no newline before opening curly braces of a block.
|
||||
7. closing curly brace on a single line.
|
||||
8. spaces surrounding assignment and comparisons.
|
||||
9. use current source code style as further reference.
|
||||
|
||||
2.2 Source code documentation style:
|
||||
|
||||
1. JavaDoc compliant and Doxygen compatible.
|
||||
2. Function documentation above functions in .c files, not .h files.
|
||||
(This forces you to synchronize documentation and implementation.)
|
||||
3. Use current documentation style as further reference.
|
||||
|
||||
2.3 Bug reports and patches:
|
||||
|
||||
1. Make sure you are reporting bugs or send patches against the latest
|
||||
sources. (From the latest release and/or the current CVS sources.)
|
||||
2. If you think you found a bug make sure it's not already filed in the
|
||||
bugtracker at Savannah.
|
||||
3. If you have a fix put the patch on Savannah. If it is a patch that affects
|
||||
both core and arch specific stuff please separate them so that the core can
|
||||
be applied separately while leaving the other patch 'open'. The prefered way
|
||||
is to NOT touch archs you can't test and let maintainers take care of them.
|
||||
This is a good way to see if they are used at all - the same goes for unix
|
||||
netifs except tapif.
|
||||
4. Do not file a bug and post a fix to it to the patch area. Either a bug report
|
||||
or a patch will be enough.
|
||||
If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area.
|
||||
5. Trivial patches (compiler warning, indentation and spelling fixes or anything obvious which takes a line or two)
|
||||
can go to the lwip-users list. This is still the fastest way of interaction and the list is not so crowded
|
||||
as to allow for loss of fixes. Putting bugs on Savannah and subsequently closing them is too much an overhead
|
||||
for reporting a compiler warning fix.
|
||||
6. Patches should be specific to a single change or to related changes.Do not mix bugfixes with spelling and other
|
||||
trivial fixes unless the bugfix is trivial too.Do not reorganize code and rename identifiers in the same patch you
|
||||
change behaviour if not necessary.A patch is easier to read and understand if it's to the point and short than
|
||||
if it's not to the point and long :) so the chances for it to be applied are greater.
|
||||
|
||||
2.4 Platform porters:
|
||||
|
||||
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
|
||||
you think it could benefit others[1] you might want discuss this on the mailing list. You
|
||||
can also ask for CVS access to submit and maintain your port in the contrib CVS module.
|
||||
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
Raw TCP/IP interface for lwIP
|
||||
|
||||
Authors: Adam Dunkels, Leon Woestenberg
|
||||
|
||||
lwIP provides two Application Program's Interfaces (APIs) for programs
|
||||
to use for communication with the TCP/IP code:
|
||||
* low-level "core" / "callback" or "raw" API.
|
||||
* higher-level "sequential" API.
|
||||
|
||||
The sequential API provides a way for ordinary, sequential, programs
|
||||
to use the lwIP stack. It is quite similar to the BSD socket API. The
|
||||
model of execution is based on the blocking open-read-write-close
|
||||
paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
|
||||
code and the application program must reside in different execution
|
||||
contexts (threads).
|
||||
|
||||
** The remainder of this document discusses the "raw" API. **
|
||||
|
||||
The raw TCP/IP interface allows the application program to integrate
|
||||
better with the TCP/IP code. Program execution is event based by
|
||||
having callback functions being called from within the TCP/IP
|
||||
code. The TCP/IP code and the application program both run in the same
|
||||
thread. The sequential API has a much higher overhead and is not very
|
||||
well suited for small systems since it forces a multithreaded paradigm
|
||||
on the application.
|
||||
|
||||
The raw TCP/IP interface is not only faster in terms of code execution
|
||||
time but is also less memory intensive. The drawback is that program
|
||||
development is somewhat harder and application programs written for
|
||||
the raw TCP/IP interface are more difficult to understand. Still, this
|
||||
is the preferred way of writing applications that should be small in
|
||||
code size and memory usage.
|
||||
|
||||
Both APIs can be used simultaneously by different application
|
||||
programs. In fact, the sequential API is implemented as an application
|
||||
program using the raw TCP/IP interface.
|
||||
|
||||
--- Callbacks
|
||||
|
||||
Program execution is driven by callbacks. Each callback is an ordinary
|
||||
C function that is called from within the TCP/IP code. Every callback
|
||||
function is passed the current TCP or UDP connection state as an
|
||||
argument. Also, in order to be able to keep program specific state,
|
||||
the callback functions are called with a program specified argument
|
||||
that is independent of the TCP/IP state.
|
||||
|
||||
The function for setting the application connection state is:
|
||||
|
||||
- void tcp_arg(struct tcp_pcb *pcb, void *arg)
|
||||
|
||||
Specifies the program specific state that should be passed to all
|
||||
other callback functions. The "pcb" argument is the current TCP
|
||||
connection control block, and the "arg" argument is the argument
|
||||
that will be passed to the callbacks.
|
||||
|
||||
|
||||
--- TCP connection setup
|
||||
|
||||
The functions used for setting up connections is similar to that of
|
||||
the sequential API and of the BSD socket API. A new TCP connection
|
||||
identifier (i.e., a protocol control block - PCB) is created with the
|
||||
tcp_new() function. This PCB can then be either set to listen for new
|
||||
incoming connections or be explicitly connected to another host.
|
||||
|
||||
- struct tcp_pcb *tcp_new(void)
|
||||
|
||||
Creates a new connection identifier (PCB). If memory is not
|
||||
available for creating the new pcb, NULL is returned.
|
||||
|
||||
- err_t tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port)
|
||||
|
||||
Binds the pcb to a local IP address and port number. The IP address
|
||||
can be specified as IP_ADDR_ANY in order to bind the connection to
|
||||
all local IP addresses.
|
||||
|
||||
If another connection is bound to the same port, the function will
|
||||
return ERR_USE, otherwise ERR_OK is returned.
|
||||
|
||||
- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb)
|
||||
|
||||
Commands a pcb to start listening for incoming connections. When an
|
||||
incoming connection is accepted, the function specified with the
|
||||
tcp_accept() function will be called. The pcb will have to be bound
|
||||
to a local port with the tcp_bind() function.
|
||||
|
||||
The tcp_listen() function returns a new connection identifier, and
|
||||
the one passed as an argument to the function will be
|
||||
deallocated. The reason for this behavior is that less memory is
|
||||
needed for a connection that is listening, so tcp_listen() will
|
||||
reclaim the memory needed for the original connection and allocate a
|
||||
new smaller memory block for the listening connection.
|
||||
|
||||
tcp_listen() may return NULL if no memory was available for the
|
||||
listening connection. If so, the memory associated with the pcb
|
||||
passed as an argument to tcp_listen() will not be deallocated.
|
||||
|
||||
- void tcp_accept(struct tcp_pcb *pcb,
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
|
||||
err_t err))
|
||||
|
||||
Specified the callback function that should be called when a new
|
||||
connection arrives on a listening connection.
|
||||
|
||||
- err_t tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port, err_t (* connected)(void *arg,
|
||||
struct tcp_pcb *tpcb,
|
||||
err_t err));
|
||||
|
||||
Sets up the pcb to connect to the remote host and sends the
|
||||
initial SYN segment which opens the connection.
|
||||
|
||||
The tcp_connect() function returns immediately; it does not wait for
|
||||
the connection to be properly setup. Instead, it will call the
|
||||
function specified as the fourth argument (the "connected" argument)
|
||||
when the connection is established. If the connection could not be
|
||||
properly established, either because the other host refused the
|
||||
connection or because the other host didn't answer, the "connected"
|
||||
function will be called with an the "err" argument set accordingly.
|
||||
|
||||
The tcp_connect() function can return ERR_MEM if no memory is
|
||||
available for enqueueing the SYN segment. If the SYN indeed was
|
||||
enqueued successfully, the tcp_connect() function returns ERR_OK.
|
||||
|
||||
|
||||
--- Sending TCP data
|
||||
|
||||
TCP data is sent by enqueueing the data with a call to
|
||||
tcp_write(). When the data is successfully transmitted to the remote
|
||||
host, the application will be notified with a call to a specified
|
||||
callback function.
|
||||
|
||||
- err_t tcp_write(struct tcp_pcb *pcb, void *dataptr, u16_t len,
|
||||
u8_t copy)
|
||||
|
||||
Enqueues the data pointed to by the argument dataptr. The length of
|
||||
the data is passed as the len parameter. The copy argument is either
|
||||
0 or 1 and indicates whether the new memory should be allocated for
|
||||
the data to be copied into. If the argument is 0, no new memory
|
||||
should be allocated and the data should only be referenced by
|
||||
pointer.
|
||||
|
||||
The tcp_write() function will fail and return ERR_MEM if the length
|
||||
of the data exceeds the current send buffer size or if the length of
|
||||
the queue of outgoing segment is larger than the upper limit defined
|
||||
in lwipopts.h. The number of bytes available in the output queue can
|
||||
be retrieved with the tcp_sndbuf() function.
|
||||
|
||||
The proper way to use this function is to call the function with at
|
||||
most tcp_sndbuf() bytes of data. If the function returns ERR_MEM,
|
||||
the application should wait until some of the currently enqueued
|
||||
data has been successfully received by the other host and try again.
|
||||
|
||||
- void tcp_sent(struct tcp_pcb *pcb,
|
||||
err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
|
||||
u16_t len))
|
||||
|
||||
Specifies the callback function that should be called when data has
|
||||
successfully been received (i.e., acknowledged) by the remote
|
||||
host. The len argument passed to the callback function gives the
|
||||
amount bytes that was acknowledged by the last acknowledgment.
|
||||
|
||||
|
||||
--- Receiving TCP data
|
||||
|
||||
TCP data reception is callback based - an application specified
|
||||
callback function is called when new data arrives. When the
|
||||
application has taken the data, it has to call the tcp_recved()
|
||||
function to indicate that TCP can advertise increase the receive
|
||||
window.
|
||||
|
||||
- void tcp_recv(struct tcp_pcb *pcb,
|
||||
err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
|
||||
struct pbuf *p, err_t err))
|
||||
|
||||
Sets the callback function that will be called when new data
|
||||
arrives. The callback function will be passed a NULL pbuf to
|
||||
indicate that the remote host has closed the connection.
|
||||
|
||||
- void tcp_recved(struct tcp_pcb *pcb, u16_t len)
|
||||
|
||||
Must be called when the application has received the data. The len
|
||||
argument indicates the length of the received data.
|
||||
|
||||
|
||||
--- Application polling
|
||||
|
||||
When a connection is idle (i.e., no data is either transmitted or
|
||||
received), lwIP will repeatedly poll the application by calling a
|
||||
specified callback function. This can be used either as a watchdog
|
||||
timer for killing connections that have stayed idle for too long, or
|
||||
as a method of waiting for memory to become available. For instance,
|
||||
if a call to tcp_write() has failed because memory wasn't available,
|
||||
the application may use the polling functionality to call tcp_write()
|
||||
again when the connection has been idle for a while.
|
||||
|
||||
- void tcp_poll(struct tcp_pcb *pcb, u8_t interval,
|
||||
err_t (* poll)(void *arg, struct tcp_pcb *tpcb))
|
||||
|
||||
Specifies the polling interval and the callback function that should
|
||||
be called to poll the application. The interval is specified in
|
||||
number of TCP coarse grained timer shots, which typically occurs
|
||||
twice a second. An interval of 10 means that the application would
|
||||
be polled every 5 seconds.
|
||||
|
||||
|
||||
--- Closing and aborting connections
|
||||
|
||||
- err_t tcp_close(struct tcp_pcb *pcb)
|
||||
|
||||
Closes the connection. The function may return ERR_MEM if no memory
|
||||
was available for closing the connection. If so, the application
|
||||
should wait and try again either by using the acknowledgment
|
||||
callback or the polling functionality. If the close succeeds, the
|
||||
function returns ERR_OK.
|
||||
|
||||
The pcb is deallocated by the TCP code after a call to tcp_close().
|
||||
|
||||
- void tcp_abort(struct tcp_pcb *pcb)
|
||||
|
||||
Aborts the connection by sending a RST (reset) segment to the remote
|
||||
host. The pcb is deallocated. This function never fails.
|
||||
|
||||
If a connection is aborted because of an error, the application is
|
||||
alerted of this event by the err callback. Errors that might abort a
|
||||
connection are when there is a shortage of memory. The callback
|
||||
function to be called is set using the tcp_err() function.
|
||||
|
||||
- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg,
|
||||
err_t err))
|
||||
|
||||
The error callback function does not get the pcb passed to it as a
|
||||
parameter since the pcb may already have been deallocated.
|
||||
|
||||
|
||||
--- Lower layer TCP interface
|
||||
|
||||
TCP provides a simple interface to the lower layers of the
|
||||
system. During system initialization, the function tcp_init() has
|
||||
to be called before any other TCP function is called. When the system
|
||||
is running, the two timer functions tcp_fasttmr() and tcp_slowtmr()
|
||||
must be called with regular intervals. The tcp_fasttmr() should be
|
||||
called every TCP_FAST_INTERVAL milliseconds (defined in tcp.h) and
|
||||
tcp_slowtmr() should be called every TCP_SLOW_INTERVAL milliseconds.
|
||||
|
||||
|
||||
--- UDP interface
|
||||
|
||||
The UDP interface is similar to that of TCP, but due to the lower
|
||||
level of complexity of UDP, the interface is significantly simpler.
|
||||
|
||||
- struct udp_pcb *udp_new(void)
|
||||
|
||||
Creates a new UDP pcb which can be used for UDP communication. The
|
||||
pcb is not active until it has either been bound to a local address
|
||||
or connected to a remote address.
|
||||
|
||||
- void udp_remove(struct udp_pcb *pcb)
|
||||
|
||||
Removes and deallocates the pcb.
|
||||
|
||||
- err_t udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port)
|
||||
|
||||
Binds the pcb to a local address. The IP-address argument "ipaddr"
|
||||
can be IP_ADDR_ANY to indicate that it should listen to any local IP
|
||||
address. The function currently always return ERR_OK.
|
||||
|
||||
- err_t udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port)
|
||||
|
||||
Sets the remote end of the pcb. This function does not generate any
|
||||
network traffic, but only set the remote address of the pcb.
|
||||
|
||||
- err_t udp_disconnect(struct udp_pcb *pcb)
|
||||
|
||||
Remove the remote end of the pcb. This function does not generate
|
||||
any network traffic, but only removes the remote address of the pcb.
|
||||
|
||||
- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
|
||||
Sends the pbuf p. The pbuf is not deallocated.
|
||||
|
||||
- void udp_recv(struct udp_pcb *pcb,
|
||||
void (* recv)(void *arg, struct udp_pcb *upcb,
|
||||
struct pbuf *p,
|
||||
struct ip_addr *addr,
|
||||
u16_t port),
|
||||
void *recv_arg)
|
||||
|
||||
Specifies a callback function that should be called when a UDP
|
||||
datagram is received.
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
Daily Use Guide for using Savannah for lwIP
|
||||
|
||||
Table of Contents:
|
||||
|
||||
1 - Obtaining lwIP from the CVS repository
|
||||
2 - Committers/developers CVS access using SSH (to be written)
|
||||
3 - Merging from DEVEL branch to main trunk (stable branch)
|
||||
4 - How to release lwIP
|
||||
|
||||
|
||||
|
||||
1 Obtaining lwIP from the CVS repository
|
||||
----------------------------------------
|
||||
|
||||
To perform an anonymous CVS checkout of the main trunk (this is where
|
||||
bug fixes and incremental enhancements occur), do this:
|
||||
|
||||
export CVS_RSH=ssh
|
||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip
|
||||
|
||||
(If SSH asks about authenticity of the host, you can check the key
|
||||
fingerprint against http://savannah.nongnu.org/cvs/?group=lwip)
|
||||
|
||||
Or, obtain a stable branch (updated with bug fixes only) as follows:
|
||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_7 -d lwip-0.7 lwip
|
||||
|
||||
Or, obtain a specific (fixed) release as follows:
|
||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_7_0 -d lwip-0.7.0 lwip
|
||||
|
||||
Or, obtain a development branch (considered unstable!) as follows:
|
||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-DEVEL lwip
|
||||
|
||||
3 Committers/developers CVS access using SSH
|
||||
--------------------------------------------
|
||||
|
||||
The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption.
|
||||
As such, CVS commits to the server occur through a SSH tunnel for project members.
|
||||
To create a SSH2 key pair in UNIX-like environments, do this:
|
||||
|
||||
ssh-keygen -t dsa
|
||||
|
||||
Under Windows, a recommended SSH client is "PuTTY", freely available with good
|
||||
documentation and a graphic user interface. Use its key generator.
|
||||
|
||||
Now paste the id_dsa.pub contents into your Savannah account public key list. Wait
|
||||
a while so that Savannah can update its configuration (This can take minutes).
|
||||
|
||||
Try to login using SSH:
|
||||
|
||||
ssh -v your_login@subversions.gnu.org
|
||||
|
||||
If it tells you:
|
||||
|
||||
Authenticating with public key "your_key_name"...
|
||||
Server refused to allocate pty
|
||||
|
||||
then you could login; Savannah refuses to give you a shell - which is OK, as we
|
||||
are allowed to use SSH for CVS only. Now, you should be able to do this:
|
||||
|
||||
export CVS_RSH=ssh
|
||||
cvs -d:ext:your_login@subversions.gnu.org:/cvsroot/lwip checkout lwip
|
||||
|
||||
after which you can edit your local files with bug fixes or new features and
|
||||
commit them. Make sure you know what you are doing when using CVS to make
|
||||
changes on the repository. If in doubt, ask on the lwip-members mailing list.
|
||||
|
||||
3 Merging from DEVEL branch to main trunk (stable)
|
||||
--------------------------------------------------
|
||||
|
||||
Merging is a delicate process in CVS and requires the
|
||||
following disciplined steps in order to prevent conflicts
|
||||
in the future. Conflicts can be hard to solve!
|
||||
|
||||
Merging from branch A to branch B requires that the A branch
|
||||
has a tag indicating the previous merger. This tag is called
|
||||
'merged_from_A_to_B'. After merging, the tag is moved in the
|
||||
A branch to remember this merger for future merge actions.
|
||||
|
||||
IMPORTANT: AFTER COMMITTING A SUCCESFUL MERGE IN THE
|
||||
REPOSITORY, THE TAG MUST BE SET ON THE SOURCE BRANCH OF THE
|
||||
MERGE ACTION (REPLACING EXISTING TAGS WITH THE SAME NAME).
|
||||
|
||||
Merge all changes in DEVEL since our last merge to main:
|
||||
|
||||
In the working copy of the main trunk:
|
||||
cvs update -P -jmerged_from_DEVEL_to_main -jDEVEL
|
||||
|
||||
(This will apply the changes between 'merged_from_DEVEL_to_main'
|
||||
and 'DEVEL' to your work set of files)
|
||||
|
||||
We can now commit the merge result.
|
||||
cvs commit -R -m "Merged from DEVEL to main."
|
||||
|
||||
If this worked out OK, we now move the tag in the DEVEL branch
|
||||
to this merge point, so we can use this point for future merges:
|
||||
|
||||
cvs rtag -F -r DEVEL merged_from_DEVEL_to_main lwip
|
||||
|
||||
4 How to release lwIP
|
||||
---------------------
|
||||
|
||||
First, checkout a clean copy of the branch to be released. Tag this set with
|
||||
tag name "STABLE-0_6_3". (I use release number 0.6.3 throughout this example).
|
||||
|
||||
Login CVS using pserver authentication, then export a clean copy of the
|
||||
tagged tree. Export is similar to a checkout, except that the CVS metadata
|
||||
is not created locally.
|
||||
|
||||
export CVS_RSH=ssh
|
||||
cvs -d:ext:anoncvs@subversions.gnu.org:/cvsroot/lwip export -r STABLE-0_6_3 -d lwip-0.6.3 lwip
|
||||
|
||||
Archive this directory using tar, gzip'd, bzip2'd and zip'd.
|
||||
|
||||
tar czvf lwip-0.6.3.tar.gz lwip-0.6.3
|
||||
tar cjvf lwip-0.6.3.tar.bz2 lwip-0.6.3
|
||||
zip -r lwip-0.6.3.zip lwip-0.6.3
|
||||
|
||||
Now, sign the archives with a detached GPG binary signature as follows:
|
||||
|
||||
gpg -b lwip-0.6.3.tar.gz
|
||||
gpg -b lwip-0.6.3.tar.bz2
|
||||
gpg -b lwip-0.6.3.zip
|
||||
|
||||
Upload these files using anonymous FTP:
|
||||
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
|
||||
|
||||
ncftp>mput *0.6.3.*
|
||||
|
||||
Additionally, you may post a news item on Savannah, like this:
|
||||
|
||||
A new 0.6.3 release is now available here:
|
||||
http://savannah.nongnu.org/files/?group=lwip&highlight=0.6.3
|
||||
|
||||
You will have to submit this via the user News interface, then approve
|
||||
this via the Administrator News interface.
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
sys_arch interface for lwIP 0.6++
|
||||
|
||||
Author: Adam Dunkels
|
||||
|
||||
The operating system emulation layer provides a common interface
|
||||
between the lwIP code and the underlying operating system kernel. The
|
||||
general idea is that porting lwIP to new architectures requires only
|
||||
small changes to a few header files and a new sys_arch
|
||||
implementation. It is also possible to do a sys_arch implementation
|
||||
that does not rely on any underlying operating system.
|
||||
|
||||
The sys_arch provides semaphores and mailboxes to lwIP. For the full
|
||||
lwIP functionality, multiple threads support can be implemented in the
|
||||
sys_arch, but this is not required for the basic lwIP
|
||||
functionality. Previous versions of lwIP required the sys_arch to
|
||||
implement timer scheduling as well but as of lwIP 0.5 this is
|
||||
implemented in a higher layer.
|
||||
|
||||
In addition to the source file providing the functionality of sys_arch,
|
||||
the OS emulation layer must provide several header files defining
|
||||
macros used throughout lwip. The files required and the macros they
|
||||
must define are listed below the sys_arch description.
|
||||
|
||||
Semaphores can be either counting or binary - lwIP works with both
|
||||
kinds. Mailboxes are used for message passing and can be implemented
|
||||
either as a queue which allows multiple messages to be posted to a
|
||||
mailbox, or as a rendez-vous point where only one message can be
|
||||
posted at a time. lwIP works with both kinds, but the former type will
|
||||
be more efficient. A message in a mailbox is just a pointer, nothing
|
||||
more.
|
||||
|
||||
Semaphores are represented by the type "sys_sem_t" which is typedef'd
|
||||
in the sys_arch.h file. Mailboxes are equivalently represented by the
|
||||
type "sys_mbox_t". lwIP does not place any restrictions on how
|
||||
sys_sem_t or sys_mbox_t are represented internally.
|
||||
|
||||
The following functions must be implemented by the sys_arch:
|
||||
|
||||
- void sys_init(void)
|
||||
|
||||
Is called to initialize the sys_arch layer.
|
||||
|
||||
- sys_sem_t sys_sem_new(u8_t count)
|
||||
|
||||
Creates and returns a new semaphore. The "count" argument specifies
|
||||
the initial state of the semaphore.
|
||||
|
||||
- void sys_sem_free(sys_sem_t sem)
|
||||
|
||||
Deallocates a semaphore.
|
||||
|
||||
- void sys_sem_signal(sys_sem_t sem)
|
||||
|
||||
Signals a semaphore.
|
||||
|
||||
- u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
|
||||
|
||||
Blocks the thread while waiting for the semaphore to be
|
||||
signaled. If the "timeout" argument is non-zero, the thread should
|
||||
only be blocked for the specified time (measured in
|
||||
milliseconds).
|
||||
|
||||
If the timeout argument is non-zero, the return value is the number of
|
||||
milliseconds spent waiting for the semaphore to be signaled. If the
|
||||
semaphore wasn't signaled within the specified time, the return value is
|
||||
SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
|
||||
(i.e., it was already signaled), the function may return zero.
|
||||
|
||||
Notice that lwIP implements a function with a similar name,
|
||||
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
|
||||
|
||||
- sys_mbox_t sys_mbox_new(void)
|
||||
|
||||
Creates an empty mailbox.
|
||||
|
||||
- void sys_mbox_free(sys_mbox_t mbox)
|
||||
|
||||
Deallocates a mailbox. If there are messages still present in the
|
||||
mailbox when the mailbox is deallocated, it is an indication of a
|
||||
programming error in lwIP and the developer should be notified.
|
||||
|
||||
- void sys_mbox_post(sys_mbox_t mbox, void *msg)
|
||||
|
||||
Posts the "msg" to the mailbox.
|
||||
|
||||
- u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
|
||||
|
||||
Blocks the thread until a message arrives in the mailbox, but does
|
||||
not block the thread longer than "timeout" milliseconds (similar to
|
||||
the sys_arch_sem_wait() function). The "msg" argument is a result
|
||||
parameter that is set by the function (i.e., by doing "*msg =
|
||||
ptr"). The "msg" parameter maybe NULL to indicate that the message
|
||||
should be dropped.
|
||||
|
||||
The return values are the same as for the sys_arch_sem_wait() function:
|
||||
Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
|
||||
timeout.
|
||||
|
||||
Note that a function with a similar name, sys_mbox_fetch(), is
|
||||
implemented by lwIP.
|
||||
|
||||
- struct sys_timeouts *sys_arch_timeouts(void)
|
||||
|
||||
Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
|
||||
each thread has a list of timeouts which is repressented as a linked
|
||||
list of sys_timeout structures. The sys_timeouts structure holds a
|
||||
pointer to a linked list of timeouts. This function is called by
|
||||
the lwIP timeout scheduler and must not return a NULL value.
|
||||
|
||||
In a single threadd sys_arch implementation, this function will
|
||||
simply return a pointer to a global sys_timeouts variable stored in
|
||||
the sys_arch module.
|
||||
|
||||
If threads are supported by the underlying operating system and if
|
||||
such functionality is needed in lwIP, the following function will have
|
||||
to be implemented as well:
|
||||
|
||||
- sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio)
|
||||
|
||||
Starts a new thread with priority "prio" that will begin its execution in the
|
||||
function "thread()". The "arg" argument will be passed as an argument to the
|
||||
thread() function. The id of the new thread is returned. Both the id and
|
||||
the priority are system dependent.
|
||||
|
||||
- sys_prot_t sys_arch_protect(void)
|
||||
|
||||
This optional function does a "fast" critical region protection and returns
|
||||
the previous protection level. This function is only called during very short
|
||||
critical regions. An embedded system which supports ISR-based drivers might
|
||||
want to implement this function by disabling interrupts. Task-based systems
|
||||
might want to implement this by using a mutex or disabling tasking. This
|
||||
function should support recursive calls from the same task or interrupt. In
|
||||
other words, sys_arch_protect() could be called while already protected. In
|
||||
that case the return value indicates that it is already protected.
|
||||
|
||||
sys_arch_protect() is only required if your port is supporting an operating
|
||||
system.
|
||||
|
||||
- void sys_arch_unprotect(sys_prot_t pval)
|
||||
|
||||
This optional function does a "fast" set of critical region protection to the
|
||||
value specified by pval. See the documentation for sys_arch_protect() for
|
||||
more information. This function is only required if your port is supporting
|
||||
an operating system.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Additional files required for the "OS support" emulation layer:
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
cc.h - Architecture environment, some compiler specific, some
|
||||
environment specific (probably should move env stuff
|
||||
to sys_arch.h.)
|
||||
|
||||
Typedefs for the types used by lwip -
|
||||
u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t
|
||||
|
||||
Compiler hints for packing lwip's structures -
|
||||
PACK_STRUCT_FIELD(x)
|
||||
PACK_STRUCT_STRUCT
|
||||
PACK_STRUCT_BEGIN
|
||||
PACK_STRUCT_END
|
||||
|
||||
Platform specific diagnostic output -
|
||||
LWIP_PLATFORM_DIAG(x) - non-fatal, print a message.
|
||||
LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution.
|
||||
|
||||
"lightweight" synchronization mechanisms -
|
||||
SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable.
|
||||
SYS_ARCH_PROTECT(x) - enter protection mode.
|
||||
SYS_ARCH_UNPROTECT(x) - leave protection mode.
|
||||
|
||||
If the compiler does not provide memset() this file must include a
|
||||
definition of it, or include a file which defines it.
|
||||
|
||||
This file must either include a system-local <errno.h> which defines
|
||||
the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO
|
||||
to make lwip/arch.h define the codes which are used throughout.
|
||||
|
||||
|
||||
perf.h - Architecture specific performance measurement.
|
||||
Measurement calls made throughout lwip, these can be defined to nothing.
|
||||
PERF_START - start measuring something.
|
||||
PERF_STOP(x) - stop measuring something, and record the result.
|
||||
|
||||
sys_arch.h - Tied to sys_arch.c
|
||||
|
||||
Arch dependent types for the following objects:
|
||||
sys_sem_t, sys_mbox_t, sys_thread_t,
|
||||
And, optionally:
|
||||
sys_prot_t
|
||||
|
||||
Defines to set vars of sys_mbox_t and sys_sem_t to NULL.
|
||||
SYS_MBOX_NULL NULL
|
||||
SYS_SEM_NULL NULL
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
api/ - The code for the high-level wrapper API. Not needed if
|
||||
you use the lowel-level call-back/raw API.
|
||||
|
||||
core/ - The core of the TPC/IP stack; protocol implementations,
|
||||
memory and buffer management, and the low-level raw API.
|
||||
|
||||
include/ - lwIP include files.
|
||||
|
||||
netif/ - Generic network interface device drivers are kept here,
|
||||
as well as the ARP module.
|
||||
|
||||
For more information on the various subdirectories, check the FILES
|
||||
file in each directory.
|
||||
|
|
@ -0,0 +1,729 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/* This is the part of the API that is linked with
|
||||
the application */
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/api_msg.h"
|
||||
#include "lwip/memp.h"
|
||||
|
||||
|
||||
struct
|
||||
netbuf *netbuf_new(void)
|
||||
{
|
||||
struct netbuf *buf;
|
||||
|
||||
buf = memp_malloc(MEMP_NETBUF);
|
||||
if (buf != NULL) {
|
||||
buf->p = NULL;
|
||||
buf->ptr = NULL;
|
||||
return buf;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_delete(struct netbuf *buf)
|
||||
{
|
||||
if (buf != NULL) {
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
buf->p = buf->ptr = NULL;
|
||||
}
|
||||
memp_free(MEMP_NETBUF, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
netbuf_alloc(struct netbuf *buf, u16_t size)
|
||||
{
|
||||
/* Deallocate any previously allocated memory. */
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
}
|
||||
buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
|
||||
if (buf->p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
buf->ptr = buf->p;
|
||||
return buf->p->payload;
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_free(struct netbuf *buf)
|
||||
{
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
}
|
||||
buf->p = buf->ptr = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
|
||||
{
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
}
|
||||
buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
|
||||
buf->p->payload = dataptr;
|
||||
buf->p->len = buf->p->tot_len = size;
|
||||
buf->ptr = buf->p;
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_chain(struct netbuf *head, struct netbuf *tail)
|
||||
{
|
||||
pbuf_chain(head->p, tail->p);
|
||||
head->ptr = head->p;
|
||||
memp_free(MEMP_NETBUF, tail);
|
||||
}
|
||||
|
||||
u16_t
|
||||
netbuf_len(struct netbuf *buf)
|
||||
{
|
||||
return buf->p->tot_len;
|
||||
}
|
||||
|
||||
err_t
|
||||
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
|
||||
{
|
||||
if (buf->ptr == NULL) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
*dataptr = buf->ptr->payload;
|
||||
*len = buf->ptr->len;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
s8_t
|
||||
netbuf_next(struct netbuf *buf)
|
||||
{
|
||||
if (buf->ptr->next == NULL) {
|
||||
return -1;
|
||||
}
|
||||
buf->ptr = buf->ptr->next;
|
||||
if (buf->ptr->next == NULL) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_first(struct netbuf *buf)
|
||||
{
|
||||
buf->ptr = buf->p;
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
||||
{
|
||||
struct pbuf *p;
|
||||
u16_t i, left;
|
||||
|
||||
left = 0;
|
||||
|
||||
if(buf == NULL || dataptr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* This implementation is bad. It should use bcopy
|
||||
instead. */
|
||||
for(p = buf->p; left < len && p != NULL; p = p->next) {
|
||||
if (offset != 0 && offset >= p->len) {
|
||||
offset -= p->len;
|
||||
} else {
|
||||
for(i = offset; i < p->len; ++i) {
|
||||
((char *)dataptr)[left] = ((char *)p->payload)[i];
|
||||
if (++left >= len) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
|
||||
{
|
||||
netbuf_copy_partial(buf, dataptr, len, 0);
|
||||
}
|
||||
|
||||
struct ip_addr *
|
||||
netbuf_fromaddr(struct netbuf *buf)
|
||||
{
|
||||
return buf->fromaddr;
|
||||
}
|
||||
|
||||
u16_t
|
||||
netbuf_fromport(struct netbuf *buf)
|
||||
{
|
||||
return buf->fromport;
|
||||
}
|
||||
|
||||
struct
|
||||
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
|
||||
void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
|
||||
{
|
||||
struct netconn *conn;
|
||||
struct api_msg *msg;
|
||||
|
||||
conn = memp_malloc(MEMP_NETCONN);
|
||||
if (conn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
conn->err = ERR_OK;
|
||||
conn->type = t;
|
||||
conn->pcb.tcp = NULL;
|
||||
|
||||
if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
|
||||
memp_free(MEMP_NETCONN, conn);
|
||||
return NULL;
|
||||
}
|
||||
conn->recvmbox = SYS_MBOX_NULL;
|
||||
conn->acceptmbox = SYS_MBOX_NULL;
|
||||
conn->sem = SYS_SEM_NULL;
|
||||
conn->state = NETCONN_NONE;
|
||||
conn->socket = 0;
|
||||
conn->callback = callback;
|
||||
conn->recv_avail = 0;
|
||||
|
||||
if((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
memp_free(MEMP_NETCONN, conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msg->type = API_MSG_NEWCONN;
|
||||
msg->msg.msg.bc.port = proto; /* misusing the port field */
|
||||
msg->msg.conn = conn;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
|
||||
if ( conn->err != ERR_OK ) {
|
||||
memp_free(MEMP_NETCONN, conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
struct
|
||||
netconn *netconn_new(enum netconn_type t)
|
||||
{
|
||||
return netconn_new_with_proto_and_callback(t,0,NULL);
|
||||
}
|
||||
|
||||
struct
|
||||
netconn *netconn_new_with_callback(enum netconn_type t,
|
||||
void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
|
||||
{
|
||||
return netconn_new_with_proto_and_callback(t,0,callback);
|
||||
}
|
||||
|
||||
|
||||
err_t
|
||||
netconn_delete(struct netconn *conn)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
void *mem;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
msg->type = API_MSG_DELCONN;
|
||||
msg->msg.conn = conn;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
|
||||
/* Drain the recvmbox. */
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
if(mem != NULL)
|
||||
pbuf_free((struct pbuf *)mem);
|
||||
} else {
|
||||
netbuf_delete((struct netbuf *)mem);
|
||||
}
|
||||
}
|
||||
sys_mbox_free(conn->recvmbox);
|
||||
conn->recvmbox = SYS_MBOX_NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Drain the acceptmbox. */
|
||||
if (conn->acceptmbox != SYS_MBOX_NULL) {
|
||||
while (sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
|
||||
netconn_delete((struct netconn *)mem);
|
||||
}
|
||||
|
||||
sys_mbox_free(conn->acceptmbox);
|
||||
conn->acceptmbox = SYS_MBOX_NULL;
|
||||
}
|
||||
|
||||
sys_mbox_free(conn->mbox);
|
||||
conn->mbox = SYS_MBOX_NULL;
|
||||
if (conn->sem != SYS_SEM_NULL) {
|
||||
sys_sem_free(conn->sem);
|
||||
}
|
||||
/* conn->sem = SYS_SEM_NULL;*/
|
||||
memp_free(MEMP_NETCONN, conn);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
enum netconn_type
|
||||
netconn_type(struct netconn *conn)
|
||||
{
|
||||
return conn->type;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_peer(struct netconn *conn, struct ip_addr *addr,
|
||||
u16_t *port)
|
||||
{
|
||||
switch (conn->type) {
|
||||
case NETCONN_RAW:
|
||||
/* return an error as connecting is only a helper for upper layers */
|
||||
return ERR_CONN;
|
||||
case NETCONN_UDPLITE:
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
case NETCONN_UDP:
|
||||
if (conn->pcb.udp == NULL ||
|
||||
((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0))
|
||||
return ERR_CONN;
|
||||
*addr = (conn->pcb.udp->remote_ip);
|
||||
*port = conn->pcb.udp->remote_port;
|
||||
break;
|
||||
case NETCONN_TCP:
|
||||
if (conn->pcb.tcp == NULL)
|
||||
return ERR_CONN;
|
||||
*addr = (conn->pcb.tcp->remote_ip);
|
||||
*port = conn->pcb.tcp->remote_port;
|
||||
break;
|
||||
}
|
||||
return (conn->err = ERR_OK);
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_addr(struct netconn *conn, struct ip_addr **addr,
|
||||
u16_t *port)
|
||||
{
|
||||
switch (conn->type) {
|
||||
case NETCONN_RAW:
|
||||
*addr = &(conn->pcb.raw->local_ip);
|
||||
*port = conn->pcb.raw->protocol;
|
||||
break;
|
||||
case NETCONN_UDPLITE:
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
case NETCONN_UDP:
|
||||
*addr = &(conn->pcb.udp->local_ip);
|
||||
*port = conn->pcb.udp->local_port;
|
||||
break;
|
||||
case NETCONN_TCP:
|
||||
*addr = &(conn->pcb.tcp->local_ip);
|
||||
*port = conn->pcb.tcp->local_port;
|
||||
break;
|
||||
}
|
||||
return (conn->err = ERR_OK);
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_bind(struct netconn *conn, struct ip_addr *addr,
|
||||
u16_t port)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if (conn->type != NETCONN_TCP &&
|
||||
conn->recvmbox == SYS_MBOX_NULL) {
|
||||
if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return (conn->err = ERR_MEM);
|
||||
}
|
||||
msg->type = API_MSG_BIND;
|
||||
msg->msg.conn = conn;
|
||||
msg->msg.msg.bc.ipaddr = addr;
|
||||
msg->msg.msg.bc.port = port;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
|
||||
err_t
|
||||
netconn_connect(struct netconn *conn, struct ip_addr *addr,
|
||||
u16_t port)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
|
||||
if (conn->recvmbox == SYS_MBOX_NULL) {
|
||||
if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
msg->type = API_MSG_CONNECT;
|
||||
msg->msg.conn = conn;
|
||||
msg->msg.msg.bc.ipaddr = addr;
|
||||
msg->msg.msg.bc.port = port;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_disconnect(struct netconn *conn)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
msg->type = API_MSG_DISCONNECT;
|
||||
msg->msg.conn = conn;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_listen(struct netconn *conn)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if (conn->acceptmbox == SYS_MBOX_NULL) {
|
||||
conn->acceptmbox = sys_mbox_new();
|
||||
if (conn->acceptmbox == SYS_MBOX_NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return (conn->err = ERR_MEM);
|
||||
}
|
||||
msg->type = API_MSG_LISTEN;
|
||||
msg->msg.conn = conn;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
struct netconn *
|
||||
netconn_accept(struct netconn *conn)
|
||||
{
|
||||
struct netconn *newconn;
|
||||
|
||||
if (conn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sys_mbox_fetch(conn->acceptmbox, (void **)&newconn);
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0);
|
||||
|
||||
return newconn;
|
||||
}
|
||||
|
||||
struct netbuf *
|
||||
netconn_recv(struct netconn *conn)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
struct netbuf *buf;
|
||||
struct pbuf *p;
|
||||
u16_t len;
|
||||
|
||||
if (conn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (conn->recvmbox == SYS_MBOX_NULL) {
|
||||
conn->err = ERR_CONN;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (conn->err != ERR_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
if (conn->pcb.tcp->state == LISTEN) {
|
||||
conn->err = ERR_CONN;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
buf = memp_malloc(MEMP_NETBUF);
|
||||
|
||||
if (buf == NULL) {
|
||||
conn->err = ERR_MEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sys_mbox_fetch(conn->recvmbox, (void **)&p);
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
len = p->tot_len;
|
||||
conn->recv_avail -= len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVMINUS, len);
|
||||
|
||||
/* If we are closed, we indicate that we no longer wish to receive
|
||||
data by setting conn->recvmbox to SYS_MBOX_NULL. */
|
||||
if (p == NULL) {
|
||||
memp_free(MEMP_NETBUF, buf);
|
||||
sys_mbox_free(conn->recvmbox);
|
||||
conn->recvmbox = SYS_MBOX_NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
buf->fromport = 0;
|
||||
buf->fromaddr = NULL;
|
||||
|
||||
/* Let the stack know that we have taken the data. */
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
conn->err = ERR_MEM;
|
||||
return buf;
|
||||
}
|
||||
msg->type = API_MSG_RECV;
|
||||
msg->msg.conn = conn;
|
||||
if (buf != NULL) {
|
||||
msg->msg.msg.len = buf->p->tot_len;
|
||||
} else {
|
||||
msg->msg.msg.len = 1;
|
||||
}
|
||||
api_msg_post(msg);
|
||||
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
} else {
|
||||
sys_mbox_fetch(conn->recvmbox, (void **)&buf);
|
||||
conn->recv_avail -= buf->p->tot_len;
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err));
|
||||
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_send(struct netconn *conn, struct netbuf *buf)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if (conn->err != ERR_OK) {
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return (conn->err = ERR_MEM);
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
|
||||
msg->type = API_MSG_SEND;
|
||||
msg->msg.conn = conn;
|
||||
msg->msg.msg.p = buf->p;
|
||||
api_msg_post(msg);
|
||||
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
u16_t len;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if (conn->err != ERR_OK) {
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
if (conn->sem == SYS_SEM_NULL) {
|
||||
conn->sem = sys_sem_new(0);
|
||||
if (conn->sem == SYS_SEM_NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return (conn->err = ERR_MEM);
|
||||
}
|
||||
msg->type = API_MSG_WRITE;
|
||||
msg->msg.conn = conn;
|
||||
|
||||
|
||||
conn->state = NETCONN_WRITE;
|
||||
while (conn->err == ERR_OK && size > 0) {
|
||||
msg->msg.msg.w.dataptr = dataptr;
|
||||
msg->msg.msg.w.copy = copy;
|
||||
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
if (tcp_sndbuf(conn->pcb.tcp) == 0) {
|
||||
sys_sem_wait(conn->sem);
|
||||
if (conn->err != ERR_OK) {
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
if (size > tcp_sndbuf(conn->pcb.tcp)) {
|
||||
/* We cannot send more than one send buffer's worth of data at a
|
||||
time. */
|
||||
len = tcp_sndbuf(conn->pcb.tcp);
|
||||
} else {
|
||||
len = size;
|
||||
}
|
||||
} else {
|
||||
len = size;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
|
||||
msg->msg.msg.w.len = len;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
if (conn->err == ERR_OK) {
|
||||
dataptr = (void *)((char *)dataptr + len);
|
||||
size -= len;
|
||||
} else if (conn->err == ERR_MEM) {
|
||||
conn->err = ERR_OK;
|
||||
sys_sem_wait(conn->sem);
|
||||
} else {
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
ret:
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
conn->state = NETCONN_NONE;
|
||||
if (conn->sem != SYS_SEM_NULL) {
|
||||
sys_sem_free(conn->sem);
|
||||
conn->sem = SYS_SEM_NULL;
|
||||
}
|
||||
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_close(struct netconn *conn)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return (conn->err = ERR_MEM);
|
||||
}
|
||||
|
||||
conn->state = NETCONN_CLOSE;
|
||||
again:
|
||||
msg->type = API_MSG_CLOSE;
|
||||
msg->msg.conn = conn;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
if (conn->err == ERR_MEM &&
|
||||
conn->sem != SYS_SEM_NULL) {
|
||||
sys_sem_wait(conn->sem);
|
||||
goto again;
|
||||
}
|
||||
conn->state = NETCONN_NONE;
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_err(struct netconn *conn)
|
||||
{
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,810 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/arch.h"
|
||||
#include "lwip/api_msg.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#if LWIP_RAW
|
||||
static u8_t
|
||||
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *addr)
|
||||
{
|
||||
struct netbuf *buf;
|
||||
struct netconn *conn;
|
||||
|
||||
conn = arg;
|
||||
if (!conn) return 0;
|
||||
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
if (!(buf = memp_malloc(MEMP_NETBUF))) {
|
||||
return 0;
|
||||
}
|
||||
pbuf_ref(p);
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
buf->fromaddr = addr;
|
||||
buf->fromport = pcb->protocol;
|
||||
|
||||
conn->recv_avail += p->tot_len;
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
|
||||
sys_mbox_post(conn->recvmbox, buf);
|
||||
}
|
||||
|
||||
return 0; /* do not eat the packet */
|
||||
}
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
static void
|
||||
recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *addr, u16_t port)
|
||||
{
|
||||
struct netbuf *buf;
|
||||
struct netconn *conn;
|
||||
|
||||
(void)pcb;
|
||||
|
||||
conn = arg;
|
||||
|
||||
if (conn == NULL) {
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
buf = memp_malloc(MEMP_NETBUF);
|
||||
if (buf == NULL) {
|
||||
pbuf_free(p);
|
||||
return;
|
||||
} else {
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
buf->fromaddr = addr;
|
||||
buf->fromport = port;
|
||||
}
|
||||
|
||||
conn->recv_avail += p->tot_len;
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
|
||||
sys_mbox_post(conn->recvmbox, buf);
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
|
||||
static err_t
|
||||
recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||
{
|
||||
struct netconn *conn;
|
||||
u16_t len;
|
||||
|
||||
(void)pcb;
|
||||
|
||||
conn = arg;
|
||||
|
||||
if (conn == NULL) {
|
||||
pbuf_free(p);
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
|
||||
conn->err = err;
|
||||
if (p != NULL) {
|
||||
len = p->tot_len;
|
||||
conn->recv_avail += len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, len);
|
||||
sys_mbox_post(conn->recvmbox, p);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
static err_t
|
||||
poll_tcp(void *arg, struct tcp_pcb *pcb)
|
||||
{
|
||||
struct netconn *conn;
|
||||
|
||||
(void)pcb;
|
||||
|
||||
conn = arg;
|
||||
if (conn != NULL &&
|
||||
(conn->state == NETCONN_WRITE || conn->state == NETCONN_CLOSE) &&
|
||||
conn->sem != SYS_SEM_NULL) {
|
||||
sys_sem_signal(conn->sem);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t
|
||||
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
|
||||
{
|
||||
struct netconn *conn;
|
||||
|
||||
(void)pcb;
|
||||
|
||||
conn = arg;
|
||||
if (conn != NULL && conn->sem != SYS_SEM_NULL) {
|
||||
sys_sem_signal(conn->sem);
|
||||
}
|
||||
|
||||
if (conn && conn->callback)
|
||||
if (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)
|
||||
(*conn->callback)(conn, NETCONN_EVT_SENDPLUS, len);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
err_tcp(void *arg, err_t err)
|
||||
{
|
||||
struct netconn *conn;
|
||||
|
||||
conn = arg;
|
||||
|
||||
conn->pcb.tcp = NULL;
|
||||
|
||||
|
||||
conn->err = err;
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
|
||||
sys_mbox_post(conn->recvmbox, NULL);
|
||||
}
|
||||
if (conn->mbox != SYS_MBOX_NULL) {
|
||||
sys_mbox_post(conn->mbox, NULL);
|
||||
}
|
||||
if (conn->acceptmbox != SYS_MBOX_NULL) {
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
|
||||
sys_mbox_post(conn->acceptmbox, NULL);
|
||||
}
|
||||
if (conn->sem != SYS_SEM_NULL) {
|
||||
sys_sem_signal(conn->sem);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_tcp(struct netconn *conn)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
|
||||
pcb = conn->pcb.tcp;
|
||||
tcp_arg(pcb, conn);
|
||||
tcp_recv(pcb, recv_tcp);
|
||||
tcp_sent(pcb, sent_tcp);
|
||||
tcp_poll(pcb, poll_tcp, 4);
|
||||
tcp_err(pcb, err_tcp);
|
||||
}
|
||||
|
||||
static err_t
|
||||
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
{
|
||||
sys_mbox_t mbox;
|
||||
struct netconn *newconn;
|
||||
struct netconn *conn;
|
||||
|
||||
#if API_MSG_DEBUG
|
||||
#if TCP_DEBUG
|
||||
tcp_debug_print_state(newpcb->state);
|
||||
#endif /* TCP_DEBUG */
|
||||
#endif /* API_MSG_DEBUG */
|
||||
conn = (struct netconn *)arg;
|
||||
mbox = conn->acceptmbox;
|
||||
newconn = memp_malloc(MEMP_NETCONN);
|
||||
if (newconn == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
newconn->type = NETCONN_TCP;
|
||||
newconn->pcb.tcp = newpcb;
|
||||
setup_tcp(newconn);
|
||||
newconn->recvmbox = sys_mbox_new();
|
||||
if (newconn->recvmbox == SYS_MBOX_NULL) {
|
||||
memp_free(MEMP_NETCONN, newconn);
|
||||
return ERR_MEM;
|
||||
}
|
||||
newconn->mbox = sys_mbox_new();
|
||||
if (newconn->mbox == SYS_MBOX_NULL) {
|
||||
sys_mbox_free(newconn->recvmbox);
|
||||
memp_free(MEMP_NETCONN, newconn);
|
||||
return ERR_MEM;
|
||||
}
|
||||
newconn->sem = sys_sem_new(0);
|
||||
if (newconn->sem == SYS_SEM_NULL) {
|
||||
sys_mbox_free(newconn->recvmbox);
|
||||
sys_mbox_free(newconn->mbox);
|
||||
memp_free(MEMP_NETCONN, newconn);
|
||||
return ERR_MEM;
|
||||
}
|
||||
newconn->acceptmbox = SYS_MBOX_NULL;
|
||||
newconn->err = err;
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
{
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
|
||||
/* We have to set the callback here even though
|
||||
* the new socket is unknown. Mark the socket as -1. */
|
||||
newconn->callback = conn->callback;
|
||||
newconn->socket = -1;
|
||||
}
|
||||
|
||||
sys_mbox_post(mbox, newconn);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
static void
|
||||
do_newconn(struct api_msg_msg *msg)
|
||||
{
|
||||
if(msg->conn->pcb.tcp != NULL) {
|
||||
/* This "new" connection already has a PCB allocated. */
|
||||
/* Is this an error condition? Should it be deleted?
|
||||
We currently just are happy and return. */
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
msg->conn->err = ERR_OK;
|
||||
|
||||
/* Allocate a PCB for this connection */
|
||||
switch(msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */
|
||||
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if(msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
break;
|
||||
}
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if(msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
break;
|
||||
}
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDP:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if(msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
break;
|
||||
}
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->pcb.tcp = tcp_new();
|
||||
if(msg->conn->pcb.tcp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
break;
|
||||
}
|
||||
setup_tcp(msg->conn);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_delconn(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
raw_remove(msg->conn->pcb.raw);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
msg->conn->pcb.udp->recv_arg = NULL;
|
||||
udp_remove(msg->conn->pcb.udp);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
if (msg->conn->pcb.tcp->state == LISTEN) {
|
||||
tcp_arg(msg->conn->pcb.tcp, NULL);
|
||||
tcp_accept(msg->conn->pcb.tcp, NULL);
|
||||
tcp_close(msg->conn->pcb.tcp);
|
||||
} else {
|
||||
tcp_arg(msg->conn->pcb.tcp, NULL);
|
||||
tcp_sent(msg->conn->pcb.tcp, NULL);
|
||||
tcp_recv(msg->conn->pcb.tcp, NULL);
|
||||
tcp_poll(msg->conn->pcb.tcp, NULL, 0);
|
||||
tcp_err(msg->conn->pcb.tcp, NULL);
|
||||
if (tcp_close(msg->conn->pcb.tcp) != ERR_OK) {
|
||||
tcp_abort(msg->conn->pcb.tcp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Trigger select() in socket layer */
|
||||
if (msg->conn->callback)
|
||||
{
|
||||
(*msg->conn->callback)(msg->conn, NETCONN_EVT_RCVPLUS, 0);
|
||||
(*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDPLUS, 0);
|
||||
}
|
||||
|
||||
if (msg->conn->mbox != SYS_MBOX_NULL) {
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_bind(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp == NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
|
||||
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDP:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->pcb.tcp = tcp_new();
|
||||
setup_tcp(msg->conn);
|
||||
#endif /* LWIP_TCP */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->err = tcp_bind(msg->conn->pcb.tcp,
|
||||
msg->msg.bc.ipaddr, msg->msg.bc.port);
|
||||
#endif /* LWIP_TCP */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
#if LWIP_TCP
|
||||
|
||||
static err_t
|
||||
do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
|
||||
{
|
||||
struct netconn *conn;
|
||||
|
||||
(void)pcb;
|
||||
|
||||
conn = arg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
conn->err = err;
|
||||
if (conn->type == NETCONN_TCP && err == ERR_OK) {
|
||||
setup_tcp(conn);
|
||||
}
|
||||
sys_mbox_post(conn->mbox, NULL);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
do_connect(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp == NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
|
||||
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if (msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
return;
|
||||
}
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if (msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
return;
|
||||
}
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDP:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if (msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
return;
|
||||
}
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->pcb.tcp = tcp_new();
|
||||
if (msg->conn->pcb.tcp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
/* tcp_arg(msg->conn->pcb.tcp, msg->conn);*/
|
||||
setup_tcp(msg->conn);
|
||||
tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,
|
||||
do_connected);
|
||||
/*tcp_output(msg->conn->pcb.tcp);*/
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_disconnect(struct api_msg_msg *msg)
|
||||
{
|
||||
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
/* Do nothing as connecting is only a helper for upper lwip layers */
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
udp_disconnect(msg->conn->pcb.udp);
|
||||
break;
|
||||
#endif
|
||||
case NETCONN_TCP:
|
||||
break;
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_listen(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);
|
||||
if (msg->conn->pcb.tcp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
} else {
|
||||
if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
|
||||
msg->conn->acceptmbox = sys_mbox_new();
|
||||
if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
tcp_arg(msg->conn->pcb.tcp, msg->conn);
|
||||
tcp_accept(msg->conn->pcb.tcp, accept_function);
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
do_accept(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
case NETCONN_TCP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_send(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
raw_send(msg->conn->pcb.raw, msg->msg.p);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
udp_send(msg->conn->pcb.udp, msg->msg.p);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
case NETCONN_TCP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
do_recv(struct api_msg_msg *msg)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
if (msg->conn->type == NETCONN_TCP) {
|
||||
tcp_recved(msg->conn->pcb.tcp, msg->msg.len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
do_write(struct api_msg_msg *msg)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
err_t err;
|
||||
#endif
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->err = ERR_VAL;
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
msg->conn->err = ERR_VAL;
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr,
|
||||
msg->msg.w.len, msg->msg.w.copy);
|
||||
/* This is the Nagle algorithm: inhibit the sending of new TCP
|
||||
segments when new outgoing data arrives from the user if any
|
||||
previously transmitted data on the connection remains
|
||||
unacknowledged. */
|
||||
if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL || (msg->conn->pcb.tcp->flags & TF_NODELAY)) ) {
|
||||
tcp_output(msg->conn->pcb.tcp);
|
||||
}
|
||||
msg->conn->err = err;
|
||||
if (msg->conn->callback)
|
||||
if (err == ERR_OK)
|
||||
{
|
||||
if (tcp_sndbuf(msg->conn->pcb.tcp) <= TCP_SNDLOWAT)
|
||||
(*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDMINUS, msg->msg.w.len);
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
do_close(struct api_msg_msg *msg)
|
||||
{
|
||||
err_t err;
|
||||
|
||||
err = ERR_OK;
|
||||
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
if (msg->conn->pcb.tcp->state == LISTEN) {
|
||||
err = tcp_close(msg->conn->pcb.tcp);
|
||||
}
|
||||
msg->conn->err = err;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
typedef void (* api_msg_decode)(struct api_msg_msg *msg);
|
||||
static api_msg_decode decode[API_MSG_MAX] = {
|
||||
do_newconn,
|
||||
do_delconn,
|
||||
do_bind,
|
||||
do_connect,
|
||||
do_disconnect,
|
||||
do_listen,
|
||||
do_accept,
|
||||
do_send,
|
||||
do_recv,
|
||||
do_write,
|
||||
do_close
|
||||
};
|
||||
void
|
||||
api_msg_input(struct api_msg *msg)
|
||||
{
|
||||
decode[msg->type](&(msg->msg));
|
||||
}
|
||||
|
||||
void
|
||||
api_msg_post(struct api_msg *msg)
|
||||
{
|
||||
tcpip_apimsg(msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
|
||||
static char *err_strerr[] = {"Ok.",
|
||||
"Out of memory error.",
|
||||
"Buffer error.",
|
||||
"Connection aborted.",
|
||||
"Connection reset.",
|
||||
"Connection closed.",
|
||||
"Not connected.",
|
||||
"Illegal value.",
|
||||
"Illegal argument.",
|
||||
"Routing problem.",
|
||||
"Address in use."
|
||||
};
|
||||
|
||||
|
||||
char *
|
||||
lwip_strerr(err_t err)
|
||||
{
|
||||
return err_strerr[-err];
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* LWIP_DEBUG */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
static void (* tcpip_init_done)(void *arg) = NULL;
|
||||
static void *tcpip_init_done_arg;
|
||||
static sys_mbox_t mbox;
|
||||
|
||||
#if LWIP_TCP
|
||||
static int tcpip_tcp_timer_active = 0;
|
||||
|
||||
static void
|
||||
tcpip_tcp_timer(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
/* call TCP timer handler */
|
||||
tcp_tmr();
|
||||
/* timer still needed? */
|
||||
if (tcp_active_pcbs || tcp_tw_pcbs) {
|
||||
/* restart timer */
|
||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||
} else {
|
||||
/* disable timer */
|
||||
tcpip_tcp_timer_active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if !NO_SYS
|
||||
void
|
||||
tcp_timer_needed(void)
|
||||
{
|
||||
/* timer is off but needed again? */
|
||||
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
|
||||
/* enable and start timer */
|
||||
tcpip_tcp_timer_active = 1;
|
||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||
}
|
||||
}
|
||||
#endif /* !NO_SYS */
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
static void
|
||||
tcpip_thread(void *arg)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
|
||||
(void)arg;
|
||||
|
||||
ip_init();
|
||||
#if LWIP_UDP
|
||||
udp_init();
|
||||
#endif
|
||||
#if LWIP_TCP
|
||||
tcp_init();
|
||||
#endif
|
||||
if (tcpip_init_done != NULL) {
|
||||
tcpip_init_done(tcpip_init_done_arg);
|
||||
}
|
||||
|
||||
while (1) { /* MAIN Loop */
|
||||
sys_mbox_fetch(mbox, (void *)&msg);
|
||||
switch (msg->type) {
|
||||
case TCPIP_MSG_API:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
|
||||
api_msg_input(msg->msg.apimsg);
|
||||
break;
|
||||
case TCPIP_MSG_INPUT:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", (void *)msg));
|
||||
ip_input(msg->msg.inp.p, msg->msg.inp.netif);
|
||||
break;
|
||||
case TCPIP_MSG_CALLBACK:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
|
||||
msg->msg.cb.f(msg->msg.cb.ctx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
memp_free(MEMP_TCPIP_MSG, msg);
|
||||
}
|
||||
}
|
||||
|
||||
err_t
|
||||
tcpip_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
|
||||
msg = memp_malloc(MEMP_TCPIP_MSG);
|
||||
if (msg == NULL) {
|
||||
pbuf_free(p);
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
msg->type = TCPIP_MSG_INPUT;
|
||||
msg->msg.inp.p = p;
|
||||
msg->msg.inp.netif = inp;
|
||||
sys_mbox_post(mbox, msg);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t
|
||||
tcpip_callback(void (*f)(void *ctx), void *ctx)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
|
||||
msg = memp_malloc(MEMP_TCPIP_MSG);
|
||||
if (msg == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
msg->type = TCPIP_MSG_CALLBACK;
|
||||
msg->msg.cb.f = f;
|
||||
msg->msg.cb.ctx = ctx;
|
||||
sys_mbox_post(mbox, msg);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
tcpip_apimsg(struct api_msg *apimsg)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
msg = memp_malloc(MEMP_TCPIP_MSG);
|
||||
if (msg == NULL) {
|
||||
memp_free(MEMP_API_MSG, apimsg);
|
||||
return;
|
||||
}
|
||||
msg->type = TCPIP_MSG_API;
|
||||
msg->msg.apimsg = apimsg;
|
||||
sys_mbox_post(mbox, msg);
|
||||
}
|
||||
|
||||
void
|
||||
tcpip_init(void (* initfunc)(void *), void *arg)
|
||||
{
|
||||
tcpip_init_done = initfunc;
|
||||
tcpip_init_done_arg = arg;
|
||||
mbox = sys_mbox_new();
|
||||
sys_thread_new(tcpip_thread, NULL, TCPIP_THREAD_PRIO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* inet.c
|
||||
*
|
||||
* Functions common to all TCP/IP modules, such as the Internet checksum and the
|
||||
* byte order functions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/inet.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
|
||||
/* This is a reference implementation of the checksum algorithm
|
||||
|
||||
- it may not work on all architectures, and all processors, particularly
|
||||
if they have issues with alignment and 16 bit access.
|
||||
|
||||
- in this case you will need to port it to your architecture and
|
||||
#define LWIP_CHKSUM <your_checksum_routine>
|
||||
in your sys_arch.h
|
||||
*/
|
||||
#ifndef LWIP_CHKSUM
|
||||
#define LWIP_CHKSUM lwip_standard_chksum
|
||||
static u16_t
|
||||
lwip_standard_chksum(void *dataptr, int len)
|
||||
{
|
||||
u32_t acc;
|
||||
|
||||
LWIP_DEBUGF(INET_DEBUG, ("lwip_chksum(%p, %d)\n", (void *)dataptr, len));
|
||||
for(acc = 0; len > 1; len -= 2) {
|
||||
/* acc = acc + *((u16_t *)dataptr)++;*/
|
||||
acc += *(u16_t *)dataptr;
|
||||
dataptr = (void *)((u16_t *)dataptr + 1);
|
||||
}
|
||||
|
||||
/* add up any odd byte */
|
||||
if (len == 1) {
|
||||
acc += htons((u16_t)((*(u8_t *)dataptr) & 0xff) << 8);
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: odd byte %d\n", (unsigned int)(*(u8_t *)dataptr)));
|
||||
} else {
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet: chksum: no odd byte\n"));
|
||||
}
|
||||
acc = (acc >> 16) + (acc & 0xffffUL);
|
||||
|
||||
if ((acc & 0xffff0000) != 0) {
|
||||
acc = (acc >> 16) + (acc & 0xffffUL);
|
||||
}
|
||||
|
||||
return (u16_t)acc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* inet_chksum_pseudo:
|
||||
*
|
||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||
*/
|
||||
|
||||
u16_t
|
||||
inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u16_t proto_len)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
/* iterate through all pbuf in chain */
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||
(void *)q, (void *)q->next));
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%lx \n", acc));*/
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
}
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%lx \n", acc));*/
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
}
|
||||
acc += (src->addr & 0xffffUL);
|
||||
acc += ((src->addr >> 16) & 0xffffUL);
|
||||
acc += (dest->addr & 0xffffUL);
|
||||
acc += ((dest->addr >> 16) & 0xffffUL);
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/* inet_chksum:
|
||||
*
|
||||
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
|
||||
* and ICMP.
|
||||
*/
|
||||
|
||||
u16_t
|
||||
inet_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc;
|
||||
|
||||
acc = LWIP_CHKSUM(dataptr, len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
return (u16_t)~(acc & 0xffff);
|
||||
}
|
||||
|
||||
u16_t
|
||||
inet_chksum_pbuf(struct pbuf *p)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = (acc & 0x00ffUL << 8) | (acc & 0xff00UL >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
}
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/* Here for now until needed in other places in lwIP */
|
||||
#ifndef isascii
|
||||
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
|
||||
#define isascii(c) in_range(c, 0x20, 0x7f)
|
||||
#define isdigit(c) in_range(c, '0', '9')
|
||||
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
||||
#define islower(c) in_range(c, 'a', 'z')
|
||||
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Ascii internet address interpretation routine.
|
||||
* The value returned is in network order.
|
||||
*/
|
||||
|
||||
/* */
|
||||
/* inet_addr */
|
||||
u32_t inet_addr(const char *cp)
|
||||
{
|
||||
struct in_addr val;
|
||||
|
||||
if (inet_aton(cp, &val)) {
|
||||
return (val.s_addr);
|
||||
}
|
||||
return (INADDR_NONE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether "cp" is a valid ascii representation
|
||||
* of an Internet address and convert to a binary address.
|
||||
* Returns 1 if the address is valid, 0 if not.
|
||||
* This replaces inet_addr, the return value from which
|
||||
* cannot distinguish between failure and a local broadcast address.
|
||||
*/
|
||||
/* */
|
||||
/* inet_aton */
|
||||
int inet_aton(const char *cp, struct in_addr *addr)
|
||||
{
|
||||
u32_t val;
|
||||
int base, n;
|
||||
char c;
|
||||
u32_t parts[4];
|
||||
u32_t* pp = parts;
|
||||
|
||||
c = *cp;
|
||||
for (;;) {
|
||||
/*
|
||||
* Collect number up to ``.''.
|
||||
* Values are specified as for C:
|
||||
* 0x=hex, 0=octal, isdigit=decimal.
|
||||
*/
|
||||
if (!isdigit(c))
|
||||
return (0);
|
||||
val = 0; base = 10;
|
||||
if (c == '0') {
|
||||
c = *++cp;
|
||||
if (c == 'x' || c == 'X')
|
||||
base = 16, c = *++cp;
|
||||
else
|
||||
base = 8;
|
||||
}
|
||||
for (;;) {
|
||||
if (isdigit(c)) {
|
||||
val = (val * base) + (int)(c - '0');
|
||||
c = *++cp;
|
||||
} else if (base == 16 && isxdigit(c)) {
|
||||
val = (val << 4) |
|
||||
(int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (c == '.') {
|
||||
/*
|
||||
* Internet format:
|
||||
* a.b.c.d
|
||||
* a.b.c (with c treated as 16 bits)
|
||||
* a.b (with b treated as 24 bits)
|
||||
*/
|
||||
if (pp >= parts + 3)
|
||||
return (0);
|
||||
*pp++ = val;
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Check for trailing characters.
|
||||
*/
|
||||
if (c != '\0' && (!isascii(c) || !isspace(c)))
|
||||
return (0);
|
||||
/*
|
||||
* Concoct the address according to
|
||||
* the number of parts specified.
|
||||
*/
|
||||
n = pp - parts + 1;
|
||||
switch (n) {
|
||||
|
||||
case 0:
|
||||
return (0); /* initial nondigit */
|
||||
|
||||
case 1: /* a -- 32 bits */
|
||||
break;
|
||||
|
||||
case 2: /* a.b -- 8.24 bits */
|
||||
if (val > 0xffffff)
|
||||
return (0);
|
||||
val |= parts[0] << 24;
|
||||
break;
|
||||
|
||||
case 3: /* a.b.c -- 8.8.16 bits */
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16);
|
||||
break;
|
||||
|
||||
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
||||
if (val > 0xff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
||||
break;
|
||||
}
|
||||
if (addr)
|
||||
addr->s_addr = htonl(val);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Convert numeric IP address into decimal dotted ASCII representation.
|
||||
* returns ptr to static buffer; not reentrant!
|
||||
*/
|
||||
char *inet_ntoa(struct in_addr addr)
|
||||
{
|
||||
static char str[16];
|
||||
u32_t s_addr = addr.s_addr;
|
||||
char inv[3];
|
||||
char *rp;
|
||||
u8_t *ap;
|
||||
u8_t rem;
|
||||
u8_t n;
|
||||
u8_t i;
|
||||
|
||||
rp = str;
|
||||
ap = (u8_t *)&s_addr;
|
||||
for(n = 0; n < 4; n++) {
|
||||
i = 0;
|
||||
do {
|
||||
rem = *ap % (u8_t)10;
|
||||
*ap /= (u8_t)10;
|
||||
inv[i++] = '0' + rem;
|
||||
} while(*ap);
|
||||
while(i--)
|
||||
*rp++ = inv[i];
|
||||
*rp++ = '.';
|
||||
ap++;
|
||||
}
|
||||
*--rp = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
#ifndef BYTE_ORDER
|
||||
#error BYTE_ORDER is not defined
|
||||
#endif
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
|
||||
u16_t
|
||||
htons(u16_t n)
|
||||
{
|
||||
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
|
||||
}
|
||||
|
||||
u16_t
|
||||
ntohs(u16_t n)
|
||||
{
|
||||
return htons(n);
|
||||
}
|
||||
|
||||
u32_t
|
||||
htonl(u32_t n)
|
||||
{
|
||||
return ((n & 0xff) << 24) |
|
||||
((n & 0xff00) << 8) |
|
||||
((n & 0xff0000) >> 8) |
|
||||
((n & 0xff000000) >> 24);
|
||||
}
|
||||
|
||||
u32_t
|
||||
ntohl(u32_t n)
|
||||
{
|
||||
return htonl(n);
|
||||
}
|
||||
|
||||
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* inet6.c
|
||||
*
|
||||
* Functions common to all TCP/IP modules, such as the Internet checksum and the
|
||||
* byte order functions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/inet.h"
|
||||
|
||||
|
||||
|
||||
/* chksum:
|
||||
*
|
||||
* Sums up all 16 bit words in a memory portion. Also includes any odd byte.
|
||||
* This function is used by the other checksum functions.
|
||||
*
|
||||
* For now, this is not optimized. Must be optimized for the particular processor
|
||||
* arcitecture on which it is to run. Preferebly coded in assembler.
|
||||
*/
|
||||
|
||||
static u32_t
|
||||
chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u16_t *sdataptr = dataptr;
|
||||
u32_t acc;
|
||||
|
||||
|
||||
for(acc = 0; len > 1; len -= 2) {
|
||||
acc += *sdataptr++;
|
||||
}
|
||||
|
||||
/* add up any odd byte */
|
||||
if (len == 1) {
|
||||
acc += htons((u16_t)(*(u8_t *)dataptr) << 8);
|
||||
}
|
||||
|
||||
return acc;
|
||||
|
||||
}
|
||||
|
||||
/* inet_chksum_pseudo:
|
||||
*
|
||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||
*/
|
||||
|
||||
u16_t
|
||||
inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u32_t proto_len)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped, i;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += chksum(q->payload, q->len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
||||
}
|
||||
|
||||
for(i = 0; i < 8; i++) {
|
||||
acc += ((u16_t *)src->addr)[i] & 0xffff;
|
||||
acc += ((u16_t *)dest->addr)[i] & 0xffff;
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
}
|
||||
acc += (u16_t)htons((u16_t)proto);
|
||||
acc += ((u16_t *)&proto_len)[0] & 0xffff;
|
||||
acc += ((u16_t *)&proto_len)[1] & 0xffff;
|
||||
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
return ~(acc & 0xffff);
|
||||
}
|
||||
|
||||
/* inet_chksum:
|
||||
*
|
||||
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
|
||||
* and ICMP.
|
||||
*/
|
||||
|
||||
u16_t
|
||||
inet_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc, sum;
|
||||
|
||||
acc = chksum(dataptr, len);
|
||||
sum = (acc & 0xffff) + (acc >> 16);
|
||||
sum += (sum >> 16);
|
||||
return ~(sum & 0xffff);
|
||||
}
|
||||
|
||||
u16_t
|
||||
inet_chksum_pbuf(struct pbuf *p)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += chksum(q->payload, q->len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = (acc & 0xff << 8) | (acc & 0xff00 >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
||||
}
|
||||
return ~(acc & 0xffff);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/* Some ICMP messages should be passed to the transport protocols. This
|
||||
is not implemented. */
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void
|
||||
icmp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
unsigned char type;
|
||||
unsigned char code;
|
||||
struct icmp_echo_hdr *iecho;
|
||||
struct ip_hdr *iphdr;
|
||||
struct ip_addr tmpaddr;
|
||||
u16_t hlen;
|
||||
|
||||
ICMP_STATS_INC(icmp.recv);
|
||||
snmp_inc_icmpinmsgs();
|
||||
|
||||
|
||||
iphdr = p->payload;
|
||||
hlen = IPH_HL(iphdr) * 4;
|
||||
if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len));
|
||||
pbuf_free(p);
|
||||
ICMP_STATS_INC(icmp.lenerr);
|
||||
snmp_inc_icmpinerrors();
|
||||
return;
|
||||
}
|
||||
|
||||
type = *((u8_t *)p->payload);
|
||||
code = *(((u8_t *)p->payload)+1);
|
||||
switch (type) {
|
||||
case ICMP_ECHO:
|
||||
/* broadcast or multicast destination address? */
|
||||
if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
|
||||
ICMP_STATS_INC(icmp.err);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
|
||||
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
|
||||
pbuf_free(p);
|
||||
ICMP_STATS_INC(icmp.lenerr);
|
||||
snmp_inc_icmpinerrors();
|
||||
|
||||
return;
|
||||
}
|
||||
iecho = p->payload;
|
||||
if (inet_chksum_pbuf(p) != 0) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
|
||||
pbuf_free(p);
|
||||
ICMP_STATS_INC(icmp.chkerr);
|
||||
snmp_inc_icmpinerrors();
|
||||
return;
|
||||
}
|
||||
tmpaddr.addr = iphdr->src.addr;
|
||||
iphdr->src.addr = iphdr->dest.addr;
|
||||
iphdr->dest.addr = tmpaddr.addr;
|
||||
ICMPH_TYPE_SET(iecho, ICMP_ER);
|
||||
/* adjust the checksum */
|
||||
if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {
|
||||
iecho->chksum += htons(ICMP_ECHO << 8) + 1;
|
||||
} else {
|
||||
iecho->chksum += htons(ICMP_ECHO << 8);
|
||||
}
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
/* increase number of messages attempted to send */
|
||||
snmp_inc_icmpoutmsgs();
|
||||
/* increase number of echo replies attempted to send */
|
||||
snmp_inc_icmpoutechoreps();
|
||||
|
||||
pbuf_header(p, hlen);
|
||||
ip_output_if(p, &(iphdr->src), IP_HDRINCL,
|
||||
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
|
||||
break;
|
||||
default:
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code));
|
||||
ICMP_STATS_INC(icmp.proterr);
|
||||
ICMP_STATS_INC(icmp.drop);
|
||||
}
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
void
|
||||
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_dur_hdr *idur;
|
||||
|
||||
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
|
||||
/* ICMP header + IP header + 8 bytes of data */
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
idur = q->payload;
|
||||
ICMPH_TYPE_SET(idur, ICMP_DUR);
|
||||
ICMPH_CODE_SET(idur, t);
|
||||
|
||||
memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);
|
||||
|
||||
/* calculate checksum */
|
||||
idur->chksum = 0;
|
||||
idur->chksum = inet_chksum(idur, q->len);
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
/* increase number of messages attempted to send */
|
||||
snmp_inc_icmpoutmsgs();
|
||||
/* increase number of destination unreachable messages attempted to send */
|
||||
snmp_inc_icmpoutdestunreachs();
|
||||
|
||||
ip_output(q, NULL, &(iphdr->src),
|
||||
ICMP_TTL, 0, IP_PROTO_ICMP);
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
#if IP_FORWARD
|
||||
void
|
||||
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_te_hdr *tehdr;
|
||||
|
||||
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
|
||||
|
||||
iphdr = p->payload;
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
|
||||
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
|
||||
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
|
||||
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
|
||||
|
||||
tehdr = q->payload;
|
||||
ICMPH_TYPE_SET(tehdr, ICMP_TE);
|
||||
ICMPH_CODE_SET(tehdr, t);
|
||||
|
||||
/* copy fields from original packet */
|
||||
memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
|
||||
|
||||
/* calculate checksum */
|
||||
tehdr->chksum = 0;
|
||||
tehdr->chksum = inet_chksum(tehdr, q->len);
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
/* increase number of messages attempted to send */
|
||||
snmp_inc_icmpoutmsgs();
|
||||
/* increase number of destination unreachable messages attempted to send */
|
||||
snmp_inc_icmpouttimeexcds();
|
||||
ip_output(q, NULL, &(iphdr->src),
|
||||
ICMP_TTL, 0, IP_PROTO_ICMP);
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
#endif /* IP_FORWARD */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,508 @@
|
|||
/* @file
|
||||
*
|
||||
* This is the IP layer implementation for incoming and outgoing IP traffic.
|
||||
*
|
||||
* @see ip_frag.c
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "arch/perf.h"
|
||||
|
||||
#include "lwip/snmp.h"
|
||||
#if LWIP_DHCP
|
||||
# include "lwip/dhcp.h"
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the IP layer.
|
||||
*/
|
||||
|
||||
void
|
||||
ip_init(void)
|
||||
{
|
||||
/* no initializations as of yet */
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the appropriate network interface for a given IP address. It
|
||||
* searches the list of network interfaces linearly. A match is found
|
||||
* if the masked IP address of the network interface equals the masked
|
||||
* IP address given to the function.
|
||||
*/
|
||||
|
||||
struct netif *
|
||||
ip_route(struct ip_addr *dest)
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
/* iterate through netifs */
|
||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
/* network mask matches? */
|
||||
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
||||
/* return netif on which to forward IP packet */
|
||||
return netif;
|
||||
}
|
||||
}
|
||||
/* no matching netif found, use default netif */
|
||||
return netif_default;
|
||||
}
|
||||
#if IP_FORWARD
|
||||
|
||||
/**
|
||||
* Forwards an IP packet. It finds an appropriate route for the
|
||||
* packet, decrements the TTL value of the packet, adjusts the
|
||||
* checksum and outputs the packet on the appropriate interface.
|
||||
*/
|
||||
|
||||
static struct netif *
|
||||
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
PERF_START;
|
||||
/* Find network interface where to forward this IP packet to. */
|
||||
netif = ip_route((struct ip_addr *)&(iphdr->dest));
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%lx found\n",
|
||||
iphdr->dest.addr));
|
||||
snmp_inc_ipnoroutes();
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
/* Do not forward packets onto the same network interface on which
|
||||
* they arrived. */
|
||||
if (netif == inp) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
|
||||
snmp_inc_ipnoroutes();
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
|
||||
/* decrement TTL */
|
||||
IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
|
||||
/* send ICMP if TTL == 0 */
|
||||
if (IPH_TTL(iphdr) == 0) {
|
||||
/* Don't send ICMP messages in response to ICMP messages */
|
||||
if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
|
||||
icmp_time_exceeded(p, ICMP_TE_TTL);
|
||||
snmp_inc_icmpouttimeexcds();
|
||||
}
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
|
||||
/* Incrementally update the IP checksum. */
|
||||
if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
|
||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
|
||||
} else {
|
||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
|
||||
iphdr->dest.addr));
|
||||
|
||||
IP_STATS_INC(ip.fw);
|
||||
IP_STATS_INC(ip.xmit);
|
||||
snmp_inc_ipforwdatagrams();
|
||||
|
||||
PERF_STOP("ip_forward");
|
||||
/* transmit pbuf on chosen interface */
|
||||
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
|
||||
return netif;
|
||||
}
|
||||
#endif /* IP_FORWARD */
|
||||
|
||||
/**
|
||||
* This function is called by the network interface device driver when
|
||||
* an IP packet is received. The function does the basic checks of the
|
||||
* IP header such as packet size being at least larger than the header
|
||||
* size etc. If the packet was not destined for us, the packet is
|
||||
* forwarded (using ip_forward). The IP checksum is always checked.
|
||||
*
|
||||
* Finally, the packet is sent to the upper layer protocol input function.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
err_t
|
||||
ip_input(struct pbuf *p, struct netif *inp) {
|
||||
struct ip_hdr *iphdr;
|
||||
struct netif *netif;
|
||||
u16_t iphdrlen;
|
||||
|
||||
IP_STATS_INC(ip.recv);
|
||||
snmp_inc_ipinreceives();
|
||||
|
||||
/* identify the IP header */
|
||||
iphdr = p->payload;
|
||||
if (IPH_V(iphdr) != 4) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %u\n", IPH_V(iphdr)));
|
||||
ip_debug_print(p);
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.err);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipunknownprotos();
|
||||
return ERR_OK;
|
||||
}
|
||||
/* obtain IP header length in number of 32-bit words */
|
||||
iphdrlen = IPH_HL(iphdr);
|
||||
/* calculate IP header length in bytes */
|
||||
iphdrlen *= 4;
|
||||
|
||||
/* header length exceeds first pbuf length? */
|
||||
if (iphdrlen > p->len) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %u) does not fit in first pbuf (len %u), IP packet droppped.\n",
|
||||
iphdrlen, p->len));
|
||||
/* free (drop) packet pbufs */
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.lenerr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipindiscards();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* verify checksum */
|
||||
#if CHECKSUM_CHECK_IP
|
||||
if (inet_chksum(iphdr, iphdrlen) != 0) {
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
|
||||
ip_debug_print(p);
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.chkerr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipindiscards();
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Trim pbuf. This should have been done at the netif layer,
|
||||
* but we'll do it anyway just to be sure that its done. */
|
||||
pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
|
||||
|
||||
/* match packet against an interface, i.e. is this packet for us? */
|
||||
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%lx netif->ip_addr 0x%lx (0x%lx, 0x%lx, 0x%lx)\n",
|
||||
iphdr->dest.addr, netif->ip_addr.addr,
|
||||
iphdr->dest.addr & netif->netmask.addr,
|
||||
netif->ip_addr.addr & netif->netmask.addr,
|
||||
iphdr->dest.addr & ~(netif->netmask.addr)));
|
||||
|
||||
/* interface is up and configured? */
|
||||
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
|
||||
{
|
||||
/* unicast to this interface address? */
|
||||
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
|
||||
/* or broadcast on this interface network address? */
|
||||
ip_addr_isbroadcast(&(iphdr->dest), netif)) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
||||
netif->name[0], netif->name[1]));
|
||||
/* break out of for loop */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LWIP_DHCP
|
||||
/* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
|
||||
* using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
|
||||
* According to RFC 1542 section 3.1.1, referred by RFC 2131).
|
||||
*/
|
||||
if (netif == NULL) {
|
||||
/* remote port is DHCP server? */
|
||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
|
||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %u\n",
|
||||
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
|
||||
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
|
||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
|
||||
netif = inp;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_DHCP */
|
||||
/* packet not for us? */
|
||||
if (netif == NULL) {
|
||||
/* packet not for us, route or discard */
|
||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
|
||||
#if IP_FORWARD
|
||||
/* non-broadcast packet? */
|
||||
if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
|
||||
/* try to forward IP packet on (other) interfaces */
|
||||
ip_forward(p, iphdr, inp);
|
||||
}
|
||||
else
|
||||
#endif /* IP_FORWARD */
|
||||
{
|
||||
snmp_inc_ipindiscards();
|
||||
}
|
||||
pbuf_free(p);
|
||||
return ERR_OK;
|
||||
}
|
||||
/* packet consists of multiple fragments? */
|
||||
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
|
||||
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
|
||||
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04x tot_len=%u len=%u MF=%u offset=%u), calling ip_reass()\n",
|
||||
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
|
||||
/* reassemble the packet*/
|
||||
p = ip_reass(p);
|
||||
/* packet not fully reassembled yet? */
|
||||
if (p == NULL) {
|
||||
return ERR_OK;
|
||||
}
|
||||
iphdr = p->payload;
|
||||
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
|
||||
ntohs(IPH_OFFSET(iphdr))));
|
||||
IP_STATS_INC(ip.opterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipunknownprotos();
|
||||
return ERR_OK;
|
||||
#endif /* IP_REASSEMBLY */
|
||||
}
|
||||
|
||||
#if IP_OPTIONS == 0 /* no support for IP options in the IP header? */
|
||||
if (iphdrlen > IP_HLEN) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.opterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipunknownprotos();
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* IP_OPTIONS == 0 */
|
||||
|
||||
/* send to upper layers */
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
|
||||
ip_debug_print(p);
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
|
||||
|
||||
#if LWIP_RAW
|
||||
/* raw input did not eat the packet? */
|
||||
if (raw_input(p, inp) == 0) {
|
||||
#endif /* LWIP_RAW */
|
||||
|
||||
switch (IPH_PROTO(iphdr)) {
|
||||
#if LWIP_UDP
|
||||
case IP_PROTO_UDP:
|
||||
case IP_PROTO_UDPLITE:
|
||||
snmp_inc_ipindelivers();
|
||||
udp_input(p, inp);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case IP_PROTO_TCP:
|
||||
snmp_inc_ipindelivers();
|
||||
tcp_input(p, inp);
|
||||
break;
|
||||
#endif /* LWIP_TCP */
|
||||
case IP_PROTO_ICMP:
|
||||
snmp_inc_ipindelivers();
|
||||
icmp_input(p, inp);
|
||||
break;
|
||||
default:
|
||||
/* send ICMP destination protocol unreachable unless is was a broadcast */
|
||||
if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
|
||||
!ip_addr_ismulticast(&(iphdr->dest))) {
|
||||
p->payload = iphdr;
|
||||
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
||||
}
|
||||
pbuf_free(p);
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
|
||||
|
||||
IP_STATS_INC(ip.proterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipunknownprotos();
|
||||
}
|
||||
#if LWIP_RAW
|
||||
} /* LWIP_RAW */
|
||||
#endif
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an IP packet on a network interface. This function constructs
|
||||
* the IP header and calculates the IP header checksum. If the source
|
||||
* IP address is NULL, the IP address of the outgoing network
|
||||
* interface is filled in as source address.
|
||||
*/
|
||||
|
||||
err_t
|
||||
ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos,
|
||||
u8_t proto, struct netif *netif)
|
||||
{
|
||||
struct ip_hdr *iphdr;
|
||||
u16_t ip_id = 0;
|
||||
|
||||
snmp_inc_ipoutrequests();
|
||||
|
||||
if (dest != IP_HDRINCL) {
|
||||
if (pbuf_header(p, IP_HLEN)) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
|
||||
|
||||
IP_STATS_INC(ip.err);
|
||||
snmp_inc_ipoutdiscards();
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
IPH_TTL_SET(iphdr, ttl);
|
||||
IPH_PROTO_SET(iphdr, proto);
|
||||
|
||||
ip_addr_set(&(iphdr->dest), dest);
|
||||
|
||||
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
|
||||
IPH_LEN_SET(iphdr, htons(p->tot_len));
|
||||
IPH_OFFSET_SET(iphdr, htons(IP_DF));
|
||||
IPH_ID_SET(iphdr, htons(ip_id));
|
||||
++ip_id;
|
||||
|
||||
if (ip_addr_isany(src)) {
|
||||
ip_addr_set(&(iphdr->src), &(netif->ip_addr));
|
||||
} else {
|
||||
ip_addr_set(&(iphdr->src), src);
|
||||
}
|
||||
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
#if CHECKSUM_GEN_IP
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
#endif
|
||||
} else {
|
||||
iphdr = p->payload;
|
||||
dest = &(iphdr->dest);
|
||||
}
|
||||
|
||||
#if IP_FRAG
|
||||
/* don't fragment if interface has mtu set to 0 [loopif] */
|
||||
if (netif->mtu && (p->tot_len > netif->mtu))
|
||||
return ip_frag(p,netif,dest);
|
||||
#endif
|
||||
|
||||
IP_STATS_INC(ip.xmit);
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
|
||||
ip_debug_print(p);
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
||||
|
||||
return netif->output(netif, p, dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple interface to ip_output_if. It finds the outgoing network
|
||||
* interface and calls upon ip_output_if to do the actual work.
|
||||
*/
|
||||
|
||||
err_t
|
||||
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto)
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
if ((netif = ip_route(dest)) == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr));
|
||||
|
||||
IP_STATS_INC(ip.rterr);
|
||||
snmp_inc_ipoutdiscards();
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
return ip_output_if(p, src, dest, ttl, tos, proto, netif);
|
||||
}
|
||||
|
||||
#if IP_DEBUG
|
||||
void
|
||||
ip_debug_print(struct pbuf *p)
|
||||
{
|
||||
struct ip_hdr *iphdr = p->payload;
|
||||
u8_t *payload;
|
||||
|
||||
payload = (u8_t *)iphdr + IP_HLEN;
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("|%2d |%2d | 0x%02x | %5u | (v, hl, tos, len)\n",
|
||||
IPH_V(iphdr),
|
||||
IPH_HL(iphdr),
|
||||
IPH_TOS(iphdr),
|
||||
ntohs(IPH_LEN(iphdr))));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %5u |%u%u%u| %4u | (id, flags, offset)\n",
|
||||
ntohs(IPH_ID(iphdr)),
|
||||
ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
|
||||
ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
|
||||
ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
|
||||
ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | 0x%04x | (ttl, proto, chksum)\n",
|
||||
IPH_TTL(iphdr),
|
||||
IPH_PROTO(iphdr),
|
||||
ntohs(IPH_CHKSUM(iphdr))));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | %3u | %3u | (src)\n",
|
||||
ip4_addr1(&iphdr->src),
|
||||
ip4_addr2(&iphdr->src),
|
||||
ip4_addr3(&iphdr->src),
|
||||
ip4_addr4(&iphdr->src)));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3u | %3u | %3u | %3u | (dest)\n",
|
||||
ip4_addr1(&iphdr->dest),
|
||||
ip4_addr2(&iphdr->dest),
|
||||
ip4_addr3(&iphdr->dest),
|
||||
ip4_addr4(&iphdr->dest)));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
}
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
|
||||
const struct ip_addr ip_addr_any = { 0x00000000UL };
|
||||
const struct ip_addr ip_addr_broadcast = { 0xffffffffUL };
|
||||
|
||||
/* Determine if an address is a broadcast address on a network interface
|
||||
*
|
||||
* @param addr address to be checked
|
||||
* @param netif the network interface against which the address is checked
|
||||
* @return returns non-zero if the address is a broadcast address
|
||||
*
|
||||
*/
|
||||
|
||||
u8_t ip_addr_isbroadcast(struct ip_addr *addr, struct netif *netif)
|
||||
{
|
||||
/* all ones (broadcast) or all zeroes (old skool broadcast) */
|
||||
if ((addr->addr == ip_addr_broadcast.addr) ||
|
||||
(addr->addr == ip_addr_any.addr))
|
||||
return 1;
|
||||
/* no broadcast support on this network interface? */
|
||||
else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0)
|
||||
/* the given address cannot be a broadcast address
|
||||
* nor can we check against any broadcast addresses */
|
||||
return 0;
|
||||
/* address matches network interface address exactly? => no broadcast */
|
||||
else if (addr->addr == netif->ip_addr.addr)
|
||||
return 0;
|
||||
/* on the same (sub) network... */
|
||||
else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask))
|
||||
/* ...and host identifier bits are all ones? =>... */
|
||||
&& ((addr->addr & ~netif->netmask.addr) ==
|
||||
(ip_addr_broadcast.addr & ~netif->netmask.addr)))
|
||||
/* => network broadcast address */
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,345 @@
|
|||
/* @file
|
||||
*
|
||||
* This is the IP packet segmentation and reassembly implementation.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Jani Monoses <jani@iv.ro>
|
||||
* original reassembly code by Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Copy len bytes from offset in pbuf to buffer
|
||||
*
|
||||
* helper used by both ip_reass and ip_frag
|
||||
*/
|
||||
static struct pbuf *
|
||||
copy_from_pbuf(struct pbuf *p, u16_t * offset,
|
||||
u8_t * buffer, u16_t len)
|
||||
{
|
||||
u16_t l;
|
||||
|
||||
p->payload = (u8_t *)p->payload + *offset;
|
||||
p->len -= *offset;
|
||||
while (len) {
|
||||
l = len < p->len ? len : p->len;
|
||||
memcpy(buffer, p->payload, l);
|
||||
buffer += l;
|
||||
len -= l;
|
||||
if (len)
|
||||
p = p->next;
|
||||
else
|
||||
*offset = l;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
#define IP_REASS_BUFSIZE 5760
|
||||
#define IP_REASS_MAXAGE 30
|
||||
#define IP_REASS_TMO 1000
|
||||
|
||||
static u8_t ip_reassbuf[IP_HLEN + IP_REASS_BUFSIZE];
|
||||
static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8)];
|
||||
static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f,
|
||||
0x0f, 0x07, 0x03, 0x01
|
||||
};
|
||||
static u16_t ip_reasslen;
|
||||
static u8_t ip_reassflags;
|
||||
#define IP_REASS_FLAG_LASTFRAG 0x01
|
||||
|
||||
static u8_t ip_reasstmr;
|
||||
|
||||
/* Reassembly timer */
|
||||
static void
|
||||
ip_reass_timer(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
if (ip_reasstmr > 1) {
|
||||
ip_reasstmr--;
|
||||
sys_timeout(IP_REASS_TMO, ip_reass_timer, NULL);
|
||||
} else if (ip_reasstmr == 1)
|
||||
ip_reasstmr = 0;
|
||||
}
|
||||
|
||||
struct pbuf *
|
||||
ip_reass(struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *fraghdr, *iphdr;
|
||||
u16_t offset, len;
|
||||
u16_t i;
|
||||
|
||||
IPFRAG_STATS_INC(ip_frag.recv);
|
||||
|
||||
iphdr = (struct ip_hdr *) ip_reassbuf;
|
||||
fraghdr = (struct ip_hdr *) p->payload;
|
||||
/* If ip_reasstmr is zero, no packet is present in the buffer, so we
|
||||
write the IP header of the fragment into the reassembly
|
||||
buffer. The timer is updated with the maximum age. */
|
||||
if (ip_reasstmr == 0) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: new packet\n"));
|
||||
memcpy(iphdr, fraghdr, IP_HLEN);
|
||||
ip_reasstmr = IP_REASS_MAXAGE;
|
||||
sys_timeout(IP_REASS_TMO, ip_reass_timer, NULL);
|
||||
ip_reassflags = 0;
|
||||
/* Clear the bitmap. */
|
||||
memset(ip_reassbitmap, 0, sizeof(ip_reassbitmap));
|
||||
}
|
||||
|
||||
/* Check if the incoming fragment matches the one currently present
|
||||
in the reasembly buffer. If so, we proceed with copying the
|
||||
fragment into the buffer. */
|
||||
if (ip_addr_cmp(&iphdr->src, &fraghdr->src) &&
|
||||
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
|
||||
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n"));
|
||||
IPFRAG_STATS_INC(ip_frag.cachehit);
|
||||
/* Find out the offset in the reassembly buffer where we should
|
||||
copy the fragment. */
|
||||
len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
|
||||
offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
|
||||
|
||||
/* If the offset or the offset + fragment length overflows the
|
||||
reassembly buffer, we discard the entire packet. */
|
||||
if (offset > IP_REASS_BUFSIZE || offset + len > IP_REASS_BUFSIZE) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: fragment outside of buffer (%d:%d/%d).\n", offset,
|
||||
offset + len, IP_REASS_BUFSIZE));
|
||||
sys_untimeout(ip_reass_timer, NULL);
|
||||
ip_reasstmr = 0;
|
||||
goto nullreturn;
|
||||
}
|
||||
|
||||
/* Copy the fragment into the reassembly buffer, at the right
|
||||
offset. */
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: copying with offset %d into %d:%d\n", offset,
|
||||
IP_HLEN + offset, IP_HLEN + offset + len));
|
||||
i = IPH_HL(fraghdr) * 4;
|
||||
copy_from_pbuf(p, &i, &ip_reassbuf[IP_HLEN + offset], len);
|
||||
|
||||
/* Update the bitmap. */
|
||||
if (offset / (8 * 8) == (offset + len) / (8 * 8)) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: updating single byte in bitmap.\n"));
|
||||
/* If the two endpoints are in the same byte, we only update
|
||||
that byte. */
|
||||
ip_reassbitmap[offset / (8 * 8)] |=
|
||||
bitmap_bits[(offset / 8) & 7] &
|
||||
~bitmap_bits[((offset + len) / 8) & 7];
|
||||
} else {
|
||||
/* If the two endpoints are in different bytes, we update the
|
||||
bytes in the endpoints and fill the stuff inbetween with
|
||||
0xff. */
|
||||
ip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7];
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: updating many bytes in bitmap (%d:%d).\n",
|
||||
1 + offset / (8 * 8), (offset + len) / (8 * 8)));
|
||||
for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
|
||||
ip_reassbitmap[i] = 0xff;
|
||||
}
|
||||
ip_reassbitmap[(offset + len) / (8 * 8)] |=
|
||||
~bitmap_bits[((offset + len) / 8) & 7];
|
||||
}
|
||||
|
||||
/* If this fragment has the More Fragments flag set to zero, we
|
||||
know that this is the last fragment, so we can calculate the
|
||||
size of the entire packet. We also set the
|
||||
IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
|
||||
the final fragment. */
|
||||
|
||||
if ((ntohs(IPH_OFFSET(fraghdr)) & IP_MF) == 0) {
|
||||
ip_reassflags |= IP_REASS_FLAG_LASTFRAG;
|
||||
ip_reasslen = offset + len;
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: last fragment seen, total len %d\n",
|
||||
ip_reasslen));
|
||||
}
|
||||
|
||||
/* Finally, we check if we have a full packet in the buffer. We do
|
||||
this by checking if we have the last fragment and if all bits
|
||||
in the bitmap are set. */
|
||||
if (ip_reassflags & IP_REASS_FLAG_LASTFRAG) {
|
||||
/* Check all bytes up to and including all but the last byte in
|
||||
the bitmap. */
|
||||
for (i = 0; i < ip_reasslen / (8 * 8) - 1; ++i) {
|
||||
if (ip_reassbitmap[i] != 0xff) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: last fragment seen, bitmap %d/%d failed (%x)\n",
|
||||
i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
|
||||
goto nullreturn;
|
||||
}
|
||||
}
|
||||
/* Check the last byte in the bitmap. It should contain just the
|
||||
right amount of bits. */
|
||||
if (ip_reassbitmap[ip_reasslen / (8 * 8)] !=
|
||||
(u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: last fragment seen, bitmap %d didn't contain %x (%x)\n",
|
||||
ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7],
|
||||
ip_reassbitmap[ip_reasslen / (8 * 8)]));
|
||||
goto nullreturn;
|
||||
}
|
||||
|
||||
/* Pretend to be a "normal" (i.e., not fragmented) IP packet
|
||||
from now on. */
|
||||
ip_reasslen += IP_HLEN;
|
||||
|
||||
IPH_LEN_SET(iphdr, htons(ip_reasslen));
|
||||
IPH_OFFSET_SET(iphdr, 0);
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
|
||||
/* If we have come this far, we have a full packet in the
|
||||
buffer, so we allocate a pbuf and copy the packet into it. We
|
||||
also reset the timer. */
|
||||
sys_untimeout(ip_reass_timer, NULL);
|
||||
ip_reasstmr = 0;
|
||||
pbuf_free(p);
|
||||
p = pbuf_alloc(PBUF_LINK, ip_reasslen, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
i = 0;
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
/* Copy enough bytes to fill this pbuf in the chain. The
|
||||
available data in the pbuf is given by the q->len
|
||||
variable. */
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: memcpy from %p (%d) to %p, %d bytes\n",
|
||||
(void *)&ip_reassbuf[i], i, q->payload,
|
||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
|
||||
memcpy(q->payload, &ip_reassbuf[i],
|
||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
|
||||
i += q->len;
|
||||
}
|
||||
IPFRAG_STATS_INC(ip_frag.fw);
|
||||
} else {
|
||||
IPFRAG_STATS_INC(ip_frag.memerr);
|
||||
}
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
nullreturn:
|
||||
IPFRAG_STATS_INC(ip_frag.drop);
|
||||
pbuf_free(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define MAX_MTU 1500
|
||||
static u8_t buf[MEM_ALIGN_SIZE(MAX_MTU)];
|
||||
|
||||
/**
|
||||
* Fragment an IP packet if too large
|
||||
*
|
||||
* Chop the packet in mtu sized chunks and send them in order
|
||||
* by using a fixed size static memory buffer (PBUF_ROM)
|
||||
*/
|
||||
err_t
|
||||
ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
{
|
||||
struct pbuf *rambuf;
|
||||
struct pbuf *header;
|
||||
struct ip_hdr *iphdr;
|
||||
u16_t nfb = 0;
|
||||
u16_t left, cop;
|
||||
u16_t mtu = netif->mtu;
|
||||
u16_t ofo, omf;
|
||||
u16_t last;
|
||||
u16_t poff = IP_HLEN;
|
||||
u16_t tmp;
|
||||
|
||||
/* Get a RAM based MTU sized pbuf */
|
||||
rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF);
|
||||
rambuf->tot_len = rambuf->len = mtu;
|
||||
rambuf->payload = MEM_ALIGN((void *)buf);
|
||||
|
||||
/* Copy the IP header in it */
|
||||
iphdr = rambuf->payload;
|
||||
memcpy(iphdr, p->payload, IP_HLEN);
|
||||
|
||||
/* Save original offset */
|
||||
tmp = ntohs(IPH_OFFSET(iphdr));
|
||||
ofo = tmp & IP_OFFMASK;
|
||||
omf = tmp & IP_MF;
|
||||
|
||||
left = p->tot_len - IP_HLEN;
|
||||
|
||||
while (left) {
|
||||
last = (left <= mtu - IP_HLEN);
|
||||
|
||||
/* Set new offset and MF flag */
|
||||
ofo += nfb;
|
||||
tmp = omf | (IP_OFFMASK & (ofo));
|
||||
if (!last)
|
||||
tmp = tmp | IP_MF;
|
||||
IPH_OFFSET_SET(iphdr, htons(tmp));
|
||||
|
||||
/* Fill this fragment */
|
||||
nfb = (mtu - IP_HLEN) / 8;
|
||||
cop = last ? left : nfb * 8;
|
||||
|
||||
p = copy_from_pbuf(p, &poff, (u8_t *) iphdr + IP_HLEN, cop);
|
||||
|
||||
/* Correct header */
|
||||
IPH_LEN_SET(iphdr, htons(cop + IP_HLEN));
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
|
||||
if (last)
|
||||
pbuf_realloc(rambuf, left + IP_HLEN);
|
||||
/* This part is ugly: we alloc a RAM based pbuf for
|
||||
* the link level header for each chunk and then
|
||||
* free it.A PBUF_ROM style pbuf for which pbuf_header
|
||||
* worked would make things simpler.
|
||||
*/
|
||||
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
|
||||
pbuf_chain(header, rambuf);
|
||||
netif->output(netif, header, dest);
|
||||
IPFRAG_STATS_INC(ip_frag.xmit);
|
||||
pbuf_free(header);
|
||||
|
||||
left -= cop;
|
||||
}
|
||||
pbuf_free(rambuf);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
IPv6 support in lwIP is very experimental.
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/* Some ICMP messages should be passed to the transport protocols. This
|
||||
is not implemented. */
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
|
||||
void
|
||||
icmp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
unsigned char type;
|
||||
struct icmp_echo_hdr *iecho;
|
||||
struct ip_hdr *iphdr;
|
||||
struct ip_addr tmpaddr;
|
||||
|
||||
#ifdef ICMP_STATS
|
||||
++lwip_stats.icmp.recv;
|
||||
#endif /* ICMP_STATS */
|
||||
|
||||
/* TODO: check length before accessing payload! */
|
||||
|
||||
type = ((char *)p->payload)[0];
|
||||
|
||||
switch (type) {
|
||||
case ICMP6_ECHO:
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
|
||||
|
||||
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
|
||||
|
||||
pbuf_free(p);
|
||||
#ifdef ICMP_STATS
|
||||
++lwip_stats.icmp.lenerr;
|
||||
#endif /* ICMP_STATS */
|
||||
|
||||
return;
|
||||
}
|
||||
iecho = p->payload;
|
||||
iphdr = (struct ip_hdr *)((char *)p->payload - IP_HLEN);
|
||||
if (inet_chksum_pbuf(p) != 0) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
||||
|
||||
#ifdef ICMP_STATS
|
||||
++lwip_stats.icmp.chkerr;
|
||||
#endif /* ICMP_STATS */
|
||||
/* return;*/
|
||||
}
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp: p->len %d p->tot_len %d\n", p->len, p->tot_len));
|
||||
ip_addr_set(&tmpaddr, &(iphdr->src));
|
||||
ip_addr_set(&(iphdr->src), &(iphdr->dest));
|
||||
ip_addr_set(&(iphdr->dest), &tmpaddr);
|
||||
iecho->type = ICMP6_ER;
|
||||
/* adjust the checksum */
|
||||
if (iecho->chksum >= htons(0xffff - (ICMP6_ECHO << 8))) {
|
||||
iecho->chksum += htons(ICMP6_ECHO << 8) + 1;
|
||||
} else {
|
||||
iecho->chksum += htons(ICMP6_ECHO << 8);
|
||||
}
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo (%x)\n", inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest), IP_PROTO_ICMP, p->tot_len)));
|
||||
#ifdef ICMP_STATS
|
||||
++lwip_stats.icmp.xmit;
|
||||
#endif /* ICMP_STATS */
|
||||
|
||||
/* LWIP_DEBUGF("icmp: p->len %u p->tot_len %u\n", p->len, p->tot_len);*/
|
||||
ip_output_if (p, &(iphdr->src), IP_HDRINCL,
|
||||
iphdr->hoplim, IP_PROTO_ICMP, inp);
|
||||
break;
|
||||
default:
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d not supported.\n", (int)type));
|
||||
#ifdef ICMP_STATS
|
||||
++lwip_stats.icmp.proterr;
|
||||
++lwip_stats.icmp.drop;
|
||||
#endif /* ICMP_STATS */
|
||||
}
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
void
|
||||
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_dur_hdr *idur;
|
||||
|
||||
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
|
||||
/* ICMP header + IP header + 8 bytes of data */
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
idur = q->payload;
|
||||
idur->type = (char)ICMP6_DUR;
|
||||
idur->icode = (char)t;
|
||||
|
||||
memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);
|
||||
|
||||
/* calculate checksum */
|
||||
idur->chksum = 0;
|
||||
idur->chksum = inet_chksum(idur, q->len);
|
||||
#ifdef ICMP_STATS
|
||||
++lwip_stats.icmp.xmit;
|
||||
#endif /* ICMP_STATS */
|
||||
|
||||
ip_output(q, NULL,
|
||||
(struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
void
|
||||
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_te_hdr *tehdr;
|
||||
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded\n"));
|
||||
|
||||
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
tehdr = q->payload;
|
||||
tehdr->type = (char)ICMP6_TE;
|
||||
tehdr->icode = (char)t;
|
||||
|
||||
/* copy fields from original packet */
|
||||
memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);
|
||||
|
||||
/* calculate checksum */
|
||||
tehdr->chksum = 0;
|
||||
tehdr->chksum = inet_chksum(tehdr, q->len);
|
||||
#ifdef ICMP_STATS
|
||||
++lwip_stats.icmp.xmit;
|
||||
#endif /* ICMP_STATS */
|
||||
ip_output(q, NULL,
|
||||
(struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,386 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* ip.c
|
||||
*
|
||||
* This is the code for the IP layer for IPv6.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "arch/perf.h"
|
||||
|
||||
/* ip_init:
|
||||
*
|
||||
* Initializes the IP layer.
|
||||
*/
|
||||
|
||||
void
|
||||
ip_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* ip_route:
|
||||
*
|
||||
* Finds the appropriate network interface for a given IP address. It searches the
|
||||
* list of network interfaces linearly. A match is found if the masked IP address of
|
||||
* the network interface equals the masked IP address given to the function.
|
||||
*/
|
||||
|
||||
struct netif *
|
||||
ip_route(struct ip_addr *dest)
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
||||
return netif;
|
||||
}
|
||||
}
|
||||
|
||||
return netif_default;
|
||||
}
|
||||
|
||||
/* ip_forward:
|
||||
*
|
||||
* Forwards an IP packet. It finds an appropriate route for the packet, decrements
|
||||
* the TTL value of the packet, adjusts the checksum and outputs the packet on the
|
||||
* appropriate interface.
|
||||
*/
|
||||
|
||||
static void
|
||||
ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
PERF_START;
|
||||
|
||||
if ((netif = ip_route((struct ip_addr *)&(iphdr->dest))) == NULL) {
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: no forwarding route found for "));
|
||||
#if IP_DEBUG
|
||||
ip_addr_debug_print(IP_DEBUG, &(iphdr->dest));
|
||||
#endif /* IP_DEBUG */
|
||||
LWIP_DEBUGF(IP_DEBUG, ("\n"));
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
/* Decrement TTL and send ICMP if ttl == 0. */
|
||||
if (--iphdr->hoplim == 0) {
|
||||
/* Don't send ICMP messages in response to ICMP messages */
|
||||
if (iphdr->nexthdr != IP_PROTO_ICMP) {
|
||||
icmp_time_exceeded(p, ICMP_TE_TTL);
|
||||
}
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Incremental update of the IP checksum. */
|
||||
/* if (iphdr->chksum >= htons(0xffff - 0x100)) {
|
||||
iphdr->chksum += htons(0x100) + 1;
|
||||
} else {
|
||||
iphdr->chksum += htons(0x100);
|
||||
}*/
|
||||
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to "));
|
||||
#if IP_DEBUG
|
||||
ip_addr_debug_print(IP_DEBUG, &(iphdr->dest));
|
||||
#endif /* IP_DEBUG */
|
||||
LWIP_DEBUGF(IP_DEBUG, ("\n"));
|
||||
|
||||
#ifdef IP_STATS
|
||||
++lwip_stats.ip.fw;
|
||||
++lwip_stats.ip.xmit;
|
||||
#endif /* IP_STATS */
|
||||
|
||||
PERF_STOP("ip_forward");
|
||||
|
||||
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
|
||||
}
|
||||
|
||||
/* ip_input:
|
||||
*
|
||||
* This function is called by the network interface device driver when an IP packet is
|
||||
* received. The function does the basic checks of the IP header such as packet size
|
||||
* being at least larger than the header size etc. If the packet was not destined for
|
||||
* us, the packet is forwarded (using ip_forward). The IP checksum is always checked.
|
||||
*
|
||||
* Finally, the packet is sent to the upper layer protocol input function.
|
||||
*/
|
||||
|
||||
void
|
||||
ip_input(struct pbuf *p, struct netif *inp) {
|
||||
struct ip_hdr *iphdr;
|
||||
struct netif *netif;
|
||||
|
||||
|
||||
PERF_START;
|
||||
|
||||
#if IP_DEBUG
|
||||
ip_debug_print(p);
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
|
||||
#ifdef IP_STATS
|
||||
++lwip_stats.ip.recv;
|
||||
#endif /* IP_STATS */
|
||||
|
||||
/* identify the IP header */
|
||||
iphdr = p->payload;
|
||||
|
||||
|
||||
if (iphdr->v != 6) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("IP packet dropped due to bad version number\n"));
|
||||
#if IP_DEBUG
|
||||
ip_debug_print(p);
|
||||
#endif /* IP_DEBUG */
|
||||
pbuf_free(p);
|
||||
#ifdef IP_STATS
|
||||
++lwip_stats.ip.err;
|
||||
++lwip_stats.ip.drop;
|
||||
#endif /* IP_STATS */
|
||||
return;
|
||||
}
|
||||
|
||||
/* is this packet for us? */
|
||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
#if IP_DEBUG
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest "));
|
||||
ip_addr_debug_print(IP_DEBUG, &(iphdr->dest));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("netif->ip_addr "));
|
||||
ip_addr_debug_print(IP_DEBUG, &(netif->ip_addr));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("\n"));
|
||||
#endif /* IP_DEBUG */
|
||||
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (netif == NULL) {
|
||||
/* packet not for us, route or discard */
|
||||
#ifdef IP_FORWARD
|
||||
ip_forward(p, iphdr);
|
||||
#endif
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
pbuf_realloc(p, IP_HLEN + ntohs(iphdr->len));
|
||||
|
||||
/* send to upper layers */
|
||||
#if IP_DEBUG
|
||||
/* LWIP_DEBUGF("ip_input: \n");
|
||||
ip_debug_print(p);
|
||||
LWIP_DEBUGF("ip_input: p->len %u p->tot_len %u\n", p->len, p->tot_len);*/
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
|
||||
pbuf_header(p, -IP_HLEN);
|
||||
|
||||
switch (iphdr->nexthdr) {
|
||||
case IP_PROTO_UDP:
|
||||
udp_input(p);
|
||||
break;
|
||||
case IP_PROTO_TCP:
|
||||
tcp_input(p);
|
||||
break;
|
||||
case IP_PROTO_ICMP:
|
||||
icmp_input(p, inp);
|
||||
break;
|
||||
default:
|
||||
/* send ICMP destination protocol unreachable */
|
||||
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(IP_DEBUG, ("Unsupported transport protocol %u\n",
|
||||
iphdr->nexthdr));
|
||||
|
||||
#ifdef IP_STATS
|
||||
++lwip_stats.ip.proterr;
|
||||
++lwip_stats.ip.drop;
|
||||
#endif /* IP_STATS */
|
||||
|
||||
}
|
||||
PERF_STOP("ip_input");
|
||||
}
|
||||
|
||||
|
||||
/* ip_output_if:
|
||||
*
|
||||
* Sends an IP packet on a network interface. This function constructs the IP header
|
||||
* and calculates the IP header checksum. If the source IP address is NULL,
|
||||
* the IP address of the outgoing network interface is filled in as source address.
|
||||
*/
|
||||
|
||||
err_t
|
||||
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl,
|
||||
u8_t proto, struct netif *netif)
|
||||
{
|
||||
struct ip_hdr *iphdr;
|
||||
|
||||
PERF_START;
|
||||
|
||||
printf("len %u tot_len %u\n", p->len, p->tot_len);
|
||||
if (pbuf_header(p, IP_HLEN)) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: not enough room for IP header in pbuf\n"));
|
||||
#ifdef IP_STATS
|
||||
++lwip_stats.ip.err;
|
||||
#endif /* IP_STATS */
|
||||
|
||||
return ERR_BUF;
|
||||
}
|
||||
printf("len %u tot_len %u\n", p->len, p->tot_len);
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
|
||||
if (dest != IP_HDRINCL) {
|
||||
printf("!IP_HDRLINCL\n");
|
||||
iphdr->hoplim = ttl;
|
||||
iphdr->nexthdr = proto;
|
||||
iphdr->len = htons(p->tot_len - IP_HLEN);
|
||||
ip_addr_set(&(iphdr->dest), dest);
|
||||
|
||||
iphdr->v = 6;
|
||||
|
||||
if (ip_addr_isany(src)) {
|
||||
ip_addr_set(&(iphdr->src), &(netif->ip_addr));
|
||||
} else {
|
||||
ip_addr_set(&(iphdr->src), src);
|
||||
}
|
||||
|
||||
} else {
|
||||
dest = &(iphdr->dest);
|
||||
}
|
||||
|
||||
#ifdef IP_STATS
|
||||
++lwip_stats.ip.xmit;
|
||||
#endif /* IP_STATS */
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c (len %u)\n", netif->name[0], netif->name[1], p->tot_len));
|
||||
#if IP_DEBUG
|
||||
ip_debug_print(p);
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
PERF_STOP("ip_output_if");
|
||||
return netif->output(netif, p, dest);
|
||||
}
|
||||
|
||||
/* ip_output:
|
||||
*
|
||||
* Simple interface to ip_output_if. It finds the outgoing network interface and
|
||||
* calls upon ip_output_if to do the actual work.
|
||||
*/
|
||||
|
||||
err_t
|
||||
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t proto)
|
||||
{
|
||||
struct netif *netif;
|
||||
if ((netif = ip_route(dest)) == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%lx\n", dest->addr));
|
||||
#ifdef IP_STATS
|
||||
++lwip_stats.ip.rterr;
|
||||
#endif /* IP_STATS */
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
return ip_output_if (p, src, dest, ttl, proto, netif);
|
||||
}
|
||||
|
||||
#if IP_DEBUG
|
||||
void
|
||||
ip_debug_print(struct pbuf *p)
|
||||
{
|
||||
struct ip_hdr *iphdr = p->payload;
|
||||
char *payload;
|
||||
|
||||
payload = (char *)iphdr + IP_HLEN;
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("|%2d | %x%x | %x%x | (v, traffic class, flow label)\n",
|
||||
iphdr->v,
|
||||
iphdr->tclass1, iphdr->tclass2,
|
||||
iphdr->flow1, iphdr->flow2));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %5u | %2u | %2u | (len, nexthdr, hoplim)\n",
|
||||
ntohs(iphdr->len),
|
||||
iphdr->nexthdr,
|
||||
iphdr->hoplim));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
||||
ntohl(iphdr->src.addr[0]) >> 16 & 0xffff,
|
||||
ntohl(iphdr->src.addr[0]) & 0xffff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
||||
ntohl(iphdr->src.addr[1]) >> 16 & 0xffff,
|
||||
ntohl(iphdr->src.addr[1]) & 0xffff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
||||
ntohl(iphdr->src.addr[2]) >> 16 & 0xffff,
|
||||
ntohl(iphdr->src.addr[2]) & 0xffff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (src)\n",
|
||||
ntohl(iphdr->src.addr[3]) >> 16 & 0xffff,
|
||||
ntohl(iphdr->src.addr[3]) & 0xffff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
||||
ntohl(iphdr->dest.addr[0]) >> 16 & 0xffff,
|
||||
ntohl(iphdr->dest.addr[0]) & 0xffff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
||||
ntohl(iphdr->dest.addr[1]) >> 16 & 0xffff,
|
||||
ntohl(iphdr->dest.addr[1]) & 0xffff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
||||
ntohl(iphdr->dest.addr[2]) >> 16 & 0xffff,
|
||||
ntohl(iphdr->dest.addr[2]) & 0xffff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %4lx | %4lx | (dest)\n",
|
||||
ntohl(iphdr->dest.addr[3]) >> 16 & 0xffff,
|
||||
ntohl(iphdr->dest.addr[3]) & 0xffff));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
}
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/inet.h"
|
||||
|
||||
|
||||
int
|
||||
ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
||||
struct ip_addr *mask)
|
||||
{
|
||||
return((addr1->addr[0] & mask->addr[0]) == (addr2->addr[0] & mask->addr[0]) &&
|
||||
(addr1->addr[1] & mask->addr[1]) == (addr2->addr[1] & mask->addr[1]) &&
|
||||
(addr1->addr[2] & mask->addr[2]) == (addr2->addr[2] & mask->addr[2]) &&
|
||||
(addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3]));
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
|
||||
{
|
||||
return(addr1->addr[0] == addr2->addr[0] &&
|
||||
addr1->addr[1] == addr2->addr[1] &&
|
||||
addr1->addr[2] == addr2->addr[2] &&
|
||||
addr1->addr[3] == addr2->addr[3]);
|
||||
}
|
||||
|
||||
void
|
||||
ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
|
||||
{
|
||||
memcpy(dest, src, sizeof(struct ip_addr));
|
||||
/* dest->addr[0] = src->addr[0];
|
||||
dest->addr[1] = src->addr[1];
|
||||
dest->addr[2] = src->addr[2];
|
||||
dest->addr[3] = src->addr[3];*/
|
||||
}
|
||||
|
||||
int
|
||||
ip_addr_isany(struct ip_addr *addr)
|
||||
{
|
||||
if (addr == NULL) return 1;
|
||||
return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0);
|
||||
}
|
||||
|
||||
|
||||
/*#if IP_DEBUG*/
|
||||
void
|
||||
ip_addr_debug_print(struct ip_addr *addr)
|
||||
{
|
||||
printf("%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx",
|
||||
ntohl(addr->addr[0]) >> 16 & 0xffff,
|
||||
ntohl(addr->addr[0]) & 0xffff,
|
||||
ntohl(addr->addr[1]) >> 16 & 0xffff,
|
||||
ntohl(addr->addr[1]) & 0xffff,
|
||||
ntohl(addr->addr[2]) >> 16 & 0xffff,
|
||||
ntohl(addr->addr[2]) & 0xffff,
|
||||
ntohl(addr->addr[3]) >> 16 & 0xffff,
|
||||
ntohl(addr->addr[3]) & 0xffff);
|
||||
}
|
||||
/*#endif*/ /* IP_DEBUG */
|
||||
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
/** @file
|
||||
*
|
||||
* Dynamic memory manager
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/arch.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
struct mem {
|
||||
mem_size_t next, prev;
|
||||
#if MEM_ALIGNMENT == 1
|
||||
u8_t used;
|
||||
#elif MEM_ALIGNMENT == 2
|
||||
u16_t used;
|
||||
#elif MEM_ALIGNMENT == 4
|
||||
u32_t used;
|
||||
#elif MEM_ALIGNMENT == 8
|
||||
u64_t used;
|
||||
#else
|
||||
#error "unhandled MEM_ALIGNMENT size"
|
||||
#endif /* MEM_ALIGNMENT */
|
||||
};
|
||||
|
||||
static struct mem *ram_end;
|
||||
static u8_t ram[MEM_SIZE + sizeof(struct mem) + MEM_ALIGNMENT];
|
||||
|
||||
#define MIN_SIZE 12
|
||||
#if 0 /* this one does not align correctly for some, resulting in crashes */
|
||||
#define SIZEOF_STRUCT_MEM (unsigned int)MEM_ALIGN_SIZE(sizeof(struct mem))
|
||||
#else
|
||||
#define SIZEOF_STRUCT_MEM (sizeof(struct mem) + \
|
||||
(((sizeof(struct mem) % MEM_ALIGNMENT) == 0)? 0 : \
|
||||
(4 - (sizeof(struct mem) % MEM_ALIGNMENT))))
|
||||
#endif
|
||||
|
||||
static struct mem *lfree; /* pointer to the lowest free block */
|
||||
|
||||
static sys_sem_t mem_sem;
|
||||
|
||||
static void
|
||||
plug_holes(struct mem *mem)
|
||||
{
|
||||
struct mem *nmem;
|
||||
struct mem *pmem;
|
||||
|
||||
LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
|
||||
LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
|
||||
LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
|
||||
|
||||
/* plug hole forward */
|
||||
LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE", mem->next <= MEM_SIZE);
|
||||
|
||||
nmem = (struct mem *)&ram[mem->next];
|
||||
if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
|
||||
if (lfree == nmem) {
|
||||
lfree = mem;
|
||||
}
|
||||
mem->next = nmem->next;
|
||||
((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;
|
||||
}
|
||||
|
||||
/* plug hole backward */
|
||||
pmem = (struct mem *)&ram[mem->prev];
|
||||
if (pmem != mem && pmem->used == 0) {
|
||||
if (lfree == mem) {
|
||||
lfree = pmem;
|
||||
}
|
||||
pmem->next = mem->next;
|
||||
((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;
|
||||
}
|
||||
|
||||
}
|
||||
void
|
||||
mem_init(void)
|
||||
{
|
||||
struct mem *mem;
|
||||
|
||||
memset(ram, 0, MEM_SIZE);
|
||||
mem = (struct mem *)ram;
|
||||
mem->next = MEM_SIZE;
|
||||
mem->prev = 0;
|
||||
mem->used = 0;
|
||||
ram_end = (struct mem *)&ram[MEM_SIZE];
|
||||
ram_end->used = 1;
|
||||
ram_end->next = MEM_SIZE;
|
||||
ram_end->prev = MEM_SIZE;
|
||||
|
||||
mem_sem = sys_sem_new(1);
|
||||
|
||||
lfree = (struct mem *)ram;
|
||||
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.avail = MEM_SIZE;
|
||||
#endif /* MEM_STATS */
|
||||
}
|
||||
void
|
||||
mem_free(void *rmem)
|
||||
{
|
||||
struct mem *mem;
|
||||
|
||||
if (rmem == NULL) {
|
||||
LWIP_DEBUGF(MEM_DEBUG | DBG_TRACE | 2, ("mem_free(p == NULL) was called.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
sys_sem_wait(mem_sem);
|
||||
|
||||
LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
|
||||
(u8_t *)rmem < (u8_t *)ram_end);
|
||||
|
||||
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
|
||||
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
|
||||
#if MEM_STATS
|
||||
++lwip_stats.mem.err;
|
||||
#endif /* MEM_STATS */
|
||||
sys_sem_signal(mem_sem);
|
||||
return;
|
||||
}
|
||||
mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
|
||||
|
||||
LWIP_ASSERT("mem_free: mem->used", mem->used);
|
||||
|
||||
mem->used = 0;
|
||||
|
||||
if (mem < lfree) {
|
||||
lfree = mem;
|
||||
}
|
||||
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
|
||||
|
||||
#endif /* MEM_STATS */
|
||||
plug_holes(mem);
|
||||
sys_sem_signal(mem_sem);
|
||||
}
|
||||
void *
|
||||
mem_reallocm(void *rmem, mem_size_t newsize)
|
||||
{
|
||||
void *nmem;
|
||||
nmem = mem_malloc(newsize);
|
||||
if (nmem == NULL) {
|
||||
return mem_realloc(rmem, newsize);
|
||||
}
|
||||
memcpy(nmem, rmem, newsize);
|
||||
mem_free(rmem);
|
||||
return nmem;
|
||||
}
|
||||
|
||||
void *
|
||||
mem_realloc(void *rmem, mem_size_t newsize)
|
||||
{
|
||||
mem_size_t size;
|
||||
mem_size_t ptr, ptr2;
|
||||
struct mem *mem, *mem2;
|
||||
|
||||
/* Expand the size of the allocated memory region so that we can
|
||||
adjust for alignment. */
|
||||
if ((newsize % MEM_ALIGNMENT) != 0) {
|
||||
newsize += MEM_ALIGNMENT - ((newsize + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
|
||||
}
|
||||
|
||||
if (newsize > MEM_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sys_sem_wait(mem_sem);
|
||||
|
||||
LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
|
||||
(u8_t *)rmem < (u8_t *)ram_end);
|
||||
|
||||
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
|
||||
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
|
||||
return rmem;
|
||||
}
|
||||
mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
|
||||
|
||||
ptr = (u8_t *)mem - ram;
|
||||
|
||||
size = mem->next - ptr - SIZEOF_STRUCT_MEM;
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.used -= (size - newsize);
|
||||
#endif /* MEM_STATS */
|
||||
|
||||
if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size) {
|
||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
|
||||
mem2 = (struct mem *)&ram[ptr2];
|
||||
mem2->used = 0;
|
||||
mem2->next = mem->next;
|
||||
mem2->prev = ptr;
|
||||
mem->next = ptr2;
|
||||
if (mem2->next != MEM_SIZE) {
|
||||
((struct mem *)&ram[mem2->next])->prev = ptr2;
|
||||
}
|
||||
|
||||
plug_holes(mem2);
|
||||
}
|
||||
sys_sem_signal(mem_sem);
|
||||
return rmem;
|
||||
}
|
||||
void *
|
||||
mem_malloc(mem_size_t size)
|
||||
{
|
||||
mem_size_t ptr, ptr2;
|
||||
struct mem *mem, *mem2;
|
||||
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Expand the size of the allocated memory region so that we can
|
||||
adjust for alignment. */
|
||||
if ((size % MEM_ALIGNMENT) != 0) {
|
||||
size += MEM_ALIGNMENT - ((size + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
|
||||
}
|
||||
|
||||
if (size > MEM_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sys_sem_wait(mem_sem);
|
||||
|
||||
for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE; ptr = ((struct mem *)&ram[ptr])->next) {
|
||||
mem = (struct mem *)&ram[ptr];
|
||||
if (!mem->used &&
|
||||
mem->next - (ptr + SIZEOF_STRUCT_MEM) >= size + SIZEOF_STRUCT_MEM) {
|
||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
|
||||
mem2 = (struct mem *)&ram[ptr2];
|
||||
|
||||
mem2->prev = ptr;
|
||||
mem2->next = mem->next;
|
||||
mem->next = ptr2;
|
||||
if (mem2->next != MEM_SIZE) {
|
||||
((struct mem *)&ram[mem2->next])->prev = ptr2;
|
||||
}
|
||||
|
||||
mem2->used = 0;
|
||||
mem->used = 1;
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
|
||||
/* if (lwip_stats.mem.max < lwip_stats.mem.used) {
|
||||
lwip_stats.mem.max = lwip_stats.mem.used;
|
||||
} */
|
||||
if (lwip_stats.mem.max < ptr2) {
|
||||
lwip_stats.mem.max = ptr2;
|
||||
}
|
||||
#endif /* MEM_STATS */
|
||||
|
||||
if (mem == lfree) {
|
||||
/* Find next free block after mem */
|
||||
while (lfree->used && lfree != ram_end) {
|
||||
lfree = (struct mem *)&ram[lfree->next];
|
||||
}
|
||||
LWIP_ASSERT("mem_malloc: !lfree->used", !lfree->used);
|
||||
}
|
||||
sys_sem_signal(mem_sem);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
|
||||
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
|
||||
(unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
|
||||
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
|
||||
}
|
||||
}
|
||||
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size));
|
||||
#if MEM_STATS
|
||||
++lwip_stats.mem.err;
|
||||
#endif /* MEM_STATS */
|
||||
sys_sem_signal(mem_sem);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/memp.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/api_msg.h"
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
struct memp {
|
||||
struct memp *next;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static struct memp *memp_tab[MEMP_MAX];
|
||||
|
||||
static const u16_t memp_sizes[MEMP_MAX] = {
|
||||
sizeof(struct pbuf),
|
||||
sizeof(struct raw_pcb),
|
||||
sizeof(struct udp_pcb),
|
||||
sizeof(struct tcp_pcb),
|
||||
sizeof(struct tcp_pcb_listen),
|
||||
sizeof(struct tcp_seg),
|
||||
sizeof(struct netbuf),
|
||||
sizeof(struct netconn),
|
||||
sizeof(struct api_msg),
|
||||
sizeof(struct tcpip_msg),
|
||||
sizeof(struct sys_timeout)
|
||||
};
|
||||
|
||||
static const u16_t memp_num[MEMP_MAX] = {
|
||||
MEMP_NUM_PBUF,
|
||||
MEMP_NUM_RAW_PCB,
|
||||
MEMP_NUM_UDP_PCB,
|
||||
MEMP_NUM_TCP_PCB,
|
||||
MEMP_NUM_TCP_PCB_LISTEN,
|
||||
MEMP_NUM_TCP_SEG,
|
||||
MEMP_NUM_NETBUF,
|
||||
MEMP_NUM_NETCONN,
|
||||
MEMP_NUM_API_MSG,
|
||||
MEMP_NUM_TCPIP_MSG,
|
||||
MEMP_NUM_SYS_TIMEOUT
|
||||
};
|
||||
|
||||
static u8_t memp_memory[(MEMP_NUM_PBUF *
|
||||
MEM_ALIGN_SIZE(sizeof(struct pbuf) +
|
||||
sizeof(struct memp)) +
|
||||
MEMP_NUM_RAW_PCB *
|
||||
MEM_ALIGN_SIZE(sizeof(struct raw_pcb) +
|
||||
sizeof(struct memp)) +
|
||||
MEMP_NUM_UDP_PCB *
|
||||
MEM_ALIGN_SIZE(sizeof(struct udp_pcb) +
|
||||
sizeof(struct memp)) +
|
||||
MEMP_NUM_TCP_PCB *
|
||||
MEM_ALIGN_SIZE(sizeof(struct tcp_pcb) +
|
||||
sizeof(struct memp)) +
|
||||
MEMP_NUM_TCP_PCB_LISTEN *
|
||||
MEM_ALIGN_SIZE(sizeof(struct tcp_pcb_listen) +
|
||||
sizeof(struct memp)) +
|
||||
MEMP_NUM_TCP_SEG *
|
||||
MEM_ALIGN_SIZE(sizeof(struct tcp_seg) +
|
||||
sizeof(struct memp)) +
|
||||
MEMP_NUM_NETBUF *
|
||||
MEM_ALIGN_SIZE(sizeof(struct netbuf) +
|
||||
sizeof(struct memp)) +
|
||||
MEMP_NUM_NETCONN *
|
||||
MEM_ALIGN_SIZE(sizeof(struct netconn) +
|
||||
sizeof(struct memp)) +
|
||||
MEMP_NUM_API_MSG *
|
||||
MEM_ALIGN_SIZE(sizeof(struct api_msg) +
|
||||
sizeof(struct memp)) +
|
||||
MEMP_NUM_TCPIP_MSG *
|
||||
MEM_ALIGN_SIZE(sizeof(struct tcpip_msg) +
|
||||
sizeof(struct memp)) +
|
||||
MEMP_NUM_SYS_TIMEOUT *
|
||||
MEM_ALIGN_SIZE(sizeof(struct sys_timeout) +
|
||||
sizeof(struct memp)))];
|
||||
|
||||
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
static sys_sem_t mutex;
|
||||
#endif
|
||||
|
||||
#if MEMP_SANITY_CHECK
|
||||
static int
|
||||
memp_sanity(void)
|
||||
{
|
||||
int i, c;
|
||||
struct memp *m, *n;
|
||||
|
||||
for(i = 0; i < MEMP_MAX; i++) {
|
||||
for(m = memp_tab[i]; m != NULL; m = m->next) {
|
||||
c = 1;
|
||||
for(n = memp_tab[i]; n != NULL; n = n->next) {
|
||||
if (n == m) {
|
||||
--c;
|
||||
}
|
||||
if (c < 0) return 0; /* LW was: abort(); */
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif /* MEMP_SANITY_CHECK*/
|
||||
|
||||
void
|
||||
memp_init(void)
|
||||
{
|
||||
struct memp *m, *memp;
|
||||
u16_t i, j;
|
||||
u16_t size;
|
||||
|
||||
#if MEMP_STATS
|
||||
for(i = 0; i < MEMP_MAX; ++i) {
|
||||
lwip_stats.memp[i].used = lwip_stats.memp[i].max =
|
||||
lwip_stats.memp[i].err = 0;
|
||||
lwip_stats.memp[i].avail = memp_num[i];
|
||||
}
|
||||
#endif /* MEMP_STATS */
|
||||
|
||||
memp = (struct memp *)&memp_memory[0];
|
||||
for(i = 0; i < MEMP_MAX; ++i) {
|
||||
size = MEM_ALIGN_SIZE(memp_sizes[i] + sizeof(struct memp));
|
||||
if (memp_num[i] > 0) {
|
||||
memp_tab[i] = memp;
|
||||
m = memp;
|
||||
|
||||
for(j = 0; j < memp_num[i]; ++j) {
|
||||
m->next = (struct memp *)MEM_ALIGN((u8_t *)m + size);
|
||||
memp = m;
|
||||
m = m->next;
|
||||
}
|
||||
memp->next = NULL;
|
||||
memp = m;
|
||||
} else {
|
||||
memp_tab[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
mutex = sys_sem_new(1);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
void *
|
||||
memp_malloc(memp_t type)
|
||||
{
|
||||
struct memp *memp;
|
||||
void *mem;
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
#endif
|
||||
|
||||
LWIP_ASSERT("memp_malloc: type < MEMP_MAX", type < MEMP_MAX);
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
#else /* SYS_LIGHTWEIGHT_PROT */
|
||||
sys_sem_wait(mutex);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
memp = memp_tab[type];
|
||||
|
||||
if (memp != NULL) {
|
||||
memp_tab[type] = memp->next;
|
||||
memp->next = NULL;
|
||||
#if MEMP_STATS
|
||||
++lwip_stats.memp[type].used;
|
||||
if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
|
||||
lwip_stats.memp[type].max = lwip_stats.memp[type].used;
|
||||
}
|
||||
#endif /* MEMP_STATS */
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
#else /* SYS_LIGHTWEIGHT_PROT */
|
||||
sys_sem_signal(mutex);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
LWIP_ASSERT("memp_malloc: memp properly aligned",
|
||||
((mem_ptr_t)MEM_ALIGN((u8_t *)memp + sizeof(struct memp)) % MEM_ALIGNMENT) == 0);
|
||||
|
||||
mem = MEM_ALIGN((u8_t *)memp + sizeof(struct memp));
|
||||
return mem;
|
||||
} else {
|
||||
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %d\n", type));
|
||||
#if MEMP_STATS
|
||||
++lwip_stats.memp[type].err;
|
||||
#endif /* MEMP_STATS */
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
#else /* SYS_LIGHTWEIGHT_PROT */
|
||||
sys_sem_signal(mutex);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
memp_free(memp_t type, void *mem)
|
||||
{
|
||||
struct memp *memp;
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
if (mem == NULL) {
|
||||
return;
|
||||
}
|
||||
memp = (struct memp *)((u8_t *)mem - sizeof(struct memp));
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
#else /* SYS_LIGHTWEIGHT_PROT */
|
||||
sys_sem_wait(mutex);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
#if MEMP_STATS
|
||||
lwip_stats.memp[type].used--;
|
||||
#endif /* MEMP_STATS */
|
||||
|
||||
memp->next = memp_tab[type];
|
||||
memp_tab[type] = memp;
|
||||
|
||||
#if MEMP_SANITY_CHECK
|
||||
LWIP_ASSERT("memp sanity", memp_sanity());
|
||||
#endif
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
#else /* SYS_LIGHTWEIGHT_PROT */
|
||||
sys_sem_signal(mutex);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
/**
|
||||
* @file
|
||||
*
|
||||
* lwIP network interface abstraction
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
struct netif *netif_list = NULL;
|
||||
struct netif *netif_default = NULL;
|
||||
|
||||
/**
|
||||
* Add a network interface to the list of lwIP netifs.
|
||||
*
|
||||
* @param netif a pre-allocated netif structure
|
||||
* @param ipaddr IP address for the new netif
|
||||
* @param netmask network mask for the new netif
|
||||
* @param gw default gateway IP address for the new netif
|
||||
* @param state opaque data passed to the new netif
|
||||
* @param init callback function that initializes the interface
|
||||
* @param input callback function that is called to pass
|
||||
* ingress packets up in the protocol layer stack.
|
||||
*
|
||||
* @return netif, or NULL if failed.
|
||||
*/
|
||||
struct netif *
|
||||
netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw,
|
||||
void *state,
|
||||
err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||
{
|
||||
static int netifnum = 0;
|
||||
|
||||
#if LWIP_DHCP
|
||||
/* netif not under DHCP control by default */
|
||||
netif->dhcp = NULL;
|
||||
#endif
|
||||
/* remember netif specific state information data */
|
||||
netif->state = state;
|
||||
netif->num = netifnum++;
|
||||
netif->input = input;
|
||||
|
||||
netif_set_addr(netif, ipaddr, netmask, gw);
|
||||
|
||||
/* call user specified initialization function for netif */
|
||||
if (init(netif) != ERR_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add this netif to the list */
|
||||
netif->next = netif_list;
|
||||
netif_list = netif;
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
|
||||
netif->name[0], netif->name[1]));
|
||||
ip_addr_debug_print(NETIF_DEBUG, ipaddr);
|
||||
LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
|
||||
ip_addr_debug_print(NETIF_DEBUG, netmask);
|
||||
LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
|
||||
ip_addr_debug_print(NETIF_DEBUG, gw);
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
|
||||
return netif;
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_addr(struct netif *netif,struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw)
|
||||
{
|
||||
netif_set_ipaddr(netif, ipaddr);
|
||||
netif_set_netmask(netif, netmask);
|
||||
netif_set_gw(netif, gw);
|
||||
}
|
||||
|
||||
void netif_remove(struct netif * netif)
|
||||
{
|
||||
if ( netif == NULL ) return;
|
||||
|
||||
/* is it the first netif? */
|
||||
if (netif_list == netif) {
|
||||
netif_list = netif->next;
|
||||
}
|
||||
else {
|
||||
/* look for netif further down the list */
|
||||
struct netif * tmpNetif;
|
||||
for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) {
|
||||
if (tmpNetif->next == netif) {
|
||||
tmpNetif->next = netif->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tmpNetif == NULL)
|
||||
return; /* we didn't find any netif today */
|
||||
}
|
||||
/* this netif is default? */
|
||||
if (netif_default == netif)
|
||||
/* reset default netif */
|
||||
netif_default = NULL;
|
||||
LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
|
||||
}
|
||||
|
||||
struct netif *
|
||||
netif_find(char *name)
|
||||
{
|
||||
struct netif *netif;
|
||||
u8_t num;
|
||||
|
||||
if (name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
num = name[2] - '0';
|
||||
|
||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
if (num == netif->num &&
|
||||
name[0] == netif->name[0] &&
|
||||
name[1] == netif->name[1]) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1]));
|
||||
return netif;
|
||||
}
|
||||
}
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
{
|
||||
/* TODO: Handling of obsolete pcbs */
|
||||
/* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */
|
||||
#if LWIP_TCP
|
||||
struct tcp_pcb *pcb;
|
||||
struct tcp_pcb_listen *lpcb;
|
||||
|
||||
/* address is actually being changed? */
|
||||
if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
|
||||
{
|
||||
/* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */
|
||||
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n"));
|
||||
pcb = tcp_active_pcbs;
|
||||
while (pcb != NULL) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
|
||||
/* this connection must be aborted */
|
||||
struct tcp_pcb *next = pcb->next;
|
||||
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
|
||||
tcp_abort(pcb);
|
||||
pcb = next;
|
||||
} else {
|
||||
pcb = pcb->next;
|
||||
}
|
||||
}
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {
|
||||
/* The PCB is listening to the old ipaddr and
|
||||
* is set to listen to the new one instead */
|
||||
ip_addr_set(&(lpcb->local_ip), ipaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ip_addr_set(&(netif->ip_addr), ipaddr);
|
||||
#if 0 /* only allowed for Ethernet interfaces TODO: how can we check? */
|
||||
/** For Ethernet network interfaces, we would like to send a
|
||||
* "gratuitous ARP"; this is an ARP packet sent by a node in order
|
||||
* to spontaneously cause other nodes to update an entry in their
|
||||
* ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6.
|
||||
*/
|
||||
etharp_query(netif, ipaddr, NULL);
|
||||
#endif
|
||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %u.%u.%u.%u\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->ip_addr),
|
||||
ip4_addr2(&netif->ip_addr),
|
||||
ip4_addr3(&netif->ip_addr),
|
||||
ip4_addr4(&netif->ip_addr)));
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_gw(struct netif *netif, struct ip_addr *gw)
|
||||
{
|
||||
ip_addr_set(&(netif->gw), gw);
|
||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %u.%u.%u.%u\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->gw),
|
||||
ip4_addr2(&netif->gw),
|
||||
ip4_addr3(&netif->gw),
|
||||
ip4_addr4(&netif->gw)));
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
|
||||
{
|
||||
ip_addr_set(&(netif->netmask), netmask);
|
||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %u.%u.%u.%u\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->netmask),
|
||||
ip4_addr2(&netif->netmask),
|
||||
ip4_addr3(&netif->netmask),
|
||||
ip4_addr4(&netif->netmask)));
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_default(struct netif *netif)
|
||||
{
|
||||
netif_default = netif;
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
|
||||
netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bring an interface up, available for processing
|
||||
* traffic.
|
||||
*
|
||||
* @note: Enabling DHCP on a down interface will make it come
|
||||
* up once configured.
|
||||
*
|
||||
* @see dhcp_start()
|
||||
*/
|
||||
void netif_set_up(struct netif *netif)
|
||||
{
|
||||
netif->flags |= NETIF_FLAG_UP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask if an interface is up
|
||||
*/
|
||||
u8_t netif_is_up(struct netif *netif)
|
||||
{
|
||||
return (netif->flags & NETIF_FLAG_UP)?1:0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bring an interface down, disabling any traffic processing.
|
||||
*
|
||||
* @note: Enabling DHCP on a down interface will make it come
|
||||
* up once configured.
|
||||
*
|
||||
* @see dhcp_start()
|
||||
*/
|
||||
void netif_set_down(struct netif *netif)
|
||||
{
|
||||
netif->flags &= ~NETIF_FLAG_UP;
|
||||
}
|
||||
|
||||
void
|
||||
netif_init(void)
|
||||
{
|
||||
netif_list = netif_default = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,962 @@
|
|||
/**
|
||||
* @file
|
||||
* Packet buffer management
|
||||
*
|
||||
* Packets are built from the pbuf data structure. It supports dynamic
|
||||
* memory allocation for packet contents or can reference externally
|
||||
* managed packet contents both in RAM and ROM. Quick allocation for
|
||||
* incoming packets is provided through pools with fixed sized pbufs.
|
||||
*
|
||||
* A packet may span over multiple pbufs, chained as a singly linked
|
||||
* list. This is called a "pbuf chain".
|
||||
*
|
||||
* Multiple packets may be queued, also using this singly linked list.
|
||||
* This is called a "packet queue".
|
||||
*
|
||||
* So, a packet queue consists of one or more pbuf chains, each of
|
||||
* which consist of one or more pbufs. Currently, queues are only
|
||||
* supported in a limited section of lwIP, this is the etharp queueing
|
||||
* code. Outside of this section no packet queues are supported yet.
|
||||
*
|
||||
* The differences between a pbuf chain and a packet queue are very
|
||||
* precise but subtle.
|
||||
*
|
||||
* The last pbuf of a packet has a ->tot_len field that equals the
|
||||
* ->len field. It can be found by traversing the list. If the last
|
||||
* pbuf of a packet has a ->next field other than NULL, more packets
|
||||
* are on the queue.
|
||||
*
|
||||
* Therefore, looping through a pbuf of a single packet, has an
|
||||
* loop end condition (tot_len == p->len), NOT (next == NULL).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "arch/perf.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static u8_t pbuf_pool_memory[(PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf)))];
|
||||
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
|
||||
static sys_sem_t pbuf_pool_free_sem;
|
||||
#endif
|
||||
|
||||
static struct pbuf *pbuf_pool = NULL;
|
||||
|
||||
/**
|
||||
* Initializes the pbuf module.
|
||||
*
|
||||
* A large part of memory is allocated for holding the pool of pbufs.
|
||||
* The size of the individual pbufs in the pool is given by the size
|
||||
* parameter, and the number of pbufs in the pool by the num parameter.
|
||||
*
|
||||
* After the memory has been allocated, the pbufs are set up. The
|
||||
* ->next pointer in each pbuf is set up to point to the next pbuf in
|
||||
* the pool.
|
||||
*
|
||||
*/
|
||||
void
|
||||
pbuf_init(void)
|
||||
{
|
||||
struct pbuf *p, *q = NULL;
|
||||
u16_t i;
|
||||
|
||||
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
|
||||
LWIP_ASSERT("pbuf_init: pool aligned", (mem_ptr_t)pbuf_pool % MEM_ALIGNMENT == 0);
|
||||
|
||||
#if PBUF_STATS
|
||||
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
|
||||
#endif /* PBUF_STATS */
|
||||
|
||||
/* Set up ->next pointers to link the pbufs of the pool together */
|
||||
p = pbuf_pool;
|
||||
|
||||
for(i = 0; i < PBUF_POOL_SIZE; ++i) {
|
||||
p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));
|
||||
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
|
||||
p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));
|
||||
p->flags = PBUF_FLAG_POOL;
|
||||
q = p;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
/* The ->next pointer of last pbuf is NULL to indicate that there
|
||||
are no more pbufs in the pool */
|
||||
q->next = NULL;
|
||||
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
pbuf_pool_alloc_lock = 0;
|
||||
pbuf_pool_free_lock = 0;
|
||||
pbuf_pool_free_sem = sys_sem_new(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal only called from pbuf_alloc()
|
||||
*/
|
||||
static struct pbuf *
|
||||
pbuf_pool_alloc(void)
|
||||
{
|
||||
struct pbuf *p = NULL;
|
||||
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
/* Next, check the actual pbuf pool, but if the pool is locked, we
|
||||
pretend to be out of buffers and return NULL. */
|
||||
if (pbuf_pool_free_lock) {
|
||||
#if PBUF_STATS
|
||||
++lwip_stats.pbuf.alloc_locked;
|
||||
#endif /* PBUF_STATS */
|
||||
return NULL;
|
||||
}
|
||||
pbuf_pool_alloc_lock = 1;
|
||||
if (!pbuf_pool_free_lock) {
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
p = pbuf_pool;
|
||||
if (p) {
|
||||
pbuf_pool = p->next;
|
||||
}
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
#if PBUF_STATS
|
||||
} else {
|
||||
++lwip_stats.pbuf.alloc_locked;
|
||||
#endif /* PBUF_STATS */
|
||||
}
|
||||
pbuf_pool_alloc_lock = 0;
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
#if PBUF_STATS
|
||||
if (p != NULL) {
|
||||
++lwip_stats.pbuf.used;
|
||||
if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) {
|
||||
lwip_stats.pbuf.max = lwip_stats.pbuf.used;
|
||||
}
|
||||
}
|
||||
#endif /* PBUF_STATS */
|
||||
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
|
||||
*
|
||||
* The actual memory allocated for the pbuf is determined by the
|
||||
* layer at which the pbuf is allocated and the requested size
|
||||
* (from the size parameter).
|
||||
*
|
||||
* @param flag this parameter decides how and where the pbuf
|
||||
* should be allocated as follows:
|
||||
*
|
||||
* - PBUF_RAM: buffer memory for pbuf is allocated as one large
|
||||
* chunk. This includes protocol headers as well.
|
||||
* - PBUF_ROM: no buffer memory is allocated for the pbuf, even for
|
||||
* protocol headers. Additional headers must be prepended
|
||||
* by allocating another pbuf and chain in to the front of
|
||||
* the ROM pbuf. It is assumed that the memory used is really
|
||||
* similar to ROM in that it is immutable and will not be
|
||||
* changed. Memory which is dynamic should generally not
|
||||
* be attached to PBUF_ROM pbufs. Use PBUF_REF instead.
|
||||
* - PBUF_REF: no buffer memory is allocated for the pbuf, even for
|
||||
* protocol headers. It is assumed that the pbuf is only
|
||||
* being used in a single thread. If the pbuf gets queued,
|
||||
* then pbuf_take should be called to copy the buffer.
|
||||
* - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from
|
||||
* the pbuf pool that is allocated during pbuf_init().
|
||||
*
|
||||
* @return the allocated pbuf. If multiple pbufs where allocated, this
|
||||
* is the first pbuf of a pbuf chain.
|
||||
*/
|
||||
struct pbuf *
|
||||
pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
||||
{
|
||||
struct pbuf *p, *q, *r;
|
||||
u16_t offset;
|
||||
s32_t rem_len; /* remaining length */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u)\n", length));
|
||||
|
||||
/* determine header offset */
|
||||
offset = 0;
|
||||
switch (l) {
|
||||
case PBUF_TRANSPORT:
|
||||
/* add room for transport (often TCP) layer header */
|
||||
offset += PBUF_TRANSPORT_HLEN;
|
||||
/* FALLTHROUGH */
|
||||
case PBUF_IP:
|
||||
/* add room for IP layer header */
|
||||
offset += PBUF_IP_HLEN;
|
||||
/* FALLTHROUGH */
|
||||
case PBUF_LINK:
|
||||
/* add room for link layer header */
|
||||
offset += PBUF_LINK_HLEN;
|
||||
break;
|
||||
case PBUF_RAW:
|
||||
break;
|
||||
default:
|
||||
LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (flag) {
|
||||
case PBUF_POOL:
|
||||
/* allocate head of pbuf chain into p */
|
||||
p = pbuf_pool_alloc();
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
|
||||
if (p == NULL) {
|
||||
#if PBUF_STATS
|
||||
++lwip_stats.pbuf.err;
|
||||
#endif /* PBUF_STATS */
|
||||
return NULL;
|
||||
}
|
||||
p->next = NULL;
|
||||
|
||||
/* make the payload pointer point 'offset' bytes into pbuf data memory */
|
||||
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
|
||||
LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
|
||||
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
|
||||
/* the total length of the pbuf chain is the requested size */
|
||||
p->tot_len = length;
|
||||
/* set the length of the first pbuf in the chain */
|
||||
p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length;
|
||||
/* set reference count (needed here in case we fail) */
|
||||
p->ref = 1;
|
||||
|
||||
/* now allocate the tail of the pbuf chain */
|
||||
|
||||
/* remember first pbuf for linkage in next iteration */
|
||||
r = p;
|
||||
/* remaining length to be allocated */
|
||||
rem_len = length - p->len;
|
||||
/* any remaining pbufs to be allocated? */
|
||||
while (rem_len > 0) {
|
||||
q = pbuf_pool_alloc();
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));
|
||||
#if PBUF_STATS
|
||||
++lwip_stats.pbuf.err;
|
||||
#endif /* PBUF_STATS */
|
||||
/* free chain so far allocated */
|
||||
pbuf_free(p);
|
||||
/* bail out unsuccesfully */
|
||||
return NULL;
|
||||
}
|
||||
q->next = NULL;
|
||||
/* make previous pbuf point to this pbuf */
|
||||
r->next = q;
|
||||
/* set total length of this pbuf and next in chain */
|
||||
q->tot_len = rem_len;
|
||||
/* this pbuf length is pool size, unless smaller sized tail */
|
||||
q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
|
||||
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
|
||||
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
|
||||
((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
|
||||
q->ref = 1;
|
||||
/* calculate remaining length to be allocated */
|
||||
rem_len -= q->len;
|
||||
/* remember this pbuf for linkage in next iteration */
|
||||
r = q;
|
||||
}
|
||||
/* end of chain */
|
||||
/*r->next = NULL;*/
|
||||
|
||||
break;
|
||||
case PBUF_RAM:
|
||||
/* If pbuf is to be allocated in RAM, allocate memory for it. */
|
||||
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + offset) + MEM_ALIGN_SIZE(length));
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
/* Set up internal structure of the pbuf. */
|
||||
p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));
|
||||
p->len = p->tot_len = length;
|
||||
p->next = NULL;
|
||||
p->flags = PBUF_FLAG_RAM;
|
||||
|
||||
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
|
||||
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
|
||||
break;
|
||||
/* pbuf references existing (non-volatile static constant) ROM payload? */
|
||||
case PBUF_ROM:
|
||||
/* pbuf references existing (externally allocated) RAM payload? */
|
||||
case PBUF_REF:
|
||||
/* only allocate memory for the pbuf structure */
|
||||
p = memp_malloc(MEMP_PBUF);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", flag == PBUF_ROM?"ROM":"REF"));
|
||||
return NULL;
|
||||
}
|
||||
/* caller must set this field properly, afterwards */
|
||||
p->payload = NULL;
|
||||
p->len = p->tot_len = length;
|
||||
p->next = NULL;
|
||||
p->flags = (flag == PBUF_ROM? PBUF_FLAG_ROM: PBUF_FLAG_REF);
|
||||
break;
|
||||
default:
|
||||
LWIP_ASSERT("pbuf_alloc: erroneous flag", 0);
|
||||
return NULL;
|
||||
}
|
||||
/* set reference count */
|
||||
p->ref = 1;
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%u) == %p\n", length, (void *)p));
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
#if PBUF_STATS
|
||||
#define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
|
||||
#else /* PBUF_STATS */
|
||||
#define DEC_PBUF_STATS
|
||||
#endif /* PBUF_STATS */
|
||||
|
||||
#define PBUF_POOL_FAST_FREE(p) do { \
|
||||
p->next = pbuf_pool; \
|
||||
pbuf_pool = p; \
|
||||
DEC_PBUF_STATS; \
|
||||
} while (0)
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
#define PBUF_POOL_FREE(p) do { \
|
||||
SYS_ARCH_DECL_PROTECT(old_level); \
|
||||
SYS_ARCH_PROTECT(old_level); \
|
||||
PBUF_POOL_FAST_FREE(p); \
|
||||
SYS_ARCH_UNPROTECT(old_level); \
|
||||
} while (0)
|
||||
#else /* SYS_LIGHTWEIGHT_PROT */
|
||||
#define PBUF_POOL_FREE(p) do { \
|
||||
sys_sem_wait(pbuf_pool_free_sem); \
|
||||
PBUF_POOL_FAST_FREE(p); \
|
||||
sys_sem_signal(pbuf_pool_free_sem); \
|
||||
} while (0)
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
/**
|
||||
* Shrink a pbuf chain to a desired length.
|
||||
*
|
||||
* @param p pbuf to shrink.
|
||||
* @param new_len desired new length of pbuf chain
|
||||
*
|
||||
* Depending on the desired length, the first few pbufs in a chain might
|
||||
* be skipped and left unchanged. The new last pbuf in the chain will be
|
||||
* resized, and any remaining pbufs will be freed.
|
||||
*
|
||||
* @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.
|
||||
* @note May not be called on a packet queue.
|
||||
*
|
||||
* @bug Cannot grow the size of a pbuf (chain) (yet).
|
||||
*/
|
||||
void
|
||||
pbuf_realloc(struct pbuf *p, u16_t new_len)
|
||||
{
|
||||
struct pbuf *q;
|
||||
u16_t rem_len; /* remaining length */
|
||||
s16_t grow;
|
||||
|
||||
LWIP_ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL ||
|
||||
p->flags == PBUF_FLAG_ROM ||
|
||||
p->flags == PBUF_FLAG_RAM ||
|
||||
p->flags == PBUF_FLAG_REF);
|
||||
|
||||
/* desired length larger than current length? */
|
||||
if (new_len >= p->tot_len) {
|
||||
/* enlarging not yet supported */
|
||||
return;
|
||||
}
|
||||
|
||||
/* the pbuf chain grows by (new_len - p->tot_len) bytes
|
||||
* (which may be negative in case of shrinking) */
|
||||
grow = new_len - p->tot_len;
|
||||
|
||||
/* first, step over any pbufs that should remain in the chain */
|
||||
rem_len = new_len;
|
||||
q = p;
|
||||
/* should this pbuf be kept? */
|
||||
while (rem_len > q->len) {
|
||||
/* decrease remaining length by pbuf length */
|
||||
rem_len -= q->len;
|
||||
/* decrease total length indicator */
|
||||
q->tot_len += grow;
|
||||
/* proceed to next pbuf in chain */
|
||||
q = q->next;
|
||||
}
|
||||
/* we have now reached the new last pbuf (in q) */
|
||||
/* rem_len == desired length for pbuf q */
|
||||
|
||||
/* shrink allocated memory for PBUF_RAM */
|
||||
/* (other types merely adjust their length fields */
|
||||
if ((q->flags == PBUF_FLAG_RAM) && (rem_len != q->len)) {
|
||||
/* reallocate and adjust the length of the pbuf that will be split */
|
||||
mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rem_len);
|
||||
}
|
||||
/* adjust length fields for new last pbuf */
|
||||
q->len = rem_len;
|
||||
q->tot_len = q->len;
|
||||
|
||||
/* any remaining pbufs in chain? */
|
||||
if (q->next != NULL) {
|
||||
/* free remaining pbufs in chain */
|
||||
pbuf_free(q->next);
|
||||
}
|
||||
/* q is last packet in chain */
|
||||
q->next = NULL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the payload pointer to hide or reveal headers in the payload.
|
||||
*
|
||||
* Adjusts the ->payload pointer so that space for a header
|
||||
* (dis)appears in the pbuf payload.
|
||||
*
|
||||
* The ->payload, ->tot_len and ->len fields are adjusted.
|
||||
*
|
||||
* @param hdr_size_inc Number of bytes to increment header size which
|
||||
* increases the size of the pbuf. New space is on the front.
|
||||
* (Using a negative value decreases the header size.)
|
||||
* If hdr_size_inc is 0, this function does nothing and returns succesful.
|
||||
*
|
||||
* PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
|
||||
* the call will fail. A check is made that the increase in header size does
|
||||
* not move the payload pointer in front of the start of the buffer.
|
||||
* @return non-zero on failure, zero on success.
|
||||
*
|
||||
*/
|
||||
u8_t
|
||||
pbuf_header(struct pbuf *p, s16_t header_size_increment)
|
||||
{
|
||||
void *payload;
|
||||
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
if ((header_size_increment == 0) || (p == NULL)) return 0;
|
||||
|
||||
/* remember current payload pointer */
|
||||
payload = p->payload;
|
||||
|
||||
/* pbuf types containing payloads? */
|
||||
if (p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL) {
|
||||
/* set new payload pointer */
|
||||
p->payload = (u8_t *)p->payload - header_size_increment;
|
||||
/* boundary check fails? */
|
||||
if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
|
||||
(void *)p->payload,
|
||||
(void *)(p + 1)));\
|
||||
/* restore old payload pointer */
|
||||
p->payload = payload;
|
||||
/* bail out unsuccesfully */
|
||||
return 1;
|
||||
}
|
||||
/* pbuf types refering to external payloads? */
|
||||
} else if (p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_ROM) {
|
||||
/* hide a header in the payload? */
|
||||
if ((header_size_increment < 0) && (header_size_increment - p->len <= 0)) {
|
||||
/* increase payload pointer */
|
||||
p->payload = (u8_t *)p->payload - header_size_increment;
|
||||
} else {
|
||||
/* cannot expand payload to front (yet!)
|
||||
* bail out unsuccesfully */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* modify pbuf length fields */
|
||||
p->len += header_size_increment;
|
||||
p->tot_len += header_size_increment;
|
||||
|
||||
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%d)\n",
|
||||
(void *)payload, (void *)p->payload, header_size_increment));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereference a pbuf chain or queue and deallocate any no-longer-used
|
||||
* pbufs at the head of this chain or queue.
|
||||
*
|
||||
* Decrements the pbuf reference count. If it reaches zero, the pbuf is
|
||||
* deallocated.
|
||||
*
|
||||
* For a pbuf chain, this is repeated for each pbuf in the chain,
|
||||
* up to the first pbuf which has a non-zero reference count after
|
||||
* decrementing. So, when all reference counts are one, the whole
|
||||
* chain is free'd.
|
||||
*
|
||||
* @param pbuf The pbuf (chain) to be dereferenced.
|
||||
*
|
||||
* @return the number of pbufs that were de-allocated
|
||||
* from the head of the chain.
|
||||
*
|
||||
* @note MUST NOT be called on a packet queue (Not verified to work yet).
|
||||
* @note the reference counter of a pbuf equals the number of pointers
|
||||
* that refer to the pbuf (or into the pbuf).
|
||||
*
|
||||
* @internal examples:
|
||||
*
|
||||
* Assuming existing chains a->b->c with the following reference
|
||||
* counts, calling pbuf_free(a) results in:
|
||||
*
|
||||
* 1->2->3 becomes ...1->3
|
||||
* 3->3->3 becomes 2->3->3
|
||||
* 1->1->2 becomes ......1
|
||||
* 2->1->1 becomes 1->1->1
|
||||
* 1->1->1 becomes .......
|
||||
*
|
||||
*/
|
||||
u8_t
|
||||
pbuf_free(struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q;
|
||||
u8_t count;
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
/* if assertions are disabled, proceed with debug output */
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
|
||||
return 0;
|
||||
}
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_free(%p)\n", (void *)p));
|
||||
|
||||
PERF_START;
|
||||
|
||||
LWIP_ASSERT("pbuf_free: sane flags",
|
||||
p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_ROM ||
|
||||
p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_POOL);
|
||||
|
||||
count = 0;
|
||||
/* Since decrementing ref cannot be guaranteed to be a single machine operation
|
||||
* we must protect it. Also, the later test of ref must be protected.
|
||||
*/
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
/* de-allocate all consecutive pbufs from the head of the chain that
|
||||
* obtain a zero reference count after decrementing*/
|
||||
while (p != NULL) {
|
||||
/* all pbufs in a chain are referenced at least once */
|
||||
LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
|
||||
/* decrease reference count (number of pointers to pbuf) */
|
||||
p->ref--;
|
||||
/* this pbuf is no longer referenced to? */
|
||||
if (p->ref == 0) {
|
||||
/* remember next pbuf in chain for next iteration */
|
||||
q = p->next;
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p));
|
||||
/* is this a pbuf from the pool? */
|
||||
if (p->flags == PBUF_FLAG_POOL) {
|
||||
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
|
||||
p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
|
||||
PBUF_POOL_FREE(p);
|
||||
/* is this a ROM or RAM referencing pbuf? */
|
||||
} else if (p->flags == PBUF_FLAG_ROM || p->flags == PBUF_FLAG_REF) {
|
||||
memp_free(MEMP_PBUF, p);
|
||||
/* p->flags == PBUF_FLAG_RAM */
|
||||
} else {
|
||||
mem_free(p);
|
||||
}
|
||||
count++;
|
||||
/* proceed to next pbuf */
|
||||
p = q;
|
||||
/* p->ref > 0, this pbuf is still referenced to */
|
||||
/* (and so the remaining pbufs in chain as well) */
|
||||
} else {
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %u, ending here.\n", (void *)p, (unsigned int)p->ref));
|
||||
/* stop walking through the chain */
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
PERF_STOP("pbuf_free");
|
||||
/* return number of de-allocated pbufs */
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count number of pbufs in a chain
|
||||
*
|
||||
* @param p first pbuf of chain
|
||||
* @return the number of pbufs in a chain
|
||||
*/
|
||||
|
||||
u8_t
|
||||
pbuf_clen(struct pbuf *p)
|
||||
{
|
||||
u8_t len;
|
||||
|
||||
len = 0;
|
||||
while (p != NULL) {
|
||||
++len;
|
||||
p = p->next;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the reference count of the pbuf.
|
||||
*
|
||||
* @param p pbuf to increase reference counter of
|
||||
*
|
||||
*/
|
||||
void
|
||||
pbuf_ref(struct pbuf *p)
|
||||
{
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
/* pbuf given? */
|
||||
if (p != NULL) {
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
++(p->ref);
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate two pbufs (each may be a pbuf chain) and take over
|
||||
* the caller's reference of the tail pbuf.
|
||||
*
|
||||
* @note The caller MAY NOT reference the tail pbuf afterwards.
|
||||
* Use pbuf_chain() for that purpose.
|
||||
*
|
||||
* @see pbuf_chain()
|
||||
*/
|
||||
|
||||
void
|
||||
pbuf_cat(struct pbuf *h, struct pbuf *t)
|
||||
{
|
||||
struct pbuf *p;
|
||||
|
||||
LWIP_ASSERT("h != NULL (programmer violates API)", h != NULL);
|
||||
LWIP_ASSERT("t != NULL (programmer violates API)", t != NULL);
|
||||
if ((h == NULL) || (t == NULL)) return;
|
||||
|
||||
/* proceed to last pbuf of chain */
|
||||
for (p = h; p->next != NULL; p = p->next) {
|
||||
/* add total length of second chain to all totals of first chain */
|
||||
p->tot_len += t->tot_len;
|
||||
}
|
||||
/* { p is last pbuf of first h chain, p->next == NULL } */
|
||||
LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
|
||||
LWIP_ASSERT("p->next == NULL", p->next == NULL);
|
||||
/* add total length of second chain to last pbuf total of first chain */
|
||||
p->tot_len += t->tot_len;
|
||||
/* chain last pbuf of head (p) with first of tail (t) */
|
||||
p->next = t;
|
||||
/* p->next now references t, but the caller will drop its reference to t,
|
||||
* so netto there is no change to the reference count of t.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Chain two pbufs (or pbuf chains) together.
|
||||
*
|
||||
* The caller MUST call pbuf_free(t) once it has stopped
|
||||
* using it. Use pbuf_cat() instead if you no longer use t.
|
||||
*
|
||||
* @param h head pbuf (chain)
|
||||
* @param t tail pbuf (chain)
|
||||
* @note The pbufs MUST belong to the same packet.
|
||||
* @note MAY NOT be called on a packet queue.
|
||||
*
|
||||
* The ->tot_len fields of all pbufs of the head chain are adjusted.
|
||||
* The ->next field of the last pbuf of the head chain is adjusted.
|
||||
* The ->ref field of the first pbuf of the tail chain is adjusted.
|
||||
*
|
||||
*/
|
||||
void
|
||||
pbuf_chain(struct pbuf *h, struct pbuf *t)
|
||||
{
|
||||
pbuf_cat(h, t);
|
||||
/* t is now referenced by h */
|
||||
pbuf_ref(t);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
|
||||
}
|
||||
|
||||
/* For packet queueing. Note that queued packets MUST be dequeued first
|
||||
* using pbuf_dequeue() before calling other pbuf_() functions. */
|
||||
#if ARP_QUEUEING
|
||||
/**
|
||||
* Add a packet to the end of a queue.
|
||||
*
|
||||
* @param q pointer to first packet on the queue
|
||||
* @param n packet to be queued
|
||||
*
|
||||
* Both packets MUST be given, and must be different.
|
||||
*/
|
||||
void
|
||||
pbuf_queue(struct pbuf *p, struct pbuf *n)
|
||||
{
|
||||
#if PBUF_DEBUG /* remember head of queue */
|
||||
struct pbuf *q = p;
|
||||
#endif
|
||||
/* programmer stupidity checks */
|
||||
LWIP_ASSERT("p == NULL in pbuf_queue: this indicates a programmer error\n", p != NULL);
|
||||
LWIP_ASSERT("n == NULL in pbuf_queue: this indicates a programmer error\n", n != NULL);
|
||||
LWIP_ASSERT("p == n in pbuf_queue: this indicates a programmer error\n", p != n);
|
||||
if ((p == NULL) || (n == NULL) || (p == n)){
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_HALT | 3, ("pbuf_queue: programmer argument error\n"))
|
||||
return;
|
||||
}
|
||||
|
||||
/* iterate through all packets on queue */
|
||||
while (p->next != NULL) {
|
||||
/* be very picky about pbuf chain correctness */
|
||||
#if PBUF_DEBUG
|
||||
/* iterate through all pbufs in packet */
|
||||
while (p->tot_len != p->len) {
|
||||
/* make sure invariant condition holds */
|
||||
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
|
||||
/* make sure each packet is complete */
|
||||
LWIP_ASSERT("p->next != NULL", p->next != NULL);
|
||||
p = p->next;
|
||||
/* { p->tot_len == p->len => p is last pbuf of a packet } */
|
||||
}
|
||||
/* { p is last pbuf of a packet } */
|
||||
/* proceed to next packet on queue */
|
||||
#endif
|
||||
/* proceed to next pbuf */
|
||||
if (p->next != NULL) p = p->next;
|
||||
}
|
||||
/* { p->tot_len == p->len and p->next == NULL } ==>
|
||||
* { p is last pbuf of last packet on queue } */
|
||||
/* chain last pbuf of queue with n */
|
||||
p->next = n;
|
||||
/* n is now referenced to by the (packet p in the) queue */
|
||||
pbuf_ref(n);
|
||||
#if PBUF_DEBUG
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2,
|
||||
("pbuf_queue: newly queued packet %p sits after packet %p in queue %p\n",
|
||||
(void *)n, (void *)p, (void *)q));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a packet from the head of a queue.
|
||||
*
|
||||
* The caller MUST reference the remainder of the queue (as returned). The
|
||||
* caller MUST NOT call pbuf_ref() as it implicitly takes over the reference
|
||||
* from p.
|
||||
*
|
||||
* @param p pointer to first packet on the queue which will be dequeued.
|
||||
* @return first packet on the remaining queue (NULL if no further packets).
|
||||
*
|
||||
*/
|
||||
struct pbuf *
|
||||
pbuf_dequeue(struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q;
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
|
||||
/* iterate through all pbufs in packet p */
|
||||
while (p->tot_len != p->len) {
|
||||
/* make sure invariant condition holds */
|
||||
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
|
||||
/* make sure each packet is complete */
|
||||
LWIP_ASSERT("p->next != NULL", p->next != NULL);
|
||||
p = p->next;
|
||||
}
|
||||
/* { p->tot_len == p->len } => p is the last pbuf of the first packet */
|
||||
/* remember next packet on queue in q */
|
||||
q = p->next;
|
||||
/* dequeue packet p from queue */
|
||||
p->next = NULL;
|
||||
/* any next packet on queue? */
|
||||
if (q != NULL) {
|
||||
/* although q is no longer referenced by p, it MUST be referenced by
|
||||
* the caller, who is maintaining this packet queue. So, we do not call
|
||||
* pbuf_free(q) here, resulting in an implicit pbuf_ref(q) for the caller. */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: first remaining packet on queue is %p\n", (void *)q));
|
||||
} else {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: no further packets on queue\n"));
|
||||
}
|
||||
return q;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* Create PBUF_POOL (or PBUF_RAM) copies of PBUF_REF pbufs.
|
||||
*
|
||||
* Used to queue packets on behalf of the lwIP stack, such as
|
||||
* ARP based queueing.
|
||||
*
|
||||
* Go through a pbuf chain and replace any PBUF_REF buffers
|
||||
* with PBUF_POOL (or PBUF_RAM) pbufs, each taking a copy of
|
||||
* the referenced data.
|
||||
*
|
||||
* @note You MUST explicitly use p = pbuf_take(p);
|
||||
* The pbuf you give as argument, may have been replaced
|
||||
* by a (differently located) copy through pbuf_take()!
|
||||
*
|
||||
* @note Any replaced pbufs will be freed through pbuf_free().
|
||||
* This may deallocate them if they become no longer referenced.
|
||||
*
|
||||
* @param p Head of pbuf chain to process
|
||||
*
|
||||
* @return Pointer to head of pbuf chain
|
||||
*/
|
||||
struct pbuf *
|
||||
pbuf_take(struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q , *prev, *head;
|
||||
LWIP_ASSERT("pbuf_take: p != NULL\n", p != NULL);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_take(%p)\n", (void*)p));
|
||||
|
||||
prev = NULL;
|
||||
head = p;
|
||||
/* iterate through pbuf chain */
|
||||
do
|
||||
{
|
||||
/* pbuf is of type PBUF_REF? */
|
||||
if (p->flags == PBUF_FLAG_REF) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE, ("pbuf_take: encountered PBUF_REF %p\n", (void *)p));
|
||||
/* allocate a pbuf (w/ payload) fully in RAM */
|
||||
/* PBUF_POOL buffers are faster if we can use them */
|
||||
if (p->len <= PBUF_POOL_BUFSIZE) {
|
||||
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
|
||||
}
|
||||
} else {
|
||||
/* no replacement pbuf yet */
|
||||
q = NULL;
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: PBUF_POOL too small to replace PBUF_REF\n"));
|
||||
}
|
||||
/* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
|
||||
if (q == NULL) {
|
||||
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));
|
||||
}
|
||||
}
|
||||
/* replacement pbuf could be allocated? */
|
||||
if (q != NULL)
|
||||
{
|
||||
/* copy p to q */
|
||||
/* copy successor */
|
||||
q->next = p->next;
|
||||
/* remove linkage from original pbuf */
|
||||
p->next = NULL;
|
||||
/* remove linkage to original pbuf */
|
||||
if (prev != NULL) {
|
||||
/* prev->next == p at this point */
|
||||
LWIP_ASSERT("prev->next == p", prev->next == p);
|
||||
/* break chain and insert new pbuf instead */
|
||||
prev->next = q;
|
||||
/* prev == NULL, so we replaced the head pbuf of the chain */
|
||||
} else {
|
||||
head = q;
|
||||
}
|
||||
/* copy pbuf payload */
|
||||
memcpy(q->payload, p->payload, p->len);
|
||||
q->tot_len = p->tot_len;
|
||||
q->len = p->len;
|
||||
/* in case p was the first pbuf, it is no longer refered to by
|
||||
* our caller, as the caller MUST do p = pbuf_take(p);
|
||||
* in case p was not the first pbuf, it is no longer refered to
|
||||
* by prev. we can safely free the pbuf here.
|
||||
* (note that we have set p->next to NULL already so that
|
||||
* we will not free the rest of the chain by accident.)
|
||||
*/
|
||||
pbuf_free(p);
|
||||
/* do not copy ref, since someone else might be using the old buffer */
|
||||
LWIP_DEBUGF(PBUF_DEBUG, ("pbuf_take: replaced PBUF_REF %p with %p\n", (void *)p, (void *)q));
|
||||
p = q;
|
||||
} else {
|
||||
/* deallocate chain */
|
||||
pbuf_free(head);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_take: failed to allocate replacement pbuf for %p\n", (void *)p));
|
||||
return NULL;
|
||||
}
|
||||
/* p->flags != PBUF_FLAG_REF */
|
||||
} else {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: skipping pbuf not of type PBUF_REF\n"));
|
||||
}
|
||||
/* remember this pbuf */
|
||||
prev = p;
|
||||
/* proceed to next pbuf in original chain */
|
||||
p = p->next;
|
||||
} while (p);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: end of chain reached.\n"));
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dechains the first pbuf from its succeeding pbufs in the chain.
|
||||
*
|
||||
* Makes p->tot_len field equal to p->len.
|
||||
* @param p pbuf to dechain
|
||||
* @return remainder of the pbuf chain, or NULL if it was de-allocated.
|
||||
* @note May not be called on a packet queue.
|
||||
*/
|
||||
struct pbuf *
|
||||
pbuf_dechain(struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q;
|
||||
u8_t tail_gone = 1;
|
||||
/* tail */
|
||||
q = p->next;
|
||||
/* pbuf has successor in chain? */
|
||||
if (q != NULL) {
|
||||
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
|
||||
LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);
|
||||
/* enforce invariant if assertion is disabled */
|
||||
q->tot_len = p->tot_len - p->len;
|
||||
/* decouple pbuf from remainder */
|
||||
p->next = NULL;
|
||||
/* total length of pbuf p is its own length only */
|
||||
p->tot_len = p->len;
|
||||
/* q is no longer referenced by p, free it */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
|
||||
tail_gone = pbuf_free(q);
|
||||
if (tail_gone > 0) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
|
||||
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
|
||||
}
|
||||
/* return remaining tail or NULL if deallocated */
|
||||
}
|
||||
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
|
||||
LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
|
||||
return (tail_gone > 0? NULL: q);
|
||||
}
|
||||
|
|
@ -0,0 +1,328 @@
|
|||
/**
|
||||
* @file
|
||||
*
|
||||
* Implementation of raw protocol PCBs for low-level handling of
|
||||
* different types of protocols besides (or overriding) those
|
||||
* already available in lwIP.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/raw.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "arch/perf.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#if LWIP_RAW
|
||||
|
||||
/** The list of RAW PCBs */
|
||||
static struct raw_pcb *raw_pcbs = NULL;
|
||||
|
||||
void
|
||||
raw_init(void)
|
||||
{
|
||||
raw_pcbs = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if in incoming IP packet is covered by a RAW PCB
|
||||
* and if so, pass it to a user-provided receive callback function.
|
||||
*
|
||||
* Given an incoming IP datagram (as a chain of pbufs) this function
|
||||
* finds a corresponding RAW PCB and calls the corresponding receive
|
||||
* callback function.
|
||||
*
|
||||
* @param pbuf pbuf to be demultiplexed to a RAW PCB.
|
||||
* @param netif network interface on which the datagram was received.
|
||||
* @Return - 1 if the packet has been eaten by a RAW PCB receive
|
||||
* callback function. The caller MAY NOT not reference the
|
||||
* packet any longer, and MAY NOT call pbuf_free().
|
||||
* @return - 0 if packet is not eaten (pbuf is still referenced by the
|
||||
* caller).
|
||||
*
|
||||
*/
|
||||
u8_t
|
||||
raw_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct raw_pcb *pcb;
|
||||
struct ip_hdr *iphdr;
|
||||
int proto;
|
||||
u8_t eaten = 0;
|
||||
|
||||
( void ) inp;
|
||||
|
||||
iphdr = p->payload;
|
||||
proto = IPH_PROTO(iphdr);
|
||||
|
||||
pcb = raw_pcbs;
|
||||
/* loop through all raw pcbs until the packet is eaten by one */
|
||||
/* this allows multiple pcbs to match against the packet by design */
|
||||
while ((eaten == 0) && (pcb != NULL)) {
|
||||
if (pcb->protocol == proto) {
|
||||
/* receive callback function available? */
|
||||
if (pcb->recv != NULL) {
|
||||
/* the receive callback function did not eat the packet? */
|
||||
if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0)
|
||||
{
|
||||
/* receive function ate the packet */
|
||||
p = NULL;
|
||||
eaten = 1;
|
||||
}
|
||||
}
|
||||
/* no receive callback function was set for this raw PCB */
|
||||
/* drop the packet */
|
||||
}
|
||||
pcb = pcb->next;
|
||||
}
|
||||
return eaten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind a RAW PCB.
|
||||
*
|
||||
* @param pcb RAW PCB to be bound with a local address ipaddr.
|
||||
* @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
|
||||
* bind to all local interfaces.
|
||||
*
|
||||
* @return lwIP error code.
|
||||
* - ERR_OK. Successful. No error occured.
|
||||
* - ERR_USE. The specified IP address is already bound to by
|
||||
* another RAW PCB.
|
||||
*
|
||||
* @see raw_disconnect()
|
||||
*/
|
||||
err_t
|
||||
raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
||||
{
|
||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect an RAW PCB. This function is required by upper layers
|
||||
* of lwip. Using the raw api you could use raw_sendto() instead
|
||||
*
|
||||
* This will associate the RAW PCB with the remote address.
|
||||
*
|
||||
* @param pcb RAW PCB to be connected with remote address ipaddr and port.
|
||||
* @param ipaddr remote IP address to connect with.
|
||||
*
|
||||
* @return lwIP error code
|
||||
*
|
||||
* @see raw_disconnect() and raw_sendto()
|
||||
*/
|
||||
err_t
|
||||
raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
||||
{
|
||||
ip_addr_set(&pcb->remote_ip, ipaddr);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the callback function for received packets that match the
|
||||
* raw PCB's protocol and binding.
|
||||
*
|
||||
* The callback function MUST either
|
||||
* - eat the packet by calling pbuf_free() and returning non-zero. The
|
||||
* packet will not be passed to other raw PCBs or other protocol layers.
|
||||
* - not free the packet, and return zero. The packet will be matched
|
||||
* against further PCBs and/or forwarded to another protocol layers.
|
||||
*
|
||||
* @return non-zero if the packet was free()d, zero if the packet remains
|
||||
* available for others.
|
||||
*/
|
||||
void
|
||||
raw_recv(struct raw_pcb *pcb,
|
||||
u8_t (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
|
||||
struct ip_addr *addr),
|
||||
void *recv_arg)
|
||||
{
|
||||
/* remember recv() callback and user data */
|
||||
pcb->recv = recv;
|
||||
pcb->recv_arg = recv_arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the raw IP packet to the given address. Note that actually you cannot
|
||||
* modify the IP headers (this is inconsistent with the receive callback where
|
||||
* you actually get the IP headers), you can only specify the IP payload here.
|
||||
* It requires some more changes in lwIP. (there will be a raw_send() function
|
||||
* then.)
|
||||
*
|
||||
* @param pcb the raw pcb which to send
|
||||
* @param p the IP payload to send
|
||||
* @param ipaddr the destination address of the IP packet
|
||||
*
|
||||
*/
|
||||
err_t
|
||||
raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
{
|
||||
err_t err;
|
||||
struct netif *netif;
|
||||
struct ip_addr *src_ip;
|
||||
struct pbuf *q; /* q will be sent down the stack */
|
||||
|
||||
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_sendto\n"));
|
||||
|
||||
/* not enough space to add an IP header to first pbuf in given p chain? */
|
||||
if (pbuf_header(p, IP_HLEN)) {
|
||||
/* allocate header in new pbuf */
|
||||
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
|
||||
/* new header pbuf could not be allocated? */
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_sendto: could not allocate header\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* chain header q in front of given pbuf p */
|
||||
pbuf_chain(q, p);
|
||||
/* { first pbuf q points to header pbuf } */
|
||||
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||
} else {
|
||||
/* first pbuf q equals given pbuf */
|
||||
q = p;
|
||||
pbuf_header(q, -IP_HLEN);
|
||||
}
|
||||
|
||||
if ((netif = ip_route(ipaddr)) == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%lx\n", ipaddr->addr));
|
||||
#if RAW_STATS
|
||||
/* ++lwip_stats.raw.rterr;*/
|
||||
#endif /* RAW_STATS */
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
}
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
if (ip_addr_isany(&pcb->local_ip)) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
src_ip = &(netif->ip_addr);
|
||||
} else {
|
||||
/* use RAW PCB local IP address as source address */
|
||||
src_ip = &(pcb->local_ip);
|
||||
}
|
||||
|
||||
err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||
|
||||
/* did we chain a header earlier? */
|
||||
if (q != p) {
|
||||
/* free the header */
|
||||
pbuf_free(q);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the raw IP packet to the address given by raw_connect()
|
||||
*
|
||||
* @param pcb the raw pcb which to send
|
||||
* @param p the IP payload to send
|
||||
* @param ipaddr the destination address of the IP packet
|
||||
*
|
||||
*/
|
||||
err_t
|
||||
raw_send(struct raw_pcb *pcb, struct pbuf *p)
|
||||
{
|
||||
return raw_sendto(pcb, p, &pcb->remote_ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an RAW PCB.
|
||||
*
|
||||
* @param pcb RAW PCB to be removed. The PCB is removed from the list of
|
||||
* RAW PCB's and the data structure is freed from memory.
|
||||
*
|
||||
* @see raw_new()
|
||||
*/
|
||||
void
|
||||
raw_remove(struct raw_pcb *pcb)
|
||||
{
|
||||
struct raw_pcb *pcb2;
|
||||
/* pcb to be removed is first in list? */
|
||||
if (raw_pcbs == pcb) {
|
||||
/* make list start at 2nd pcb */
|
||||
raw_pcbs = raw_pcbs->next;
|
||||
/* pcb not 1st in list */
|
||||
} else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
|
||||
/* find pcb in raw_pcbs list */
|
||||
if (pcb2->next != NULL && pcb2->next == pcb) {
|
||||
/* remove pcb from list */
|
||||
pcb2->next = pcb->next;
|
||||
}
|
||||
}
|
||||
memp_free(MEMP_RAW_PCB, pcb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a RAW PCB.
|
||||
*
|
||||
* @return The RAW PCB which was created. NULL if the PCB data structure
|
||||
* could not be allocated.
|
||||
*
|
||||
* @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP)
|
||||
*
|
||||
* @see raw_remove()
|
||||
*/
|
||||
struct raw_pcb *
|
||||
raw_new(u16_t proto) {
|
||||
struct raw_pcb *pcb;
|
||||
|
||||
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_new\n"));
|
||||
|
||||
pcb = memp_malloc(MEMP_RAW_PCB);
|
||||
/* could allocate RAW PCB? */
|
||||
if (pcb != NULL) {
|
||||
/* initialize PCB to all zeroes */
|
||||
memset(pcb, 0, sizeof(struct raw_pcb));
|
||||
pcb->protocol = proto;
|
||||
pcb->ttl = RAW_TTL;
|
||||
pcb->next = raw_pcbs;
|
||||
raw_pcbs = pcb;
|
||||
}
|
||||
return pcb;
|
||||
}
|
||||
|
||||
#endif /* LWIP_RAW */
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/mem.h"
|
||||
|
||||
|
||||
#if LWIP_STATS
|
||||
struct stats_ lwip_stats;
|
||||
|
||||
void
|
||||
stats_init(void)
|
||||
{
|
||||
memset(&lwip_stats, 0, sizeof(struct stats_));
|
||||
}
|
||||
#if LWIP_STATS_DISPLAY
|
||||
void
|
||||
stats_display_proto(struct stats_proto *proto, char *name)
|
||||
{
|
||||
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
||||
LWIP_PLATFORM_DIAG(("xmit: %d\n\t", proto->xmit));
|
||||
LWIP_PLATFORM_DIAG(("rexmit: %d\n\t", proto->rexmit));
|
||||
LWIP_PLATFORM_DIAG(("recv: %d\n\t", proto->recv));
|
||||
LWIP_PLATFORM_DIAG(("fw: %d\n\t", proto->fw));
|
||||
LWIP_PLATFORM_DIAG(("drop: %d\n\t", proto->drop));
|
||||
LWIP_PLATFORM_DIAG(("chkerr: %d\n\t", proto->chkerr));
|
||||
LWIP_PLATFORM_DIAG(("lenerr: %d\n\t", proto->lenerr));
|
||||
LWIP_PLATFORM_DIAG(("memerr: %d\n\t", proto->memerr));
|
||||
LWIP_PLATFORM_DIAG(("rterr: %d\n\t", proto->rterr));
|
||||
LWIP_PLATFORM_DIAG(("proterr: %d\n\t", proto->proterr));
|
||||
LWIP_PLATFORM_DIAG(("opterr: %d\n\t", proto->opterr));
|
||||
LWIP_PLATFORM_DIAG(("err: %d\n\t", proto->err));
|
||||
LWIP_PLATFORM_DIAG(("cachehit: %d\n", proto->cachehit));
|
||||
}
|
||||
|
||||
void
|
||||
stats_display_pbuf(struct stats_pbuf *pbuf)
|
||||
{
|
||||
LWIP_PLATFORM_DIAG(("\nPBUF\n\t"));
|
||||
LWIP_PLATFORM_DIAG(("avail: %d\n\t", pbuf->avail));
|
||||
LWIP_PLATFORM_DIAG(("used: %d\n\t", pbuf->used));
|
||||
LWIP_PLATFORM_DIAG(("max: %d\n\t", pbuf->max));
|
||||
LWIP_PLATFORM_DIAG(("err: %d\n\t", pbuf->err));
|
||||
LWIP_PLATFORM_DIAG(("alloc_locked: %d\n\t", pbuf->alloc_locked));
|
||||
LWIP_PLATFORM_DIAG(("refresh_locked: %d\n", pbuf->refresh_locked));
|
||||
}
|
||||
|
||||
void
|
||||
stats_display_mem(struct stats_mem *mem, char *name)
|
||||
{
|
||||
LWIP_PLATFORM_DIAG(("\n MEM %s\n\t", name));
|
||||
LWIP_PLATFORM_DIAG(("avail: %d\n\t", mem->avail));
|
||||
LWIP_PLATFORM_DIAG(("used: %d\n\t", mem->used));
|
||||
LWIP_PLATFORM_DIAG(("max: %d\n\t", mem->max));
|
||||
LWIP_PLATFORM_DIAG(("err: %d\n", mem->err));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
stats_display(void)
|
||||
{
|
||||
int i;
|
||||
char * memp_names[] = {"PBUF", "RAW_PCB", "UDP_PCB", "TCP_PCB", "TCP_PCB_LISTEN",
|
||||
"TCP_SEG", "NETBUF", "NETCONN", "API_MSG", "TCP_MSG", "TIMEOUT"};
|
||||
stats_display_proto(&lwip_stats.link, "LINK");
|
||||
stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG");
|
||||
stats_display_proto(&lwip_stats.ip, "IP");
|
||||
stats_display_proto(&lwip_stats.icmp, "ICMP");
|
||||
stats_display_proto(&lwip_stats.udp, "UDP");
|
||||
stats_display_proto(&lwip_stats.tcp, "TCP");
|
||||
stats_display_pbuf(&lwip_stats.pbuf);
|
||||
stats_display_mem(&lwip_stats.mem, "HEAP");
|
||||
for (i = 0; i < MEMP_MAX; i++) {
|
||||
stats_display_mem(&lwip_stats.memp[i], memp_names[i]);
|
||||
}
|
||||
|
||||
}
|
||||
#endif /* LWIP_STATS_DISPLAY */
|
||||
#endif /* LWIP_STATS */
|
||||
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
|
||||
#if (NO_SYS == 0)
|
||||
|
||||
struct sswt_cb
|
||||
{
|
||||
int timeflag;
|
||||
sys_sem_t *psem;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void
|
||||
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
|
||||
{
|
||||
u32_t time;
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeout *tmptimeout;
|
||||
sys_timeout_handler h;
|
||||
void *arg;
|
||||
|
||||
|
||||
again:
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
if (!timeouts || !timeouts->next) {
|
||||
sys_arch_mbox_fetch(mbox, msg, 0);
|
||||
} else {
|
||||
if (timeouts->next->time > 0) {
|
||||
time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
|
||||
} else {
|
||||
time = SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
if (time == SYS_ARCH_TIMEOUT) {
|
||||
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
|
||||
could be fetched. We should now call the timeout handler and
|
||||
deallocate the memory allocated for the timeout. */
|
||||
tmptimeout = timeouts->next;
|
||||
timeouts->next = tmptimeout->next;
|
||||
h = tmptimeout->h;
|
||||
arg = tmptimeout->arg;
|
||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
||||
if (h != NULL) {
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", (void *)h, (void *)arg));
|
||||
h(arg);
|
||||
}
|
||||
|
||||
/* We try again to fetch a message from the mbox. */
|
||||
goto again;
|
||||
} else {
|
||||
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
|
||||
occured. The time variable is set to the number of
|
||||
milliseconds we waited for the message. */
|
||||
if (time <= timeouts->next->time) {
|
||||
timeouts->next->time -= time;
|
||||
} else {
|
||||
timeouts->next->time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sys_sem_wait(sys_sem_t sem)
|
||||
{
|
||||
u32_t time;
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeout *tmptimeout;
|
||||
sys_timeout_handler h;
|
||||
void *arg;
|
||||
|
||||
/* while (sys_arch_sem_wait(sem, 1000) == 0);
|
||||
return;*/
|
||||
|
||||
again:
|
||||
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
if (!timeouts || !timeouts->next) {
|
||||
sys_arch_sem_wait(sem, 0);
|
||||
} else {
|
||||
if (timeouts->next->time > 0) {
|
||||
time = sys_arch_sem_wait(sem, timeouts->next->time);
|
||||
} else {
|
||||
time = SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
if (time == SYS_ARCH_TIMEOUT) {
|
||||
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
|
||||
could be fetched. We should now call the timeout handler and
|
||||
deallocate the memory allocated for the timeout. */
|
||||
tmptimeout = timeouts->next;
|
||||
timeouts->next = tmptimeout->next;
|
||||
h = tmptimeout->h;
|
||||
arg = tmptimeout->arg;
|
||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
||||
if (h != NULL) {
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", (void *)h, (void *)arg));
|
||||
h(arg);
|
||||
}
|
||||
|
||||
|
||||
/* We try again to fetch a message from the mbox. */
|
||||
goto again;
|
||||
} else {
|
||||
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
|
||||
occured. The time variable is set to the number of
|
||||
milliseconds we waited for the message. */
|
||||
if (time <= timeouts->next->time) {
|
||||
timeouts->next->time -= time;
|
||||
} else {
|
||||
timeouts->next->time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
||||
{
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeout *timeout, *t;
|
||||
|
||||
timeout = memp_malloc(MEMP_SYS_TIMEOUT);
|
||||
if (timeout == NULL) {
|
||||
return;
|
||||
}
|
||||
timeout->next = NULL;
|
||||
timeout->h = h;
|
||||
timeout->arg = arg;
|
||||
timeout->time = msecs;
|
||||
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%lu h=%p arg=%p\n",
|
||||
(void *)timeout, msecs, (void *)h, (void *)arg));
|
||||
|
||||
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
|
||||
|
||||
if (timeouts->next == NULL) {
|
||||
timeouts->next = timeout;
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeouts->next->time > msecs) {
|
||||
timeouts->next->time -= msecs;
|
||||
timeout->next = timeouts->next;
|
||||
timeouts->next = timeout;
|
||||
} else {
|
||||
for(t = timeouts->next; t != NULL; t = t->next) {
|
||||
timeout->time -= t->time;
|
||||
if (t->next == NULL || t->next->time > timeout->time) {
|
||||
if (t->next != NULL) {
|
||||
t->next->time -= timeout->time;
|
||||
}
|
||||
timeout->next = t->next;
|
||||
t->next = timeout;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Go through timeout list (for this task only) and remove the first matching entry,
|
||||
even though the timeout has not triggered yet.
|
||||
*/
|
||||
|
||||
void
|
||||
sys_untimeout(sys_timeout_handler h, void *arg)
|
||||
{
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeout *prev_t, *t;
|
||||
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
if (timeouts->next == NULL)
|
||||
return;
|
||||
|
||||
for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next)
|
||||
{
|
||||
if ((t->h == h) && (t->arg == arg))
|
||||
{
|
||||
/* We have a match */
|
||||
/* Unlink from previous in list */
|
||||
if (prev_t == NULL)
|
||||
timeouts->next = t->next;
|
||||
else
|
||||
prev_t->next = t->next;
|
||||
/* If not the last one, add time of this one back to next */
|
||||
if (t->next != NULL)
|
||||
t->next->time += t->time;
|
||||
memp_free(MEMP_SYS_TIMEOUT, t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
sswt_handler(void *arg)
|
||||
{
|
||||
struct sswt_cb *sswt_cb = (struct sswt_cb *) arg;
|
||||
|
||||
/* Timeout. Set flag to TRUE and signal semaphore */
|
||||
sswt_cb->timeflag = 1;
|
||||
sys_sem_signal(*(sswt_cb->psem));
|
||||
}
|
||||
|
||||
/* Wait for a semaphore with timeout (specified in ms) */
|
||||
/* timeout = 0: wait forever */
|
||||
/* Returns 0 on timeout. 1 otherwise */
|
||||
|
||||
int
|
||||
sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
|
||||
{
|
||||
struct sswt_cb sswt_cb;
|
||||
|
||||
sswt_cb.psem = &sem;
|
||||
sswt_cb.timeflag = 0;
|
||||
|
||||
/* If timeout is zero, then just wait forever */
|
||||
if (timeout > 0)
|
||||
/* Create a timer and pass it the address of our flag */
|
||||
sys_timeout(timeout, sswt_handler, &sswt_cb);
|
||||
sys_sem_wait(sem);
|
||||
/* Was it a timeout? */
|
||||
if (sswt_cb.timeflag)
|
||||
{
|
||||
/* timeout */
|
||||
return 0;
|
||||
} else {
|
||||
/* Not a timeout. Remove timeout entry */
|
||||
sys_untimeout(sswt_handler, &sswt_cb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sys_msleep(u32_t ms)
|
||||
{
|
||||
sys_sem_t delaysem = sys_sem_new(0);
|
||||
|
||||
sys_sem_wait_timeout(delaysem, ms);
|
||||
|
||||
sys_sem_free(delaysem);
|
||||
}
|
||||
|
||||
|
||||
#endif /* NO_SYS */
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,724 @@
|
|||
/**
|
||||
* @file
|
||||
*
|
||||
* Transmission Control Protocol, outgoing traffic
|
||||
*
|
||||
* The output functions of TCP.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if LWIP_TCP
|
||||
|
||||
/* Forward declarations.*/
|
||||
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
|
||||
|
||||
err_t
|
||||
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
|
||||
{
|
||||
/* no data, no length, flags, copy=1, no optdata, no optdatalen */
|
||||
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data for sending (but does not send it immediately).
|
||||
*
|
||||
* It waits in the expectation of more data being sent soon (as
|
||||
* it can send them more efficiently by combining them together).
|
||||
* To prompt the system to send data now, call tcp_output() after
|
||||
* calling tcp_write().
|
||||
*
|
||||
* @arg pcb Protocol control block of the TCP connection to enqueue data for.
|
||||
*
|
||||
* @see tcp_write()
|
||||
*/
|
||||
|
||||
err_t
|
||||
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
|
||||
{
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb,
|
||||
arg, len, (unsigned int)copy));
|
||||
/* connection is in valid state for data transmission? */
|
||||
if (pcb->state == ESTABLISHED ||
|
||||
pcb->state == CLOSE_WAIT ||
|
||||
pcb->state == SYN_SENT ||
|
||||
pcb->state == SYN_RCVD) {
|
||||
if (len > 0) {
|
||||
return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
|
||||
}
|
||||
return ERR_OK;
|
||||
} else {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
|
||||
return ERR_CONN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue either data or TCP options (but not both) for tranmission
|
||||
*
|
||||
*
|
||||
*
|
||||
* @arg pcb Protocol control block for the TCP connection to enqueue data for.
|
||||
* @arg arg Pointer to the data to be enqueued for sending.
|
||||
* @arg len Data length in bytes
|
||||
* @arg flags
|
||||
* @arg copy 1 if data must be copied, 0 if data is non-volatile and can be
|
||||
* referenced.
|
||||
* @arg optdata
|
||||
* @arg optlen
|
||||
*/
|
||||
err_t
|
||||
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
u8_t flags, u8_t copy,
|
||||
u8_t *optdata, u8_t optlen)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_seg *seg, *useg, *queue=NULL;
|
||||
u32_t left, seqno;
|
||||
u16_t seglen;
|
||||
void *ptr;
|
||||
u8_t queuelen;
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%u, flags=%x, copy=%u)\n",
|
||||
(void *)pcb, arg, len, (unsigned int)flags, (unsigned int)copy));
|
||||
LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
|
||||
len == 0 || optlen == 0);
|
||||
LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
|
||||
arg == NULL || optdata == NULL);
|
||||
/* fail on too much data */
|
||||
if (len > pcb->snd_buf) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%u > snd_buf=%u)\n", len, pcb->snd_buf));
|
||||
return ERR_MEM;
|
||||
}
|
||||
left = len;
|
||||
ptr = arg;
|
||||
|
||||
/* seqno will be the sequence number of the first segment enqueued
|
||||
* by the call to this function. */
|
||||
seqno = pcb->snd_lbb;
|
||||
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %u\n", (unsigned int)pcb->snd_queuelen));
|
||||
|
||||
/* If total number of pbufs on the unsent/unacked queues exceeds the
|
||||
* configured maximum, return an error */
|
||||
queuelen = pcb->snd_queuelen;
|
||||
if (queuelen >= TCP_SND_QUEUELEN) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %u (max %u)\n", queuelen, TCP_SND_QUEUELEN));
|
||||
goto memerr;
|
||||
}
|
||||
if (queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
|
||||
pcb->unacked != NULL || pcb->unsent != NULL);
|
||||
} else {
|
||||
LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
|
||||
pcb->unacked == NULL && pcb->unsent == NULL);
|
||||
}
|
||||
|
||||
/* First, break up the data into segments and tuck them together in
|
||||
* the local "queue" variable. */
|
||||
useg = NULL;
|
||||
queue = NULL;
|
||||
seg = NULL;
|
||||
seglen = 0;
|
||||
while (queue == NULL || left > 0) {
|
||||
|
||||
/* The segment length should be the MSS if the data to be enqueued
|
||||
* is larger than the MSS. */
|
||||
seglen = left > pcb->mss? pcb->mss: left;
|
||||
|
||||
/* Allocate memory for tcp_seg, and fill in fields. */
|
||||
seg = memp_malloc(MEMP_TCP_SEG);
|
||||
if (seg == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
|
||||
goto memerr;
|
||||
}
|
||||
seg->next = NULL;
|
||||
seg->p = NULL;
|
||||
|
||||
/* first segment of to-be-queued data? */
|
||||
if (queue == NULL) {
|
||||
queue = seg;
|
||||
}
|
||||
/* subsequent segments of to-be-queued data */
|
||||
else {
|
||||
/* Attach the segment to the end of the queued segments */
|
||||
LWIP_ASSERT("useg != NULL", useg != NULL);
|
||||
useg->next = seg;
|
||||
}
|
||||
/* remember last segment of to-be-queued data for next iteration */
|
||||
useg = seg;
|
||||
|
||||
/* If copy is set, memory should be allocated
|
||||
* and data copied into pbuf, otherwise data comes from
|
||||
* ROM or other static memory, and need not be copied. If
|
||||
* optdata is != NULL, we have options instead of data. */
|
||||
|
||||
/* options? */
|
||||
if (optdata != NULL) {
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
|
||||
goto memerr;
|
||||
}
|
||||
++queuelen;
|
||||
seg->dataptr = seg->p->payload;
|
||||
}
|
||||
/* copy from volatile memory? */
|
||||
else if (copy) {
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %u\n", seglen));
|
||||
goto memerr;
|
||||
}
|
||||
++queuelen;
|
||||
if (arg != NULL) {
|
||||
memcpy(seg->p->payload, ptr, seglen);
|
||||
}
|
||||
seg->dataptr = seg->p->payload;
|
||||
}
|
||||
/* do not copy data */
|
||||
else {
|
||||
/* First, allocate a pbuf for holding the data.
|
||||
* since the referenced data is available at least until it is sent out on the
|
||||
* link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
|
||||
* instead of PBUF_REF here.
|
||||
*/
|
||||
if ((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
|
||||
goto memerr;
|
||||
}
|
||||
++queuelen;
|
||||
/* reference the non-volatile payload data */
|
||||
p->payload = ptr;
|
||||
seg->dataptr = ptr;
|
||||
|
||||
/* Second, allocate a pbuf for the headers. */
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
|
||||
/* If allocation fails, we have to deallocate the data pbuf as
|
||||
* well. */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
|
||||
goto memerr;
|
||||
}
|
||||
++queuelen;
|
||||
|
||||
/* Concatenate the headers and data pbufs together. */
|
||||
pbuf_cat(seg->p/*header*/, p/*data*/);
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
/* Now that there are more segments queued, we check again if the
|
||||
length of the queue exceeds the configured maximum. */
|
||||
if (queuelen > TCP_SND_QUEUELEN) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %u (%u)\n", queuelen, TCP_SND_QUEUELEN));
|
||||
goto memerr;
|
||||
}
|
||||
|
||||
seg->len = seglen;
|
||||
|
||||
/* build TCP header */
|
||||
if (pbuf_header(seg->p, TCP_HLEN)) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
|
||||
TCP_STATS_INC(tcp.err);
|
||||
goto memerr;
|
||||
}
|
||||
seg->tcphdr = seg->p->payload;
|
||||
seg->tcphdr->src = htons(pcb->local_port);
|
||||
seg->tcphdr->dest = htons(pcb->remote_port);
|
||||
seg->tcphdr->seqno = htonl(seqno);
|
||||
seg->tcphdr->urgp = 0;
|
||||
TCPH_FLAGS_SET(seg->tcphdr, flags);
|
||||
/* don't fill in tcphdr->ackno and tcphdr->wnd until later */
|
||||
|
||||
/* Copy the options into the header, if they are present. */
|
||||
if (optdata == NULL) {
|
||||
TCPH_HDRLEN_SET(seg->tcphdr, 5);
|
||||
}
|
||||
else {
|
||||
TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
|
||||
/* Copy options into data portion of segment.
|
||||
Options can thus only be sent in non data carrying
|
||||
segments such as SYN|ACK. */
|
||||
memcpy(seg->dataptr, optdata, optlen);
|
||||
}
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %lu:%lu (0x%x)\n",
|
||||
ntohl(seg->tcphdr->seqno),
|
||||
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
|
||||
flags));
|
||||
|
||||
left -= seglen;
|
||||
seqno += seglen;
|
||||
ptr = (void *)((char *)ptr + seglen);
|
||||
}
|
||||
|
||||
/* Now that the data to be enqueued has been broken up into TCP
|
||||
segments in the queue variable, we add them to the end of the
|
||||
pcb->unsent queue. */
|
||||
if (pcb->unsent == NULL) {
|
||||
useg = NULL;
|
||||
}
|
||||
else {
|
||||
for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
|
||||
}
|
||||
/* { useg is last segment on the unsent queue, NULL if list is empty } */
|
||||
|
||||
/* If there is room in the last pbuf on the unsent queue,
|
||||
chain the first pbuf on the queue together with that. */
|
||||
if (useg != NULL &&
|
||||
TCP_TCPLEN(useg) != 0 &&
|
||||
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
|
||||
!(flags & (TCP_SYN | TCP_FIN)) &&
|
||||
/* fit within max seg size */
|
||||
useg->len + queue->len <= pcb->mss) {
|
||||
/* Remove TCP header from first segment of our to-be-queued list */
|
||||
pbuf_header(queue->p, -TCP_HLEN);
|
||||
pbuf_cat(useg->p, queue->p);
|
||||
useg->len += queue->len;
|
||||
useg->next = queue->next;
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %u\n", useg->len));
|
||||
if (seg == queue) {
|
||||
seg = NULL;
|
||||
}
|
||||
memp_free(MEMP_TCP_SEG, queue);
|
||||
}
|
||||
else {
|
||||
/* empty list */
|
||||
if (useg == NULL) {
|
||||
/* initialize list with this segment */
|
||||
pcb->unsent = queue;
|
||||
}
|
||||
/* enqueue segment */
|
||||
else {
|
||||
useg->next = queue;
|
||||
}
|
||||
}
|
||||
if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
|
||||
++len;
|
||||
}
|
||||
pcb->snd_lbb += len;
|
||||
pcb->snd_buf -= len;
|
||||
/* update number of segments on the queues */
|
||||
pcb->snd_queuelen = queuelen;
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %d (after enqueued)\n", pcb->snd_queuelen));
|
||||
if (pcb->snd_queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_enqueue: valid queue length",
|
||||
pcb->unacked != NULL || pcb->unsent != NULL);
|
||||
}
|
||||
|
||||
/* Set the PSH flag in the last segment that we enqueued, but only
|
||||
if the segment has data (indicated by seglen > 0). */
|
||||
if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
|
||||
TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
memerr:
|
||||
TCP_STATS_INC(tcp.memerr);
|
||||
|
||||
if (queue != NULL) {
|
||||
tcp_segs_free(queue);
|
||||
}
|
||||
if (pcb->snd_queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
|
||||
pcb->unsent != NULL);
|
||||
}
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (with mem err)\n", pcb->snd_queuelen));
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
/* find out what we can send and send it */
|
||||
err_t
|
||||
tcp_output(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
struct tcp_seg *seg, *useg;
|
||||
u32_t wnd;
|
||||
#if TCP_CWND_DEBUG
|
||||
int i = 0;
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
|
||||
/* First, check if we are invoked by the TCP input processing
|
||||
code. If so, we do not output anything. Instead, we rely on the
|
||||
input processing code to call us when input processing is done
|
||||
with. */
|
||||
if (tcp_input_pcb == pcb) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
|
||||
|
||||
seg = pcb->unsent;
|
||||
|
||||
/* useg should point to last segment on unacked queue */
|
||||
useg = pcb->unacked;
|
||||
if (useg != NULL) {
|
||||
for (; useg->next != NULL; useg = useg->next);
|
||||
}
|
||||
|
||||
/* If the TF_ACK_NOW flag is set and no data will be sent (either
|
||||
* because the ->unsent queue is empty or because the window does
|
||||
* not allow it), construct an empty ACK segment and send it.
|
||||
*
|
||||
* If data is to be sent, we will just piggyback the ACK (see below).
|
||||
*/
|
||||
if (pcb->flags & TF_ACK_NOW &&
|
||||
(seg == NULL ||
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
||||
return ERR_BUF;
|
||||
}
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %lu\n", pcb->rcv_nxt));
|
||||
/* remove ACK flags from the PCB, as we send an empty ACK now */
|
||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||
|
||||
tcphdr = p->payload;
|
||||
tcphdr->src = htons(pcb->local_port);
|
||||
tcphdr->dest = htons(pcb->remote_port);
|
||||
tcphdr->seqno = htonl(pcb->snd_nxt);
|
||||
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
|
||||
tcphdr->wnd = htons(pcb->rcv_wnd);
|
||||
tcphdr->urgp = 0;
|
||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||
|
||||
tcphdr->chksum = 0;
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
pbuf_free(p);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#if TCP_OUTPUT_DEBUG
|
||||
if (seg == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", pcb->unsent));
|
||||
}
|
||||
#endif /* TCP_OUTPUT_DEBUG */
|
||||
#if TCP_CWND_DEBUG
|
||||
if (seg == NULL) {
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, seg == NULL, ack %lu\n",
|
||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||
pcb->lastack));
|
||||
} else {
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu\n",
|
||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
|
||||
ntohl(seg->tcphdr->seqno), pcb->lastack));
|
||||
}
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
/* data available and window allows it to be sent? */
|
||||
while (seg != NULL &&
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
|
||||
#if TCP_CWND_DEBUG
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %lu, cwnd %lu, wnd %lu, effwnd %lu, seq %lu, ack %lu, i%d\n",
|
||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||
ntohl(seg->tcphdr->seqno) + seg->len -
|
||||
pcb->lastack,
|
||||
ntohl(seg->tcphdr->seqno), pcb->lastack, i));
|
||||
++i;
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
|
||||
pcb->unsent = seg->next;
|
||||
|
||||
if (pcb->state != SYN_SENT) {
|
||||
TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
|
||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||
}
|
||||
|
||||
tcp_output_segment(seg, pcb);
|
||||
pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
|
||||
if (TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) {
|
||||
pcb->snd_max = pcb->snd_nxt;
|
||||
}
|
||||
/* put segment on unacknowledged list if length > 0 */
|
||||
if (TCP_TCPLEN(seg) > 0) {
|
||||
seg->next = NULL;
|
||||
/* unacked list is empty? */
|
||||
if (pcb->unacked == NULL) {
|
||||
pcb->unacked = seg;
|
||||
useg = seg;
|
||||
/* unacked list is not empty? */
|
||||
} else {
|
||||
/* In the case of fast retransmit, the packet should not go to the tail
|
||||
* of the unacked queue, but rather at the head. We need to check for
|
||||
* this case. -STJ Jul 27, 2004 */
|
||||
if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
|
||||
/* add segment to head of unacked list */
|
||||
seg->next = pcb->unacked;
|
||||
pcb->unacked = seg;
|
||||
} else {
|
||||
/* add segment to tail of unacked list */
|
||||
useg->next = seg;
|
||||
useg = useg->next;
|
||||
}
|
||||
}
|
||||
/* do not queue empty segments on the unacked list */
|
||||
} else {
|
||||
tcp_seg_free(seg);
|
||||
}
|
||||
seg = pcb->unsent;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually send a TCP segment over IP
|
||||
*/
|
||||
static void
|
||||
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
{
|
||||
u16_t len;
|
||||
struct netif *netif;
|
||||
|
||||
/* The TCP header has already been constructed, but the ackno and
|
||||
wnd fields remain. */
|
||||
seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||
|
||||
/* silly window avoidance */
|
||||
if (pcb->rcv_wnd < pcb->mss) {
|
||||
seg->tcphdr->wnd = 0;
|
||||
} else {
|
||||
/* advertise our receive window size in this TCP segment */
|
||||
seg->tcphdr->wnd = htons(pcb->rcv_wnd);
|
||||
}
|
||||
|
||||
/* If we don't have a local IP address, we get one by
|
||||
calling ip_route(). */
|
||||
if (ip_addr_isany(&(pcb->local_ip))) {
|
||||
netif = ip_route(&(pcb->remote_ip));
|
||||
if (netif == NULL) {
|
||||
return;
|
||||
}
|
||||
ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
|
||||
}
|
||||
|
||||
pcb->rtime = 0;
|
||||
|
||||
if (pcb->rttest == 0) {
|
||||
pcb->rttest = tcp_ticks;
|
||||
pcb->rtseq = ntohl(seg->tcphdr->seqno);
|
||||
|
||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %lu\n", pcb->rtseq));
|
||||
}
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %lu:%lu\n",
|
||||
htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
|
||||
seg->len));
|
||||
|
||||
len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
|
||||
|
||||
seg->p->len -= len;
|
||||
seg->p->tot_len -= len;
|
||||
|
||||
seg->p->payload = seg->tcphdr;
|
||||
|
||||
seg->tcphdr->chksum = 0;
|
||||
#if CHECKSUM_GEN_TCP
|
||||
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
|
||||
&(pcb->local_ip),
|
||||
&(pcb->remote_ip),
|
||||
IP_PROTO_TCP, seg->p->tot_len);
|
||||
#endif
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
}
|
||||
|
||||
void
|
||||
tcp_rst(u32_t seqno, u32_t ackno,
|
||||
struct ip_addr *local_ip, struct ip_addr *remote_ip,
|
||||
u16_t local_port, u16_t remote_port)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
tcphdr = p->payload;
|
||||
tcphdr->src = htons(local_port);
|
||||
tcphdr->dest = htons(remote_port);
|
||||
tcphdr->seqno = htonl(seqno);
|
||||
tcphdr->ackno = htonl(ackno);
|
||||
TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
|
||||
tcphdr->wnd = htons(TCP_WND);
|
||||
tcphdr->urgp = 0;
|
||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||
|
||||
tcphdr->chksum = 0;
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
/* Send output with hardcoded TTL since we have no access to the pcb */
|
||||
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %lu ackno %lu.\n", seqno, ackno));
|
||||
}
|
||||
|
||||
/* requeue all unacked segments for retransmission */
|
||||
void
|
||||
tcp_rexmit_rto(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct tcp_seg *seg;
|
||||
|
||||
if (pcb->unacked == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Move all unacked segments to the head of the unsent queue */
|
||||
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
|
||||
/* concatenate unsent queue after unacked queue */
|
||||
seg->next = pcb->unsent;
|
||||
/* unsent queue is the concatenated queue (of unacked, unsent) */
|
||||
pcb->unsent = pcb->unacked;
|
||||
/* unacked queue is now empty */
|
||||
pcb->unacked = NULL;
|
||||
|
||||
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||
/* increment number of retransmissions */
|
||||
++pcb->nrtx;
|
||||
|
||||
/* Don't take any RTT measurements after retransmitting. */
|
||||
pcb->rttest = 0;
|
||||
|
||||
/* Do the actual retransmission */
|
||||
tcp_output(pcb);
|
||||
}
|
||||
|
||||
void
|
||||
tcp_rexmit(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct tcp_seg *seg;
|
||||
|
||||
if (pcb->unacked == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Move the first unacked segment to the unsent queue */
|
||||
seg = pcb->unacked->next;
|
||||
pcb->unacked->next = pcb->unsent;
|
||||
pcb->unsent = pcb->unacked;
|
||||
pcb->unacked = seg;
|
||||
|
||||
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||
|
||||
++pcb->nrtx;
|
||||
|
||||
/* Don't take any rtt measurements after retransmitting. */
|
||||
pcb->rttest = 0;
|
||||
|
||||
/* Do the actual retransmission. */
|
||||
tcp_output(pcb);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tcp_keepalive(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %u.%u.%u.%u\n",
|
||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %lu pcb->tmr %lu pcb->keep_cnt %u\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
|
||||
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||
|
||||
if(p == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
tcphdr = p->payload;
|
||||
tcphdr->src = htons(pcb->local_port);
|
||||
tcphdr->dest = htons(pcb->remote_port);
|
||||
tcphdr->seqno = htonl(pcb->snd_nxt - 1);
|
||||
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||
tcphdr->wnd = htons(pcb->rcv_wnd);
|
||||
tcphdr->urgp = 0;
|
||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||
|
||||
tcphdr->chksum = 0;
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
/* Send output to IP */
|
||||
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
||||
|
||||
pbuf_free(p);
|
||||
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
|
||||
}
|
||||
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,801 @@
|
|||
/**
|
||||
* @file
|
||||
* User Datagram Protocol module
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* udp.c
|
||||
*
|
||||
* The code for the User Datagram Protocol UDP.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/icmp.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "arch/perf.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
/* The list of UDP PCBs */
|
||||
#if LWIP_UDP
|
||||
/* was static, but we may want to access this from a socket layer */
|
||||
struct udp_pcb *udp_pcbs = NULL;
|
||||
|
||||
static struct udp_pcb *pcb_cache = NULL;
|
||||
|
||||
|
||||
void
|
||||
udp_init(void)
|
||||
{
|
||||
udp_pcbs = pcb_cache = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming UDP datagram.
|
||||
*
|
||||
* Given an incoming UDP datagram (as a chain of pbufs) this function
|
||||
* finds a corresponding UDP PCB and
|
||||
*
|
||||
* @param pbuf pbuf to be demultiplexed to a UDP PCB.
|
||||
* @param netif network interface on which the datagram was received.
|
||||
*
|
||||
*/
|
||||
void
|
||||
udp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct udp_hdr *udphdr;
|
||||
struct udp_pcb *pcb;
|
||||
struct ip_hdr *iphdr;
|
||||
u16_t src, dest;
|
||||
|
||||
#if SO_REUSE
|
||||
struct udp_pcb *pcb_temp;
|
||||
int reuse = 0;
|
||||
int reuse_port_1 = 0;
|
||||
int reuse_port_2 = 0;
|
||||
#endif /* SO_REUSE */
|
||||
|
||||
PERF_START;
|
||||
|
||||
UDP_STATS_INC(udp.recv);
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
|
||||
/* drop short packets */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
|
||||
UDP_STATS_INC(udp.lenerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
|
||||
udphdr = (struct udp_hdr *)((u8_t *)p->payload - UDP_HLEN);
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %u\n", p->tot_len));
|
||||
|
||||
src = ntohs(udphdr->src);
|
||||
dest = ntohs(udphdr->dest);
|
||||
|
||||
udp_debug_print(udphdr);
|
||||
|
||||
/* print the UDP source and destination */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n",
|
||||
ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest),
|
||||
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
|
||||
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
|
||||
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
|
||||
|
||||
#if SO_REUSE
|
||||
pcb_temp = udp_pcbs;
|
||||
|
||||
again_1:
|
||||
|
||||
/* Iterate through the UDP pcb list for a fully matching pcb */
|
||||
for (pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
|
||||
#else /* SO_REUSE */
|
||||
/* Iterate through the UDP pcb list for a fully matching pcb */
|
||||
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
#endif /* SO_REUSE */
|
||||
/* print the PCB local and remote address */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
|
||||
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
|
||||
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
|
||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
|
||||
|
||||
/* PCB remote port matches UDP source port? */
|
||||
if ((pcb->remote_port == src) &&
|
||||
/* PCB local port matches UDP destination port? */
|
||||
(pcb->local_port == dest) &&
|
||||
/* accepting from any remote (source) IP address? or... */
|
||||
(ip_addr_isany(&pcb->remote_ip) ||
|
||||
/* PCB remote IP address matches UDP source IP address? */
|
||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src))) &&
|
||||
/* accepting on any local (netif) IP address? or... */
|
||||
(ip_addr_isany(&pcb->local_ip) ||
|
||||
/* PCB local IP address matches UDP destination IP address? */
|
||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
||||
#if SO_REUSE
|
||||
if (pcb->so_options & SOF_REUSEPORT) {
|
||||
if(reuse) {
|
||||
/* We processed one PCB already */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
|
||||
} else {
|
||||
/* First PCB with this address */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
|
||||
reuse = 1;
|
||||
}
|
||||
|
||||
reuse_port_1 = 1;
|
||||
p->ref++;
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
|
||||
} else {
|
||||
if (reuse) {
|
||||
/* We processed one PCB already */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
|
||||
}
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* no fully matching pcb found? then look for an unconnected pcb */
|
||||
if (pcb == NULL) {
|
||||
/* Iterate through the UDP PCB list for a pcb that matches
|
||||
the local address. */
|
||||
|
||||
#if SO_REUSE
|
||||
pcb_temp = udp_pcbs;
|
||||
|
||||
again_2:
|
||||
|
||||
for (pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
|
||||
#else /* SO_REUSE */
|
||||
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
#endif /* SO_REUSE */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
|
||||
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
|
||||
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
|
||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
|
||||
/* unconnected? */
|
||||
if (((pcb->flags & UDP_FLAGS_CONNECTED) == 0) &&
|
||||
/* destination port matches? */
|
||||
(pcb->local_port == dest) &&
|
||||
/* not bound to a specific (local) interface address? or... */
|
||||
(ip_addr_isany(&pcb->local_ip) ||
|
||||
/* ...matching interface address? */
|
||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
|
||||
#if SO_REUSE
|
||||
if (pcb->so_options & SOF_REUSEPORT) {
|
||||
if (reuse) {
|
||||
/* We processed one PCB already */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
|
||||
} else {
|
||||
/* First PCB with this address */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
|
||||
reuse = 1;
|
||||
}
|
||||
|
||||
reuse_port_2 = 1;
|
||||
p->ref++;
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
|
||||
} else {
|
||||
if (reuse) {
|
||||
/* We processed one PCB already */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
|
||||
}
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check checksum if this is a match or if it was directed at us. */
|
||||
if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &iphdr->dest))
|
||||
{
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: calculating checksum\n"));
|
||||
pbuf_header(p, UDP_HLEN);
|
||||
#ifdef IPv6
|
||||
if (iphdr->nexthdr == IP_PROTO_UDPLITE) {
|
||||
#else
|
||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
|
||||
#endif /* IPv4 */
|
||||
/* Do the UDP Lite checksum */
|
||||
#if CHECKSUM_CHECK_UDP
|
||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||
(struct ip_addr *)&(iphdr->dest),
|
||||
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if CHECKSUM_CHECK_UDP
|
||||
if (udphdr->chksum != 0) {
|
||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||
(struct ip_addr *)&(iphdr->dest),
|
||||
IP_PROTO_UDP, p->tot_len) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n"));
|
||||
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
pbuf_header(p, -UDP_HLEN);
|
||||
if (pcb != NULL) {
|
||||
snmp_inc_udpindatagrams();
|
||||
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
|
||||
#if SO_REUSE
|
||||
/* First socket should receive now */
|
||||
if(reuse_port_1 || reuse_port_2) {
|
||||
/* We want to search on next socket after receiving */
|
||||
pcb_temp = pcb->next;
|
||||
|
||||
if(reuse_port_1) {
|
||||
/* We are searching connected sockets */
|
||||
reuse_port_1 = 0;
|
||||
reuse_port_2 = 0;
|
||||
goto again_1;
|
||||
} else {
|
||||
/* We are searching unconnected sockets */
|
||||
reuse_port_1 = 0;
|
||||
reuse_port_2 = 0;
|
||||
goto again_2;
|
||||
}
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
} else {
|
||||
#if SO_REUSE
|
||||
if(reuse) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
|
||||
|
||||
/* No match was found, send ICMP destination port unreachable unless
|
||||
destination address was broadcast/multicast. */
|
||||
|
||||
if (!ip_addr_isbroadcast(&iphdr->dest, inp) &&
|
||||
!ip_addr_ismulticast(&iphdr->dest)) {
|
||||
|
||||
/* adjust pbuf pointer */
|
||||
p->payload = iphdr;
|
||||
icmp_dest_unreach(p, ICMP_DUR_PORT);
|
||||
}
|
||||
UDP_STATS_INC(udp.proterr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpnoports();
|
||||
pbuf_free(p);
|
||||
}
|
||||
} else {
|
||||
pbuf_free(p);
|
||||
}
|
||||
end:
|
||||
|
||||
PERF_STOP("udp_input");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to a specified address using UDP.
|
||||
*
|
||||
* @param pcb UDP PCB used to send the data.
|
||||
* @param pbuf chain of pbuf's to be sent.
|
||||
* @param dst_ip Destination IP address.
|
||||
* @param dst_port Destination UDP port.
|
||||
*
|
||||
* If the PCB already has a remote address association, it will
|
||||
* be restored after the data is sent.
|
||||
*
|
||||
* @return lwIP error code.
|
||||
* - ERR_OK. Successful. No error occured.
|
||||
* - ERR_MEM. Out of memory.
|
||||
* - ERR_RTE. Could not find route to destination address.
|
||||
*
|
||||
* @see udp_disconnect() udp_send()
|
||||
*/
|
||||
err_t
|
||||
udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *dst_ip, u16_t dst_port)
|
||||
{
|
||||
err_t err;
|
||||
/* temporary space for current PCB remote address */
|
||||
struct ip_addr pcb_remote_ip;
|
||||
u16_t pcb_remote_port;
|
||||
/* remember current remote peer address of PCB */
|
||||
pcb_remote_ip.addr = pcb->remote_ip.addr;
|
||||
pcb_remote_port = pcb->remote_port;
|
||||
/* copy packet destination address to PCB remote peer address */
|
||||
pcb->remote_ip.addr = dst_ip->addr;
|
||||
pcb->remote_port = dst_port;
|
||||
/* send to the packet destination address */
|
||||
err = udp_send(pcb, p);
|
||||
/* restore PCB remote peer address */
|
||||
pcb->remote_ip.addr = pcb_remote_ip.addr;
|
||||
pcb->remote_port = pcb_remote_port;
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data using UDP.
|
||||
*
|
||||
* @param pcb UDP PCB used to send the data.
|
||||
* @param pbuf chain of pbuf's to be sent.
|
||||
*
|
||||
* @return lwIP error code.
|
||||
* - ERR_OK. Successful. No error occured.
|
||||
* - ERR_MEM. Out of memory.
|
||||
* - ERR_RTE. Could not find route to destination address.
|
||||
*
|
||||
* @see udp_disconnect() udp_sendto()
|
||||
*/
|
||||
err_t
|
||||
udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
{
|
||||
struct udp_hdr *udphdr;
|
||||
struct netif *netif;
|
||||
struct ip_addr *src_ip;
|
||||
err_t err;
|
||||
struct pbuf *q; /* q will be sent down the stack */
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_send\n"));
|
||||
|
||||
/* if the PCB is not yet bound to a port, bind it here */
|
||||
if (pcb->local_port == 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: not yet bound to a port, binding now\n"));
|
||||
err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: forced port bind failed\n"));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* not enough space to add an UDP header to first pbuf in given p chain? */
|
||||
if (pbuf_header(p, UDP_HLEN)) {
|
||||
/* allocate header in a seperate new pbuf */
|
||||
q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
|
||||
/* new header pbuf could not be allocated? */
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: could not allocate header\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* chain header q in front of given pbuf p */
|
||||
pbuf_chain(q, p);
|
||||
/* { first pbuf q points to header pbuf } */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||
/* adding a header within p succeeded */
|
||||
} else {
|
||||
/* first pbuf q equals given pbuf */
|
||||
q = p;
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
|
||||
}
|
||||
/* { q now represents the packet to be sent } */
|
||||
udphdr = q->payload;
|
||||
udphdr->src = htons(pcb->local_port);
|
||||
udphdr->dest = htons(pcb->remote_port);
|
||||
/* in UDP, 0 checksum means 'no checksum' */
|
||||
udphdr->chksum = 0x0000;
|
||||
|
||||
/* find the outgoing network interface for this packet */
|
||||
netif = ip_route(&(pcb->remote_ip));
|
||||
/* no outgoing network interface could be found? */
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr));
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
/* PCB local address is IP_ANY_ADDR? */
|
||||
if (ip_addr_isany(&pcb->local_ip)) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
src_ip = &(netif->ip_addr);
|
||||
} else {
|
||||
/* use UDP PCB local IP address as source address */
|
||||
src_ip = &(pcb->local_ip);
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %u\n", q->tot_len));
|
||||
|
||||
/* UDP Lite protocol? */
|
||||
if (pcb->flags & UDP_FLAGS_UDPLITE) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %u\n", q->tot_len));
|
||||
/* set UDP message length in UDP header */
|
||||
udphdr->len = htons(pcb->chksum_len);
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip),
|
||||
IP_PROTO_UDP, pcb->chksum_len);
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
|
||||
#else
|
||||
udphdr->chksum = 0x0000;
|
||||
#endif
|
||||
/* output to IP */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
|
||||
err = ip_output_if (q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
||||
/* UDP */
|
||||
} else {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len));
|
||||
udphdr->len = htons(q->tot_len);
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
||||
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &pcb->remote_ip, IP_PROTO_UDP, q->tot_len);
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
|
||||
}
|
||||
#else
|
||||
udphdr->chksum = 0x0000;
|
||||
#endif
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04x\n", udphdr->chksum));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
|
||||
/* output to IP */
|
||||
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
||||
}
|
||||
/* TODO: must this be increased even if error occured? */
|
||||
snmp_inc_udpoutdatagrams();
|
||||
|
||||
/* did we chain a seperate header pbuf earlier? */
|
||||
if (q != p) {
|
||||
/* free the header pbuf */
|
||||
pbuf_free(q); q = NULL;
|
||||
/* { p is still referenced by the caller, and will live on } */
|
||||
}
|
||||
|
||||
UDP_STATS_INC(udp.xmit);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind an UDP PCB.
|
||||
*
|
||||
* @param pcb UDP PCB to be bound with a local address ipaddr and port.
|
||||
* @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
|
||||
* bind to all local interfaces.
|
||||
* @param port local UDP port to bind with.
|
||||
*
|
||||
* @return lwIP error code.
|
||||
* - ERR_OK. Successful. No error occured.
|
||||
* - ERR_USE. The specified ipaddr and port are already bound to by
|
||||
* another UDP PCB.
|
||||
*
|
||||
* @see udp_disconnect()
|
||||
*/
|
||||
err_t
|
||||
udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
{
|
||||
struct udp_pcb *ipcb;
|
||||
u8_t rebind;
|
||||
#if SO_REUSE
|
||||
int reuse_port_all_set = 1;
|
||||
#endif /* SO_REUSE */
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
|
||||
ip_addr_debug_print(UDP_DEBUG, ipaddr);
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %u)\n", port));
|
||||
|
||||
rebind = 0;
|
||||
/* Check for double bind and rebind of the same pcb */
|
||||
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
||||
/* is this UDP PCB already on active list? */
|
||||
if (pcb == ipcb) {
|
||||
/* pcb may occur at most once in active list */
|
||||
LWIP_ASSERT("rebind == 0", rebind == 0);
|
||||
/* pcb already in list, just rebind */
|
||||
rebind = 1;
|
||||
}
|
||||
|
||||
#if SO_REUSE == 0
|
||||
/* this code does not allow upper layer to share a UDP port for
|
||||
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
|
||||
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
|
||||
combine with implementation of UDP PCB flags. Leon Woestenberg. */
|
||||
#ifdef LWIP_UDP_TODO
|
||||
/* port matches that of PCB in list? */
|
||||
else if ((ipcb->local_port == port) &&
|
||||
/* IP address matches, or one is IP_ADDR_ANY? */
|
||||
(ip_addr_isany(&(ipcb->local_ip)) ||
|
||||
ip_addr_isany(ipaddr) ||
|
||||
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
|
||||
/* other PCB already binds to this local IP and port */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: local port %u already bound by another pcb\n", port));
|
||||
return ERR_USE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* SO_REUSE */
|
||||
/* Search through list of PCB's.
|
||||
|
||||
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
|
||||
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
|
||||
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
|
||||
But no two PCB's bound to same local port and same local address is valid.
|
||||
|
||||
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
|
||||
all PCB's must have the SOF_REUSEPORT option set.
|
||||
|
||||
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
|
||||
address is already in use. */
|
||||
else if (ipcb->local_port == port) {
|
||||
if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {
|
||||
if(pcb->so_options & SOF_REUSEPORT) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n"));
|
||||
reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT));
|
||||
}
|
||||
else {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n"));
|
||||
return ERR_USE;
|
||||
}
|
||||
}
|
||||
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) ||
|
||||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) {
|
||||
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
|
||||
return ERR_USE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
|
||||
}
|
||||
|
||||
#if SO_REUSE
|
||||
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
|
||||
{IP, port} can't be reused. */
|
||||
if(!reuse_port_all_set) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n"));
|
||||
return ERR_USE;
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
|
||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
||||
/* no port specified? */
|
||||
if (port == 0) {
|
||||
#ifndef UDP_LOCAL_PORT_RANGE_START
|
||||
#define UDP_LOCAL_PORT_RANGE_START 4096
|
||||
#define UDP_LOCAL_PORT_RANGE_END 0x7fff
|
||||
#endif
|
||||
port = UDP_LOCAL_PORT_RANGE_START;
|
||||
ipcb = udp_pcbs;
|
||||
while ((ipcb != NULL) && (port != UDP_LOCAL_PORT_RANGE_END)) {
|
||||
if (ipcb->local_port == port) {
|
||||
port++;
|
||||
ipcb = udp_pcbs;
|
||||
} else
|
||||
ipcb = ipcb->next;
|
||||
}
|
||||
if (ipcb != NULL) {
|
||||
/* no more ports available in local range */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
|
||||
return ERR_USE;
|
||||
}
|
||||
}
|
||||
pcb->local_port = port;
|
||||
/* pcb not active yet? */
|
||||
if (rebind == 0) {
|
||||
/* place the PCB on the active list if not already there */
|
||||
pcb->next = udp_pcbs;
|
||||
udp_pcbs = pcb;
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_bind: bound to %u.%u.%u.%u, port %u\n",
|
||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
|
||||
return ERR_OK;
|
||||
}
|
||||
/**
|
||||
* Connect an UDP PCB.
|
||||
*
|
||||
* This will associate the UDP PCB with the remote address.
|
||||
*
|
||||
* @param pcb UDP PCB to be connected with remote address ipaddr and port.
|
||||
* @param ipaddr remote IP address to connect with.
|
||||
* @param port remote UDP port to connect with.
|
||||
*
|
||||
* @return lwIP error code
|
||||
*
|
||||
* @see udp_disconnect()
|
||||
*/
|
||||
err_t
|
||||
udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
{
|
||||
struct udp_pcb *ipcb;
|
||||
|
||||
if (pcb->local_port == 0) {
|
||||
err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
|
||||
if (err != ERR_OK)
|
||||
return err;
|
||||
}
|
||||
|
||||
ip_addr_set(&pcb->remote_ip, ipaddr);
|
||||
pcb->remote_port = port;
|
||||
pcb->flags |= UDP_FLAGS_CONNECTED;
|
||||
/** TODO: this functionality belongs in upper layers */
|
||||
#ifdef LWIP_UDP_TODO
|
||||
/* Nail down local IP for netconn_addr()/getsockname() */
|
||||
if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
|
||||
struct netif *netif;
|
||||
|
||||
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
/** TODO: this will bind the udp pcb locally, to the interface which
|
||||
is used to route output packets to the remote address. However, we
|
||||
might want to accept incoming packets on any interface! */
|
||||
pcb->local_ip = netif->ip_addr;
|
||||
} else if (ip_addr_isany(&pcb->remote_ip)) {
|
||||
pcb->local_ip.addr = 0;
|
||||
}
|
||||
#endif
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE, ("udp_connect: connected to %u.%u.%u.%u, port %u\n",
|
||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
|
||||
(unsigned int)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
|
||||
|
||||
/* Insert UDP PCB into the list of active UDP PCBs. */
|
||||
for(ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
||||
if (pcb == ipcb) {
|
||||
/* already on the list, just return */
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
/* PCB not yet on the list, add PCB now */
|
||||
pcb->next = udp_pcbs;
|
||||
udp_pcbs = pcb;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
udp_disconnect(struct udp_pcb *pcb)
|
||||
{
|
||||
/* reset remote address association */
|
||||
ip_addr_set(&pcb->remote_ip, IP_ADDR_ANY);
|
||||
pcb->remote_port = 0;
|
||||
/* mark PCB as unconnected */
|
||||
pcb->flags &= ~UDP_FLAGS_CONNECTED;
|
||||
}
|
||||
|
||||
void
|
||||
udp_recv(struct udp_pcb *pcb,
|
||||
void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
|
||||
struct ip_addr *addr, u16_t port),
|
||||
void *recv_arg)
|
||||
{
|
||||
/* remember recv() callback and user data */
|
||||
pcb->recv = recv;
|
||||
pcb->recv_arg = recv_arg;
|
||||
}
|
||||
/**
|
||||
* Remove an UDP PCB.
|
||||
*
|
||||
* @param pcb UDP PCB to be removed. The PCB is removed from the list of
|
||||
* UDP PCB's and the data structure is freed from memory.
|
||||
*
|
||||
* @see udp_new()
|
||||
*/
|
||||
void
|
||||
udp_remove(struct udp_pcb *pcb)
|
||||
{
|
||||
struct udp_pcb *pcb2;
|
||||
/* pcb to be removed is first in list? */
|
||||
if (udp_pcbs == pcb) {
|
||||
/* make list start at 2nd pcb */
|
||||
udp_pcbs = udp_pcbs->next;
|
||||
/* pcb not 1st in list */
|
||||
} else for(pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
|
||||
/* find pcb in udp_pcbs list */
|
||||
if (pcb2->next != NULL && pcb2->next == pcb) {
|
||||
/* remove pcb from list */
|
||||
pcb2->next = pcb->next;
|
||||
}
|
||||
}
|
||||
memp_free(MEMP_UDP_PCB, pcb);
|
||||
}
|
||||
/**
|
||||
* Create a UDP PCB.
|
||||
*
|
||||
* @return The UDP PCB which was created. NULL if the PCB data structure
|
||||
* could not be allocated.
|
||||
*
|
||||
* @see udp_remove()
|
||||
*/
|
||||
struct udp_pcb *
|
||||
udp_new(void) {
|
||||
struct udp_pcb *pcb;
|
||||
pcb = memp_malloc(MEMP_UDP_PCB);
|
||||
/* could allocate UDP PCB? */
|
||||
if (pcb != NULL) {
|
||||
/* initialize PCB to all zeroes */
|
||||
memset(pcb, 0, sizeof(struct udp_pcb));
|
||||
pcb->ttl = UDP_TTL;
|
||||
}
|
||||
|
||||
|
||||
return pcb;
|
||||
}
|
||||
|
||||
#if UDP_DEBUG
|
||||
int
|
||||
udp_debug_print(struct udp_hdr *udphdr)
|
||||
{
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
|
||||
ntohs(udphdr->src), ntohs(udphdr->dest)));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("| %5u | 0x%04x | (len, chksum)\n",
|
||||
ntohs(udphdr->len), ntohs(udphdr->chksum)));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||
return 0;
|
||||
}
|
||||
#endif /* UDP_DEBUG */
|
||||
|
||||
#endif /* LWIP_UDP */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_ICMP_H__
|
||||
#define __LWIP_ICMP_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#define ICMP_ER 0 /* echo reply */
|
||||
#define ICMP_DUR 3 /* destination unreachable */
|
||||
#define ICMP_SQ 4 /* source quench */
|
||||
#define ICMP_RD 5 /* redirect */
|
||||
#define ICMP_ECHO 8 /* echo */
|
||||
#define ICMP_TE 11 /* time exceeded */
|
||||
#define ICMP_PP 12 /* parameter problem */
|
||||
#define ICMP_TS 13 /* timestamp */
|
||||
#define ICMP_TSR 14 /* timestamp reply */
|
||||
#define ICMP_IRQ 15 /* information request */
|
||||
#define ICMP_IR 16 /* information reply */
|
||||
|
||||
enum icmp_dur_type {
|
||||
ICMP_DUR_NET = 0, /* net unreachable */
|
||||
ICMP_DUR_HOST = 1, /* host unreachable */
|
||||
ICMP_DUR_PROTO = 2, /* protocol unreachable */
|
||||
ICMP_DUR_PORT = 3, /* port unreachable */
|
||||
ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
|
||||
ICMP_DUR_SR = 5 /* source route failed */
|
||||
};
|
||||
|
||||
enum icmp_te_type {
|
||||
ICMP_TE_TTL = 0, /* time to live exceeded in transit */
|
||||
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
|
||||
};
|
||||
|
||||
void icmp_input(struct pbuf *p, struct netif *inp);
|
||||
|
||||
void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
|
||||
void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct icmp_echo_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u16_t id);
|
||||
PACK_STRUCT_FIELD(u16_t seqno);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
|
||||
PACK_STRUCT_BEGIN
|
||||
struct icmp_dur_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u32_t unused);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
|
||||
PACK_STRUCT_BEGIN
|
||||
struct icmp_te_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u32_t unused);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define ICMPH_TYPE(hdr) (ntohs((hdr)->_type_code) >> 8)
|
||||
#define ICMPH_CODE(hdr) (ntohs((hdr)->_type_code) & 0xff)
|
||||
|
||||
#define ICMPH_TYPE_SET(hdr, type) ((hdr)->_type_code = htons(ICMPH_CODE(hdr) | ((type) << 8)))
|
||||
#define ICMPH_CODE_SET(hdr, code) ((hdr)->_type_code = htons((code) | (ICMPH_TYPE(hdr) << 8)))
|
||||
|
||||
#endif /* __LWIP_ICMP_H__ */
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_INET_H__
|
||||
#define __LWIP_INET_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
u16_t inet_chksum(void *dataptr, u16_t len);
|
||||
u16_t inet_chksum_pbuf(struct pbuf *p);
|
||||
u16_t inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u16_t proto_len);
|
||||
|
||||
u32_t inet_addr(const char *cp);
|
||||
int inet_aton(const char *cp, struct in_addr *addr);
|
||||
char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */
|
||||
|
||||
#ifdef htons
|
||||
#undef htons
|
||||
#endif /* htons */
|
||||
#ifdef htonl
|
||||
#undef htonl
|
||||
#endif /* htonl */
|
||||
#ifdef ntohs
|
||||
#undef ntohs
|
||||
#endif /* ntohs */
|
||||
#ifdef ntohl
|
||||
#undef ntohl
|
||||
#endif /* ntohl */
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define htons(x) (x)
|
||||
#define ntohs(x) (x)
|
||||
#define htonl(x) (x)
|
||||
#define ntohl(x) (x)
|
||||
#else
|
||||
#ifdef LWIP_PREFIX_BYTEORDER_FUNCS
|
||||
/* workaround for naming collisions on some platforms */
|
||||
#define htons lwip_htons
|
||||
#define ntohs lwip_ntohs
|
||||
#define htonl lwip_htonl
|
||||
#define ntohl lwip_ntohl
|
||||
#endif
|
||||
u16_t htons(u16_t x);
|
||||
u16_t ntohs(u16_t x);
|
||||
u32_t htonl(u32_t x);
|
||||
u32_t ntohl(u32_t x);
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_INET_H__ */
|
||||
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_IP_H__
|
||||
#define __LWIP_IP_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
|
||||
void ip_init(void);
|
||||
struct netif *ip_route(struct ip_addr *dest);
|
||||
err_t ip_input(struct pbuf *p, struct netif *inp);
|
||||
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto);
|
||||
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto,
|
||||
struct netif *netif);
|
||||
|
||||
#define IP_HLEN 20
|
||||
|
||||
#define IP_PROTO_ICMP 1
|
||||
#define IP_PROTO_UDP 17
|
||||
#define IP_PROTO_UDPLITE 170
|
||||
#define IP_PROTO_TCP 6
|
||||
|
||||
/* This is passed as the destination address to ip_output_if (not
|
||||
to ip_output), meaning that an IP header already is constructed
|
||||
in the pbuf. This is used when TCP retransmits. */
|
||||
#ifdef IP_HDRINCL
|
||||
#undef IP_HDRINCL
|
||||
#endif /* IP_HDRINCL */
|
||||
#define IP_HDRINCL NULL
|
||||
|
||||
|
||||
/* This is the common part of all PCB types. It needs to be at the
|
||||
beginning of a PCB type definition. It is located here so that
|
||||
changes to this common part are made in one location instead of
|
||||
having to change all PCB structs. */
|
||||
#define IP_PCB struct ip_addr local_ip; \
|
||||
struct ip_addr remote_ip; \
|
||||
/* Socket options */ \
|
||||
u16_t so_options; \
|
||||
/* Type Of Service */ \
|
||||
u8_t tos; \
|
||||
/* Time To Live */ \
|
||||
u8_t ttl
|
||||
|
||||
/*
|
||||
* Option flags per-socket. These are the same like SO_XXX.
|
||||
*/
|
||||
#define SOF_DEBUG (u16_t)0x0001U /* turn on debugging info recording */
|
||||
#define SOF_ACCEPTCONN (u16_t)0x0002U /* socket has had listen() */
|
||||
#define SOF_REUSEADDR (u16_t)0x0004U /* allow local address reuse */
|
||||
#define SOF_KEEPALIVE (u16_t)0x0008U /* keep connections alive */
|
||||
#define SOF_DONTROUTE (u16_t)0x0010U /* just use interface addresses */
|
||||
#define SOF_BROADCAST (u16_t)0x0020U /* permit sending of broadcast msgs */
|
||||
#define SOF_USELOOPBACK (u16_t)0x0040U /* bypass hardware when possible */
|
||||
#define SOF_LINGER (u16_t)0x0080U /* linger on close if data present */
|
||||
#define SOF_OOBINLINE (u16_t)0x0100U /* leave received OOB data in line */
|
||||
#define SOF_REUSEPORT (u16_t)0x0200U /* allow local address & port reuse */
|
||||
|
||||
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip_hdr {
|
||||
/* version / header length / type of service */
|
||||
PACK_STRUCT_FIELD(u16_t _v_hl_tos);
|
||||
/* total length */
|
||||
PACK_STRUCT_FIELD(u16_t _len);
|
||||
/* identification */
|
||||
PACK_STRUCT_FIELD(u16_t _id);
|
||||
/* fragment offset field */
|
||||
PACK_STRUCT_FIELD(u16_t _offset);
|
||||
#define IP_RF 0x8000 /* reserved fragment flag */
|
||||
#define IP_DF 0x4000 /* dont fragment flag */
|
||||
#define IP_MF 0x2000 /* more fragments flag */
|
||||
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||
/* time to live / protocol*/
|
||||
PACK_STRUCT_FIELD(u16_t _ttl_proto);
|
||||
/* checksum */
|
||||
PACK_STRUCT_FIELD(u16_t _chksum);
|
||||
/* source and destination IP addresses */
|
||||
PACK_STRUCT_FIELD(struct ip_addr src);
|
||||
PACK_STRUCT_FIELD(struct ip_addr dest);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12)
|
||||
#define IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f)
|
||||
#define IPH_TOS(hdr) (ntohs((hdr)->_v_hl_tos) & 0xff)
|
||||
#define IPH_LEN(hdr) ((hdr)->_len)
|
||||
#define IPH_ID(hdr) ((hdr)->_id)
|
||||
#define IPH_OFFSET(hdr) ((hdr)->_offset)
|
||||
#define IPH_TTL(hdr) (ntohs((hdr)->_ttl_proto) >> 8)
|
||||
#define IPH_PROTO(hdr) (ntohs((hdr)->_ttl_proto) & 0xff)
|
||||
#define IPH_CHKSUM(hdr) ((hdr)->_chksum)
|
||||
|
||||
#define IPH_VHLTOS_SET(hdr, v, hl, tos) (hdr)->_v_hl_tos = (htons(((v) << 12) | ((hl) << 8) | (tos)))
|
||||
#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len)
|
||||
#define IPH_ID_SET(hdr, id) (hdr)->_id = (id)
|
||||
#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off)
|
||||
#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl_proto = (htons(IPH_PROTO(hdr) | ((ttl) << 8)))
|
||||
#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8)))
|
||||
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
|
||||
|
||||
#if IP_DEBUG
|
||||
void ip_debug_print(struct pbuf *p);
|
||||
#else
|
||||
#define ip_debug_print(p)
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
#endif /* __LWIP_IP_H__ */
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_IP_ADDR_H__
|
||||
#define __LWIP_IP_ADDR_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip_addr {
|
||||
PACK_STRUCT_FIELD(u32_t addr);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip_addr2 {
|
||||
PACK_STRUCT_FIELD(u16_t addrw[2]);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/* For compatibility with BSD code */
|
||||
struct in_addr {
|
||||
u32_t s_addr;
|
||||
};
|
||||
|
||||
struct netif;
|
||||
|
||||
extern const struct ip_addr ip_addr_any;
|
||||
extern const struct ip_addr ip_addr_broadcast;
|
||||
|
||||
/** IP_ADDR_ can be used as a fixed IP address
|
||||
* for the wildcard and the broadcast address
|
||||
*/
|
||||
#define IP_ADDR_ANY ((struct ip_addr *)&ip_addr_any)
|
||||
#define IP_ADDR_BROADCAST ((struct ip_addr *)&ip_addr_broadcast)
|
||||
|
||||
#define INADDR_NONE ((u32_t) 0xffffffff) /* 255.255.255.255 */
|
||||
#define INADDR_LOOPBACK ((u32_t) 0x7f000001) /* 127.0.0.1 */
|
||||
|
||||
/* Definitions of the bits in an Internet address integer.
|
||||
|
||||
On subnets, host and network parts are found according to
|
||||
the subnet mask, not these masks. */
|
||||
|
||||
#define IN_CLASSA(a) ((((u32_t)(a)) & 0x80000000) == 0)
|
||||
#define IN_CLASSA_NET 0xff000000
|
||||
#define IN_CLASSA_NSHIFT 24
|
||||
#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
|
||||
#define IN_CLASSA_MAX 128
|
||||
|
||||
#define IN_CLASSB(a) ((((u32_t)(a)) & 0xc0000000) == 0x80000000)
|
||||
#define IN_CLASSB_NET 0xffff0000
|
||||
#define IN_CLASSB_NSHIFT 16
|
||||
#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
|
||||
#define IN_CLASSB_MAX 65536
|
||||
|
||||
#define IN_CLASSC(a) ((((u32_t)(a)) & 0xe0000000) == 0xc0000000)
|
||||
#define IN_CLASSC_NET 0xffffff00
|
||||
#define IN_CLASSC_NSHIFT 8
|
||||
#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
|
||||
|
||||
#define IN_CLASSD(a) (((u32_t)(a) & 0xf0000000) == 0xe0000000)
|
||||
#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */
|
||||
#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */
|
||||
#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */
|
||||
#define IN_MULTICAST(a) IN_CLASSD(a)
|
||||
|
||||
#define IN_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000) == 0xf0000000)
|
||||
#define IN_BADCLASS(a) (((u32_t)(a) & 0xf0000000) == 0xf0000000)
|
||||
|
||||
#define IN_LOOPBACKNET 127 /* official! */
|
||||
|
||||
|
||||
#define IP4_ADDR(ipaddr, a,b,c,d) (ipaddr)->addr = htonl(((u32_t)(a & 0xff) << 24) | ((u32_t)(b & 0xff) << 16) | \
|
||||
((u32_t)(c & 0xff) << 8) | (u32_t)(d & 0xff))
|
||||
|
||||
#define ip_addr_set(dest, src) (dest)->addr = \
|
||||
((src) == NULL? 0:\
|
||||
(src)->addr)
|
||||
/**
|
||||
* Determine if two address are on the same network.
|
||||
*
|
||||
* @arg addr1 IP address 1
|
||||
* @arg addr2 IP address 2
|
||||
* @arg mask network identifier mask
|
||||
* @return !0 if the network identifiers of both address match
|
||||
*/
|
||||
#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \
|
||||
(mask)->addr) == \
|
||||
((addr2)->addr & \
|
||||
(mask)->addr))
|
||||
#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr)
|
||||
|
||||
#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0)
|
||||
|
||||
u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
|
||||
|
||||
#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))
|
||||
|
||||
|
||||
#define ip_addr_debug_print(debug, ipaddr) LWIP_DEBUGF(debug, ("%u.%u.%u.%u", \
|
||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff:0, \
|
||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff:0, \
|
||||
ipaddr?(unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff:0, \
|
||||
ipaddr?(unsigned int)ntohl((ipaddr)->addr) & 0xff:0U))
|
||||
|
||||
/* cast to unsigned int, as it is used as argument to printf functions
|
||||
* which expect integer arguments */
|
||||
#define ip4_addr1(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 24) & 0xff)
|
||||
#define ip4_addr2(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 16) & 0xff)
|
||||
#define ip4_addr3(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr) >> 8) & 0xff)
|
||||
#define ip4_addr4(ipaddr) ((unsigned int)(ntohl((ipaddr)->addr)) & 0xff)
|
||||
#endif /* __LWIP_IP_ADDR_H__ */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Jani Monoses <jani@iv.ro>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_IP_FRAG_H__
|
||||
#define __LWIP_IP_FRAG_H__
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
struct pbuf * ip_reass(struct pbuf *);
|
||||
err_t ip_frag(struct pbuf *, struct netif *, struct ip_addr *);
|
||||
|
||||
#endif /* __LWIP_IP_FRAG_H__ */
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_ICMP_H__
|
||||
#define __LWIP_ICMP_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#define ICMP6_DUR 1
|
||||
#define ICMP6_TE 3
|
||||
#define ICMP6_ECHO 128 /* echo */
|
||||
#define ICMP6_ER 129 /* echo reply */
|
||||
|
||||
|
||||
enum icmp_dur_type {
|
||||
ICMP_DUR_NET = 0, /* net unreachable */
|
||||
ICMP_DUR_HOST = 1, /* host unreachable */
|
||||
ICMP_DUR_PROTO = 2, /* protocol unreachable */
|
||||
ICMP_DUR_PORT = 3, /* port unreachable */
|
||||
ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
|
||||
ICMP_DUR_SR = 5 /* source route failed */
|
||||
};
|
||||
|
||||
enum icmp_te_type {
|
||||
ICMP_TE_TTL = 0, /* time to live exceeded in transit */
|
||||
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
|
||||
};
|
||||
|
||||
void icmp_input(struct pbuf *p, struct netif *inp);
|
||||
|
||||
void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
|
||||
void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
|
||||
|
||||
struct icmp_echo_hdr {
|
||||
u8_t type;
|
||||
u8_t icode;
|
||||
u16_t chksum;
|
||||
u16_t id;
|
||||
u16_t seqno;
|
||||
};
|
||||
|
||||
struct icmp_dur_hdr {
|
||||
u8_t type;
|
||||
u8_t icode;
|
||||
u16_t chksum;
|
||||
u32_t unused;
|
||||
};
|
||||
|
||||
struct icmp_te_hdr {
|
||||
u8_t type;
|
||||
u8_t icode;
|
||||
u16_t chksum;
|
||||
u32_t unused;
|
||||
};
|
||||
|
||||
#endif /* __LWIP_ICMP_H__ */
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_INET_H__
|
||||
#define __LWIP_INET_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
u16_t inet_chksum(void *data, u16_t len);
|
||||
u16_t inet_chksum_pbuf(struct pbuf *p);
|
||||
u16_t inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u32_t proto_len);
|
||||
|
||||
u32_t inet_addr(const char *cp);
|
||||
int inet_aton(const char *cp, struct in_addr *addr);
|
||||
|
||||
#ifndef _MACHINE_ENDIAN_H_
|
||||
#ifndef _NETINET_IN_H
|
||||
#ifndef _LINUX_BYTEORDER_GENERIC_H
|
||||
u16_t htons(u16_t n);
|
||||
u16_t ntohs(u16_t n);
|
||||
u32_t htonl(u32_t n);
|
||||
u32_t ntohl(u32_t n);
|
||||
#endif /* _LINUX_BYTEORDER_GENERIC_H */
|
||||
#endif /* _NETINET_IN_H */
|
||||
#endif /* _MACHINE_ENDIAN_H_ */
|
||||
|
||||
#endif /* __LWIP_INET_H__ */
|
||||
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_IP_H__
|
||||
#define __LWIP_IP_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
#define IP_HLEN 40
|
||||
|
||||
#define IP_PROTO_ICMP 58
|
||||
#define IP_PROTO_UDP 17
|
||||
#define IP_PROTO_UDPLITE 170
|
||||
#define IP_PROTO_TCP 6
|
||||
|
||||
/* This is passed as the destination address to ip_output_if (not
|
||||
to ip_output), meaning that an IP header already is constructed
|
||||
in the pbuf. This is used when TCP retransmits. */
|
||||
#ifdef IP_HDRINCL
|
||||
#undef IP_HDRINCL
|
||||
#endif /* IP_HDRINCL */
|
||||
#define IP_HDRINCL NULL
|
||||
|
||||
|
||||
/* The IPv6 header. */
|
||||
struct ip_hdr {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
u8_t tclass1:4, v:4;
|
||||
u8_t flow1:4, tclass2:4;
|
||||
#else
|
||||
u8_t v:4, tclass1:4;
|
||||
u8_t tclass2:8, flow1:4;
|
||||
#endif
|
||||
u16_t flow2;
|
||||
u16_t len; /* payload length */
|
||||
u8_t nexthdr; /* next header */
|
||||
u8_t hoplim; /* hop limit (TTL) */
|
||||
struct ip_addr src, dest; /* source and destination IP addresses */
|
||||
};
|
||||
|
||||
void ip_init(void);
|
||||
|
||||
#include "lwip/netif.h"
|
||||
|
||||
struct netif *ip_route(struct ip_addr *dest);
|
||||
|
||||
void ip_input(struct pbuf *p, struct netif *inp);
|
||||
|
||||
/* source and destination addresses in network byte order, please */
|
||||
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
unsigned char ttl, unsigned char proto);
|
||||
|
||||
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
unsigned char ttl, unsigned char proto,
|
||||
struct netif *netif);
|
||||
|
||||
#if IP_DEBUG
|
||||
void ip_debug_print(struct pbuf *p);
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
#endif /* __LWIP_IP_H__ */
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_IP_ADDR_H__
|
||||
#define __LWIP_IP_ADDR_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#define IP_ADDR_ANY 0
|
||||
|
||||
struct ip_addr {
|
||||
u32_t addr[4];
|
||||
};
|
||||
|
||||
#define IP6_ADDR(ipaddr, a,b,c,d,e,f,g,h) do { (ipaddr)->addr[0] = htonl((u32_t)((a & 0xffff) << 16) | (b & 0xffff)); \
|
||||
(ipaddr)->addr[1] = htonl(((c & 0xffff) << 16) | (d & 0xffff)); \
|
||||
(ipaddr)->addr[2] = htonl(((e & 0xffff) << 16) | (f & 0xffff)); \
|
||||
(ipaddr)->addr[3] = htonl(((g & 0xffff) << 16) | (h & 0xffff)); } while(0)
|
||||
|
||||
int ip_addr_netcmp(struct ip_addr *addr1, struct ip_addr *addr2,
|
||||
struct ip_addr *mask);
|
||||
int ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2);
|
||||
void ip_addr_set(struct ip_addr *dest, struct ip_addr *src);
|
||||
int ip_addr_isany(struct ip_addr *addr);
|
||||
|
||||
|
||||
#if IP_DEBUG
|
||||
void ip_addr_debug_print(struct ip_addr *addr);
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
#endif /* __LWIP_IP_ADDR_H__ */
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_API_H__
|
||||
#define __LWIP_API_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/ip.h"
|
||||
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
#define NETCONN_NOCOPY 0x00
|
||||
#define NETCONN_COPY 0x01
|
||||
|
||||
enum netconn_type {
|
||||
NETCONN_TCP,
|
||||
NETCONN_UDP,
|
||||
NETCONN_UDPLITE,
|
||||
NETCONN_UDPNOCHKSUM,
|
||||
NETCONN_RAW
|
||||
};
|
||||
|
||||
enum netconn_state {
|
||||
NETCONN_NONE,
|
||||
NETCONN_WRITE,
|
||||
NETCONN_ACCEPT,
|
||||
NETCONN_RECV,
|
||||
NETCONN_CONNECT,
|
||||
NETCONN_CLOSE
|
||||
};
|
||||
|
||||
enum netconn_evt {
|
||||
NETCONN_EVT_RCVPLUS,
|
||||
NETCONN_EVT_RCVMINUS,
|
||||
NETCONN_EVT_SENDPLUS,
|
||||
NETCONN_EVT_SENDMINUS
|
||||
};
|
||||
|
||||
struct netbuf {
|
||||
struct pbuf *p, *ptr;
|
||||
struct ip_addr *fromaddr;
|
||||
u16_t fromport;
|
||||
err_t err;
|
||||
};
|
||||
|
||||
struct netconn {
|
||||
enum netconn_type type;
|
||||
enum netconn_state state;
|
||||
union {
|
||||
struct tcp_pcb *tcp;
|
||||
struct udp_pcb *udp;
|
||||
struct raw_pcb *raw;
|
||||
} pcb;
|
||||
err_t err;
|
||||
sys_mbox_t mbox;
|
||||
sys_mbox_t recvmbox;
|
||||
sys_mbox_t acceptmbox;
|
||||
sys_sem_t sem;
|
||||
int socket;
|
||||
u16_t recv_avail;
|
||||
void (* callback)(struct netconn *, enum netconn_evt, u16_t len);
|
||||
};
|
||||
|
||||
/* Network buffer functions: */
|
||||
struct netbuf * netbuf_new (void);
|
||||
void netbuf_delete (struct netbuf *buf);
|
||||
void * netbuf_alloc (struct netbuf *buf, u16_t size);
|
||||
void netbuf_free (struct netbuf *buf);
|
||||
void netbuf_ref (struct netbuf *buf,
|
||||
void *dataptr, u16_t size);
|
||||
void netbuf_chain (struct netbuf *head,
|
||||
struct netbuf *tail);
|
||||
|
||||
u16_t netbuf_len (struct netbuf *buf);
|
||||
err_t netbuf_data (struct netbuf *buf,
|
||||
void **dataptr, u16_t *len);
|
||||
s8_t netbuf_next (struct netbuf *buf);
|
||||
void netbuf_first (struct netbuf *buf);
|
||||
|
||||
void netbuf_copy (struct netbuf *buf,
|
||||
void *dataptr, u16_t len);
|
||||
void netbuf_copy_partial(struct netbuf *buf, void *dataptr,
|
||||
u16_t len, u16_t offset);
|
||||
struct ip_addr * netbuf_fromaddr (struct netbuf *buf);
|
||||
u16_t netbuf_fromport (struct netbuf *buf);
|
||||
|
||||
/* Network connection functions: */
|
||||
struct netconn * netconn_new (enum netconn_type type);
|
||||
struct
|
||||
netconn *netconn_new_with_callback(enum netconn_type t,
|
||||
void (*callback)(struct netconn *, enum netconn_evt, u16_t len));
|
||||
struct
|
||||
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
|
||||
void (*callback)(struct netconn *, enum netconn_evt, u16_t len));
|
||||
err_t netconn_delete (struct netconn *conn);
|
||||
enum netconn_type netconn_type (struct netconn *conn);
|
||||
err_t netconn_peer (struct netconn *conn,
|
||||
struct ip_addr *addr,
|
||||
u16_t *port);
|
||||
err_t netconn_addr (struct netconn *conn,
|
||||
struct ip_addr **addr,
|
||||
u16_t *port);
|
||||
err_t netconn_bind (struct netconn *conn,
|
||||
struct ip_addr *addr,
|
||||
u16_t port);
|
||||
err_t netconn_connect (struct netconn *conn,
|
||||
struct ip_addr *addr,
|
||||
u16_t port);
|
||||
err_t netconn_disconnect (struct netconn *conn);
|
||||
err_t netconn_listen (struct netconn *conn);
|
||||
struct netconn * netconn_accept (struct netconn *conn);
|
||||
struct netbuf * netconn_recv (struct netconn *conn);
|
||||
err_t netconn_send (struct netconn *conn,
|
||||
struct netbuf *buf);
|
||||
err_t netconn_write (struct netconn *conn,
|
||||
void *dataptr, u16_t size,
|
||||
u8_t copy);
|
||||
err_t netconn_close (struct netconn *conn);
|
||||
|
||||
err_t netconn_err (struct netconn *conn);
|
||||
|
||||
#endif /* __LWIP_API_H__ */
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_API_MSG_H__
|
||||
#define __LWIP_API_MSG_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/ip.h"
|
||||
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include "lwip/api.h"
|
||||
|
||||
enum api_msg_type {
|
||||
API_MSG_NEWCONN,
|
||||
API_MSG_DELCONN,
|
||||
|
||||
API_MSG_BIND,
|
||||
API_MSG_CONNECT,
|
||||
API_MSG_DISCONNECT,
|
||||
|
||||
API_MSG_LISTEN,
|
||||
API_MSG_ACCEPT,
|
||||
|
||||
API_MSG_SEND,
|
||||
API_MSG_RECV,
|
||||
API_MSG_WRITE,
|
||||
|
||||
API_MSG_CLOSE,
|
||||
|
||||
API_MSG_MAX
|
||||
};
|
||||
|
||||
struct api_msg_msg {
|
||||
struct netconn *conn;
|
||||
enum netconn_type conntype;
|
||||
union {
|
||||
struct pbuf *p;
|
||||
struct {
|
||||
struct ip_addr *ipaddr;
|
||||
u16_t port;
|
||||
} bc;
|
||||
struct {
|
||||
void *dataptr;
|
||||
u16_t len;
|
||||
unsigned char copy;
|
||||
} w;
|
||||
sys_mbox_t mbox;
|
||||
u16_t len;
|
||||
} msg;
|
||||
};
|
||||
|
||||
struct api_msg {
|
||||
enum api_msg_type type;
|
||||
struct api_msg_msg msg;
|
||||
};
|
||||
|
||||
void api_msg_input(struct api_msg *msg);
|
||||
void api_msg_post(struct api_msg *msg);
|
||||
|
||||
#endif /* __LWIP_API_MSG_H__ */
|
||||
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_ARCH_H__
|
||||
#define __LWIP_ARCH_H__
|
||||
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
|
||||
#ifndef BIG_ENDIAN
|
||||
#define BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
#ifndef PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#endif /* PACK_STRUCT_BEGIN */
|
||||
|
||||
#ifndef PACK_STRUCT_END
|
||||
#define PACK_STRUCT_END
|
||||
#endif /* PACK_STRUCT_END */
|
||||
|
||||
#ifndef PACK_STRUCT_FIELD
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
#endif /* PACK_STRUCT_FIELD */
|
||||
|
||||
|
||||
|
||||
#ifdef LWIP_PROVIDE_ERRNO
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Arg list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
#define ENOSYS 38 /* Function not implemented */
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
|
||||
#define EDEADLOCK EDEADLK
|
||||
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale NFS file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
|
||||
|
||||
#define ENSROK 0 /* DNS server returned answer with no data */
|
||||
#define ENSRNODATA 160 /* DNS server returned answer with no data */
|
||||
#define ENSRFORMERR 161 /* DNS server claims query was misformatted */
|
||||
#define ENSRSERVFAIL 162 /* DNS server returned general failure */
|
||||
#define ENSRNOTFOUND 163 /* Domain name not found */
|
||||
#define ENSRNOTIMP 164 /* DNS server does not implement requested operation */
|
||||
#define ENSRREFUSED 165 /* DNS server refused query */
|
||||
#define ENSRBADQUERY 166 /* Misformatted DNS query */
|
||||
#define ENSRBADNAME 167 /* Misformatted domain name */
|
||||
#define ENSRBADFAMILY 168 /* Unsupported address family */
|
||||
#define ENSRBADRESP 169 /* Misformatted DNS reply */
|
||||
#define ENSRCONNREFUSED 170 /* Could not contact DNS servers */
|
||||
#define ENSRTIMEOUT 171 /* Timeout while contacting DNS servers */
|
||||
#define ENSROF 172 /* End of file */
|
||||
#define ENSRFILE 173 /* Error reading file */
|
||||
#define ENSRNOMEM 174 /* Out of memory */
|
||||
#define ENSRDESTRUCTION 175 /* Application terminated lookup */
|
||||
#define ENSRQUERYDOMAINTOOLONG 176 /* Domain name is too long */
|
||||
#define ENSRCNAMELOOP 177 /* Domain name is too long */
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_PROVIDE_ERRNO */
|
||||
|
||||
#endif /* __LWIP_ARCH_H__ */
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_DEBUG_H__
|
||||
#define __LWIP_DEBUG_H__
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
/** lower two bits indicate debug level
|
||||
* - 0 off
|
||||
* - 1 warning
|
||||
* - 2 serious
|
||||
* - 3 severe
|
||||
*/
|
||||
|
||||
#define DBG_LEVEL_OFF 0
|
||||
#define DBG_LEVEL_WARNING 1 /* bad checksums, dropped packets, ... */
|
||||
#define DBG_LEVEL_SERIOUS 2 /* memory allocation failures, ... */
|
||||
#define DBG_LEVEL_SEVERE 3 /* */
|
||||
#define DBG_MASK_LEVEL 3
|
||||
|
||||
/** flag for LWIP_DEBUGF to enable that debug message */
|
||||
#define DBG_ON 0x80U
|
||||
/** flag for LWIP_DEBUGF to disable that debug message */
|
||||
#define DBG_OFF 0x00U
|
||||
|
||||
/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */
|
||||
#define DBG_TRACE 0x40U
|
||||
/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */
|
||||
#define DBG_STATE 0x20U
|
||||
/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */
|
||||
#define DBG_FRESH 0x10U
|
||||
/** flag for LWIP_DEBUGF to halt after printing this debug message */
|
||||
#define DBG_HALT 0x08U
|
||||
|
||||
#ifndef LWIP_NOASSERT
|
||||
# define LWIP_ASSERT(x,y) do { if(!(y)) LWIP_PLATFORM_ASSERT(x); } while(0)
|
||||
#else
|
||||
# define LWIP_ASSERT(x,y)
|
||||
#endif
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
/** print debug message only if debug message type is enabled...
|
||||
* AND is of correct type AND is at least DBG_LEVEL
|
||||
*/
|
||||
# define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && ((int)((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0)
|
||||
# define LWIP_ERROR(x) do { LWIP_PLATFORM_DIAG(x); } while(0)
|
||||
#else /* LWIP_DEBUG */
|
||||
# define LWIP_DEBUGF(debug,x)
|
||||
# define LWIP_ERROR(x)
|
||||
#endif /* LWIP_DEBUG */
|
||||
|
||||
#endif /* __LWIP_DEBUG_H__ */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_DEF_H__
|
||||
#define __LWIP_DEF_H__
|
||||
|
||||
/* this might define NULL already */
|
||||
#include "arch/cc.h"
|
||||
|
||||
#define LWIP_MAX(x , y) (x) > (y) ? (x) : (y)
|
||||
#define LWIP_MIN(x , y) (x) < (y) ? (x) : (y)
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __LWIP_DEF_H__ */
|
||||
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
/** @file
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_DHCP_H__
|
||||
#define __LWIP_DHCP_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/udp.h"
|
||||
|
||||
/** period (in seconds) of the application calling dhcp_coarse_tmr() */
|
||||
#define DHCP_COARSE_TIMER_SECS 60
|
||||
/** period (in milliseconds) of the application calling dhcp_fine_tmr() */
|
||||
#define DHCP_FINE_TIMER_MSECS 500
|
||||
|
||||
struct dhcp
|
||||
{
|
||||
/** current DHCP state machine state */
|
||||
u8_t state;
|
||||
/** retries of current request */
|
||||
u8_t tries;
|
||||
/** transaction identifier of last sent request */
|
||||
u32_t xid;
|
||||
/** our connection to the DHCP server */
|
||||
struct udp_pcb *pcb;
|
||||
/** (first) pbuf of incoming msg */
|
||||
struct pbuf *p;
|
||||
/** incoming msg */
|
||||
struct dhcp_msg *msg_in;
|
||||
/** incoming msg options */
|
||||
struct dhcp_msg *options_in;
|
||||
/** ingoing msg options length */
|
||||
u16_t options_in_len;
|
||||
|
||||
struct pbuf *p_out; /* pbuf of outcoming msg */
|
||||
struct dhcp_msg *msg_out; /* outgoing msg */
|
||||
u16_t options_out_len; /* outgoing msg options length */
|
||||
u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */
|
||||
u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */
|
||||
u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */
|
||||
struct ip_addr server_ip_addr; /* dhcp server address that offered this lease */
|
||||
struct ip_addr offered_ip_addr;
|
||||
struct ip_addr offered_sn_mask;
|
||||
struct ip_addr offered_gw_addr;
|
||||
struct ip_addr offered_bc_addr;
|
||||
#define DHCP_MAX_DNS 2
|
||||
u32_t dns_count; /* actual number of DNS servers obtained */
|
||||
struct ip_addr offered_dns_addr[DHCP_MAX_DNS]; /* DNS server addresses */
|
||||
|
||||
u32_t offered_t0_lease; /* lease period (in seconds) */
|
||||
u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
|
||||
u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */
|
||||
/** Patch #1308
|
||||
* TODO: See dhcp.c "TODO"s
|
||||
*/
|
||||
#if 0
|
||||
struct ip_addr offered_si_addr;
|
||||
u8_t *boot_file_name;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* MUST be compiled with "pack structs" or equivalent! */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** minimum set of fields of any DHCP message */
|
||||
struct dhcp_msg
|
||||
{
|
||||
PACK_STRUCT_FIELD(u8_t op);
|
||||
PACK_STRUCT_FIELD(u8_t htype);
|
||||
PACK_STRUCT_FIELD(u8_t hlen);
|
||||
PACK_STRUCT_FIELD(u8_t hops);
|
||||
PACK_STRUCT_FIELD(u32_t xid);
|
||||
PACK_STRUCT_FIELD(u16_t secs);
|
||||
PACK_STRUCT_FIELD(u16_t flags);
|
||||
PACK_STRUCT_FIELD(struct ip_addr ciaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr yiaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr siaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr giaddr);
|
||||
#define DHCP_CHADDR_LEN 16U
|
||||
PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]);
|
||||
#define DHCP_SNAME_LEN 64U
|
||||
PACK_STRUCT_FIELD(u8_t sname[DHCP_SNAME_LEN]);
|
||||
#define DHCP_FILE_LEN 128U
|
||||
PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]);
|
||||
PACK_STRUCT_FIELD(u32_t cookie);
|
||||
#define DHCP_MIN_OPTIONS_LEN 68U
|
||||
/** make sure user does not configure this too small */
|
||||
#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
|
||||
# undef DHCP_OPTIONS_LEN
|
||||
#endif
|
||||
/** allow this to be configured in lwipopts.h, but not too small */
|
||||
#if (!defined(DHCP_OPTIONS_LEN))
|
||||
/** set this to be sufficient for your options in outgoing DHCP msgs */
|
||||
# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN
|
||||
#endif
|
||||
PACK_STRUCT_FIELD(u8_t options[DHCP_OPTIONS_LEN]);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** start DHCP configuration */
|
||||
err_t dhcp_start(struct netif *netif);
|
||||
/** enforce early lease renewal (not needed normally)*/
|
||||
err_t dhcp_renew(struct netif *netif);
|
||||
/** release the DHCP lease, usually called before dhcp_stop()*/
|
||||
err_t dhcp_release(struct netif *netif);
|
||||
/** stop DHCP configuration */
|
||||
void dhcp_stop(struct netif *netif);
|
||||
/** inform server of our manual IP address */
|
||||
void dhcp_inform(struct netif *netif);
|
||||
|
||||
/** if enabled, check whether the offered IP address is not in use, using ARP */
|
||||
#if DHCP_DOES_ARP_CHECK
|
||||
void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr);
|
||||
#endif
|
||||
|
||||
/** to be called every minute */
|
||||
void dhcp_coarse_tmr(void);
|
||||
/** to be called every half second */
|
||||
void dhcp_fine_tmr(void);
|
||||
|
||||
/** DHCP message item offsets and length */
|
||||
#define DHCP_MSG_OFS (UDP_DATA_OFS)
|
||||
#define DHCP_OP_OFS (DHCP_MSG_OFS + 0)
|
||||
#define DHCP_HTYPE_OFS (DHCP_MSG_OFS + 1)
|
||||
#define DHCP_HLEN_OFS (DHCP_MSG_OFS + 2)
|
||||
#define DHCP_HOPS_OFS (DHCP_MSG_OFS + 3)
|
||||
#define DHCP_XID_OFS (DHCP_MSG_OFS + 4)
|
||||
#define DHCP_SECS_OFS (DHCP_MSG_OFS + 8)
|
||||
#define DHCP_FLAGS_OFS (DHCP_MSG_OFS + 10)
|
||||
#define DHCP_CIADDR_OFS (DHCP_MSG_OFS + 12)
|
||||
#define DHCP_YIADDR_OFS (DHCP_MSG_OFS + 16)
|
||||
#define DHCP_SIADDR_OFS (DHCP_MSG_OFS + 20)
|
||||
#define DHCP_GIADDR_OFS (DHCP_MSG_OFS + 24)
|
||||
#define DHCP_CHADDR_OFS (DHCP_MSG_OFS + 28)
|
||||
#define DHCP_SNAME_OFS (DHCP_MSG_OFS + 44)
|
||||
#define DHCP_FILE_OFS (DHCP_MSG_OFS + 108)
|
||||
#define DHCP_MSG_LEN 236
|
||||
|
||||
#define DHCP_COOKIE_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN)
|
||||
#define DHCP_OPTIONS_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN + 4)
|
||||
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
#define DHCP_SERVER_PORT 67
|
||||
|
||||
/** DHCP client states */
|
||||
#define DHCP_REQUESTING 1
|
||||
#define DHCP_INIT 2
|
||||
#define DHCP_REBOOTING 3
|
||||
#define DHCP_REBINDING 4
|
||||
#define DHCP_RENEWING 5
|
||||
#define DHCP_SELECTING 6
|
||||
#define DHCP_INFORMING 7
|
||||
#define DHCP_CHECKING 8
|
||||
#define DHCP_PERMANENT 9
|
||||
#define DHCP_BOUND 10
|
||||
/** not yet implemented #define DHCP_RELEASING 11 */
|
||||
#define DHCP_BACKING_OFF 12
|
||||
#define DHCP_OFF 13
|
||||
|
||||
#define DHCP_BOOTREQUEST 1
|
||||
#define DHCP_BOOTREPLY 2
|
||||
|
||||
#define DHCP_DISCOVER 1
|
||||
#define DHCP_OFFER 2
|
||||
#define DHCP_REQUEST 3
|
||||
#define DHCP_DECLINE 4
|
||||
#define DHCP_ACK 5
|
||||
#define DHCP_NAK 6
|
||||
#define DHCP_RELEASE 7
|
||||
#define DHCP_INFORM 8
|
||||
|
||||
#define DHCP_HTYPE_ETH 1
|
||||
|
||||
#define DHCP_HLEN_ETH 6
|
||||
|
||||
#define DHCP_BROADCAST_FLAG 15
|
||||
#define DHCP_BROADCAST_MASK (1 << DHCP_FLAG_BROADCAST)
|
||||
|
||||
/** BootP options */
|
||||
#define DHCP_OPTION_PAD 0
|
||||
#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */
|
||||
#define DHCP_OPTION_ROUTER 3
|
||||
#define DHCP_OPTION_DNS_SERVER 6
|
||||
#define DHCP_OPTION_HOSTNAME 12
|
||||
#define DHCP_OPTION_IP_TTL 23
|
||||
#define DHCP_OPTION_MTU 26
|
||||
#define DHCP_OPTION_BROADCAST 28
|
||||
#define DHCP_OPTION_TCP_TTL 37
|
||||
#define DHCP_OPTION_END 255
|
||||
|
||||
/** DHCP options */
|
||||
#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */
|
||||
#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */
|
||||
#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */
|
||||
|
||||
#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */
|
||||
#define DHCP_OPTION_MESSAGE_TYPE_LEN 1
|
||||
|
||||
|
||||
#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */
|
||||
#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */
|
||||
|
||||
#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */
|
||||
#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2
|
||||
|
||||
#define DHCP_OPTION_T1 58 /* T1 renewal time */
|
||||
#define DHCP_OPTION_T2 59 /* T2 rebinding time */
|
||||
#define DHCP_OPTION_CLIENT_ID 61
|
||||
#define DHCP_OPTION_TFTP_SERVERNAME 66
|
||||
#define DHCP_OPTION_BOOTFILE 67
|
||||
|
||||
/** possible combinations of overloading the file and sname fields with options */
|
||||
#define DHCP_OVERLOAD_NONE 0
|
||||
#define DHCP_OVERLOAD_FILE 1
|
||||
#define DHCP_OVERLOAD_SNAME 2
|
||||
#define DHCP_OVERLOAD_SNAME_FILE 3
|
||||
|
||||
#endif /*__LWIP_DHCP_H__*/
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_ERR_H__
|
||||
#define __LWIP_ERR_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
typedef s8_t err_t;
|
||||
|
||||
/* Definitions for error constants. */
|
||||
|
||||
#define ERR_OK 0 /* No error, everything OK. */
|
||||
#define ERR_MEM -1 /* Out of memory error. */
|
||||
#define ERR_BUF -2 /* Buffer error. */
|
||||
|
||||
|
||||
#define ERR_ABRT -3 /* Connection aborted. */
|
||||
#define ERR_RST -4 /* Connection reset. */
|
||||
#define ERR_CLSD -5 /* Connection closed. */
|
||||
#define ERR_CONN -6 /* Not connected. */
|
||||
|
||||
#define ERR_VAL -7 /* Illegal value. */
|
||||
|
||||
#define ERR_ARG -8 /* Illegal argument. */
|
||||
|
||||
#define ERR_RTE -9 /* Routing problem. */
|
||||
|
||||
#define ERR_USE -10 /* Address in use. */
|
||||
|
||||
#define ERR_IF -11 /* Low-level netif error */
|
||||
#define ERR_ISCONN -12 /* Already connected. */
|
||||
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
extern char *lwip_strerr(err_t err);
|
||||
#else
|
||||
#define lwip_strerr(x) ""
|
||||
#endif /* LWIP_DEBUG */
|
||||
#endif /* __LWIP_ERR_H__ */
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_MEM_H__
|
||||
#define __LWIP_MEM_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#if MEM_SIZE > 64000l
|
||||
typedef u32_t mem_size_t;
|
||||
#else
|
||||
typedef u16_t mem_size_t;
|
||||
#endif /* MEM_SIZE > 64000 */
|
||||
|
||||
|
||||
void mem_init(void);
|
||||
|
||||
void *mem_malloc(mem_size_t size);
|
||||
void mem_free(void *mem);
|
||||
void *mem_realloc(void *mem, mem_size_t size);
|
||||
void *mem_reallocm(void *mem, mem_size_t size);
|
||||
|
||||
#ifndef MEM_ALIGN_SIZE
|
||||
#define MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1))
|
||||
#endif
|
||||
|
||||
#ifndef MEM_ALIGN
|
||||
#define MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_MEM_H__ */
|
||||
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_MEMP_H__
|
||||
#define __LWIP_MEMP_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
typedef enum {
|
||||
MEMP_PBUF,
|
||||
MEMP_RAW_PCB,
|
||||
MEMP_UDP_PCB,
|
||||
MEMP_TCP_PCB,
|
||||
MEMP_TCP_PCB_LISTEN,
|
||||
MEMP_TCP_SEG,
|
||||
|
||||
MEMP_NETBUF,
|
||||
MEMP_NETCONN,
|
||||
MEMP_API_MSG,
|
||||
MEMP_TCPIP_MSG,
|
||||
|
||||
MEMP_SYS_TIMEOUT,
|
||||
|
||||
MEMP_MAX
|
||||
} memp_t;
|
||||
|
||||
void memp_init(void);
|
||||
|
||||
void *memp_malloc(memp_t type);
|
||||
void *memp_realloc(memp_t fromtype, memp_t totype, void *mem);
|
||||
void memp_free(memp_t type, void *mem);
|
||||
|
||||
#endif /* __LWIP_MEMP_H__ */
|
||||
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_NETIF_H__
|
||||
#define __LWIP_NETIF_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#if LWIP_DHCP
|
||||
# include "lwip/dhcp.h"
|
||||
#endif
|
||||
|
||||
/** must be the maximum of all used hardware address lengths
|
||||
across all types of interfaces in use */
|
||||
#define NETIF_MAX_HWADDR_LEN 6U
|
||||
|
||||
/** TODO: define the use (where, when, whom) of netif flags */
|
||||
|
||||
/** whether the network interface is 'up'. this is
|
||||
* a software flag used to control whether this network
|
||||
* interface is enabled and processes traffic.
|
||||
*/
|
||||
#define NETIF_FLAG_UP 0x1U
|
||||
/** if set, the netif has broadcast capability */
|
||||
#define NETIF_FLAG_BROADCAST 0x2U
|
||||
/** if set, the netif is one end of a point-to-point connection */
|
||||
#define NETIF_FLAG_POINTTOPOINT 0x4U
|
||||
/** if set, the interface is configured using DHCP */
|
||||
#define NETIF_FLAG_DHCP 0x08U
|
||||
/** if set, the interface has an active link
|
||||
* (set by the network interface driver) */
|
||||
#define NETIF_FLAG_LINK_UP 0x10U
|
||||
|
||||
/** Generic data structure used for all lwIP network interfaces.
|
||||
* The following fields should be filled in by the initialization
|
||||
* function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
|
||||
|
||||
struct netif {
|
||||
/** pointer to next in linked list */
|
||||
struct netif *next;
|
||||
|
||||
/** IP address configuration in network byte order */
|
||||
struct ip_addr ip_addr;
|
||||
struct ip_addr netmask;
|
||||
struct ip_addr gw;
|
||||
|
||||
/** This function is called by the network device driver
|
||||
* to pass a packet up the TCP/IP stack. */
|
||||
err_t (* input)(struct pbuf *p, struct netif *inp);
|
||||
/** This function is called by the IP module when it wants
|
||||
* to send a packet on the interface. This function typically
|
||||
* first resolves the hardware address, then sends the packet. */
|
||||
err_t (* output)(struct netif *netif, struct pbuf *p,
|
||||
struct ip_addr *ipaddr);
|
||||
/** This function is called by the ARP module when it wants
|
||||
* to send a packet on the interface. This function outputs
|
||||
* the pbuf as-is on the link medium. */
|
||||
err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
|
||||
/** This field can be set by the device driver and could point
|
||||
* to state information for the device. */
|
||||
void *state;
|
||||
#if LWIP_DHCP
|
||||
/** the DHCP client state information for this netif */
|
||||
struct dhcp *dhcp;
|
||||
#endif
|
||||
/** number of bytes used in hwaddr */
|
||||
unsigned char hwaddr_len;
|
||||
/** link level hardware address of this interface */
|
||||
unsigned char hwaddr[NETIF_MAX_HWADDR_LEN];
|
||||
/** maximum transfer unit (in bytes) */
|
||||
u16_t mtu;
|
||||
/** flags (see NETIF_FLAG_ above) */
|
||||
u8_t flags;
|
||||
/** link type */
|
||||
u8_t link_type;
|
||||
/** descriptive abbreviation */
|
||||
char name[2];
|
||||
/** number of this interface */
|
||||
u8_t num;
|
||||
};
|
||||
|
||||
/** The list of network interfaces. */
|
||||
extern struct netif *netif_list;
|
||||
/** The default network interface. */
|
||||
extern struct netif *netif_default;
|
||||
|
||||
/* netif_init() must be called first. */
|
||||
void netif_init(void);
|
||||
|
||||
struct netif *netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw,
|
||||
void *state,
|
||||
err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif));
|
||||
|
||||
void
|
||||
netif_set_addr(struct netif *netif,struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw);
|
||||
void netif_remove(struct netif * netif);
|
||||
|
||||
/* Returns a network interface given its name. The name is of the form
|
||||
"et0", where the first two letters are the "name" field in the
|
||||
netif structure, and the digit is in the num field in the same
|
||||
structure. */
|
||||
struct netif *netif_find(char *name);
|
||||
|
||||
void netif_set_default(struct netif *netif);
|
||||
|
||||
void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr);
|
||||
void netif_set_netmask(struct netif *netif, struct ip_addr *netmast);
|
||||
void netif_set_gw(struct netif *netif, struct ip_addr *gw);
|
||||
void netif_set_up(struct netif *netif);
|
||||
void netif_set_down(struct netif *netif);
|
||||
u8_t netif_is_up(struct netif *netif);
|
||||
|
||||
#endif /* __LWIP_NETIF_H__ */
|
||||
|
|
@ -0,0 +1,669 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_OPT_H__
|
||||
#define __LWIP_OPT_H__
|
||||
|
||||
/* Include user defined options first */
|
||||
#include "lwipopts.h"
|
||||
#include "lwip/debug.h"
|
||||
|
||||
/* Define default values for unconfigured parameters. */
|
||||
|
||||
/* Platform specific locking */
|
||||
|
||||
/*
|
||||
* enable SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection
|
||||
* for certain critical regions during buffer allocation, deallocation and memory
|
||||
* allocation and deallocation.
|
||||
*/
|
||||
#ifndef SYS_LIGHTWEIGHT_PROT
|
||||
#define SYS_LIGHTWEIGHT_PROT 0
|
||||
#endif
|
||||
|
||||
#ifndef NO_SYS
|
||||
#define NO_SYS 0
|
||||
#endif
|
||||
/* ---------- Memory options ---------- */
|
||||
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
|
||||
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
|
||||
byte alignment -> define MEM_ALIGNMENT to 2. */
|
||||
|
||||
#ifndef MEM_ALIGNMENT
|
||||
#define MEM_ALIGNMENT 1
|
||||
#endif
|
||||
|
||||
/* MEM_SIZE: the size of the heap memory. If the application will send
|
||||
a lot of data that needs to be copied, this should be set high. */
|
||||
#ifndef MEM_SIZE
|
||||
#define MEM_SIZE 1600
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_SANITY_CHECK
|
||||
#define MEMP_SANITY_CHECK 0
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
|
||||
sends a lot of data out of ROM (or other static memory), this
|
||||
should be set high. */
|
||||
#ifndef MEMP_NUM_PBUF
|
||||
#define MEMP_NUM_PBUF 16
|
||||
#endif
|
||||
|
||||
/* Number of raw connection PCBs */
|
||||
#ifndef MEMP_NUM_RAW_PCB
|
||||
#define MEMP_NUM_RAW_PCB 4
|
||||
#endif
|
||||
|
||||
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
|
||||
per active UDP "connection". */
|
||||
#ifndef MEMP_NUM_UDP_PCB
|
||||
#define MEMP_NUM_UDP_PCB 4
|
||||
#endif
|
||||
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
|
||||
connections. */
|
||||
#ifndef MEMP_NUM_TCP_PCB
|
||||
#define MEMP_NUM_TCP_PCB 5
|
||||
#endif
|
||||
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
|
||||
connections. */
|
||||
#ifndef MEMP_NUM_TCP_PCB_LISTEN
|
||||
#define MEMP_NUM_TCP_PCB_LISTEN 8
|
||||
#endif
|
||||
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
|
||||
segments. */
|
||||
#ifndef MEMP_NUM_TCP_SEG
|
||||
#define MEMP_NUM_TCP_SEG 16
|
||||
#endif
|
||||
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
|
||||
timeouts. */
|
||||
#ifndef MEMP_NUM_SYS_TIMEOUT
|
||||
#define MEMP_NUM_SYS_TIMEOUT 3
|
||||
#endif
|
||||
|
||||
/* The following four are used only with the sequential API and can be
|
||||
set to 0 if the application only will use the raw API. */
|
||||
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
|
||||
#ifndef MEMP_NUM_NETBUF
|
||||
#define MEMP_NUM_NETBUF 2
|
||||
#endif
|
||||
/* MEMP_NUM_NETCONN: the number of struct netconns. */
|
||||
#ifndef MEMP_NUM_NETCONN
|
||||
#define MEMP_NUM_NETCONN 4
|
||||
#endif
|
||||
/* MEMP_NUM_APIMSG: the number of struct api_msg, used for
|
||||
communication between the TCP/IP stack and the sequential
|
||||
programs. */
|
||||
#ifndef MEMP_NUM_API_MSG
|
||||
#define MEMP_NUM_API_MSG 8
|
||||
#endif
|
||||
/* MEMP_NUM_TCPIPMSG: the number of struct tcpip_msg, which is used
|
||||
for sequential API communication and incoming packets. Used in
|
||||
src/api/tcpip.c. */
|
||||
#ifndef MEMP_NUM_TCPIP_MSG
|
||||
#define MEMP_NUM_TCPIP_MSG 8
|
||||
#endif
|
||||
|
||||
/* ---------- Pbuf options ---------- */
|
||||
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
|
||||
|
||||
#ifndef PBUF_POOL_SIZE
|
||||
#define PBUF_POOL_SIZE 16
|
||||
#endif
|
||||
|
||||
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
|
||||
|
||||
#ifndef PBUF_POOL_BUFSIZE
|
||||
#define PBUF_POOL_BUFSIZE 128
|
||||
#endif
|
||||
|
||||
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
|
||||
link level header. Defaults to 14 for Ethernet. */
|
||||
|
||||
#ifndef PBUF_LINK_HLEN
|
||||
#define PBUF_LINK_HLEN 14
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* ---------- ARP options ---------- */
|
||||
|
||||
/** Number of active hardware address, IP address pairs cached */
|
||||
#ifndef ARP_TABLE_SIZE
|
||||
#define ARP_TABLE_SIZE 10
|
||||
#endif
|
||||
|
||||
/**
|
||||
* If enabled, outgoing packets are queued during hardware address
|
||||
* resolution.
|
||||
*
|
||||
* This feature has not stabilized yet. Single-packet queueing is
|
||||
* believed to be stable, multi-packet queueing is believed to
|
||||
* clash with the TCP segment queueing.
|
||||
*
|
||||
* As multi-packet-queueing is currently disabled, enabling this
|
||||
* _should_ work, but we need your testing feedback on lwip-users.
|
||||
*
|
||||
*/
|
||||
#ifndef ARP_QUEUEING
|
||||
#define ARP_QUEUEING 1
|
||||
#endif
|
||||
|
||||
/* This option is deprecated */
|
||||
#ifdef ETHARP_QUEUE_FIRST
|
||||
#error ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h.
|
||||
#endif
|
||||
|
||||
/* This option is removed to comply with the ARP standard */
|
||||
#ifdef ETHARP_ALWAYS_INSERT
|
||||
#error ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h.
|
||||
#endif
|
||||
|
||||
/* ---------- IP options ---------- */
|
||||
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
|
||||
IP packets across network interfaces. If you are going to run lwIP
|
||||
on a device with only one network interface, define this to 0. */
|
||||
#ifndef IP_FORWARD
|
||||
#define IP_FORWARD 0
|
||||
#endif
|
||||
|
||||
/* If defined to 1, IP options are allowed (but not parsed). If
|
||||
defined to 0, all packets with IP options are dropped. */
|
||||
#ifndef IP_OPTIONS
|
||||
#define IP_OPTIONS 1
|
||||
#endif
|
||||
|
||||
/** IP reassembly and segmentation. Even if they both deal with IP
|
||||
* fragments, note that these are orthogonal, one dealing with incoming
|
||||
* packets, the other with outgoing packets
|
||||
*/
|
||||
|
||||
/** Reassemble incoming fragmented IP packets */
|
||||
#ifndef IP_REASSEMBLY
|
||||
#define IP_REASSEMBLY 1
|
||||
#endif
|
||||
|
||||
/** Fragment outgoing IP packets if their size exceeds MTU */
|
||||
#ifndef IP_FRAG
|
||||
#define IP_FRAG 1
|
||||
#endif
|
||||
|
||||
/* ---------- ICMP options ---------- */
|
||||
|
||||
#ifndef ICMP_TTL
|
||||
#define ICMP_TTL 255
|
||||
#endif
|
||||
|
||||
/* ---------- RAW options ---------- */
|
||||
|
||||
#ifndef LWIP_RAW
|
||||
#define LWIP_RAW 1
|
||||
#endif
|
||||
|
||||
#ifndef RAW_TTL
|
||||
#define RAW_TTL 255
|
||||
#endif
|
||||
|
||||
/* ---------- DHCP options ---------- */
|
||||
|
||||
#ifndef LWIP_DHCP
|
||||
#define LWIP_DHCP 0
|
||||
#endif
|
||||
|
||||
/* 1 if you want to do an ARP check on the offered address
|
||||
(recommended). */
|
||||
#ifndef DHCP_DOES_ARP_CHECK
|
||||
#define DHCP_DOES_ARP_CHECK 1
|
||||
#endif
|
||||
|
||||
/* ---------- UDP options ---------- */
|
||||
#ifndef LWIP_UDP
|
||||
#define LWIP_UDP 1
|
||||
#endif
|
||||
|
||||
#ifndef UDP_TTL
|
||||
#define UDP_TTL 255
|
||||
#endif
|
||||
|
||||
/* ---------- TCP options ---------- */
|
||||
#ifndef LWIP_TCP
|
||||
#define LWIP_TCP 1
|
||||
#endif
|
||||
|
||||
#ifndef TCP_TTL
|
||||
#define TCP_TTL 255
|
||||
#endif
|
||||
|
||||
#ifndef TCP_WND
|
||||
#define TCP_WND 2048
|
||||
#endif
|
||||
|
||||
#ifndef TCP_MAXRTX
|
||||
#define TCP_MAXRTX 12
|
||||
#endif
|
||||
|
||||
#ifndef TCP_SYNMAXRTX
|
||||
#define TCP_SYNMAXRTX 6
|
||||
#endif
|
||||
|
||||
|
||||
/* Controls if TCP should queue segments that arrive out of
|
||||
order. Define to 0 if your device is low on memory. */
|
||||
#ifndef TCP_QUEUE_OOSEQ
|
||||
#define TCP_QUEUE_OOSEQ 1
|
||||
#endif
|
||||
|
||||
/* TCP Maximum segment size. */
|
||||
#ifndef TCP_MSS
|
||||
#define TCP_MSS 128 /* A *very* conservative default. */
|
||||
#endif
|
||||
|
||||
/* TCP sender buffer space (bytes). */
|
||||
#ifndef TCP_SND_BUF
|
||||
#define TCP_SND_BUF 256
|
||||
#endif
|
||||
|
||||
/* TCP sender buffer space (pbufs). This must be at least = 2 *
|
||||
TCP_SND_BUF/TCP_MSS for things to work. */
|
||||
#ifndef TCP_SND_QUEUELEN
|
||||
#define TCP_SND_QUEUELEN 4 * TCP_SND_BUF/TCP_MSS
|
||||
#endif
|
||||
|
||||
|
||||
/* Maximum number of retransmissions of data segments. */
|
||||
|
||||
/* Maximum number of retransmissions of SYN segments. */
|
||||
|
||||
/* TCP writable space (bytes). This must be less than or equal
|
||||
to TCP_SND_BUF. It is the amount of space which must be
|
||||
available in the tcp snd_buf for select to return writable */
|
||||
#ifndef TCP_SNDLOWAT
|
||||
#define TCP_SNDLOWAT TCP_SND_BUF/2
|
||||
#endif
|
||||
|
||||
/* Support loop interface (127.0.0.1) */
|
||||
#ifndef LWIP_HAVE_LOOPIF
|
||||
#define LWIP_HAVE_LOOPIF 1
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_EVENT_API
|
||||
#define LWIP_EVENT_API 0
|
||||
#define LWIP_CALLBACK_API 1
|
||||
#else
|
||||
#define LWIP_EVENT_API 1
|
||||
#define LWIP_CALLBACK_API 0
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_COMPAT_SOCKETS
|
||||
#define LWIP_COMPAT_SOCKETS 1
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef TCPIP_THREAD_PRIO
|
||||
#define TCPIP_THREAD_PRIO 1
|
||||
#endif
|
||||
|
||||
#ifndef SLIPIF_THREAD_PRIO
|
||||
#define SLIPIF_THREAD_PRIO 1
|
||||
#endif
|
||||
|
||||
#ifndef PPP_THREAD_PRIO
|
||||
#define PPP_THREAD_PRIO 1
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_THREAD_PRIO
|
||||
#define DEFAULT_THREAD_PRIO 1
|
||||
#endif
|
||||
|
||||
|
||||
/* ---------- Socket Options ---------- */
|
||||
/* Enable SO_REUSEADDR and SO_REUSEPORT options */
|
||||
#ifndef SO_REUSE
|
||||
# define SO_REUSE 0
|
||||
#endif
|
||||
|
||||
|
||||
/* ---------- Statistics options ---------- */
|
||||
#ifndef LWIP_STATS
|
||||
#define LWIP_STATS 1
|
||||
#endif
|
||||
|
||||
#if LWIP_STATS
|
||||
|
||||
#ifndef LWIP_STATS_DISPLAY
|
||||
#define LWIP_STATS_DISPLAY 0
|
||||
#endif
|
||||
|
||||
#ifndef LINK_STATS
|
||||
#define LINK_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef IP_STATS
|
||||
#define IP_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef IPFRAG_STATS
|
||||
#define IPFRAG_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef ICMP_STATS
|
||||
#define ICMP_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef UDP_STATS
|
||||
#define UDP_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef TCP_STATS
|
||||
#define TCP_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef MEM_STATS
|
||||
#define MEM_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_STATS
|
||||
#define MEMP_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef PBUF_STATS
|
||||
#define PBUF_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef SYS_STATS
|
||||
#define SYS_STATS 1
|
||||
#endif
|
||||
|
||||
#ifndef RAW_STATS
|
||||
#define RAW_STATS 0
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define LINK_STATS 0
|
||||
#define IP_STATS 0
|
||||
#define IPFRAG_STATS 0
|
||||
#define ICMP_STATS 0
|
||||
#define UDP_STATS 0
|
||||
#define TCP_STATS 0
|
||||
#define MEM_STATS 0
|
||||
#define MEMP_STATS 0
|
||||
#define PBUF_STATS 0
|
||||
#define SYS_STATS 0
|
||||
#define RAW_STATS 0
|
||||
#define LWIP_STATS_DISPLAY 0
|
||||
|
||||
#endif /* LWIP_STATS */
|
||||
|
||||
/* ---------- PPP options ---------- */
|
||||
|
||||
#ifndef PPP_SUPPORT
|
||||
#define PPP_SUPPORT 0 /* Set for PPP */
|
||||
#endif
|
||||
|
||||
#if PPP_SUPPORT
|
||||
|
||||
#define NUM_PPP 1 /* Max PPP sessions. */
|
||||
|
||||
|
||||
|
||||
#ifndef PAP_SUPPORT
|
||||
#define PAP_SUPPORT 0 /* Set for PAP. */
|
||||
#endif
|
||||
|
||||
#ifndef CHAP_SUPPORT
|
||||
#define CHAP_SUPPORT 0 /* Set for CHAP. */
|
||||
#endif
|
||||
|
||||
#define MSCHAP_SUPPORT 0 /* Set for MSCHAP (NOT FUNCTIONAL!) */
|
||||
#define CBCP_SUPPORT 0 /* Set for CBCP (NOT FUNCTIONAL!) */
|
||||
#define CCP_SUPPORT 0 /* Set for CCP (NOT FUNCTIONAL!) */
|
||||
|
||||
#ifndef VJ_SUPPORT
|
||||
#define VJ_SUPPORT 0 /* Set for VJ header compression. */
|
||||
#endif
|
||||
|
||||
#ifndef MD5_SUPPORT
|
||||
#define MD5_SUPPORT 0 /* Set for MD5 (see also CHAP) */
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Timeouts.
|
||||
*/
|
||||
#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */
|
||||
#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */
|
||||
#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */
|
||||
#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */
|
||||
|
||||
#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */
|
||||
#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */
|
||||
|
||||
#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */
|
||||
#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */
|
||||
|
||||
|
||||
/* Interval in seconds between keepalive echo requests, 0 to disable. */
|
||||
#if 1
|
||||
#define LCP_ECHOINTERVAL 0
|
||||
#else
|
||||
#define LCP_ECHOINTERVAL 10
|
||||
#endif
|
||||
|
||||
/* Number of unanswered echo requests before failure. */
|
||||
#define LCP_MAXECHOFAILS 3
|
||||
|
||||
/* Max Xmit idle time (in jiffies) before resend flag char. */
|
||||
#define PPP_MAXIDLEFLAG 100
|
||||
|
||||
/*
|
||||
* Packet sizes
|
||||
*
|
||||
* Note - lcp shouldn't be allowed to negotiate stuff outside these
|
||||
* limits. See lcp.h in the pppd directory.
|
||||
* (XXX - these constants should simply be shared by lcp.c instead
|
||||
* of living in lcp.h)
|
||||
*/
|
||||
#define PPP_MTU 1500 /* Default MTU (size of Info field) */
|
||||
#if 0
|
||||
#define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN)
|
||||
#else
|
||||
#define PPP_MAXMTU 1500 /* Largest MTU we allow */
|
||||
#endif
|
||||
#define PPP_MINMTU 64
|
||||
#define PPP_MRU 1500 /* default MRU = max length of info field */
|
||||
#define PPP_MAXMRU 1500 /* Largest MRU we allow */
|
||||
#define PPP_DEFMRU 296 /* Try for this */
|
||||
#define PPP_MINMRU 128 /* No MRUs below this */
|
||||
|
||||
|
||||
#define MAXNAMELEN 256 /* max length of hostname or name for auth */
|
||||
#define MAXSECRETLEN 256 /* max length of password or secret */
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
||||
|
||||
/* checksum options - set to zero for hardware checksum support */
|
||||
|
||||
#ifndef CHECKSUM_GEN_IP
|
||||
#define CHECKSUM_GEN_IP 1
|
||||
#endif
|
||||
|
||||
#ifndef CHECKSUM_GEN_UDP
|
||||
#define CHECKSUM_GEN_UDP 1
|
||||
#endif
|
||||
|
||||
#ifndef CHECKSUM_GEN_TCP
|
||||
#define CHECKSUM_GEN_TCP 1
|
||||
#endif
|
||||
|
||||
#ifndef CHECKSUM_CHECK_IP
|
||||
#define CHECKSUM_CHECK_IP 1
|
||||
#endif
|
||||
|
||||
#ifndef CHECKSUM_CHECK_UDP
|
||||
#define CHECKSUM_CHECK_UDP 1
|
||||
#endif
|
||||
|
||||
#ifndef CHECKSUM_CHECK_TCP
|
||||
#define CHECKSUM_CHECK_TCP 1
|
||||
#endif
|
||||
|
||||
/* Debugging options all default to off */
|
||||
|
||||
#ifndef DBG_TYPES_ON
|
||||
#define DBG_TYPES_ON 0
|
||||
#endif
|
||||
|
||||
#ifndef ETHARP_DEBUG
|
||||
#define ETHARP_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef NETIF_DEBUG
|
||||
#define NETIF_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef PBUF_DEBUG
|
||||
#define PBUF_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef API_LIB_DEBUG
|
||||
#define API_LIB_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef API_MSG_DEBUG
|
||||
#define API_MSG_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef SOCKETS_DEBUG
|
||||
#define SOCKETS_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef ICMP_DEBUG
|
||||
#define ICMP_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef INET_DEBUG
|
||||
#define INET_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef IP_DEBUG
|
||||
#define IP_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef IP_REASS_DEBUG
|
||||
#define IP_REASS_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef RAW_DEBUG
|
||||
#define RAW_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef MEM_DEBUG
|
||||
#define MEM_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_DEBUG
|
||||
#define MEMP_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef SYS_DEBUG
|
||||
#define SYS_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_DEBUG
|
||||
#define TCP_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_INPUT_DEBUG
|
||||
#define TCP_INPUT_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_FR_DEBUG
|
||||
#define TCP_FR_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_RTO_DEBUG
|
||||
#define TCP_RTO_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_REXMIT_DEBUG
|
||||
#define TCP_REXMIT_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_CWND_DEBUG
|
||||
#define TCP_CWND_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_WND_DEBUG
|
||||
#define TCP_WND_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_OUTPUT_DEBUG
|
||||
#define TCP_OUTPUT_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_RST_DEBUG
|
||||
#define TCP_RST_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCP_QLEN_DEBUG
|
||||
#define TCP_QLEN_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef UDP_DEBUG
|
||||
#define UDP_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef TCPIP_DEBUG
|
||||
#define TCPIP_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef PPP_DEBUG
|
||||
#define PPP_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef SLIP_DEBUG
|
||||
#define SLIP_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
#ifndef DHCP_DEBUG
|
||||
#define DHCP_DEBUG DBG_OFF
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef DBG_MIN_LEVEL
|
||||
#define DBG_MIN_LEVEL DBG_LEVEL_OFF
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_OPT_H__ */
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_PBUF_H__
|
||||
#define __LWIP_PBUF_H__
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
|
||||
#define PBUF_TRANSPORT_HLEN 20
|
||||
#define PBUF_IP_HLEN 20
|
||||
|
||||
typedef enum {
|
||||
PBUF_TRANSPORT,
|
||||
PBUF_IP,
|
||||
PBUF_LINK,
|
||||
PBUF_RAW
|
||||
} pbuf_layer;
|
||||
|
||||
typedef enum {
|
||||
PBUF_RAM,
|
||||
PBUF_ROM,
|
||||
PBUF_REF,
|
||||
PBUF_POOL
|
||||
} pbuf_flag;
|
||||
|
||||
/* Definitions for the pbuf flag field. These are NOT the flags that
|
||||
* are passed to pbuf_alloc(). */
|
||||
#define PBUF_FLAG_RAM 0x00U /* Flags that pbuf data is stored in RAM */
|
||||
#define PBUF_FLAG_ROM 0x01U /* Flags that pbuf data is stored in ROM */
|
||||
#define PBUF_FLAG_POOL 0x02U /* Flags that the pbuf comes from the pbuf pool */
|
||||
#define PBUF_FLAG_REF 0x04U /* Flags thet the pbuf payload refers to RAM */
|
||||
|
||||
/** indicates this packet was broadcast on the link */
|
||||
#define PBUF_FLAG_LINK_BROADCAST 0x80U
|
||||
|
||||
struct pbuf {
|
||||
/** next pbuf in singly linked pbuf chain */
|
||||
struct pbuf *next;
|
||||
|
||||
/** pointer to the actual data in the buffer */
|
||||
void *payload;
|
||||
|
||||
/**
|
||||
* total length of this buffer and all next buffers in chain
|
||||
* belonging to the same packet.
|
||||
*
|
||||
* For non-queue packet chains this is the invariant:
|
||||
* p->tot_len == p->len + (p->next? p->next->tot_len: 0)
|
||||
*/
|
||||
u16_t tot_len;
|
||||
|
||||
/** length of this buffer */
|
||||
u16_t len;
|
||||
|
||||
/** flags telling the type of pbuf, see PBUF_FLAG_ */
|
||||
u16_t flags;
|
||||
|
||||
/**
|
||||
* the reference count always equals the number of pointers
|
||||
* that refer to this pbuf. This can be pointers from an application,
|
||||
* the stack itself, or pbuf->next pointers from a chain.
|
||||
*/
|
||||
u16_t ref;
|
||||
|
||||
};
|
||||
|
||||
void pbuf_init(void);
|
||||
|
||||
struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag);
|
||||
void pbuf_realloc(struct pbuf *p, u16_t size);
|
||||
u8_t pbuf_header(struct pbuf *p, s16_t header_size);
|
||||
void pbuf_ref(struct pbuf *p);
|
||||
void pbuf_ref_chain(struct pbuf *p);
|
||||
u8_t pbuf_free(struct pbuf *p);
|
||||
u8_t pbuf_clen(struct pbuf *p);
|
||||
void pbuf_cat(struct pbuf *h, struct pbuf *t);
|
||||
void pbuf_chain(struct pbuf *h, struct pbuf *t);
|
||||
struct pbuf *pbuf_take(struct pbuf *f);
|
||||
struct pbuf *pbuf_dechain(struct pbuf *p);
|
||||
void pbuf_queue(struct pbuf *p, struct pbuf *n);
|
||||
struct pbuf * pbuf_dequeue(struct pbuf *p);
|
||||
|
||||
#endif /* __LWIP_PBUF_H__ */
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_RAW_H__
|
||||
#define __LWIP_RAW_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip.h"
|
||||
|
||||
struct raw_pcb {
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
|
||||
struct raw_pcb *next;
|
||||
|
||||
u16_t protocol;
|
||||
|
||||
u8_t (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *addr);
|
||||
void *recv_arg;
|
||||
};
|
||||
|
||||
/* The following functions is the application layer interface to the
|
||||
RAW code. */
|
||||
struct raw_pcb * raw_new (u16_t proto);
|
||||
void raw_remove (struct raw_pcb *pcb);
|
||||
err_t raw_bind (struct raw_pcb *pcb, struct ip_addr *ipaddr);
|
||||
err_t raw_connect (struct raw_pcb *pcb, struct ip_addr *ipaddr);
|
||||
|
||||
void raw_recv (struct raw_pcb *pcb,
|
||||
u8_t (* recv)(void *arg, struct raw_pcb *pcb,
|
||||
struct pbuf *p,
|
||||
struct ip_addr *addr),
|
||||
void *recv_arg);
|
||||
err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr);
|
||||
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
|
||||
|
||||
/* The following functions are the lower layer interface to RAW. */
|
||||
u8_t raw_input (struct pbuf *p, struct netif *inp);
|
||||
void raw_init (void);
|
||||
|
||||
|
||||
#endif /* __LWIP_RAW_H__ */
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the interface to the platform specific serial IO module
|
||||
* It needs to be implemented by those platforms which need SLIP or PPP
|
||||
*/
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
#ifndef __sio_fd_t_defined
|
||||
typedef void * sio_fd_t;
|
||||
#endif
|
||||
|
||||
#ifndef sio_open
|
||||
sio_fd_t sio_open(u8_t);
|
||||
#endif
|
||||
|
||||
#ifndef sio_send
|
||||
void sio_send(u8_t, sio_fd_t);
|
||||
#endif
|
||||
|
||||
#ifndef sio_recv
|
||||
u8_t sio_recv(sio_fd_t);
|
||||
#endif
|
||||
|
||||
#ifndef sio_read
|
||||
u32_t sio_read(sio_fd_t, u8_t *, u32_t);
|
||||
#endif
|
||||
|
||||
#ifndef sio_write
|
||||
u32_t sio_write(sio_fd_t, u8_t *, u32_t);
|
||||
#endif
|
||||
|
||||
#ifndef sio_read_abort
|
||||
void sio_read_abort(sio_fd_t);
|
||||
#endif
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2002 Leon Woestenberg <leon.woestenberg@axon.tv>
|
||||
* Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Leon Woestenberg <leon.woestenberg@axon.tv>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_SNMP_H__
|
||||
#define __LWIP_SNMP_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
/* SNMP support available? */
|
||||
#if defined(LWIP_SNMP) && (LWIP_SNMP > 0)
|
||||
|
||||
/* network interface */
|
||||
void snmp_add_ifinoctets(unsigned long value);
|
||||
void snmp_inc_ifinucastpkts(void);
|
||||
void snmp_inc_ifinnucastpkts(void);
|
||||
void snmp_inc_ifindiscards(void);
|
||||
void snmp_add_ifoutoctets(unsigned long value);
|
||||
void snmp_inc_ifoutucastpkts(void);
|
||||
void snmp_inc_ifoutnucastpkts(void);
|
||||
void snmp_inc_ifoutdiscards(void);
|
||||
|
||||
/* IP */
|
||||
void snmp_inc_ipinreceives(void);
|
||||
void snmp_inc_ipindelivers(void);
|
||||
void snmp_inc_ipindiscards(void);
|
||||
void snmp_inc_ipoutdiscards(void);
|
||||
void snmp_inc_ipoutrequests(void);
|
||||
void snmp_inc_ipunknownprotos(void);
|
||||
void snmp_inc_ipnoroutes(void);
|
||||
void snmp_inc_ipforwdatagrams(void);
|
||||
|
||||
/* ICMP */
|
||||
void snmp_inc_icmpinmsgs(void);
|
||||
void snmp_inc_icmpinerrors(void);
|
||||
void snmp_inc_icmpindestunreachs(void);
|
||||
void snmp_inc_icmpintimeexcds(void);
|
||||
void snmp_inc_icmpinparmprobs(void);
|
||||
void snmp_inc_icmpinsrcquenchs(void);
|
||||
void snmp_inc_icmpinredirects(void);
|
||||
void snmp_inc_icmpinechos(void);
|
||||
void snmp_inc_icmpinechoreps(void);
|
||||
void snmp_inc_icmpintimestamps(void);
|
||||
void snmp_inc_icmpintimestampreps(void);
|
||||
void snmp_inc_icmpinaddrmasks(void);
|
||||
void snmp_inc_icmpinaddrmaskreps(void);
|
||||
void snmp_inc_icmpoutmsgs(void);
|
||||
void snmp_inc_icmpouterrors(void);
|
||||
void snmp_inc_icmpoutdestunreachs(void);
|
||||
void snmp_inc_icmpouttimeexcds(void);
|
||||
void snmp_inc_icmpoutparmprobs(void);
|
||||
void snmp_inc_icmpoutsrcquenchs(void);
|
||||
void snmp_inc_icmpoutredirects(void);
|
||||
void snmp_inc_icmpoutechos(void);
|
||||
void snmp_inc_icmpoutechoreps(void);
|
||||
void snmp_inc_icmpouttimestamps(void);
|
||||
void snmp_inc_icmpouttimestampreps(void);
|
||||
void snmp_inc_icmpoutaddrmasks(void);
|
||||
void snmp_inc_icmpoutaddrmaskreps(void);
|
||||
|
||||
/* TCP */
|
||||
void snmp_inc_tcpactiveopens(void);
|
||||
void snmp_inc_tcppassiveopens(void);
|
||||
void snmp_inc_tcpattemptfails(void);
|
||||
void snmp_inc_tcpestabresets(void);
|
||||
void snmp_inc_tcpcurrestab(void);
|
||||
void snmp_inc_tcpinsegs(void);
|
||||
void snmp_inc_tcpoutsegs(void);
|
||||
void snmp_inc_tcpretranssegs(void);
|
||||
void snmp_inc_tcpinerrs(void);
|
||||
void snmp_inc_tcpoutrsts(void);
|
||||
|
||||
/* UDP */
|
||||
void snmp_inc_udpindatagrams(void);
|
||||
void snmp_inc_udpnoports(void);
|
||||
void snmp_inc_udpinerrors(void);
|
||||
void snmp_inc_udpoutdatagrams(void);
|
||||
|
||||
/* LWIP_SNMP support not available */
|
||||
/* define everything to be empty */
|
||||
#else
|
||||
|
||||
/* network interface */
|
||||
#define snmp_add_ifinoctets(value)
|
||||
#define snmp_inc_ifinucastpkts()
|
||||
#define snmp_inc_ifinnucastpkts()
|
||||
#define snmp_inc_ifindiscards()
|
||||
#define snmp_add_ifoutoctets(value)
|
||||
#define snmp_inc_ifoutucastpkts()
|
||||
#define snmp_inc_ifoutnucastpkts()
|
||||
#define snmp_inc_ifoutdiscards()
|
||||
|
||||
/* IP */
|
||||
#define snmp_inc_ipinreceives()
|
||||
#define snmp_inc_ipindelivers()
|
||||
#define snmp_inc_ipindiscards()
|
||||
#define snmp_inc_ipoutdiscards()
|
||||
#define snmp_inc_ipoutrequests()
|
||||
#define snmp_inc_ipunknownprotos()
|
||||
#define snmp_inc_ipnoroutes()
|
||||
#define snmp_inc_ipforwdatagrams()
|
||||
|
||||
/* ICMP */
|
||||
#define snmp_inc_icmpinmsgs()
|
||||
#define snmp_inc_icmpinerrors()
|
||||
#define snmp_inc_icmpindestunreachs()
|
||||
#define snmp_inc_icmpintimeexcds()
|
||||
#define snmp_inc_icmpinparmprobs()
|
||||
#define snmp_inc_icmpinsrcquenchs()
|
||||
#define snmp_inc_icmpinredirects()
|
||||
#define snmp_inc_icmpinechos()
|
||||
#define snmp_inc_icmpinechoreps()
|
||||
#define snmp_inc_icmpintimestamps()
|
||||
#define snmp_inc_icmpintimestampreps()
|
||||
#define snmp_inc_icmpinaddrmasks()
|
||||
#define snmp_inc_icmpinaddrmaskreps()
|
||||
#define snmp_inc_icmpoutmsgs()
|
||||
#define snmp_inc_icmpouterrors()
|
||||
#define snmp_inc_icmpoutdestunreachs()
|
||||
#define snmp_inc_icmpouttimeexcds()
|
||||
#define snmp_inc_icmpoutparmprobs()
|
||||
#define snmp_inc_icmpoutsrcquenchs()
|
||||
#define snmp_inc_icmpoutredirects()
|
||||
#define snmp_inc_icmpoutechos()
|
||||
#define snmp_inc_icmpoutechoreps()
|
||||
#define snmp_inc_icmpouttimestamps()
|
||||
#define snmp_inc_icmpouttimestampreps()
|
||||
#define snmp_inc_icmpoutaddrmasks()
|
||||
#define snmp_inc_icmpoutaddrmaskreps()
|
||||
/* TCP */
|
||||
#define snmp_inc_tcpactiveopens()
|
||||
#define snmp_inc_tcppassiveopens()
|
||||
#define snmp_inc_tcpattemptfails()
|
||||
#define snmp_inc_tcpestabresets()
|
||||
#define snmp_inc_tcpcurrestab()
|
||||
#define snmp_inc_tcpinsegs()
|
||||
#define snmp_inc_tcpoutsegs()
|
||||
#define snmp_inc_tcpretranssegs()
|
||||
#define snmp_inc_tcpinerrs()
|
||||
#define snmp_inc_tcpoutrsts()
|
||||
|
||||
/* UDP */
|
||||
#define snmp_inc_udpindatagrams()
|
||||
#define snmp_inc_udpnoports()
|
||||
#define snmp_inc_udpinerrors()
|
||||
#define snmp_inc_udpoutdatagrams()
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_SNMP_H__ */
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __LWIP_SOCKETS_H__
|
||||
#define __LWIP_SOCKETS_H__
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
struct sockaddr_in {
|
||||
u8_t sin_len;
|
||||
u8_t sin_family;
|
||||
u16_t sin_port;
|
||||
struct in_addr sin_addr;
|
||||
char sin_zero[8];
|
||||
};
|
||||
|
||||
struct sockaddr {
|
||||
u8_t sa_len;
|
||||
u8_t sa_family;
|
||||
char sa_data[14];
|
||||
};
|
||||
|
||||
#ifndef socklen_t
|
||||
# define socklen_t int
|
||||
#endif
|
||||
|
||||
|
||||
#define SOCK_STREAM 1
|
||||
#define SOCK_DGRAM 2
|
||||
#define SOCK_RAW 3
|
||||
|
||||
/*
|
||||
* Option flags per-socket.
|
||||
*/
|
||||
#define SO_DEBUG 0x0001 /* turn on debugging info recording */
|
||||
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
|
||||
#define SO_REUSEADDR 0x0004 /* allow local address reuse */
|
||||
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
|
||||
#define SO_DONTROUTE 0x0010 /* just use interface addresses */
|
||||
#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
|
||||
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
|
||||
#define SO_LINGER 0x0080 /* linger on close if data present */
|
||||
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
|
||||
#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */
|
||||
|
||||
#define SO_DONTLINGER (int)(~SO_LINGER)
|
||||
|
||||
/*
|
||||
* Additional options, not kept in so_options.
|
||||
*/
|
||||
#define SO_SNDBUF 0x1001 /* send buffer size */
|
||||
#define SO_RCVBUF 0x1002 /* receive buffer size */
|
||||
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
|
||||
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
|
||||
#define SO_SNDTIMEO 0x1005 /* send timeout */
|
||||
#define SO_RCVTIMEO 0x1006 /* receive timeout */
|
||||
#define SO_ERROR 0x1007 /* get error status and clear */
|
||||
#define SO_TYPE 0x1008 /* get socket type */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Structure used for manipulating linger option.
|
||||
*/
|
||||
struct linger {
|
||||
int l_onoff; /* option on/off */
|
||||
int l_linger; /* linger time */
|
||||
};
|
||||
|
||||
/*
|
||||
* Level number for (get/set)sockopt() to apply to socket itself.
|
||||
*/
|
||||
#define SOL_SOCKET 0xfff /* options for socket level */
|
||||
|
||||
|
||||
#define AF_UNSPEC 0
|
||||
#define AF_INET 2
|
||||
#define PF_INET AF_INET
|
||||
#define PF_UNSPEC AF_UNSPEC
|
||||
|
||||
#define IPPROTO_IP 0
|
||||
#define IPPROTO_TCP 6
|
||||
#define IPPROTO_UDP 17
|
||||
|
||||
#define INADDR_ANY 0
|
||||
#define INADDR_BROADCAST 0xffffffff
|
||||
|
||||
/* Flags we can use with send and recv. */
|
||||
#define MSG_DONTWAIT 0x40 /* Nonblocking i/o for this operation only */
|
||||
|
||||
|
||||
/*
|
||||
* Options for level IPPROTO_IP
|
||||
*/
|
||||
#define IP_TOS 1
|
||||
#define IP_TTL 2
|
||||
|
||||
|
||||
#define IPTOS_TOS_MASK 0x1E
|
||||
#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
|
||||
#define IPTOS_LOWDELAY 0x10
|
||||
#define IPTOS_THROUGHPUT 0x08
|
||||
#define IPTOS_RELIABILITY 0x04
|
||||
#define IPTOS_LOWCOST 0x02
|
||||
#define IPTOS_MINCOST IPTOS_LOWCOST
|
||||
|
||||
/*
|
||||
* Definitions for IP precedence (also in ip_tos) (hopefully unused)
|
||||
*/
|
||||
#define IPTOS_PREC_MASK 0xe0
|
||||
#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK)
|
||||
#define IPTOS_PREC_NETCONTROL 0xe0
|
||||
#define IPTOS_PREC_INTERNETCONTROL 0xc0
|
||||
#define IPTOS_PREC_CRITIC_ECP 0xa0
|
||||
#define IPTOS_PREC_FLASHOVERRIDE 0x80
|
||||
#define IPTOS_PREC_FLASH 0x60
|
||||
#define IPTOS_PREC_IMMEDIATE 0x40
|
||||
#define IPTOS_PREC_PRIORITY 0x20
|
||||
#define IPTOS_PREC_ROUTINE 0x00
|
||||
|
||||
|
||||
/*
|
||||
* Commands for ioctlsocket(), taken from the BSD file fcntl.h.
|
||||
*
|
||||
*
|
||||
* Ioctl's have the command encoded in the lower word,
|
||||
* and the size of any in or out parameters in the upper
|
||||
* word. The high 2 bits of the upper word are used
|
||||
* to encode the in/out status of the parameter; for now
|
||||
* we restrict parameters to at most 128 bytes.
|
||||
*/
|
||||
#if !defined(FIONREAD) || !defined(FIONBIO)
|
||||
#define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */
|
||||
#define IOC_VOID 0x20000000 /* no parameters */
|
||||
#define IOC_OUT 0x40000000 /* copy out parameters */
|
||||
#define IOC_IN 0x80000000 /* copy in parameters */
|
||||
#define IOC_INOUT (IOC_IN|IOC_OUT)
|
||||
/* 0x20000000 distinguishes new &
|
||||
old ioctl's */
|
||||
#define _IO(x,y) (IOC_VOID|((x)<<8)|(y))
|
||||
|
||||
#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
|
||||
|
||||
#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
|
||||
#endif
|
||||
|
||||
#ifndef FIONREAD
|
||||
#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */
|
||||
#endif
|
||||
#ifndef FIONBIO
|
||||
#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */
|
||||
#endif
|
||||
|
||||
/* Socket I/O Controls */
|
||||
#ifndef SIOCSHIWAT
|
||||
#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */
|
||||
#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */
|
||||
#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */
|
||||
#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */
|
||||
#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */
|
||||
#endif
|
||||
|
||||
#ifndef O_NONBLOCK
|
||||
#define O_NONBLOCK 04000U
|
||||
#endif
|
||||
|
||||
#ifndef FD_SET
|
||||
#undef FD_SETSIZE
|
||||
#define FD_SETSIZE 16
|
||||
#define FD_SET(n, p) ((p)->fd_bits[(n)/8] |= (1 << ((n) & 7)))
|
||||
#define FD_CLR(n, p) ((p)->fd_bits[(n)/8] &= ~(1 << ((n) & 7)))
|
||||
#define FD_ISSET(n,p) ((p)->fd_bits[(n)/8] & (1 << ((n) & 7)))
|
||||
#define FD_ZERO(p) memset((void*)(p),0,sizeof(*(p)))
|
||||
|
||||
typedef struct fd_set {
|
||||
unsigned char fd_bits [(FD_SETSIZE+7)/8];
|
||||
} fd_set;
|
||||
|
||||
/*
|
||||
* only define this in sockets.c so it does not interfere
|
||||
* with other projects namespaces where timeval is present
|
||||
*/
|
||||
#ifndef LWIP_TIMEVAL_PRIVATE
|
||||
#define LWIP_TIMEVAL_PRIVATE 1
|
||||
#endif
|
||||
|
||||
#if LWIP_TIMEVAL_PRIVATE
|
||||
struct timeval {
|
||||
long tv_sec; /* seconds */
|
||||
long tv_usec; /* and microseconds */
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int lwip_bind(int s, struct sockaddr *name, socklen_t namelen);
|
||||
int lwip_shutdown(int s, int how);
|
||||
int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen);
|
||||
int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen);
|
||||
int lwip_close(int s);
|
||||
int lwip_connect(int s, struct sockaddr *name, socklen_t namelen);
|
||||
int lwip_listen(int s, int backlog);
|
||||
int lwip_recv(int s, void *mem, int len, unsigned int flags);
|
||||
int lwip_read(int s, void *mem, int len);
|
||||
int lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen);
|
||||
int lwip_send(int s, void *dataptr, int size, unsigned int flags);
|
||||
int lwip_sendto(int s, void *dataptr, int size, unsigned int flags,
|
||||
struct sockaddr *to, socklen_t tolen);
|
||||
int lwip_socket(int domain, int type, int protocol);
|
||||
int lwip_write(int s, void *dataptr, int size);
|
||||
int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
struct timeval *timeout);
|
||||
int lwip_ioctl(int s, long cmd, void *argp);
|
||||
|
||||
#if LWIP_COMPAT_SOCKETS
|
||||
#define accept(a,b,c) lwip_accept(a,b,c)
|
||||
#define bind(a,b,c) lwip_bind(a,b,c)
|
||||
#define shutdown(a,b) lwip_shutdown(a,b)
|
||||
#define close(s) lwip_close(s)
|
||||
#define connect(a,b,c) lwip_connect(a,b,c)
|
||||
#define getsockname(a,b,c) lwip_getsockname(a,b,c)
|
||||
#define getpeername(a,b,c) lwip_getpeername(a,b,c)
|
||||
#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e)
|
||||
#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e)
|
||||
#define listen(a,b) lwip_listen(a,b)
|
||||
#define recv(a,b,c,d) lwip_recv(a,b,c,d)
|
||||
#define read(a,b,c) lwip_read(a,b,c)
|
||||
#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f)
|
||||
#define send(a,b,c,d) lwip_send(a,b,c,d)
|
||||
#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f)
|
||||
#define socket(a,b,c) lwip_socket(a,b,c)
|
||||
#define write(a,b,c) lwip_write(a,b,c)
|
||||
#define select(a,b,c,d,e) lwip_select(a,b,c,d,e)
|
||||
#define ioctlsocket(a,b,c) lwip_ioctl(a,b,c)
|
||||
#endif /* LWIP_COMPAT_SOCKETS */
|
||||
|
||||
#endif /* __LWIP_SOCKETS_H__ */
|
||||
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_STATS_H__
|
||||
#define __LWIP_STATS_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "arch/cc.h"
|
||||
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
|
||||
#if LWIP_STATS
|
||||
|
||||
struct stats_proto {
|
||||
u16_t xmit; /* Transmitted packets. */
|
||||
u16_t rexmit; /* Retransmitted packets. */
|
||||
u16_t recv; /* Received packets. */
|
||||
u16_t fw; /* Forwarded packets. */
|
||||
u16_t drop; /* Dropped packets. */
|
||||
u16_t chkerr; /* Checksum error. */
|
||||
u16_t lenerr; /* Invalid length error. */
|
||||
u16_t memerr; /* Out of memory error. */
|
||||
u16_t rterr; /* Routing error. */
|
||||
u16_t proterr; /* Protocol error. */
|
||||
u16_t opterr; /* Error in options. */
|
||||
u16_t err; /* Misc error. */
|
||||
u16_t cachehit;
|
||||
};
|
||||
|
||||
struct stats_mem {
|
||||
mem_size_t avail;
|
||||
mem_size_t used;
|
||||
mem_size_t max;
|
||||
mem_size_t err;
|
||||
};
|
||||
|
||||
struct stats_pbuf {
|
||||
u16_t avail;
|
||||
u16_t used;
|
||||
u16_t max;
|
||||
u16_t err;
|
||||
|
||||
u16_t alloc_locked;
|
||||
u16_t refresh_locked;
|
||||
};
|
||||
|
||||
struct stats_syselem {
|
||||
u16_t used;
|
||||
u16_t max;
|
||||
u16_t err;
|
||||
};
|
||||
|
||||
struct stats_sys {
|
||||
struct stats_syselem sem;
|
||||
struct stats_syselem mbox;
|
||||
};
|
||||
|
||||
struct stats_ {
|
||||
struct stats_proto link;
|
||||
struct stats_proto ip_frag;
|
||||
struct stats_proto ip;
|
||||
struct stats_proto icmp;
|
||||
struct stats_proto udp;
|
||||
struct stats_proto tcp;
|
||||
struct stats_pbuf pbuf;
|
||||
struct stats_mem mem;
|
||||
struct stats_mem memp[MEMP_MAX];
|
||||
struct stats_sys sys;
|
||||
};
|
||||
|
||||
extern struct stats_ lwip_stats;
|
||||
|
||||
|
||||
void stats_init(void);
|
||||
|
||||
#define STATS_INC(x) ++lwip_stats.x
|
||||
#else
|
||||
#define stats_init()
|
||||
#define STATS_INC(x)
|
||||
#endif /* LWIP_STATS */
|
||||
|
||||
#if TCP_STATS
|
||||
#define TCP_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define TCP_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
#if UDP_STATS
|
||||
#define UDP_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define UDP_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
#if ICMP_STATS
|
||||
#define ICMP_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define ICMP_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
#if IP_STATS
|
||||
#define IP_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define IP_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
#if IPFRAG_STATS
|
||||
#define IPFRAG_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define IPFRAG_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
#if LINK_STATS
|
||||
#define LINK_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define LINK_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
/* Display of statistics */
|
||||
#if LWIP_STATS_DISPLAY
|
||||
void stats_display(void);
|
||||
#else
|
||||
#define stats_display()
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_STATS_H__ */
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_SYS_H__
|
||||
#define __LWIP_SYS_H__
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
|
||||
#if NO_SYS
|
||||
|
||||
/* For a totally minimal and standalone system, we provide null
|
||||
definitions of the sys_ functions. */
|
||||
typedef u8_t sys_sem_t;
|
||||
typedef u8_t sys_mbox_t;
|
||||
struct sys_timeout {u8_t dummy;};
|
||||
|
||||
#define sys_init()
|
||||
#define sys_timeout(m,h,a)
|
||||
#define sys_untimeout(m,a)
|
||||
#define sys_sem_new(c) c
|
||||
#define sys_sem_signal(s)
|
||||
#define sys_sem_wait(s)
|
||||
#define sys_sem_free(s)
|
||||
#define sys_mbox_new() 0
|
||||
#define sys_mbox_fetch(m,d)
|
||||
#define sys_mbox_post(m,d)
|
||||
#define sys_mbox_free(m)
|
||||
|
||||
#define sys_thread_new(t,a,p)
|
||||
|
||||
#else /* NO_SYS */
|
||||
|
||||
#include "arch/sys_arch.h"
|
||||
|
||||
/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */
|
||||
#define SYS_ARCH_TIMEOUT 0xffffffff
|
||||
|
||||
typedef void (* sys_timeout_handler)(void *arg);
|
||||
|
||||
struct sys_timeout {
|
||||
struct sys_timeout *next;
|
||||
u32_t time;
|
||||
sys_timeout_handler h;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
struct sys_timeouts {
|
||||
struct sys_timeout *next;
|
||||
};
|
||||
|
||||
/* sys_init() must be called before anthing else. */
|
||||
void sys_init(void);
|
||||
|
||||
/*
|
||||
* sys_timeout():
|
||||
*
|
||||
* Schedule a timeout a specified amount of milliseconds in the
|
||||
* future. When the timeout occurs, the specified timeout handler will
|
||||
* be called. The handler will be passed the "arg" argument when
|
||||
* called.
|
||||
*
|
||||
*/
|
||||
void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
|
||||
void sys_untimeout(sys_timeout_handler h, void *arg);
|
||||
struct sys_timeouts *sys_arch_timeouts(void);
|
||||
|
||||
/* Semaphore functions. */
|
||||
sys_sem_t sys_sem_new(u8_t count);
|
||||
void sys_sem_signal(sys_sem_t sem);
|
||||
u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout);
|
||||
void sys_sem_free(sys_sem_t sem);
|
||||
void sys_sem_wait(sys_sem_t sem);
|
||||
int sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout);
|
||||
|
||||
/* Time functions. */
|
||||
#ifndef sys_msleep
|
||||
void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */
|
||||
#endif
|
||||
#ifndef sys_jiffies
|
||||
u32_t sys_jiffies(void); /* since power up. */
|
||||
#endif
|
||||
|
||||
/* Mailbox functions. */
|
||||
sys_mbox_t sys_mbox_new(void);
|
||||
void sys_mbox_post(sys_mbox_t mbox, void *msg);
|
||||
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout);
|
||||
void sys_mbox_free(sys_mbox_t mbox);
|
||||
void sys_mbox_fetch(sys_mbox_t mbox, void **msg);
|
||||
|
||||
|
||||
/* Thread functions. */
|
||||
sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio);
|
||||
|
||||
/* The following functions are used only in Unix code, and
|
||||
can be omitted when porting the stack. */
|
||||
/* Returns the current time in microseconds. */
|
||||
unsigned long sys_now(void);
|
||||
|
||||
#endif /* NO_SYS */
|
||||
|
||||
/* Critical Region Protection */
|
||||
/* These functions must be implemented in the sys_arch.c file.
|
||||
In some implementations they can provide a more light-weight protection
|
||||
mechanism than using semaphores. Otherwise semaphores can be used for
|
||||
implementation */
|
||||
#ifndef SYS_ARCH_PROTECT
|
||||
/** SYS_LIGHTWEIGHT_PROT
|
||||
* define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection
|
||||
* for certain critical regions during buffer allocation, deallocation and memory
|
||||
* allocation and deallocation.
|
||||
*/
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
|
||||
/** SYS_ARCH_DECL_PROTECT
|
||||
* declare a protection variable. This macro will default to defining a variable of
|
||||
* type sys_prot_t. If a particular port needs a different implementation, then
|
||||
* this macro may be defined in sys_arch.h.
|
||||
*/
|
||||
#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev
|
||||
/** SYS_ARCH_PROTECT
|
||||
* Perform a "fast" protect. This could be implemented by
|
||||
* disabling interrupts for an embedded system or by using a semaphore or
|
||||
* mutex. The implementation should allow calling SYS_ARCH_PROTECT when
|
||||
* already protected. The old protection level is returned in the variable
|
||||
* "lev". This macro will default to calling the sys_arch_protect() function
|
||||
* which should be implemented in sys_arch.c. If a particular port needs a
|
||||
* different implementation, then this macro may be defined in sys_arch.h
|
||||
*/
|
||||
#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect()
|
||||
/** SYS_ARCH_UNPROTECT
|
||||
* Perform a "fast" set of the protection level to "lev". This could be
|
||||
* implemented by setting the interrupt level to "lev" within the MACRO or by
|
||||
* using a semaphore or mutex. This macro will default to calling the
|
||||
* sys_arch_unprotect() function which should be implemented in
|
||||
* sys_arch.c. If a particular port needs a different implementation, then
|
||||
* this macro may be defined in sys_arch.h
|
||||
*/
|
||||
#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev)
|
||||
sys_prot_t sys_arch_protect(void);
|
||||
void sys_arch_unprotect(sys_prot_t pval);
|
||||
|
||||
#else
|
||||
|
||||
#define SYS_ARCH_DECL_PROTECT(lev)
|
||||
#define SYS_ARCH_PROTECT(lev)
|
||||
#define SYS_ARCH_UNPROTECT(lev)
|
||||
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
#endif /* SYS_ARCH_PROTECT */
|
||||
|
||||
#endif /* __LWIP_SYS_H__ */
|
||||
|
|
@ -0,0 +1,531 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_TCP_H__
|
||||
#define __LWIP_TCP_H__
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/mem.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/icmp.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
struct tcp_pcb;
|
||||
|
||||
/* Functions for interfacing with TCP: */
|
||||
|
||||
/* Lower layer interface to TCP: */
|
||||
void tcp_init (void); /* Must be called first to
|
||||
initialize TCP. */
|
||||
void tcp_tmr (void); /* Must be called every
|
||||
TCP_TMR_INTERVAL
|
||||
ms. (Typically 250 ms). */
|
||||
/* Application program's interface: */
|
||||
struct tcp_pcb * tcp_new (void);
|
||||
struct tcp_pcb * tcp_alloc (u8_t prio);
|
||||
|
||||
void tcp_arg (struct tcp_pcb *pcb, void *arg);
|
||||
void tcp_accept (struct tcp_pcb *pcb,
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
|
||||
err_t err));
|
||||
void tcp_recv (struct tcp_pcb *pcb,
|
||||
err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
|
||||
struct pbuf *p, err_t err));
|
||||
void tcp_sent (struct tcp_pcb *pcb,
|
||||
err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
|
||||
u16_t len));
|
||||
void tcp_poll (struct tcp_pcb *pcb,
|
||||
err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
|
||||
u8_t interval);
|
||||
void tcp_err (struct tcp_pcb *pcb,
|
||||
void (* err)(void *arg, err_t err));
|
||||
|
||||
#define tcp_mss(pcb) ((pcb)->mss)
|
||||
#define tcp_sndbuf(pcb) ((pcb)->snd_buf)
|
||||
|
||||
void tcp_recved (struct tcp_pcb *pcb, u16_t len);
|
||||
err_t tcp_bind (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port);
|
||||
err_t tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port, err_t (* connected)(void *arg,
|
||||
struct tcp_pcb *tpcb,
|
||||
err_t err));
|
||||
struct tcp_pcb * tcp_listen (struct tcp_pcb *pcb);
|
||||
void tcp_abort (struct tcp_pcb *pcb);
|
||||
err_t tcp_close (struct tcp_pcb *pcb);
|
||||
err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
|
||||
u8_t copy);
|
||||
|
||||
void tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
|
||||
|
||||
#define TCP_PRIO_MIN 1
|
||||
#define TCP_PRIO_NORMAL 64
|
||||
#define TCP_PRIO_MAX 127
|
||||
|
||||
/* It is also possible to call these two functions at the right
|
||||
intervals (instead of calling tcp_tmr()). */
|
||||
void tcp_slowtmr (void);
|
||||
void tcp_fasttmr (void);
|
||||
|
||||
|
||||
/* Only used by IP to pass a TCP segment to TCP: */
|
||||
void tcp_input (struct pbuf *p, struct netif *inp);
|
||||
/* Used within the TCP code only: */
|
||||
err_t tcp_output (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit_rto (struct tcp_pcb *pcb);
|
||||
|
||||
|
||||
|
||||
#define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0)
|
||||
#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
|
||||
#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
|
||||
#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
|
||||
/* is b<=a<=c? */
|
||||
#if 0 /* see bug #10548 */
|
||||
#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
|
||||
#endif
|
||||
#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
|
||||
#define TCP_FIN 0x01U
|
||||
#define TCP_SYN 0x02U
|
||||
#define TCP_RST 0x04U
|
||||
#define TCP_PSH 0x08U
|
||||
#define TCP_ACK 0x10U
|
||||
#define TCP_URG 0x20U
|
||||
#define TCP_ECE 0x40U
|
||||
#define TCP_CWR 0x80U
|
||||
|
||||
#define TCP_FLAGS 0x3fU
|
||||
|
||||
/* Length of the TCP header, excluding options. */
|
||||
#define TCP_HLEN 20
|
||||
|
||||
#ifndef TCP_TMR_INTERVAL
|
||||
#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in
|
||||
milliseconds. */
|
||||
#endif /* TCP_TMR_INTERVAL */
|
||||
|
||||
#ifndef TCP_FAST_INTERVAL
|
||||
#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in
|
||||
milliseconds */
|
||||
#endif /* TCP_FAST_INTERVAL */
|
||||
|
||||
#ifndef TCP_SLOW_INTERVAL
|
||||
#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in
|
||||
milliseconds */
|
||||
#endif /* TCP_SLOW_INTERVAL */
|
||||
|
||||
#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */
|
||||
#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */
|
||||
|
||||
#define TCP_OOSEQ_TIMEOUT 6 /* x RTO */
|
||||
|
||||
#define TCP_MSL 60000 /* The maximum segment lifetime in microseconds */
|
||||
|
||||
/*
|
||||
* User-settable options (used with setsockopt).
|
||||
*/
|
||||
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
|
||||
#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keepalive miliseconds */
|
||||
|
||||
/* Keepalive values */
|
||||
#define TCP_KEEPDEFAULT 7200000 /* KEEPALIVE timer in miliseconds */
|
||||
#define TCP_KEEPINTVL 75000 /* Time between KEEPALIVE probes in miliseconds */
|
||||
#define TCP_KEEPCNT 9 /* Counter for KEEPALIVE probes */
|
||||
#define TCP_MAXIDLE TCP_KEEPCNT * TCP_KEEPINTVL /* Maximum KEEPALIVE probe time */
|
||||
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct tcp_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t src);
|
||||
PACK_STRUCT_FIELD(u16_t dest);
|
||||
PACK_STRUCT_FIELD(u32_t seqno);
|
||||
PACK_STRUCT_FIELD(u32_t ackno);
|
||||
PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
|
||||
PACK_STRUCT_FIELD(u16_t wnd);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u16_t urgp);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
|
||||
#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
|
||||
#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
|
||||
|
||||
#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
|
||||
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
|
||||
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons((ntohs((phdr)->_hdrlen_rsvd_flags) & ~TCP_FLAGS) | (flags))
|
||||
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (flags))
|
||||
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
|
||||
|
||||
#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & TCP_FIN || \
|
||||
TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0))
|
||||
|
||||
enum tcp_state {
|
||||
CLOSED = 0,
|
||||
LISTEN = 1,
|
||||
SYN_SENT = 2,
|
||||
SYN_RCVD = 3,
|
||||
ESTABLISHED = 4,
|
||||
FIN_WAIT_1 = 5,
|
||||
FIN_WAIT_2 = 6,
|
||||
CLOSE_WAIT = 7,
|
||||
CLOSING = 8,
|
||||
LAST_ACK = 9,
|
||||
TIME_WAIT = 10
|
||||
};
|
||||
|
||||
/* the TCP protocol control block */
|
||||
struct tcp_pcb {
|
||||
/** common PCB members */
|
||||
IP_PCB;
|
||||
/** protocol specific PCB members */
|
||||
struct tcp_pcb *next; /* for the linked list */
|
||||
enum tcp_state state; /* TCP state */
|
||||
u8_t prio;
|
||||
void *callback_arg;
|
||||
|
||||
u16_t local_port;
|
||||
u16_t remote_port;
|
||||
|
||||
u8_t flags;
|
||||
#define TF_ACK_DELAY (u8_t)0x01U /* Delayed ACK. */
|
||||
#define TF_ACK_NOW (u8_t)0x02U /* Immediate ACK. */
|
||||
#define TF_INFR (u8_t)0x04U /* In fast recovery. */
|
||||
#define TF_RESET (u8_t)0x08U /* Connection was reset. */
|
||||
#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */
|
||||
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
|
||||
#define TF_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */
|
||||
|
||||
/* receiver variables */
|
||||
u32_t rcv_nxt; /* next seqno expected */
|
||||
u16_t rcv_wnd; /* receiver window */
|
||||
|
||||
/* Timers */
|
||||
u32_t tmr;
|
||||
u8_t polltmr, pollinterval;
|
||||
|
||||
/* Retransmission timer. */
|
||||
u16_t rtime;
|
||||
|
||||
u16_t mss; /* maximum segment size */
|
||||
|
||||
/* RTT (round trip time) estimation variables */
|
||||
u32_t rttest; /* RTT estimate in 500ms ticks */
|
||||
u32_t rtseq; /* sequence number being timed */
|
||||
s16_t sa, sv; /* @todo document this */
|
||||
|
||||
u16_t rto; /* retransmission time-out */
|
||||
u8_t nrtx; /* number of retransmissions */
|
||||
|
||||
/* fast retransmit/recovery */
|
||||
u32_t lastack; /* Highest acknowledged seqno. */
|
||||
u8_t dupacks;
|
||||
|
||||
/* congestion avoidance/control variables */
|
||||
u16_t cwnd;
|
||||
u16_t ssthresh;
|
||||
|
||||
/* sender variables */
|
||||
u32_t snd_nxt, /* next seqno to be sent */
|
||||
snd_max, /* Highest seqno sent. */
|
||||
snd_wnd, /* sender window */
|
||||
snd_wl1, snd_wl2, /* Sequence and acknowledgement numbers of last
|
||||
window update. */
|
||||
snd_lbb; /* Sequence number of next byte to be buffered. */
|
||||
|
||||
u16_t acked;
|
||||
|
||||
u16_t snd_buf; /* Available buffer space for sending (in bytes). */
|
||||
u8_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
|
||||
|
||||
|
||||
/* These are ordered by sequence number: */
|
||||
struct tcp_seg *unsent; /* Unsent (queued) segments. */
|
||||
struct tcp_seg *unacked; /* Sent but unacknowledged segments. */
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
struct tcp_seg *ooseq; /* Received out of sequence segments. */
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
/* Function to be called when more send buffer space is available. */
|
||||
err_t (* sent)(void *arg, struct tcp_pcb *pcb, u16_t space);
|
||||
|
||||
/* Function to be called when (in-sequence) data has arrived. */
|
||||
err_t (* recv)(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
|
||||
|
||||
/* Function to be called when a connection has been set up. */
|
||||
err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err);
|
||||
|
||||
/* Function to call when a listener has been connected. */
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
|
||||
|
||||
/* Function which is called periodically. */
|
||||
err_t (* poll)(void *arg, struct tcp_pcb *pcb);
|
||||
|
||||
/* Function to be called whenever a fatal error occurs. */
|
||||
void (* errf)(void *arg, err_t err);
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
/* idle time before KEEPALIVE is sent */
|
||||
u32_t keepalive;
|
||||
|
||||
/* KEEPALIVE counter */
|
||||
u8_t keep_cnt;
|
||||
};
|
||||
|
||||
struct tcp_pcb_listen {
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
|
||||
/* Protocol specific PCB members */
|
||||
struct tcp_pcb_listen *next; /* for the linked list */
|
||||
|
||||
/* Even if state is obviously LISTEN this is here for
|
||||
* field compatibility with tpc_pcb to which it is cast sometimes
|
||||
* Until a cleaner solution emerges this is here.FIXME
|
||||
*/
|
||||
enum tcp_state state; /* TCP state */
|
||||
|
||||
u8_t prio;
|
||||
void *callback_arg;
|
||||
|
||||
u16_t local_port;
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
/* Function to call when a listener has been connected. */
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
};
|
||||
|
||||
#if LWIP_EVENT_API
|
||||
|
||||
enum lwip_event {
|
||||
LWIP_EVENT_ACCEPT,
|
||||
LWIP_EVENT_SENT,
|
||||
LWIP_EVENT_RECV,
|
||||
LWIP_EVENT_CONNECTED,
|
||||
LWIP_EVENT_POLL,
|
||||
LWIP_EVENT_ERR
|
||||
};
|
||||
|
||||
err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
|
||||
enum lwip_event,
|
||||
struct pbuf *p,
|
||||
u16_t size,
|
||||
err_t err);
|
||||
|
||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_ACCEPT, NULL, 0, err)
|
||||
#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_SENT, NULL, space, ERR_OK)
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_RECV, (p), 0, (err))
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_CONNECTED, NULL, 0, (err))
|
||||
#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_POLL, NULL, 0, ERR_OK)
|
||||
#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
|
||||
LWIP_EVENT_ERR, NULL, 0, (err))
|
||||
#else /* LWIP_EVENT_API */
|
||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) \
|
||||
if((pcb)->accept != NULL) \
|
||||
(ret = (pcb)->accept((pcb)->callback_arg,(pcb),(err)))
|
||||
#define TCP_EVENT_SENT(pcb,space,ret) \
|
||||
if((pcb)->sent != NULL) \
|
||||
(ret = (pcb)->sent((pcb)->callback_arg,(pcb),(space)))
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) \
|
||||
if((pcb)->recv != NULL) \
|
||||
{ ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
|
||||
if (p) pbuf_free(p); }
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
|
||||
if((pcb)->connected != NULL) \
|
||||
(ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
|
||||
#define TCP_EVENT_POLL(pcb,ret) \
|
||||
if((pcb)->poll != NULL) \
|
||||
(ret = (pcb)->poll((pcb)->callback_arg,(pcb)))
|
||||
#define TCP_EVENT_ERR(errf,arg,err) \
|
||||
if((errf) != NULL) \
|
||||
(errf)((arg),(err))
|
||||
#endif /* LWIP_EVENT_API */
|
||||
|
||||
/* This structure represents a TCP segment on the unsent and unacked queues */
|
||||
struct tcp_seg {
|
||||
struct tcp_seg *next; /* used when putting segements on a queue */
|
||||
struct pbuf *p; /* buffer containing data + TCP header */
|
||||
void *dataptr; /* pointer to the TCP data in the pbuf */
|
||||
u16_t len; /* the TCP length of this segment */
|
||||
struct tcp_hdr *tcphdr; /* the TCP header */
|
||||
};
|
||||
|
||||
/* Internal functions and global variables: */
|
||||
struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
|
||||
void tcp_pcb_purge(struct tcp_pcb *pcb);
|
||||
void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
|
||||
|
||||
u8_t tcp_segs_free(struct tcp_seg *seg);
|
||||
u8_t tcp_seg_free(struct tcp_seg *seg);
|
||||
struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
|
||||
|
||||
#define tcp_ack(pcb) if((pcb)->flags & TF_ACK_DELAY) { \
|
||||
(pcb)->flags &= ~TF_ACK_DELAY; \
|
||||
(pcb)->flags |= TF_ACK_NOW; \
|
||||
tcp_output(pcb); \
|
||||
} else { \
|
||||
(pcb)->flags |= TF_ACK_DELAY; \
|
||||
}
|
||||
|
||||
#define tcp_ack_now(pcb) (pcb)->flags |= TF_ACK_NOW; \
|
||||
tcp_output(pcb)
|
||||
|
||||
err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags);
|
||||
err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len,
|
||||
u8_t flags, u8_t copy,
|
||||
u8_t *optdata, u8_t optlen);
|
||||
|
||||
void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
|
||||
|
||||
void tcp_rst(u32_t seqno, u32_t ackno,
|
||||
struct ip_addr *local_ip, struct ip_addr *remote_ip,
|
||||
u16_t local_port, u16_t remote_port);
|
||||
|
||||
u32_t tcp_next_iss(void);
|
||||
|
||||
void tcp_keepalive(struct tcp_pcb *pcb);
|
||||
|
||||
extern struct tcp_pcb *tcp_input_pcb;
|
||||
extern u32_t tcp_ticks;
|
||||
|
||||
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
|
||||
void tcp_debug_print(struct tcp_hdr *tcphdr);
|
||||
void tcp_debug_print_flags(u8_t flags);
|
||||
void tcp_debug_print_state(enum tcp_state s);
|
||||
void tcp_debug_print_pcbs(void);
|
||||
int tcp_pcbs_sane(void);
|
||||
#else
|
||||
# define tcp_debug_print(tcphdr)
|
||||
# define tcp_debug_print_flags(flags)
|
||||
# define tcp_debug_print_state(s)
|
||||
# define tcp_debug_print_pcbs()
|
||||
# define tcp_pcbs_sane() 1
|
||||
#endif /* TCP_DEBUG */
|
||||
|
||||
#if NO_SYS
|
||||
#define tcp_timer_needed()
|
||||
#else
|
||||
void tcp_timer_needed(void);
|
||||
#endif
|
||||
|
||||
/* The TCP PCB lists. */
|
||||
union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
|
||||
struct tcp_pcb_listen *listen_pcbs;
|
||||
struct tcp_pcb *pcbs;
|
||||
};
|
||||
extern union tcp_listen_pcbs_t tcp_listen_pcbs;
|
||||
extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
|
||||
state in which they accept or send
|
||||
data. */
|
||||
extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
|
||||
|
||||
extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
|
||||
|
||||
/* Axioms about the above lists:
|
||||
1) Every TCP PCB that is not CLOSED is in one of the lists.
|
||||
2) A PCB is only in one of the lists.
|
||||
3) All PCBs in the tcp_listen_pcbs list is in LISTEN state.
|
||||
4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state.
|
||||
*/
|
||||
|
||||
/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
|
||||
with a PCB list or removes a PCB from a list, respectively. */
|
||||
#if 0
|
||||
#define TCP_REG(pcbs, npcb) do {\
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \
|
||||
for(tcp_tmp_pcb = *pcbs; \
|
||||
tcp_tmp_pcb != NULL; \
|
||||
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \
|
||||
} \
|
||||
LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \
|
||||
npcb->next = *pcbs; \
|
||||
LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \
|
||||
*(pcbs) = npcb; \
|
||||
LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
|
||||
tcp_timer_needed(); \
|
||||
} while(0)
|
||||
#define TCP_RMV(pcbs, npcb) do { \
|
||||
LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \
|
||||
if(*pcbs == npcb) { \
|
||||
*pcbs = (*pcbs)->next; \
|
||||
} else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
|
||||
tcp_tmp_pcb->next = npcb->next; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
npcb->next = NULL; \
|
||||
LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \
|
||||
} while(0)
|
||||
|
||||
#else /* LWIP_DEBUG */
|
||||
#define TCP_REG(pcbs, npcb) do { \
|
||||
npcb->next = *pcbs; \
|
||||
*(pcbs) = npcb; \
|
||||
tcp_timer_needed(); \
|
||||
} while(0)
|
||||
#define TCP_RMV(pcbs, npcb) do { \
|
||||
if(*(pcbs) == npcb) { \
|
||||
(*(pcbs)) = (*pcbs)->next; \
|
||||
} else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
|
||||
tcp_tmp_pcb->next = npcb->next; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
npcb->next = NULL; \
|
||||
} while(0)
|
||||
#endif /* LWIP_DEBUG */
|
||||
#endif /* __LWIP_TCP_H__ */
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_TCPIP_H__
|
||||
#define __LWIP_TCPIP_H__
|
||||
|
||||
#include "lwip/api_msg.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
void tcpip_init(void (* tcpip_init_done)(void *), void *arg);
|
||||
void tcpip_apimsg(struct api_msg *apimsg);
|
||||
err_t tcpip_input(struct pbuf *p, struct netif *inp);
|
||||
err_t tcpip_callback(void (*f)(void *ctx), void *ctx);
|
||||
|
||||
void tcpip_tcp_timer_needed(void);
|
||||
|
||||
enum tcpip_msg_type {
|
||||
TCPIP_MSG_API,
|
||||
TCPIP_MSG_INPUT,
|
||||
TCPIP_MSG_CALLBACK
|
||||
};
|
||||
|
||||
struct tcpip_msg {
|
||||
enum tcpip_msg_type type;
|
||||
sys_sem_t *sem;
|
||||
union {
|
||||
struct api_msg *apimsg;
|
||||
struct {
|
||||
struct pbuf *p;
|
||||
struct netif *netif;
|
||||
} inp;
|
||||
struct {
|
||||
void (*f)(void *ctx);
|
||||
void *ctx;
|
||||
} cb;
|
||||
} msg;
|
||||
};
|
||||
|
||||
|
||||
#endif /* __LWIP_TCPIP_H__ */
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_UDP_H__
|
||||
#define __LWIP_UDP_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip.h"
|
||||
|
||||
#define UDP_HLEN 8
|
||||
|
||||
struct udp_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t src);
|
||||
PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */
|
||||
PACK_STRUCT_FIELD(u16_t len);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
|
||||
#define UDP_FLAGS_NOCHKSUM 0x01U
|
||||
#define UDP_FLAGS_UDPLITE 0x02U
|
||||
#define UDP_FLAGS_CONNECTED 0x04U
|
||||
|
||||
struct udp_pcb {
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
|
||||
/* Protocol specific PCB members */
|
||||
|
||||
struct udp_pcb *next;
|
||||
|
||||
u8_t flags;
|
||||
u16_t local_port, remote_port;
|
||||
|
||||
u16_t chksum_len;
|
||||
|
||||
void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *addr, u16_t port);
|
||||
void *recv_arg;
|
||||
};
|
||||
|
||||
/* The following functions is the application layer interface to the
|
||||
UDP code. */
|
||||
struct udp_pcb * udp_new (void);
|
||||
void udp_remove (struct udp_pcb *pcb);
|
||||
err_t udp_bind (struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port);
|
||||
err_t udp_connect (struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port);
|
||||
void udp_disconnect (struct udp_pcb *pcb);
|
||||
void udp_recv (struct udp_pcb *pcb,
|
||||
void (* recv)(void *arg, struct udp_pcb *upcb,
|
||||
struct pbuf *p,
|
||||
struct ip_addr *addr,
|
||||
u16_t port),
|
||||
void *recv_arg);
|
||||
err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port);
|
||||
err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);
|
||||
|
||||
#define udp_flags(pcb) ((pcb)->flags)
|
||||
#define udp_setflags(pcb, f) ((pcb)->flags = (f))
|
||||
|
||||
/* The following functions are the lower layer interface to UDP. */
|
||||
void udp_input (struct pbuf *p, struct netif *inp);
|
||||
void udp_init (void);
|
||||
|
||||
#if UDP_DEBUG
|
||||
int udp_debug_print(struct udp_hdr *udphdr);
|
||||
#else
|
||||
#define udp_debug_print(udphdr)
|
||||
#endif
|
||||
#endif /* __LWIP_UDP_H__ */
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
|
||||
* Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __NETIF_ETHARP_H__
|
||||
#define __NETIF_ETHARP_H__
|
||||
|
||||
#ifndef ETH_PAD_SIZE
|
||||
#define ETH_PAD_SIZE 0
|
||||
#endif
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip.h"
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct eth_addr {
|
||||
PACK_STRUCT_FIELD(u8_t addr[6]);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct eth_hdr {
|
||||
#if ETH_PAD_SIZE
|
||||
PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
|
||||
#endif
|
||||
PACK_STRUCT_FIELD(struct eth_addr dest);
|
||||
PACK_STRUCT_FIELD(struct eth_addr src);
|
||||
PACK_STRUCT_FIELD(u16_t type);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** the ARP message */
|
||||
struct etharp_hdr {
|
||||
PACK_STRUCT_FIELD(struct eth_hdr ethhdr);
|
||||
PACK_STRUCT_FIELD(u16_t hwtype);
|
||||
PACK_STRUCT_FIELD(u16_t proto);
|
||||
PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
|
||||
PACK_STRUCT_FIELD(u16_t opcode);
|
||||
PACK_STRUCT_FIELD(struct eth_addr shwaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr2 sipaddr);
|
||||
PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr2 dipaddr);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ethip_hdr {
|
||||
PACK_STRUCT_FIELD(struct eth_hdr eth);
|
||||
PACK_STRUCT_FIELD(struct ip_hdr ip);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** 5 seconds period */
|
||||
#define ARP_TMR_INTERVAL 5000
|
||||
|
||||
#define ETHTYPE_ARP 0x0806
|
||||
#define ETHTYPE_IP 0x0800
|
||||
|
||||
void etharp_init(void);
|
||||
void etharp_tmr(void);
|
||||
void etharp_ip_input(struct netif *netif, struct pbuf *p);
|
||||
void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
|
||||
struct pbuf *p);
|
||||
err_t etharp_output(struct netif *netif, struct ip_addr *ipaddr,
|
||||
struct pbuf *q);
|
||||
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q);
|
||||
err_t etharp_request(struct netif *netif, struct ip_addr *ipaddr);
|
||||
|
||||
#endif /* __NETIF_ARP_H__ */
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __NETIF_LOOPIF_H__
|
||||
#define __NETIF_LOOPIF_H__
|
||||
|
||||
#include "lwip/netif.h"
|
||||
|
||||
err_t loopif_init(struct netif *netif);
|
||||
|
||||
#endif /* __NETIF_LOOPIF_H__ */
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2001, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __NETIF_SLIPIF_H__
|
||||
#define __NETIF_SLIPIF_H__
|
||||
|
||||
#include "lwip/netif.h"
|
||||
|
||||
err_t slipif_init(struct netif * netif);
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue