diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2008-04-16 18:37:33 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2008-04-16 18:37:33 +0000 |
commit | 311dfa65d823ebb1448a12e9a24d09c7ca7a9e2a (patch) | |
tree | 47eaf22ca7bb8cc68486ffe964abd54b535902ad /c/src/lib/libbsp/arm/nds/dswifi | |
parent | 2008-04-16 Matthieu Bucchianeri <mbucchia@gmail.com> (diff) | |
download | rtems-311dfa65d823ebb1448a12e9a24d09c7ca7a9e2a.tar.bz2 |
2008-04-16 Matthieu Bucchianeri <mbucchia@gmail.com>
* ChangeLog, Makefile.am, README, bsp_specs, configure.ac,
mk_libnds.sh, patch.libnds, preinstall.am, block/block.c,
clock/clock.c, console/console.c, coproc/coproc.S, coproc/coproc.c,
coproc/coproc.ld, dswifi/dswifi_license.txt, dswifi/makefile,
dswifi/arm7/makefile, dswifi/arm7/source/wifi_arm7.c,
dswifi/arm7/source/wifi_arm7.h, dswifi/arm9/makefile,
dswifi/arm9/source/sgIP.c, dswifi/arm9/source/sgIP.h,
dswifi/arm9/source/sgIP_ARP.c, dswifi/arm9/source/sgIP_ARP.h,
dswifi/arm9/source/sgIP_Config.h, dswifi/arm9/source/sgIP_DHCP.c,
dswifi/arm9/source/sgIP_DHCP.h, dswifi/arm9/source/sgIP_DNS.c,
dswifi/arm9/source/sgIP_DNS.h, dswifi/arm9/source/sgIP_Hub.c,
dswifi/arm9/source/sgIP_Hub.h, dswifi/arm9/source/sgIP_ICMP.c,
dswifi/arm9/source/sgIP_ICMP.h, dswifi/arm9/source/sgIP_IP.c,
dswifi/arm9/source/sgIP_IP.h, dswifi/arm9/source/sgIP_TCP.c,
dswifi/arm9/source/sgIP_TCP.h, dswifi/arm9/source/sgIP_UDP.c,
dswifi/arm9/source/sgIP_UDP.h, dswifi/arm9/source/sgIP_memblock.c,
dswifi/arm9/source/sgIP_memblock.h,
dswifi/arm9/source/sgIP_sockets.c, dswifi/arm9/source/sgIP_sockets.h,
dswifi/arm9/source/wifi_arm9.c, dswifi/arm9/source/wifi_arm9.h,
dswifi/common/source/dsregs.h, dswifi/common/source/spinlock.h,
dswifi/common/source/spinlock.s, dswifi/common/source/wifi_shared.h,
dswifi/include/dswifi7.h, dswifi/include/dswifi9.h,
dswifi/include/dswifi_version.h, dswifi/include/netdb.h,
dswifi/include/sgIP_errno.h, dswifi/include/netinet/in.h, fb/fb.c,
fb/fb.h, include/bsp.h, include/my_ipc.h, include/tm27.h,
include/types.h, include/sys/iosupport.h, irq/irq.c, irq/irq.h,
libfat/gba/include/fat.h, libfat/include/fat.h,
libfat/nds/include/fat.h, libfat/source/bit_ops.h,
libfat/source/cache.c, libfat/source/cache.h, libfat/source/common.h,
libfat/source/directory.c, libfat/source/directory.h,
libfat/source/fatdir.c, libfat/source/fatdir.h,
libfat/source/fatfile.c, libfat/source/fatfile.h,
libfat/source/file_allocation_table.c,
libfat/source/file_allocation_table.h, libfat/source/filetime.c,
libfat/source/filetime.h, libfat/source/libfat.c,
libfat/source/mem_allocate.h, libfat/source/partition.c,
libfat/source/partition.h, libfat/source/disc_io/disc.c,
libfat/source/disc_io/disc.h, libfat/source/disc_io/disc_io.h,
libfat/source/disc_io/io_cf_common.c,
libfat/source/disc_io/io_cf_common.h,
libfat/source/disc_io/io_dldi.h, libfat/source/disc_io/io_dldi.s,
libfat/source/disc_io/io_efa2.c, libfat/source/disc_io/io_efa2.h,
libfat/source/disc_io/io_fcsr.c, libfat/source/disc_io/io_fcsr.h,
libfat/source/disc_io/io_m3_common.c,
libfat/source/disc_io/io_m3_common.h,
libfat/source/disc_io/io_m3cf.c, libfat/source/disc_io/io_m3cf.h,
libfat/source/disc_io/io_m3sd.c, libfat/source/disc_io/io_m3sd.h,
libfat/source/disc_io/io_mpcf.c, libfat/source/disc_io/io_mpcf.h,
libfat/source/disc_io/io_njsd.c, libfat/source/disc_io/io_njsd.h,
libfat/source/disc_io/io_nmmc.c, libfat/source/disc_io/io_nmmc.h,
libfat/source/disc_io/io_sc_common.c,
libfat/source/disc_io/io_sc_common.h,
libfat/source/disc_io/io_sccf.c, libfat/source/disc_io/io_sccf.h,
libfat/source/disc_io/io_scsd.c, libfat/source/disc_io/io_scsd.h,
libfat/source/disc_io/io_scsd_s.s,
libfat/source/disc_io/io_sd_common.c,
libfat/source/disc_io/io_sd_common.h, libnds/Makefile.arm7,
libnds/Makefile.arm9, libnds/libnds_license.txt,
libnds/basicARM7/source/defaultARM7.c,
libnds/include/default_font_bin.h, libnds/include/gbfs.h,
libnds/include/nds.h, libnds/include/nds/bios.h,
libnds/include/nds/card.h, libnds/include/nds/dma.h,
libnds/include/nds/interrupts.h, libnds/include/nds/ipc.h,
libnds/include/nds/jtypes.h, libnds/include/nds/memory.h,
libnds/include/nds/registers_alt.h, libnds/include/nds/reload.h,
libnds/include/nds/system.h, libnds/include/nds/timers.h,
libnds/include/nds/arm7/audio.h, libnds/include/nds/arm7/clock.h,
libnds/include/nds/arm7/serial.h, libnds/include/nds/arm7/touch.h,
libnds/include/nds/arm9/background.h,
libnds/include/nds/arm9/boxtest.h, libnds/include/nds/arm9/cache.h,
libnds/include/nds/arm9/console.h,
libnds/include/nds/arm9/exceptions.h,
libnds/include/nds/arm9/image.h, libnds/include/nds/arm9/input.h,
libnds/include/nds/arm9/math.h, libnds/include/nds/arm9/ndsmotion.h,
libnds/include/nds/arm9/pcx.h, libnds/include/nds/arm9/postest.h,
libnds/include/nds/arm9/rumble.h, libnds/include/nds/arm9/sound.h,
libnds/include/nds/arm9/sprite.h, libnds/include/nds/arm9/trig_lut.h,
libnds/include/nds/arm9/video.h, libnds/include/nds/arm9/videoGL.h,
libnds/source/arm7/audio.c, libnds/source/arm7/clock.c,
libnds/source/arm7/microphone.c, libnds/source/arm7/spi.c,
libnds/source/arm7/touch.c, libnds/source/arm7/userSettings.c,
libnds/source/arm9/COS.bin, libnds/source/arm9/COS.s,
libnds/source/arm9/SIN.bin, libnds/source/arm9/SIN.s,
libnds/source/arm9/TAN.bin, libnds/source/arm9/TAN.s,
libnds/source/arm9/boxtest.c, libnds/source/arm9/console.c,
libnds/source/arm9/dcache.s, libnds/source/arm9/default_font.bin,
libnds/source/arm9/default_font.s,
libnds/source/arm9/exceptionHandler.S,
libnds/source/arm9/exceptionHandler.s,
libnds/source/arm9/exceptions.c, libnds/source/arm9/gurumeditation.c,
libnds/source/arm9/icache.s, libnds/source/arm9/image.c,
libnds/source/arm9/initSystem.c, libnds/source/arm9/keys.c,
libnds/source/arm9/ndsmotion.c, libnds/source/arm9/pcx.c,
libnds/source/arm9/rumble.c, libnds/source/arm9/sound.c,
libnds/source/arm9/system.c, libnds/source/arm9/touch.c,
libnds/source/arm9/video.c, libnds/source/arm9/videoGL.c,
libnds/source/common/biosCalls.s, libnds/source/common/card.c,
libnds/source/common/gbfs.c,
libnds/source/common/interruptDispatcher.s,
libnds/source/common/interrupts.c, rtc/rtc.c, sound/sound.c,
sound/sound.h, start/start.S, startup/linkcmds, startup/start.c,
timer/timer.c, tools/Makefile.am, tools/bin2s, tools/bin2s.c,
tools/configure.ac, tools/runtest,
tools/ndstool/include/arm7_sha1_homebrew.h,
tools/ndstool/include/arm7_sha1_nintendo.h,
tools/ndstool/include/banner.h, tools/ndstool/include/bigint.h,
tools/ndstool/include/crc.h, tools/ndstool/include/default_icon.h,
tools/ndstool/include/encryption.h, tools/ndstool/include/header.h,
tools/ndstool/include/hook.h, tools/ndstool/include/little.h,
tools/ndstool/include/loadme.h, tools/ndstool/include/logo.h,
tools/ndstool/include/ndscreate.h,
tools/ndstool/include/ndsextract.h, tools/ndstool/include/ndstool.h,
tools/ndstool/include/ndstree.h, tools/ndstool/include/overlay.h,
tools/ndstool/include/passme.h, tools/ndstool/include/passme_sram.h,
tools/ndstool/include/passme_vhd1.h,
tools/ndstool/include/passme_vhd2.h, tools/ndstool/include/raster.h,
tools/ndstool/include/sha1.h, tools/ndstool/include/types.h,
tools/ndstool/source/arm7_sha1_homebrew.c,
tools/ndstool/source/arm7_sha1_nintendo.c,
tools/ndstool/source/banner.cpp, tools/ndstool/source/bigint.cpp,
tools/ndstool/source/compile_date.c, tools/ndstool/source/crc.cpp,
tools/ndstool/source/default_icon.c,
tools/ndstool/source/encryption.cpp, tools/ndstool/source/header.cpp,
tools/ndstool/source/hook.cpp, tools/ndstool/source/loadme.c,
tools/ndstool/source/logo.cpp, tools/ndstool/source/ndscodes.cpp,
tools/ndstool/source/ndscreate.cpp,
tools/ndstool/source/ndsextract.cpp,
tools/ndstool/source/ndstool.cpp, tools/ndstool/source/ndstree.cpp,
tools/ndstool/source/passme.cpp, tools/ndstool/source/passme_sram.c,
tools/ndstool/source/raster.cpp, tools/ndstool/source/sha1.cpp,
touchscreen/README.reco, touchscreen/parser.c, touchscreen/reco.c,
touchscreen/reco.h, touchscreen/touchscreen.c,
touchscreen/touchscreen.h, wifi/compat.c, wifi/compat.h, wifi/wifi.c:
New files.
Diffstat (limited to 'c/src/lib/libbsp/arm/nds/dswifi')
41 files changed, 9313 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm7/makefile b/c/src/lib/libbsp/arm/nds/dswifi/arm7/makefile new file mode 100644 index 0000000000..4124871f6c --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm7/makefile @@ -0,0 +1,145 @@ +#---------------------------------------------------------------------------------
+.SUFFIXES:
+#---------------------------------------------------------------------------------
+ifeq ($(strip $(DEVKITARM)),)
+$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM)
+endif
+
+include $(DEVKITARM)/ds_rules
+
+TOPDIR ?= $(CURDIR)/..
+
+#---------------------------------------------------------------------------------
+# BUILD is the directory where object files & intermediate files will be placed
+# SOURCES is a list of directories containing source code
+# INCLUDES is a list of directories containing extra header files
+# DATA is a list of directories containing binary files
+# all directories are relative to this makefile
+#---------------------------------------------------------------------------------
+BUILD ?= release
+SOURCES := source ../common/source
+INCLUDES := include build ../common/source ../include
+DATA :=
+
+#---------------------------------------------------------------------------------
+# options for code generation
+#---------------------------------------------------------------------------------
+ARCH := -mthumb-interwork
+
+CFLAGS := -g -Wall -O2\
+ -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\
+ -ffast-math \
+ $(ARCH)
+
+CFLAGS += $(INCLUDE) -DARM7
+CXXFLAGS := $(CFLAGS)
+
+
+ASFLAGS := -g $(ARCH)
+LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -mno-fpu -Wl,-Map,$(notdir $*).map
+
+
+ifneq ($(BUILD),debug)
+export ARM7BIN := $(TOPDIR)/lib/libdswifi7.a
+else
+export ARM7BIN := $(TOPDIR)/lib/libdswifi7d.a
+CFLAGS += -DSGIP_DEBUG
+endif
+
+
+LIBS :=
+#-lnds7
+
+#---------------------------------------------------------------------------------
+# list of directories containing libraries, this must be the top level containing
+# include and lib
+#---------------------------------------------------------------------------------
+LIBDIRS := $(LIBNDS)
+
+
+#---------------------------------------------------------------------------------
+# no real need to edit anything past this point unless you need to add additional
+# rules for different file extensions
+#---------------------------------------------------------------------------------
+ifneq ($(BUILD),$(notdir $(CURDIR)))
+#---------------------------------------------------------------------------------
+
+export DEPSDIR := $(CURDIR)/$(BUILD)
+
+export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
+
+export CC := $(PREFIX)gcc
+export CXX := $(PREFIX)g++
+export AR := $(PREFIX)ar
+export OBJCOPY := $(PREFIX)objcopy
+
+CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
+CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
+SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
+BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
+
+export OFILES := $(addsuffix .o,$(BINFILES)) \
+ $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
+
+export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
+ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+ -I$(CURDIR)/$(BUILD)
+
+export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
+
+#---------------------------------------------------------------------------------
+# use CXX for linking C++ projects, CC for standard C
+#---------------------------------------------------------------------------------
+ifeq ($(strip $(CPPFILES)),)
+#---------------------------------------------------------------------------------
+ export LD := $(CC)
+#---------------------------------------------------------------------------------
+else
+#---------------------------------------------------------------------------------
+ export LD := $(CXX)
+#---------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------
+
+.PHONY: $(BUILD) clean
+
+#---------------------------------------------------------------------------------
+$(BUILD):
+ @[ -d $@ ] || mkdir -p $@
+ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/makefile
+
+#---------------------------------------------------------------------------------
+clean:
+ @echo clean ...
+ @rm -fr debug release
+ @rm -f $(TOPDIR)/lib/libdswifi7*
+
+all: $(ARM7BIN)
+
+#---------------------------------------------------------------------------------
+else
+
+DEPENDS := $(OFILES:.o=.d)
+
+#---------------------------------------------------------------------------------
+# main targets
+#---------------------------------------------------------------------------------
+$(ARM7BIN) : $(OFILES)
+ @rm -f "$(ARM7BIN)"
+ @$(AR) rcs "$(ARM7BIN)" $(OFILES)
+ @echo built ... $(notdir $@)
+
+
+#---------------------------------------------------------------------------------
+# you need a rule like this for each extension you use as binary data
+#---------------------------------------------------------------------------------
+%.bin.o : %.bin
+#---------------------------------------------------------------------------------
+ @echo $(notdir $<)
+ @$(bin2o)
+
+-include $(DEPENDS)
+
+#---------------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------------
diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm7/source/wifi_arm7.c b/c/src/lib/libbsp/arm/nds/dswifi/arm7/source/wifi_arm7.c new file mode 100644 index 0000000000..342ac9017b --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm7/source/wifi_arm7.c @@ -0,0 +1,1637 @@ +// DS Wifi interface code +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +// wifi_arm7.c - arm7 wifi interface code +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + + +#include <nds.h> +#include "dsregs.h" +#include "wifi_arm7.h" + +#include "spinlock.h" // .h file with code for spinlocking in it. + +volatile Wifi_MainStruct * WifiData = 0; +WifiSyncHandler synchandler = 0; +int keepalive_time = 0; +int chdata_save5 = 0; + +////////////////////////////////////////////////////////////////////////// +// +// Flash support functions +// +char FlashData[512]; +void Read_Flash(int address, char * destination, int length) { + int i; + while(SPI_CR&0x80); + SPI_CR=0x8900; + SPI_DATA=3; + while(SPI_CR&0x80); + SPI_DATA=(address>>16)&255; + while(SPI_CR&0x80); + SPI_DATA=(address>>8)&255; + while(SPI_CR&0x80); + SPI_DATA=(address)&255; + while(SPI_CR&0x80); + for(i=0;i<length;i++) { + SPI_DATA=0; + while(SPI_CR&0x80); + destination[i]=SPI_DATA; + } + SPI_CR=0; +} + +void InitFlashData() { + Read_Flash(0,FlashData,512); +} + +int ReadFlashByte(int address) { + if(address<0 || address>511) return 0; + return FlashData[address]; +} + +int ReadFlashBytes(int address, int numbytes) { + int dataout=0; + int i; + for(i=0;i<numbytes;i++) { + dataout |= ReadFlashByte(i+address)<<(i*8); + } + return dataout; +} +int ReadFlashHWord(int address) { + if(address<0 || address>510) return 0; + return ReadFlashBytes(address,2); +} + +////////////////////////////////////////////////////////////////////////// +// +// WFC data loading +// +/* +int crc16_slow(u8 * data, int length) { + int i,j,d, crc; + crc=0x0000; + for(i=0;i<length;i++) { + d=data[i]; + for(j=0;j<8;j++) { + if(((d)^(crc>>15))&1) crc = (crc<<1)^0x8005; else crc=crc<<1; + d=d>>1; + } + } + crc &=0xFFFF; + return crc; +} +*/ +int crc16_slow(u8 * data, int length) { + int i,j, crc; + crc=0x0000; + for(i=0;i<length;i++) { + crc ^=data[i]; + for(j=0;j<8;j++) { + if((crc)&1) crc = (crc>>1)^0xA001; else crc=crc>>1; + } + } + crc &=0xFFFF; + return crc; +} + +void GetWfcSettings() { + u8 data[256]; + int i,n, c; + unsigned long s; + c=0; + u32 wfcBase = ReadFlashBytes(0x20, 2) * 8 - 0x400; + for(i=0;i<3;i++) WifiData->wfc_enable[i]=0; + for(i=0;i<3;i++) { + Read_Flash( wfcBase +(i<<8),(char *)data,256); + // check for validity (crc16) + if(crc16_slow(data,256)==0x0000 && data[0xE7]==0x00) { // passed the test + WifiData->wfc_enable[c] = 0x80 | (data[0xE6]&0x0F); + WifiData->wfc_ap[c].channel=0; + for(n=0;n<6;n++) WifiData->wfc_ap[c].bssid[n]=0; + for(n=0;n<16;n++) WifiData->wfc_wepkey[c][n]=data[0x80+n]; + for(n=0;n<32;n++) WifiData->wfc_ap[c].ssid[n]=data[0x40+n]; + for(n=0;n<32;n++) if(!data[0x40+n]) break; + WifiData->wfc_ap[c].ssid_len=n; + WifiData->wfc_config[c][0]=((unsigned long *)(data+0xC0))[0]; + WifiData->wfc_config[c][1]=((unsigned long *)(data+0xC0))[1]; + WifiData->wfc_config[c][3]=((unsigned long *)(data+0xC0))[2]; + WifiData->wfc_config[c][4]=((unsigned long *)(data+0xC0))[3]; + s=0; + for(n=0;n<data[0xD0];n++) { + s |= 1<<(31-n); + } + s= (s<<24) | (s>>24) | ((s&0xFF00)<<8) | ((s&0xFF0000)>>8); // htonl + WifiData->wfc_config[c][2]=s; + c++; + } + } +} + + +////////////////////////////////////////////////////////////////////////// +// +// Other support +// + +int Wifi_BBRead(int a) { + while(W_BBSIOBUSY&1); + W_BBSIOCNT=a | 0x6000; + while(W_BBSIOBUSY&1); + return W_BBSIOREAD; +} +int Wifi_BBWrite(int a, int b) { + int i; + i=0x2710; + while((W_BBSIOBUSY&1)) { + if(!i--) return -1; + } + W_BBSIOWRITE=b; + W_BBSIOCNT=a | 0x5000; + i=0x2710; + while((W_BBSIOBUSY&1)) { + if(!i--) return 0; + } + return 0; +} +void Wifi_RFWrite(int writedata) { + while(W_RFSIOBUSY&1); + W_RFSIODATA1=writedata; + W_RFSIODATA2=writedata>>16; + while(W_RFSIOBUSY&1); +} + +int PowerChip_ReadWrite(int cmd, int data) { + if(cmd&0x80) data=0; + while(SPI_CR&0x80); + SPI_CR=0x8802; + SPI_DATA=cmd; + while(SPI_CR&0x80); + SPI_CR=0x8002; + SPI_DATA=data; + while(SPI_CR&0x80); + data=SPI_DATA; + SPI_CR=0; + return data; +} + +#define LED_LONGBLINK 1 +#define LED_SHORTBLINK 3 +#define LED_ON 0 +int led_state=0; +void SetLedState(int state) { + int i; + if(state>3 || state<0) return; + if(state!=led_state) { + led_state=state; + i=PowerChip_ReadWrite(0x80,0); + i=i&0xCF; + i |= state<<4; + PowerChip_ReadWrite(0,i); + } +} + +void ProxySetLedState(int state) { + if(WifiData->flags9&WFLAG_ARM9_USELED) SetLedState(state); +} + +////////////////////////////////////////////////////////////////////////// +// +// Main functionality +// + +int RF_Reglist[] = { 0x146, 0x148, 0x14A, 0x14C, 0x120, 0x122, 0x154, 0x144, 0x130, 0x132, 0x140, 0x142, 0x38, 0x124, 0x128, 0x150 }; + +void Wifi_RFInit() { + int i,j; + int channel_extrabits; + int numchannels; + int channel_extrabytes; + int temp; + for(i=0;i<16;i++) { + WIFI_REG(RF_Reglist[i])=ReadFlashHWord(0x44+i*2); + } + numchannels=ReadFlashByte(0x42); + channel_extrabits=ReadFlashByte(0x41); + channel_extrabytes=(channel_extrabits+7)/8; + WIFI_REG(0x184)=((channel_extrabits>>7)<<8) | (channel_extrabits&0x7F); + j=0xCE; + if(ReadFlashByte(0x40)==3) { + for(i=0;i<numchannels;i++) { + Wifi_RFWrite(ReadFlashByte(j++)|(i<<8)|0x50000); + } + } else if(ReadFlashByte(0x40)==2) { + for(i=0;i<numchannels;i++) { + temp = ReadFlashBytes(j,channel_extrabytes); + Wifi_RFWrite(temp); + j+=channel_extrabytes; + if( (temp>>18)==9 ) { + chdata_save5 = temp&(~0x7C00); + } + } + } else { + for(i=0;i<numchannels;i++) { + Wifi_RFWrite(ReadFlashBytes(j,channel_extrabytes)); + j+=channel_extrabytes; + } + } +} + +void Wifi_BBInit() { + int i; + WIFI_REG(0x160)=0x0100; + for(i=0;i<0x69;i++) { + Wifi_BBWrite(i,ReadFlashByte(0x64+i)); + } +} + +// 22 entry list +int MAC_Reglist[] = { 0x04, 0x08, 0x0A, 0x12, 0x10, 0x254, 0xB4, 0x80, 0x2A, 0x28, 0xE8, 0xEA, 0xEE, 0xEC, 0x1A2, 0x1A0, 0x110, 0xBC, 0xD4, 0xD8, 0xDA, 0x76 }; +int MAC_Vallist[] = { 0, 0, 0, 0, 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 1, 0x3F03, 1, 0, 0x0800, 1, 3, 4, 0x0602, 0}; +void Wifi_MacInit() { + int i; + for(i=0;i<22;i++) { + WIFI_REG(MAC_Reglist[i]) = MAC_Vallist[i]; + } +} + + +void Wifi_TxSetup() { +/* switch(WIFI_REG(0x8006)&7) { + case 0: // + // 4170, 4028, 4000 + // TxqEndData, TxqEndManCtrl, TxqEndPsPoll + WIFI_REG(0x4024)=0xB6B8; + WIFI_REG(0x4026)=0x1D46; + WIFI_REG(0x416C)=0xB6B8; + WIFI_REG(0x416E)=0x1D46; + WIFI_REG(0x4790)=0xB6B8; + WIFI_REG(0x4792)=0x1D46; + WIFI_REG(0x80AE) = 1; + break; + case 1: // + // 4AA0, 4958, 4334 + // TxqEndData, TxqEndManCtrl, TxqEndBroadCast + // 4238, 4000 + WIFI_REG(0x4234)=0xB6B8; + WIFI_REG(0x4236)=0x1D46; + WIFI_REG(0x4330)=0xB6B8; + WIFI_REG(0x4332)=0x1D46; + WIFI_REG(0x4954)=0xB6B8; + WIFI_REG(0x4956)=0x1D46; + WIFI_REG(0x4A9C)=0xB6B8; + WIFI_REG(0x4A9E)=0x1D46; + WIFI_REG(0x50C0)=0xB6B8; + WIFI_REG(0x50C2)=0x1D46; + //... + break; + case 2: + // 45D8, 4490, 4468 + // TxqEndData, TxqEndManCtrl, TxqEndPsPoll + + WIFI_REG(0x4230)=0xB6B8; + WIFI_REG(0x4232)=0x1D46; + WIFI_REG(0x4464)=0xB6B8; + WIFI_REG(0x4466)=0x1D46; + WIFI_REG(0x448C)=0xB6B8; + WIFI_REG(0x448E)=0x1D46; + WIFI_REG(0x45D4)=0xB6B8; + WIFI_REG(0x45D6)=0x1D46; + WIFI_REG(0x4BF8)=0xB6B8; + WIFI_REG(0x4BFA)=0x1D46; +*/ + WIFI_REG(0x80AE)=0x000D; +// } +} + +void Wifi_RxSetup() { + WIFI_REG(0x8030) = 0x8000; +/* switch(WIFI_REG(0x8006)&7) { + case 0: + WIFI_REG(0x8050) = 0x4794; + WIFI_REG(0x8056) = 0x03CA; + // 17CC ? + break; + case 1: + WIFI_REG(0x8050) = 0x50C4; + WIFI_REG(0x8056) = 0x0862; + // 0E9C ? + break; + case 2: + WIFI_REG(0x8050) = 0x4BFC; + WIFI_REG(0x8056) = 0x05FE; + // 1364 ? + break; + case 3: + WIFI_REG(0x8050) = 0x4794; + WIFI_REG(0x8056) = 0x03CA; + // 17CC ? + break; + } + */ + WIFI_REG(0x8050) = 0x4C00; + WIFI_REG(0x8056) = 0x0600; + + WIFI_REG(0x8052) = 0x5F60; + WIFI_REG(0x805A) = (WIFI_REG(0x8050)&0x3FFF)>>1; + WIFI_REG(0x8062) = 0x5F5E; + WIFI_REG(0x8030) = 0x8001; +} + + +void Wifi_WakeUp() { + u32 i; + WIFI_REG(0x8036)=0; + + swiDelay( 67109 ); // 8ms delay + + WIFI_REG(0x8168)=0; + + i=Wifi_BBRead(1); + Wifi_BBWrite(1,i&0x7f); + Wifi_BBWrite(1,i); + + swiDelay( 335544 ); // 40ms delay + + Wifi_RFInit(); +} +void Wifi_Shutdown() { + int a; + if(ReadFlashByte(0x40)==2) { + Wifi_RFWrite(0xC008); + } + a=Wifi_BBRead(0x1E); + Wifi_BBWrite(0x1E,a|0x3F); + WIFI_REG(0x168)=0x800D; + WIFI_REG(0x36)=1; +} + + +void Wifi_CopyMacAddr(volatile void * dest, volatile void * src) { + ((u16 *)dest)[0]=((u16 *)src)[0]; + ((u16 *)dest)[1]=((u16 *)src)[1]; + ((u16 *)dest)[2]=((u16 *)src)[2]; +} + +int Wifi_CmpMacAddr(volatile void * mac1,volatile void * mac2) { + return (((u16 *)mac1)[0]==((u16 *)mac2)[0]) && (((u16 *)mac1)[1]==((u16 *)mac2)[1]) && (((u16 *)mac1)[2]==((u16 *)mac2)[2]); +} + +////////////////////////////////////////////////////////////////////////// +// +// MAC Copy functions +// + +u16 inline Wifi_MACRead(u32 MAC_Base, u32 MAC_Offset) { + MAC_Base += MAC_Offset; + if(MAC_Base>=(WIFI_REG(0x52)&0x1FFE)) MAC_Base -= ((WIFI_REG(0x52)&0x1FFE)-(WIFI_REG(0x50)&0x1FFE)); + return WIFI_REG(0x4000+MAC_Base); +} + +void Wifi_MACCopy(u16 * dest, u32 MAC_Base, u32 MAC_Offset, u32 length) { + int endrange,subval; + int thislength; + endrange = (WIFI_REG(0x52)&0x1FFE); + subval=((WIFI_REG(0x52)&0x1FFE)-(WIFI_REG(0x50)&0x1FFE)); + MAC_Base += MAC_Offset; + if(MAC_Base>=endrange) MAC_Base -= subval; + while(length>0) { + thislength=length; + if(thislength>(endrange-MAC_Base)) thislength=endrange-MAC_Base; + length-=thislength; + while(thislength>0) { + *(dest++) = WIFI_REG(0x4000+MAC_Base); + MAC_Base+=2; + thislength-=2; + } + MAC_Base-=subval; + } +} + +void Wifi_MACWrite(u16 * src, u32 MAC_Base, u32 MAC_Offset, u32 length) { + int endrange,subval; + int thislength; + endrange = (WIFI_REG(0x52)&0x1FFE); + subval=((WIFI_REG(0x52)&0x1FFE)-(WIFI_REG(0x50)&0x1FFE)); + MAC_Base += MAC_Offset; + if(MAC_Base>=endrange) MAC_Base -= subval; + while(length>0) { + thislength=length; + if(length>(endrange-MAC_Base)) length=endrange-MAC_Base; + length-=thislength; + while(thislength>0) { + WIFI_REG(0x4000+MAC_Base) = *(src++); + MAC_Base+=2; + thislength-=2; + } + MAC_Base-=subval; + } +} +int Wifi_QueueRxMacData(u32 base, u32 len) { + int buflen, temp,macofs, tempout; + macofs=0; + buflen=(WifiData->rxbufIn-WifiData->rxbufOut-1)*2; + if(buflen<0) buflen += WIFI_RXBUFFER_SIZE; + if(buflen<len) { WifiData->stats[WSTAT_RXQUEUEDLOST]++; return 0; } + WifiData->stats[WSTAT_RXQUEUEDPACKETS]++; + WifiData->stats[WSTAT_RXQUEUEDBYTES]+=len; + temp=WIFI_RXBUFFER_SIZE-(WifiData->rxbufOut*2); + tempout=WifiData->rxbufOut; + if(len>temp) { + Wifi_MACCopy((u16*)WifiData->rxbufData+tempout,base,macofs,temp); + macofs+=temp; + len-=temp; + tempout=0; + } + Wifi_MACCopy((u16*)WifiData->rxbufData+tempout,base,macofs,len); + tempout+=len/2; + if(tempout>=(WIFI_RXBUFFER_SIZE/2)) tempout-=(WIFI_RXBUFFER_SIZE/2); + WifiData->rxbufOut=tempout; + if(synchandler) synchandler(); + return 1; +} + +int Wifi_CheckTxBuf(s32 offset) { + offset+=WifiData->txbufIn; + if(offset>=WIFI_TXBUFFER_SIZE/2) offset-=WIFI_TXBUFFER_SIZE/2; + return WifiData->txbufData[offset]; +} + +// non-wrapping function. +int Wifi_CopyFirstTxData(s32 macbase) { + int seglen, readbase,max, packetlen,length; + packetlen=Wifi_CheckTxBuf(5); + readbase=WifiData->txbufIn; + length = (packetlen+12-4+1)/2; + max=WifiData->txbufOut-WifiData->txbufIn; + if(max<0) max+=WIFI_TXBUFFER_SIZE/2; + if(max<length) return 0; + while(length>0) { + seglen=length; + if(readbase+seglen>WIFI_TXBUFFER_SIZE/2) seglen=WIFI_TXBUFFER_SIZE/2-readbase; + length-=seglen; + while(seglen--) { WIFI_REG(0x4000+macbase)=WifiData->txbufData[readbase++]; macbase+=2; } + if(readbase>=WIFI_TXBUFFER_SIZE/2) readbase-=WIFI_TXBUFFER_SIZE/2; + } + WifiData->txbufIn=readbase; + + WifiData->stats[WSTAT_TXPACKETS]++; + WifiData->stats[WSTAT_TXBYTES]+=packetlen+12-4; + WifiData->stats[WSTAT_TXDATABYTES]+=packetlen-4; + + return packetlen; +} + + + +u16 arm7q[1024]; +u16 arm7qlen = 0; + +void Wifi_TxRaw(u16 * data, int datalen) { + datalen = (datalen+3)&(~3); + Wifi_MACWrite(data, 0, 0, datalen); +// WIFI_REG(0xB8)=0x0001; + WIFI_REG(0xA8)=0x8000; + WifiData->stats[WSTAT_TXPACKETS]++; + WifiData->stats[WSTAT_TXBYTES]+=datalen; + WifiData->stats[WSTAT_TXDATABYTES]+=datalen-12; +} + +int Wifi_TxCheck() { + if(WIFI_REG(0xA8)&0x8000) return 0; + return 1; +} + + +////////////////////////////////////////////////////////////////////////// +// +// Wifi Interrupts +// + +void Wifi_Intr_RxEnd() { + int base; + int packetlen; + int full_packetlen; + int cut, temp; + int tIME; + tIME=REG_IME; + REG_IME=0; + cut=0; + + while(WIFI_REG(0x54)!=WIFI_REG(0x5A)) { + base = WIFI_REG(0x5A)<<1; + packetlen=Wifi_MACRead(base,8); + full_packetlen=12+((packetlen+3)&(~3)); + WifiData->stats[WSTAT_RXPACKETS]++; + WifiData->stats[WSTAT_RXBYTES]+=full_packetlen; + WifiData->stats[WSTAT_RXDATABYTES]+=full_packetlen-12; + + + // process packet here + temp=Wifi_ProcessReceivedFrame(base,full_packetlen); // returns packet type + if(temp&WifiData->reqPacketFlags || WifiData->reqReqFlags&WFLAG_REQ_PROMISC) { // if packet type is requested, forward it to the rx queue + keepalive_time=0; + if(!Wifi_QueueRxMacData(base,full_packetlen)) { + // failed, ignore for now. + } + } + + base += full_packetlen; + if(base>=(WIFI_REG(0x52)&0x1FFE)) base -= ((WIFI_REG(0x52)&0x1FFE)-(WIFI_REG(0x50)&0x1FFE)); + WIFI_REG(0x5A)=base>>1; + + if(cut++>5) break; + } + REG_IME=tIME; +} + +#define CNT_STAT_START WSTAT_HW_1B0 +#define CNT_STAT_NUM 18 +u16 count_ofs_list[CNT_STAT_NUM] = { + 0x1B0, 0x1B2, 0x1B4, 0x1B6, 0x1B8, 0x1BA, 0x1BC, 0x1BE, 0x1C0, 0x1C4, 0x1D0, 0x1D2, 0x1D4, 0x1D6, 0x1D8, 0x1DA, 0x1DC, 0x1DE +}; +void Wifi_Intr_CntOverflow() { + int i; + int s,d; + s=CNT_STAT_START; + for(i=0;i<CNT_STAT_NUM;i++) { + d=WIFI_REG(count_ofs_list[i]); + WifiData->stats[s++]+=(d&0xFF); + WifiData->stats[s++]+=((d>>8)&0xFF); + } +} + +void Wifi_Intr_StartTx() { + if(WifiData->reqReqFlags&WFLAG_REQ_PROMISC) { // attempt to ensure packet is received + + } +} + +void Wifi_Intr_TxEnd() { // assume that we can now tx something new. + if(arm7qlen) { + Wifi_TxRaw(arm7q, arm7qlen); + keepalive_time=0; + arm7qlen=0; + return; + } + if((WifiData->txbufOut!=WifiData->txbufIn) && (!(WifiData->curReqFlags&WFLAG_REQ_APCONNECT) || WifiData->authlevel==WIFI_AUTHLEVEL_ASSOCIATED)) { + if(Wifi_CopyFirstTxData(0)) { + keepalive_time=0; + if(WIFI_REG(0x4008)==0) { WIFI_REG(0x4008)=WifiData->maxrate7; } // if rate dne, fill it in. + if(WIFI_REG(0x400C)&0x4000) { // wep is enabled, fill in the IV. + WIFI_REG(0x4024) = (W_RANDOM ^ (W_RANDOM<<7) ^ (W_RANDOM<<15))&0xFFFF; + WIFI_REG(0x4026) = ((W_RANDOM ^ (W_RANDOM>>7))&0xFF) | (WifiData->wepkeyid7<<14); + } + // WIFI_REG(0xB8)=0x0001; + WIFI_REG(0xA8)=0x8000; + WIFI_REG(0xAE)=0x000D; + } + } +} + +void Wifi_Intr_TBTT() { + if(WIFI_REG(0xA8)&0x8000) { + WIFI_REG(0xAE)=0x000D; + } +} + +void Wifi_Intr_DoNothing() { +} + + + +void Wifi_Interrupt() { + int wIF; + if(!WifiData) return; + if(!(WifiData->flags7&WFLAG_ARM7_RUNNING)) return; + do { + REG_IF=0x01000000; // now that we've cleared the wireless IF, kill the bit in regular IF. + wIF= W_IE & W_IF; + if(wIF& 0x0001) { W_IF=0x0001; Wifi_Intr_RxEnd(); } // 0) Rx End + if(wIF& 0x0002) { W_IF=0x0002; Wifi_Intr_TxEnd(); } // 1) Tx End + if(wIF& 0x0004) { W_IF=0x0004; Wifi_Intr_DoNothing(); } // 2) Rx Cntup + if(wIF& 0x0008) { W_IF=0x0008; Wifi_Intr_DoNothing(); } // 3) Tx Err + if(wIF& 0x0010) { W_IF=0x0010; Wifi_Intr_CntOverflow(); } // 4) Count Overflow + if(wIF& 0x0020) { W_IF=0x0020; Wifi_Intr_CntOverflow(); } // 5) AckCount Overflow + if(wIF& 0x0040) { W_IF=0x0040; Wifi_Intr_DoNothing(); } // 6) Start Rx + if(wIF& 0x0080) { W_IF=0x0080; Wifi_Intr_StartTx(); } // 7) Start Tx + if(wIF& 0x0100) { W_IF=0x0100; Wifi_Intr_DoNothing(); } // 8) + if(wIF& 0x0200) { W_IF=0x0200; Wifi_Intr_DoNothing(); } // 9) + if(wIF& 0x0400) { W_IF=0x0400; Wifi_Intr_DoNothing(); } //10) + if(wIF& 0x0800) { W_IF=0x0800; Wifi_Intr_DoNothing(); } //11) RF Wakeup + if(wIF& 0x1000) { W_IF=0x1000; Wifi_Intr_DoNothing(); } //12) MP End + if(wIF& 0x2000) { W_IF=0x2000; Wifi_Intr_DoNothing(); } //13) ACT End + if(wIF& 0x4000) { W_IF=0x4000; Wifi_Intr_TBTT(); } //14) TBTT + if(wIF& 0x8000) { W_IF=0x8000; Wifi_Intr_DoNothing(); } //15) PreTBTT + wIF= W_IE & W_IF; + } while(wIF); + +} + + + + + + +void Wifi_Update() { + int i; + if(!WifiData) return; + WifiData->random ^=(W_RANDOM ^ (W_RANDOM<<11) ^ (W_RANDOM<<22)); + WifiData->stats[WSTAT_ARM7_UPDATES]++; + WifiData->stats[WSTAT_DEBUG]=WIFI_REG(0xA8); + if(WIFI_REG(0xA8)&0x8000) { + WIFI_REG(0xAE)=0x000D; + } + // check flags, to see if we need to change anything + switch(WifiData->curMode) { + case WIFIMODE_DISABLED: + ProxySetLedState(LED_ON); + if(WifiData->reqMode!=WIFIMODE_DISABLED) { + Wifi_Start(); + WifiData->curMode=WIFIMODE_NORMAL; + } + break; + case WIFIMODE_NORMAL: // main switcher function + ProxySetLedState(LED_LONGBLINK); + if(WifiData->reqMode==WIFIMODE_DISABLED) { + Wifi_Stop(); + WifiData->curMode=WIFIMODE_DISABLED; + break; + } + if(WifiData->reqMode==WIFIMODE_SCAN) { + WifiData->counter7=WIFI_REG(0xFA); // timer hword 2 (each tick is 65.5ms) + WifiData->curMode=WIFIMODE_SCAN; + break; + } + if((WifiData->reqReqFlags ^ WifiData->curReqFlags) & WFLAG_REQ_APCONNECT) { + if(WifiData->curReqFlags& WFLAG_REQ_APCONNECT) { // already connected; disconnect + WifiData->curReqFlags &=~WFLAG_REQ_APCONNECT; + } else { // not connected - connect! + if(WifiData->reqReqFlags&WFLAG_REQ_APCOPYVALUES) { + WifiData->wepkeyid7=WifiData->wepkeyid9; + WifiData->wepmode7=WifiData->wepmode9; + WifiData->apchannel7=WifiData->apchannel9; + Wifi_CopyMacAddr(WifiData->bssid7,WifiData->bssid9); + Wifi_CopyMacAddr(WifiData->apmac7,WifiData->apmac9); + for(i=0;i<20;i++) WifiData->wepkey7[i]=WifiData->wepkey9[i]; + for(i=0;i<34;i++) WifiData->ssid7[i]=WifiData->ssid9[i]; + for(i=0;i<16;i++) WifiData->baserates7[i]=WifiData->baserates9[i]; + if(WifiData->reqReqFlags&WFLAG_REQ_APADHOC) WifiData->curReqFlags |= WFLAG_REQ_APADHOC; else WifiData->curReqFlags &= ~WFLAG_REQ_APADHOC; + } + Wifi_SetWepKey((void *)WifiData->wepkey7); + Wifi_SetWepMode(WifiData->wepmode7); + // latch BSSID + W_BSSID[0]= ((u16 *)WifiData->bssid7)[0]; + W_BSSID[1]= ((u16 *)WifiData->bssid7)[1]; + W_BSSID[2]= ((u16 *)WifiData->bssid7)[2]; + //WIFI_REG(0xD0) &= ~0x0400; + WIFI_REG(0xD0) |= 0x0400; + WifiData->reqChannel=WifiData->apchannel7; + Wifi_SetChannel(WifiData->apchannel7); + if(WifiData->curReqFlags&WFLAG_REQ_APADHOC) { + WifiData->authlevel=WIFI_AUTHLEVEL_ASSOCIATED; + } else { + Wifi_SendOpenSystemAuthPacket(); + WifiData->authlevel=WIFI_AUTHLEVEL_DISCONNECTED; + } + WifiData->txbufIn=WifiData->txbufOut; // empty tx buffer. + WifiData->curReqFlags |= WFLAG_REQ_APCONNECT; + WifiData->counter7=WIFI_REG(0xFA); // timer hword 2 (each tick is 65.5ms) + WifiData->curMode=WIFIMODE_ASSOCIATE; + WifiData->authctr=0; + } + } + break; + case WIFIMODE_SCAN: + ProxySetLedState(LED_LONGBLINK); + if(WifiData->reqMode!=WIFIMODE_SCAN) { + WifiData->curMode=WIFIMODE_NORMAL; + break; + } + if(((u16)(WIFI_REG(0xFA)-WifiData->counter7))>6) { // jump ship! + WifiData->counter7=WIFI_REG(0xFA); + WifiData->reqChannel++; + { + int i; + for(i=0;i<WIFI_MAX_AP;i++) { + if(WifiData->aplist[i].flags & WFLAG_APDATA_ACTIVE) { + WifiData->aplist[i].timectr++; + if(WifiData->aplist[i].timectr>WIFI_AP_TIMEOUT) { + WifiData->aplist[i].rssi=0; + WifiData->aplist[i].rssi_past[0]=WifiData->aplist[i].rssi_past[1]= + WifiData->aplist[i].rssi_past[2]=WifiData->aplist[i].rssi_past[3]= + WifiData->aplist[i].rssi_past[4]=WifiData->aplist[i].rssi_past[5]= + WifiData->aplist[i].rssi_past[6]=WifiData->aplist[i].rssi_past[7]=0; // update rssi later. + } + } + } + } + if(WifiData->reqChannel==14) WifiData->reqChannel=1; + } + break; + case WIFIMODE_ASSOCIATE: + ProxySetLedState(LED_LONGBLINK); + if(WifiData->authlevel==WIFI_AUTHLEVEL_ASSOCIATED) { + WifiData->curMode=WIFIMODE_ASSOCIATED; + break; + } + if(((u16)(WIFI_REG(0xFA)-WifiData->counter7))>20) { // ~1 second, reattempt connect stage + WifiData->counter7=WIFI_REG(0xFA); + WifiData->authctr++; + if(WifiData->authctr>WIFI_MAX_ASSOC_RETRY) { + WifiData->curMode=WIFIMODE_CANNOTASSOCIATE; + break; + } + switch(WifiData->authlevel) { + case WIFI_AUTHLEVEL_DISCONNECTED: // send auth packet + if(!(WifiData->curReqFlags&WFLAG_REQ_APADHOC)) { + Wifi_SendOpenSystemAuthPacket(); + break; + } + WifiData->authlevel=WIFI_AUTHLEVEL_ASSOCIATED; + break; + case WIFI_AUTHLEVEL_DEASSOCIATED: + case WIFI_AUTHLEVEL_AUTHENTICATED: // send assoc packet + Wifi_SendAssocPacket(); + break; + case WIFI_AUTHLEVEL_ASSOCIATED: + WifiData->curMode=WIFIMODE_ASSOCIATED; + break; + } + } + if(!(WifiData->reqReqFlags & WFLAG_REQ_APCONNECT)) { + WifiData->curReqFlags &=~WFLAG_REQ_APCONNECT; + WifiData->curMode=WIFIMODE_NORMAL; + break; + } + break; + case WIFIMODE_ASSOCIATED: + ProxySetLedState(LED_SHORTBLINK); + keepalive_time++; + if(keepalive_time>WIFI_KEEPALIVE_COUNT) { + keepalive_time=0; + Wifi_SendNullFrame(); + } + if((u16)(WIFI_REG(0xFA)-WifiData->pspoll_period)>WIFI_PS_POLL_CONST) { + WifiData->pspoll_period=WIFI_REG(0xFA); + // Wifi_SendPSPollFrame(); + } + if(!(WifiData->reqReqFlags & WFLAG_REQ_APCONNECT)) { + W_BSSID[0]= ((u16 *)WifiData->bssid7)[0]; + W_BSSID[1]= ((u16 *)WifiData->bssid7)[1]; + W_BSSID[2]= ((u16 *)WifiData->bssid7)[2]; + //WIFI_REG(0xD0) &= ~0x0400; + WifiData->curMode=WIFIMODE_NORMAL; + WifiData->authlevel=WIFI_AUTHLEVEL_DISCONNECTED; + if(WifiData->curReqFlags &WFLAG_REQ_APCONNECT) { // deassociate, then return + WifiData->curReqFlags &=~WFLAG_REQ_APCONNECT; + } else { // not connected for some reason, return. + WifiData->curReqFlags &=~WFLAG_REQ_APCONNECT; + WifiData->curMode=WIFIMODE_ASSOCIATE; + } + break; + } + if(WifiData->authlevel!=WIFI_AUTHLEVEL_ASSOCIATED) { + WifiData->curMode=WIFIMODE_ASSOCIATE; + break; + } + break; + case WIFIMODE_CANNOTASSOCIATE: + ProxySetLedState(LED_LONGBLINK); + if(!(WifiData->reqReqFlags & WFLAG_REQ_APCONNECT)) { + WifiData->curReqFlags &=~WFLAG_REQ_APCONNECT; + WifiData->curMode=WIFIMODE_NORMAL; + break; + } + break; + + + } + if(WifiData->curChannel!=WifiData->reqChannel) { + Wifi_SetChannel(WifiData->reqChannel); + } + // check Rx + Wifi_Intr_RxEnd(); + // check if we need to tx anything + if(Wifi_TxCheck()) Wifi_Intr_TxEnd(); // easiest way to do so at the moment. +} + + + + +////////////////////////////////////////////////////////////////////////// +// +// Wifi User-called Functions +// +void erasemem(void * mem, int length) { + int i; + char * m = (char *)mem; + for(i=0;i<length;i++) + m[i]=0; +} + + +void Wifi_Init(u32 wifidata) { + WifiData = (Wifi_MainStruct *)wifidata; + + POWERCNT7 |= 2; // enable power for the wifi + *((volatile u16 *)0x04000206) = 0x30; // ??? + + InitFlashData(); + + // reset/shutdown wifi: + WIFI_REG(0x4)=0xffff; + Wifi_Stop(); + Wifi_Shutdown(); // power off wifi + + WifiData->curChannel=1; + WifiData->reqChannel=1; + WifiData->curMode=WIFIMODE_DISABLED; + WifiData->reqMode=WIFIMODE_DISABLED; + WifiData->reqPacketFlags=WFLAG_PACKET_ALL & (~WFLAG_PACKET_BEACON); + WifiData->curReqFlags=0; + WifiData->reqReqFlags=0; + WifiData->maxrate7=0x0A; + + int i; + for(i=0x4000;i<0x6000;i+=2) WIFI_REG(i)=0; + + + // load in the WFC data. + GetWfcSettings(); + + for(i=0;i<6;i++) WifiData->MacAddr[i]=ReadFlashByte(0x36+i); + + W_IE=0; + Wifi_WakeUp(); + + Wifi_MacInit(); + Wifi_RFInit(); + Wifi_BBInit(); + + // Set Default Settings + W_MACADDR[0]=((u16 *)WifiData->MacAddr)[0]; + W_MACADDR[1]=((u16 *)WifiData->MacAddr)[1]; + W_MACADDR[2]=((u16 *)WifiData->MacAddr)[2]; + + W_RETRLIMIT=7; + Wifi_SetMode(2); + Wifi_SetWepMode(WEPMODE_NONE); + + + Wifi_SetChannel(1); + + Wifi_BBWrite(0x13, 0x00); + Wifi_BBWrite(0x35, 0x1F); + +// Wifi_Shutdown(); + WifiData->random ^=(W_RANDOM ^ (W_RANDOM<<11) ^ (W_RANDOM<<22)); + + WifiData->flags7 |= WFLAG_ARM7_ACTIVE; +} + +void Wifi_Deinit() { + Wifi_Stop(); + POWERCNT7 &= ~2; +} + +void Wifi_Start() { + int i, tIME; + tIME=REG_IME; + REG_IME=0; + Wifi_Stop(); + +// Wifi_WakeUp(); + + WIFI_REG(0x8032) = 0x8000; + WIFI_REG(0x8134) = 0xFFFF; + WIFI_REG(0x802A) = 0; + W_AIDS = 0; + WIFI_REG(0x80E8) = 1; + WIFI_REG(0x8038) = 0x0000; + WIFI_REG(0x20) = 0x0000; + WIFI_REG(0x22) = 0x0000; + WIFI_REG(0x24) = 0x0000; + + Wifi_TxSetup(); + Wifi_RxSetup(); + + WIFI_REG(0x8030) = 0x8000; +/* + switch(WIFI_REG(0x8006)&7) { + case 0: // infrastructure mode? + W_IF=0xFFFF; + W_IE=0x003F; + WIFI_REG(0x81AE)=0x1fff; + //WIFI_REG(0x81AA)=0x0400; + WIFI_REG(0x80D0)=0xffff; + WIFI_REG(0x80E0)=0x0008; + WIFI_REG(0x8008)=0; + WIFI_REG(0x800A)=0; + WIFI_REG(0x80E8)=0; + WIFI_REG(0x8004)=1; + //SetStaState(0x40); + break; + case 1: // ad-hoc mode? -- beacons are required to be created! + W_IF=0xFFF; + W_IE=0x703F; + WIFI_REG(0x81AE)=0x1fff; + WIFI_REG(0x81AA)=0; // 0x400 + WIFI_REG(0x80D0)=0x0301; + WIFI_REG(0x80E0)=0x000D; + WIFI_REG(0x8008)=0xE000; + WIFI_REG(0x800A)=0; + WIFI_REG(0x8004)=1; + //?? + WIFI_REG(0x80EA)=1; + WIFI_REG(0x80AE)=2; + break; + case 2: // DS comms mode? + */ + W_IF=0xFFFF; + //W_IE=0xE03F; + W_IE=0x40B3; + WIFI_REG(0x81AE)=0x1fff; + WIFI_REG(0x81AA)=0; //0x68 + W_BSSID[0]=0xFFFF; + W_BSSID[1]=0xFFFF; + W_BSSID[2]=0xFFFF; + WIFI_REG(0x80D0)=0x0181; // 0x181 + WIFI_REG(0x80E0)=0x000B; + WIFI_REG(0x8008)=0; + WIFI_REG(0x800A)=0; + WIFI_REG(0x8004)=1; + WIFI_REG(0x80E8)=1; + WIFI_REG(0x80EA)=1; + //SetStaState(0x20); + /* + break; + case 3: + case 4: + break; + } + */ + + WIFI_REG(0x8048)=0x0000; + Wifi_DisableTempPowerSave(); + //WIFI_REG(0x80AE)=0x0002; + W_POWERSTATE |= 2; + WIFI_REG(0xAC) = 0xFFFF; + i=0xFA0; + while(i!=0 && !(WIFI_REG(0x819C)&0x80)) i--; + WifiData->flags7 |=WFLAG_ARM7_RUNNING; + REG_IME=tIME; +} + +void Wifi_Stop() { + int tIME; + tIME=REG_IME; + WifiData->flags7 &= ~WFLAG_ARM7_RUNNING; + W_IE=0; + WIFI_REG(0x8004) = 0; + WIFI_REG(0x80EA) = 0; + WIFI_REG(0x80E8) = 0; + WIFI_REG(0x8008) = 0; + WIFI_REG(0x800A) = 0; + + WIFI_REG(0x80AC) = 0xFFFF; + WIFI_REG(0x80B4) = 0xFFFF; +// Wifi_Shutdown(); + REG_IME=tIME; +} + +void Wifi_SetChannel(int channel) { + int i,n,l; + if(channel<1 || channel>13) return; + channel-=1; + + switch(ReadFlashByte(0x40)) { + case 2: + case 5: + Wifi_RFWrite(ReadFlashBytes(0xf2+channel*6,3)); + Wifi_RFWrite(ReadFlashBytes(0xf5+channel*6,3)); + + swiDelay( 12583 ); // 1500 us delay + + if(chdata_save5 & 0x10000) + { + if(chdata_save5 & 0x8000) break; + n = ReadFlashByte(0x154+channel); + Wifi_RFWrite( chdata_save5 | ((n&0x1F)<<10) ); + } else { + Wifi_BBWrite(0x1E, ReadFlashByte(0x146+channel)); + } + + break; + case 3: + n=ReadFlashByte(0x42); + n+=0xCF; + l=ReadFlashByte(n-1); + for(i=0;i<l;i++) { + Wifi_BBWrite(ReadFlashByte(n),ReadFlashByte(n+channel+1)); + n+=15; + } + for(i=0;i<ReadFlashByte(0x43);i++) { + Wifi_RFWrite( (ReadFlashByte(n)<<8) | ReadFlashByte(n+channel+1) | 0x050000 ); + n+=15; + } + + swiDelay( 12583 ); // 1500 us delay + + break; + default: + break; + } + WifiData->curChannel=channel+1; +} +void Wifi_SetWepKey(void * wepkey) { + int i; + for(i=0;i<16;i++) { + W_WEPKEY0[i]=((u16 *)wepkey)[i]; + W_WEPKEY1[i]=((u16 *)wepkey)[i]; + W_WEPKEY2[i]=((u16 *)wepkey)[i]; + W_WEPKEY3[i]=((u16 *)wepkey)[i]; + } +} + +void Wifi_SetWepMode(int wepmode) { + if(wepmode<0 || wepmode>7) return; + if(wepmode==0) { + WIFI_REG(0x32)=0x0000; + } else { + WIFI_REG(0x32)=0x8000; + } + if(wepmode==0) wepmode=1; + W_MODE_WEP = (W_MODE_WEP & 0xFFC7) | (wepmode<<3); +} + +void Wifi_SetBeaconPeriod(int beacon_period) { + if(beacon_period<0x10 || beacon_period>0x3E7) return; + WIFI_REG(0x8C)=beacon_period; +} + +void Wifi_SetMode(int wifimode) { + if(wifimode>3 || wifimode<0) return; + W_MODE_WEP = (W_MODE_WEP& 0xfff8) | wifimode; +} +void Wifi_SetPreambleType(int preamble_type) { + if(preamble_type>1 || preamble_type<0) return; + WIFI_REG(0x80BC) = (WIFI_REG(0x80BC) & 0xFFBF) | (preamble_type<<6); +} +void Wifi_DisableTempPowerSave() { + WIFI_REG(0x8038) &= ~2; + WIFI_REG(0x8048) = 0; +} + + + + + +////////////////////////////////////////////////////////////////////////// +// +// 802.11b system, tied in a bit with the : + + +int Wifi_TxQueue(u16 * data, int datalen) { + int i,j; + if(arm7qlen) { + if(Wifi_TxCheck()) { + Wifi_TxRaw(arm7q,arm7qlen); + arm7qlen=0; + j=(datalen+1)>>1; + if(j>1024) return 0; + for(i=0;i<j;i++) arm7q[i]=data[i]; + arm7qlen=datalen; + return 1; + } + return 0; + } + if(Wifi_TxCheck()) { + Wifi_TxRaw(data,datalen); + return 1; + } + arm7qlen=0; + j=(datalen+1)>>1; + if(j>1024) return 0; + for(i=0;i<j;i++) arm7q[i]=data[i]; + arm7qlen=datalen; + return 1; +} + +int Wifi_GenMgtHeader(u8 * data, u16 headerflags) { + // tx header + ((u16 *)data)[0]=0; + ((u16 *)data)[1]=0; + ((u16 *)data)[2]=0; + ((u16 *)data)[3]=0; + ((u16 *)data)[4]=0; + ((u16 *)data)[5]=0; + // fill in most header fields + ((u16 *)data)[7]=0x0000; + Wifi_CopyMacAddr(data+16,WifiData->apmac7); + Wifi_CopyMacAddr(data+22,WifiData->MacAddr); + Wifi_CopyMacAddr(data+28,WifiData->bssid7); + ((u16 *)data)[17]=0; + + // fill in wep-specific stuff + if(headerflags&0x4000) { + ((u32 *)data)[9]=((W_RANDOM ^ (W_RANDOM<<7) ^ (W_RANDOM<<15))&0x0FFF) | (WifiData->wepkeyid7<<30); // I'm lazy and certainly haven't done this to spec. + ((u16 *)data)[6]=headerflags; + return 28+12; + } else { + ((u16 *)data)[6]=headerflags; + return 24+12; + } +} + +int Wifi_SendOpenSystemAuthPacket() { + // max size is 12+24+4+6 = 46 + u8 data[64]; + int i; + i=Wifi_GenMgtHeader(data,0x00B0); + + ((u16 *)(data+i))[0]=0; // Authentication algorithm number (0=open system) + ((u16 *)(data+i))[1]=1; // Authentication sequence number + ((u16 *)(data+i))[2]=0; // Authentication status code (reserved for this message, =0) + + ((u16 *)data)[4]=0x000A; + ((u16 *)data)[5]=i+6-12+4; + + return Wifi_TxQueue((u16 *)data, i+6); +} + +int Wifi_SendSharedKeyAuthPacket() { + // max size is 12+24+4+6 = 46 + u8 data[64]; + int i; + i=Wifi_GenMgtHeader(data,0x00B0); + + ((u16 *)(data+i))[0]=1; // Authentication algorithm number (1=shared key) + ((u16 *)(data+i))[1]=1; // Authentication sequence number + ((u16 *)(data+i))[2]=0; // Authentication status code (reserved for this message, =0) + + ((u16 *)data)[4]=0x000A; + ((u16 *)data)[5]=i+6-12+4; + + return Wifi_TxQueue((u16 *)data, i+6); +} + +int Wifi_SendSharedKeyAuthPacket2(int challenge_length, u8 * challenge_Text) { + // max size is 12+24+4+6 = 46 + u8 data[320]; + int i,j; + i=Wifi_GenMgtHeader(data,0x40B0); + + ((u16 *)(data+i))[0]=1; // Authentication algorithm number (1=shared key) + ((u16 *)(data+i))[1]=3; // Authentication sequence number + ((u16 *)(data+i))[2]=0; // Authentication status code (reserved for this message, =0) + + data[i+6]=0x10; // 16=challenge text block + data[i+7]=challenge_length; + + for(j=0;j<challenge_length;j++) { + data[i+j+8]=challenge_Text[j]; + } + + ((u16 *)data)[4]=0x000A; + ((u16 *)data)[5]=i+8+challenge_length-12+4 +4; + + return Wifi_TxQueue((u16 *)data, i+8+challenge_length); +} + + +int Wifi_SendAssocPacket() { // uses arm7 data in our struct + // max size is 12+24+4+34+4 = 66 + u8 data[96]; + int i,j,numrates; + + i=Wifi_GenMgtHeader(data,0x0000); + + if(WifiData->wepmode7) { + ((u16 *)(data+i))[0]=0x0031; // CAPS info + } else { + ((u16 *)(data+i))[0]=0x0021; // CAPS info + } + + ((u16 *)(data+i))[1]=WIFI_REG(0x8E); // Listen interval + i+=4; + data[i++]=0; // SSID element + data[i++]=WifiData->ssid7[0]; + for(j=0;j<WifiData->ssid7[0];j++) data[i++]=WifiData->ssid7[1+j]; + + if((WifiData->baserates7[0]&0x7f)!=2) { + for(j=1;j<16;j++) WifiData->baserates7[i]=WifiData->baserates7[j-1]; + } + WifiData->baserates7[0]=0x82; + if((WifiData->baserates7[1]&0x7f)!=4) { + for(j=2;j<16;j++) WifiData->baserates7[j]=WifiData->baserates7[j-1]; + } + WifiData->baserates7[1]=0x04; + + WifiData->baserates7[15]=0; + for(j=0;j<16;j++) if(WifiData->baserates7[j]==0) break; + numrates=j; + for(j=2;j<numrates;j++) WifiData->baserates7[j] &= 0x7F; + + data[i++]=1; // rate set + data[i++]=numrates; + for(j=0;j<numrates;j++) data[i++]=WifiData->baserates7[j]; + + // reset header fields with needed data + ((u16 *)data)[4]=0x000A; + ((u16 *)data)[5]=i-12+4; + + return Wifi_TxQueue((u16 *)data, i); +} + +int Wifi_SendNullFrame() { + // max size is 12+16 = 28 + u8 data[32]; + // tx header + ((u16 *)data)[0]=0; + ((u16 *)data)[1]=0; + ((u16 *)data)[2]=0; + ((u16 *)data)[3]=0; + ((u16 *)data)[4]=WifiData->maxrate7; + ((u16 *)data)[5]=18+4; + // fill in packet header fields + ((u16 *)data)[6]=0x0148; + ((u16 *)data)[7]=0; + Wifi_CopyMacAddr(data+16,WifiData->apmac7); + Wifi_CopyMacAddr(data+22,WifiData->MacAddr); + + return Wifi_TxQueue((u16 *)data, 30); +} + +int Wifi_SendPSPollFrame() { + // max size is 12+16 = 28 + u8 data[32]; + // tx header + ((u16 *)data)[0]=0; + ((u16 *)data)[1]=0; + ((u16 *)data)[2]=0; + ((u16 *)data)[3]=0; + ((u16 *)data)[4]=WifiData->maxrate7; + ((u16 *)data)[5]=16+4; + // fill in packet header fields + ((u16 *)data)[6]=0x01A4; + ((u16 *)data)[7]=0xC000 | W_AIDS; + Wifi_CopyMacAddr(data+16,WifiData->apmac7); + Wifi_CopyMacAddr(data+22,WifiData->MacAddr); + + return Wifi_TxQueue((u16 *)data, 28); +} + +int Wifi_ProcessReceivedFrame(int macbase, int framelen) { + Wifi_RxHeader packetheader; + u16 control_802; + Wifi_MACCopy((u16 *)&packetheader,macbase,0,12); + control_802=Wifi_MACRead(macbase,12); + switch((control_802>>2)&0x3F) { + // Management Frames + case 0x20: // 1000 00 Beacon + case 0x14: // 0101 00 Probe Response // process probe responses too. + // mine data from the beacon... + { + u8 data[512]; + u8 wepmode,fromsta; + u8 segtype,seglen; + u8 channel; + u8 wpamode; + u8 rateset[16]; + u16 ptr_ssid; + u16 maxrate; + u16 curloc; + u32 datalen; + u16 i,j,compatible; + datalen=packetheader.byteLength; + if(datalen>512) datalen=512; + Wifi_MACCopy((u16 *)data,macbase,12,(datalen+1)&~1); + wepmode=0; + maxrate=0; + if(((u16 *)data)[5+12]&0x0010) { // capability info, WEP bit + wepmode=1; + } + fromsta=Wifi_CmpMacAddr(data+10, data+16); + curloc=12+24; // 12 fixed bytes, 24 802.11 header + compatible=1; + ptr_ssid=0; + channel=WifiData->curChannel; + wpamode=0; + do { + if(curloc>=datalen) break; + segtype=data[curloc++]; + seglen=data[curloc++]; + switch(segtype) { + case 0: // SSID element + ptr_ssid=curloc-2; + break; + case 1: // rate set (make sure we're compatible) + compatible=0; + maxrate=0; + j=0; + for(i=0;i<seglen;i++) { + if((data[curloc+i]&0x7F)>maxrate) maxrate=data[curloc+i]&0x7F; + if(j<15 && data[curloc+i]&0x80) rateset[j++]=data[curloc+i]; + } + for(i=0;i<seglen;i++) { + if(data[curloc+i]==0x82 || data[curloc+i]==0x84) compatible=1; // 1-2mbit, fully compatible + else if(data[curloc+i]==0x8B || data[curloc+i]==0x96) compatible=2; // 5.5,11mbit, have to fake our way in. + else if(data[curloc+i]&0x80) { compatible=0; break; } + } + rateset[j]=0; + break; + case 3: // DS set (current channel) + channel=data[curloc]; + break; + case 48: // RSN(A) field- WPA enabled. + wpamode=1; + break; + + } // don't care about the others. + curloc+=seglen; + } while(curloc<datalen); + if(wpamode==1) compatible=0; + if(1) { + seglen=0; + segtype=255; + for(i=0;i<WIFI_MAX_AP;i++) { + if( Wifi_CmpMacAddr(WifiData->aplist[i].bssid,data+16)) { + seglen++; + if(Spinlock_Acquire(WifiData->aplist[i])==SPINLOCK_OK) { + WifiData->aplist[i].timectr=0; + WifiData->aplist[i].flags=WFLAG_APDATA_ACTIVE | (wepmode?WFLAG_APDATA_WEP:0) | (fromsta?0:WFLAG_APDATA_ADHOC); + if(compatible==1) WifiData->aplist[i].flags |= WFLAG_APDATA_COMPATIBLE; + if(compatible==2) WifiData->aplist[i].flags |= WFLAG_APDATA_EXTCOMPATIBLE; + if(wpamode==1) WifiData->aplist[i].flags |= WFLAG_APDATA_WPA; + WifiData->aplist[i].maxrate=maxrate; + + Wifi_CopyMacAddr(WifiData->aplist[i].macaddr,data+10); // src: +10 + if(ptr_ssid) { + WifiData->aplist[i].ssid_len=data[ptr_ssid+1]; + if(WifiData->aplist[i].ssid_len>32) WifiData->aplist[i].ssid_len=32; + for(j=0;j<WifiData->aplist[i].ssid_len;j++) { + WifiData->aplist[i].ssid[j]=data[ptr_ssid+2+j]; + } + WifiData->aplist[i].ssid[j]=0; + } + if(WifiData->curChannel==channel) { // only use RSSI when we're on the right channel + if(WifiData->aplist[i].rssi_past[0]==0) { // min rssi is 2, heh. + WifiData->aplist[i].rssi_past[0]=WifiData->aplist[i].rssi_past[1]= + WifiData->aplist[i].rssi_past[2]=WifiData->aplist[i].rssi_past[3]= + WifiData->aplist[i].rssi_past[4]=WifiData->aplist[i].rssi_past[5]= + WifiData->aplist[i].rssi_past[6]=WifiData->aplist[i].rssi_past[7]=packetheader.rssi_&255; + } else { + for(j=0;j<7;j++) { + WifiData->aplist[i].rssi_past[j]=WifiData->aplist[i].rssi_past[j+1]; + } + WifiData->aplist[i].rssi_past[7]=packetheader.rssi_&255; + } + } + WifiData->aplist[i].channel=channel; + for(j=0;j<16;j++) WifiData->aplist[i].base_rates[j]=rateset[j]; + Spinlock_Release(WifiData->aplist[i]); + } else { + // couldn't update beacon - oh well :\ there'll be other beacons. + } + } else { + if(WifiData->aplist[i].flags & WFLAG_APDATA_ACTIVE) { + // WifiData->aplist[i].timectr++; + } else { + if(segtype==255) segtype=i; + } + } + } + if(seglen==0) { // we couldn't find an existing record + if(segtype==255) { + j=0; + for(i=0;i<WIFI_MAX_AP;i++) { + if(WifiData->aplist[i].timectr>j) { + j=WifiData->aplist[i].timectr; + segtype=i; + } + } + } + // stuff new data in + i=segtype; + if(Spinlock_Acquire(WifiData->aplist[i])==SPINLOCK_OK) { + Wifi_CopyMacAddr(WifiData->aplist[i].bssid,data+16); // bssid: +16 + Wifi_CopyMacAddr(WifiData->aplist[i].macaddr,data+10); // src: +10 + WifiData->aplist[i].timectr=0; + WifiData->aplist[i].flags=WFLAG_APDATA_ACTIVE | (wepmode?WFLAG_APDATA_WEP:0) | (fromsta?0:WFLAG_APDATA_ADHOC); + if(compatible==1) WifiData->aplist[i].flags |= WFLAG_APDATA_COMPATIBLE; + if(compatible==2) WifiData->aplist[i].flags |= WFLAG_APDATA_EXTCOMPATIBLE; + if(wpamode==1) WifiData->aplist[i].flags |= WFLAG_APDATA_WPA; + WifiData->aplist[i].maxrate=maxrate; + + if(ptr_ssid) { + WifiData->aplist[i].ssid_len=data[ptr_ssid+1]; + if(WifiData->aplist[i].ssid_len>32) WifiData->aplist[i].ssid_len=32; + for(j=0;j<WifiData->aplist[i].ssid_len;j++) { + WifiData->aplist[i].ssid[j]=data[ptr_ssid+2+j]; + } + WifiData->aplist[i].ssid[j]=0; + } + if(WifiData->curChannel==channel) { // only use RSSI when we're on the right channel + WifiData->aplist[i].rssi_past[0]=WifiData->aplist[i].rssi_past[1]= + WifiData->aplist[i].rssi_past[2]=WifiData->aplist[i].rssi_past[3]= + WifiData->aplist[i].rssi_past[4]=WifiData->aplist[i].rssi_past[5]= + WifiData->aplist[i].rssi_past[6]=WifiData->aplist[i].rssi_past[7]=packetheader.rssi_&255; + } else { + WifiData->aplist[i].rssi_past[0]=WifiData->aplist[i].rssi_past[1]= + WifiData->aplist[i].rssi_past[2]=WifiData->aplist[i].rssi_past[3]= + WifiData->aplist[i].rssi_past[4]=WifiData->aplist[i].rssi_past[5]= + WifiData->aplist[i].rssi_past[6]=WifiData->aplist[i].rssi_past[7]=0; // update rssi later. + } + WifiData->aplist[i].channel=channel; + for(j=0;j<16;j++) WifiData->aplist[i].base_rates[j]=rateset[j]; + + Spinlock_Release(WifiData->aplist[i]); + } else { + // couldn't update beacon - oh well :\ there'll be other beacons. + } + } + } + } + if(((control_802>>2)&0x3F)==0x14) return WFLAG_PACKET_MGT; + return WFLAG_PACKET_BEACON; + case 0x04: // 0001 00 Assoc Response + case 0x0C: // 0011 00 Reassoc Response + // we might have been associated, let's check. + { + int datalen,i; + u8 data[64]; + datalen=packetheader.byteLength; + if(datalen>64) datalen=64; + Wifi_MACCopy((u16 *)data,macbase,12,(datalen+1)&~1); + + if(Wifi_CmpMacAddr(data+4,WifiData->MacAddr)) { // packet is indeed sent to us. + if(Wifi_CmpMacAddr(data+16,WifiData->bssid7)) { // packet is indeed from the base station we're trying to associate to. + if(((u16 *)(data+24))[1]==0) { // status code, 0==success + W_AIDS=((u16 *)(data+24))[2]; + WIFI_REG(0x2A)=((u16 *)(data+24))[2]; + // set max rate + WifiData->maxrate7=0xA; + for(i=0;i<((u8 *)(data+24))[7];i++) { + if(((u8 *)(data+24))[8+i]==0x84 || ((u8 *)(data+24))[8+i]==0x04) { + WifiData->maxrate7=0x14; + } + } + if(WifiData->authlevel==WIFI_AUTHLEVEL_AUTHENTICATED || WifiData->authlevel==WIFI_AUTHLEVEL_DEASSOCIATED) { + WifiData->authlevel=WIFI_AUTHLEVEL_ASSOCIATED; + WifiData->authctr=0; + + + + } + } else { // status code = failure! + WifiData->curMode=WIFIMODE_CANNOTASSOCIATE; + } + } + } + } + + + return WFLAG_PACKET_MGT; + case 0x00: // 0000 00 Assoc Request + case 0x08: // 0010 00 Reassoc Request + case 0x10: // 0100 00 Probe Request + case 0x24: // 1001 00 ATIM + case 0x28: // 1010 00 Disassociation + return WFLAG_PACKET_MGT; + case 0x2C: // 1011 00 Authentication + // check auth response to ensure we're in + { + int datalen; + u8 data[384]; + datalen=packetheader.byteLength; + if(datalen>384) datalen=384; + Wifi_MACCopy((u16 *)data,macbase,12,(datalen+1)&~1); + + if(Wifi_CmpMacAddr(data+4,WifiData->MacAddr)) { // packet is indeed sent to us. + if(Wifi_CmpMacAddr(data+16,WifiData->bssid7)) { // packet is indeed from the base station we're trying to associate to. + if(((u16 *)(data+24))[0]==0) { // open system auth + if(((u16 *)(data+24))[1]==2) { // seq 2, should be final sequence + if(((u16 *)(data+24))[2]==0) { // status code: successful + if(WifiData->authlevel==WIFI_AUTHLEVEL_DISCONNECTED) { + WifiData->authlevel=WIFI_AUTHLEVEL_AUTHENTICATED; + WifiData->authctr=0; + Wifi_SendAssocPacket(); + } + } else { // status code: rejected, try something else + Wifi_SendSharedKeyAuthPacket(); + } + } + } else if(((u16 *)(data+24))[0]==1) { // shared key auth + if(((u16 *)(data+24))[1]==2) { // seq 2, challenge text + if(((u16 *)(data+24))[2]==0) { // status code: successful + // scrape challenge text and send challenge reply + if(data[24+6]==0x10) { // 16 = challenge text - this value must be 0x10 or else! + Wifi_SendSharedKeyAuthPacket2(data[24+7],data+24+8); + } + } else { // rejected, just give up. + WifiData->curMode=WIFIMODE_CANNOTASSOCIATE; + } + } else if(((u16 *)(data+24))[1]==4) { // seq 4, accept/deny + if(((u16 *)(data+24))[2]==0) { // status code: successful + if(WifiData->authlevel==WIFI_AUTHLEVEL_DISCONNECTED) { + WifiData->authlevel=WIFI_AUTHLEVEL_AUTHENTICATED; + WifiData->authctr=0; + Wifi_SendAssocPacket(); + } + } else { // status code: rejected. Cry in the corner. + WifiData->curMode=WIFIMODE_CANNOTASSOCIATE; + } + } + } + } + } + } + return WFLAG_PACKET_MGT; + case 0x30: // 1100 00 Deauthentication + { + int datalen; + u8 data[64]; + datalen=packetheader.byteLength; + if(datalen>64) datalen=64; + Wifi_MACCopy((u16 *)data,macbase,12,(datalen+1)&~1); + + if(Wifi_CmpMacAddr(data+4,WifiData->MacAddr)) { // packet is indeed sent to us. + if(Wifi_CmpMacAddr(data+16,WifiData->bssid7)) { // packet is indeed from the base station we're trying to associate to. + // bad things! they booted us!. + // back to square 1. + if(WifiData->curReqFlags&WFLAG_REQ_APADHOC){ + WifiData->authlevel=WIFI_AUTHLEVEL_AUTHENTICATED; + Wifi_SendAssocPacket(); + } else { + WifiData->authlevel=WIFI_AUTHLEVEL_DISCONNECTED; + Wifi_SendOpenSystemAuthPacket(); + } + } + } + } + return WFLAG_PACKET_MGT; + // Control Frames + case 0x29: // 1010 01 PowerSave Poll + case 0x2D: // 1011 01 RTS + case 0x31: // 1100 01 CTS + case 0x35: // 1101 01 ACK + case 0x39: // 1110 01 CF-End + case 0x3D: // 1111 01 CF-End+CF-Ack + return WFLAG_PACKET_CTRL; + // Data Frames + case 0x02: // 0000 10 Data + case 0x06: // 0001 10 Data + CF-Ack + case 0x0A: // 0010 10 Data + CF-Poll + case 0x0E: // 0011 10 Data + CF-Ack + CF-Poll + // We like data! + + return WFLAG_PACKET_DATA; + case 0x12: // 0100 10 Null Function + case 0x16: // 0101 10 CF-Ack + case 0x1A: // 0110 10 CF-Poll + case 0x1E: // 0111 10 CF-Ack + CF-Poll + return WFLAG_PACKET_DATA; + default: // ignore! + return 0; + } +} +int Wifi_CreateTxFrame(int frametype, void * dest, int destlen) { + switch(frametype) { + + default: + return 0; + } +} + +////////////////////////////////////////////////////////////////////////// +// sync functions + +void Wifi_Sync() { + Wifi_Update(); +} +void Wifi_SetSyncHandler(WifiSyncHandler sh) { + synchandler=sh; +} + + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm7/source/wifi_arm7.h b/c/src/lib/libbsp/arm/nds/dswifi/arm7/source/wifi_arm7.h new file mode 100644 index 0000000000..875a956a3f --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm7/source/wifi_arm7.h @@ -0,0 +1,136 @@ +// DS Wifi interface code +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +// wifi_arm7.h - arm7 wifi interface header +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef WIFI_ARM7_H +#define WIFI_ARM7_H + +#ifndef ARM7 +#error Wifi is only accessible from the ARM7 +#endif + + +// keepalive updated in the update handler, which should be called in vblank +// keepalive set for 2 minutes. +#define WIFI_KEEPALIVE_COUNT (60*60*2) + + +#define WIFI_REG(ofs) (*((volatile u16 *)(0x04800000+(ofs)))) +// Wifi regs +#define W_WEPKEY0 (((volatile u16 *)(0x04805F80))) +#define W_WEPKEY1 (((volatile u16 *)(0x04805FA0))) +#define W_WEPKEY2 (((volatile u16 *)(0x04805FC0))) +#define W_WEPKEY3 (((volatile u16 *)(0x04805FE0))) + +#define W_MODE_RST (*((volatile u16 *)(0x04800004))) +#define W_MODE_WEP (*((volatile u16 *)(0x04800006))) +#define W_IF (*((volatile u16 *)(0x04800010))) +#define W_IE (*((volatile u16 *)(0x04800012))) +#define W_MACADDR (((volatile u16 *)(0x04800018))) +#define W_BSSID (((volatile u16 *)(0x04800020))) +#define W_AIDS (*((volatile u16 *)(0x04800028))) +#define W_RETRLIMIT (*((volatile u16 *)(0x0480002C))) +#define W_POWERSTATE (*((volatile u16 *)(0x0480003C))) +#define W_RANDOM (*((volatile u16 *)(0x04800044))) + +#define W_BBSIOCNT (*((volatile u16 *)(0x04800158))) +#define W_BBSIOWRITE (*((volatile u16 *)(0x0480015A))) +#define W_BBSIOREAD (*((volatile u16 *)(0x0480015C))) +#define W_BBSIOBUSY (*((volatile u16 *)(0x0480015E))) +#define W_RFSIODATA2 (*((volatile u16 *)(0x0480017C))) +#define W_RFSIODATA1 (*((volatile u16 *)(0x0480017E))) +#define W_RFSIOBUSY (*((volatile u16 *)(0x04800180))) + + + + + + +#include "wifi_shared.h" + +extern volatile Wifi_MainStruct * WifiData; + +// Wifi Sync Handler function: Callback function that is called when the arm9 needs to be told to synchronize with new fifo data. +// If this callback is used (see Wifi_SetSyncHandler()), it should send a message via the fifo to the arm9, which will call Wifi_Sync() on arm9. +typedef void (*WifiSyncHandler)(); + + +#ifdef __cplusplus +extern "C" { +#endif + + + +extern void Read_Flash(int address, char * destination, int length); +extern void InitFlashData(); +extern int ReadFlashByte(int address); +extern int ReadFlashHWord(int address); +extern int ReadFlashBytes(int address, int numbytes); + +extern int Wifi_BBRead(int a); +extern int Wifi_BBWrite(int a, int b); +extern void Wifi_RFWrite(int writedata); + +extern void Wifi_RFInit(); +extern void Wifi_BBInit(); +extern void Wifi_WakeUp(); +extern void Wifi_Shutdown(); +extern void Wifi_MacInit(); +extern void Wifi_Interrupt(); +extern void Wifi_Update(); + +extern void Wifi_CopyMacAddr(volatile void * dest, volatile void * src); +extern int Wifi_CmpMacAddr(volatile void * mac1, volatile void * mac2); + +extern void Wifi_Init(u32 WifiData); +extern void Wifi_Deinit(); +extern void Wifi_Start(); +extern void Wifi_Stop(); +extern void Wifi_SetChannel(int channel); +extern void Wifi_SetWepKey(void * wepkey); +extern void Wifi_SetWepMode(int wepmode); +extern void Wifi_SetBeaconPeriod(int beacon_period); +extern void Wifi_SetMode(int wifimode); +extern void Wifi_SetPreambleType(int preamble_type); +extern void Wifi_TxSetup(); +extern void Wifi_RxSetup(); +extern void Wifi_DisableTempPowerSave(); + +extern int Wifi_SendOpenSystemAuthPacket(); +extern int Wifi_SendAssocPacket(); +extern int Wifi_SendNullFrame(); +extern int Wifi_SendPSPollFrame(); +extern int Wifi_ProcessReceivedFrame(int macbase, int framelen); + +extern void Wifi_Sync(); +extern void Wifi_SetSyncHandler(WifiSyncHandler sh); + + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/makefile b/c/src/lib/libbsp/arm/nds/dswifi/arm9/makefile new file mode 100644 index 0000000000..96f7b446e5 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/makefile @@ -0,0 +1,150 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM) +endif + +include $(DEVKITARM)/ds_rules + +TOPDIR ?= $(CURDIR)/.. + +#--------------------------------------------------------------------------------- +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +# DATA is a list of directories containing binary files +# all directories are relative to this makefile +#--------------------------------------------------------------------------------- +BUILD ?= release +SOURCES := source ../common/source +INCLUDES := include ../common/source ../include +DATA := data + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -mthumb -mthumb-interwork + +# note: arm9tdmi isn't the correct CPU arch, but anything newer and LD +# *insists* it has a FPU or VFP, and it won't take no for an answer! +CFLAGS := -g -Wall -O2\ + -mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\ + -ffast-math \ + $(ARCH) + +CFLAGS += $(INCLUDE) -DARM9 +CXXFLAGS := $(CFLAGS) + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -mno-fpu -Wl,-Map,$(notdir $*.map) + +ifneq ($(BUILD),debug) +export ARM9BIN := $(TOPDIR)/lib/libdswifi9.a +else +export ARM9BIN := $(TOPDIR)/lib/libdswifi9d.a +CFLAGS += -DSGIP_DEBUG +endif + + +#--------------------------------------------------------------------------------- +# any extra libraries we wish to link with the project +#--------------------------------------------------------------------------------- +LIBS := +#-lnds9 + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(LIBNDS) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + + +export DEPSDIR := $(CURDIR)/$(BUILD) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export CC := $(PREFIX)gcc +export CXX := $(PREFIX)g++ +export AR := $(PREFIX)ar +export OBJCOPY := $(PREFIX)objcopy + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr debug release + @rm -f $(TOPDIR)/lib/libdswifi9* + +all: $(ARM9BIN) + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(ARM9BIN) : $(OFILES) + @rm -f "$(ARM9BIN)" + @$(AR) rcs "$(ARM9BIN)" $(OFILES) + @echo built ... $(notdir $@) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP.c new file mode 100644 index 0000000000..d2561b8fc7 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP.c @@ -0,0 +1,63 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "sgIP.h" + +unsigned long volatile sgIP_timems; +int sgIP_errno; + +// sgIP_Init(): Initializes sgIP hub and sets up a default surrounding interface (ARP and IP) +void sgIP_Init() { + sgIP_timems = 0; + sgIP_memblock_Init(); + sgIP_Hub_Init(); + sgIP_ARP_Init(); + sgIP_TCP_Init(); + sgIP_UDP_Init(); + sgIP_DNS_Init(); + sgIP_DHCP_Init(); + sgIP_Hub_AddProtocolInterface(PROTOCOL_ETHER_IP,&sgIP_IP_ReceivePacket,0); +} + + +unsigned long count_100ms; +unsigned long count_1000ms; +void sgIP_Timer(int num_ms) { + sgIP_timems+=num_ms; + count_100ms+=num_ms; + if(count_100ms>=100) { + count_100ms-=100; + if(count_100ms>=100) count_100ms=0; + sgIP_ARP_Timer100ms(); + } + count_1000ms+=num_ms; + if(count_1000ms>=1000) { + count_1000ms-=1000; + if(count_1000ms>=1000) count_1000ms=0; + sgIP_DNS_Timer1000ms(); + } + sgIP_TCP_Timer(); +} + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP.h new file mode 100644 index 0000000000..911e9ff482 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP.h @@ -0,0 +1,56 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + + +#ifndef SGIP_H +#define SGIP_H + +#include "sgIP_Config.h" +#include "sgIP_memblock.h" +#include "sgIP_Hub.h" +#include "sgIP_IP.h" +#include "sgIP_ARP.h" +#include "sgIP_ICMP.h" +#include "sgIP_TCP.h" +#include "sgIP_UDP.h" +#include "sgIP_DNS.h" +#include "sgIP_DHCP.h" + +extern unsigned long volatile sgIP_timems; + +#ifdef __cplusplus +extern "C" { +#endif + + void sgIP_Init(); + void sgIP_Timer(int num_ms); + + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ARP.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ARP.c new file mode 100644 index 0000000000..1dd4d72e20 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ARP.c @@ -0,0 +1,304 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "sgIP_ARP.h" + +sgIP_ARP_Record ArpRecords[SGIP_ARP_MAXENTRIES]; + + +int sgIP_FindArpSlot(sgIP_Hub_HWInterface * hw, unsigned long destip) { + int i; + for(i=0;i<SGIP_ARP_MAXENTRIES;i++) { + if(ArpRecords[i].flags&SGIP_ARP_FLAG_ACTIVE) { + if(ArpRecords[i].linked_interface==hw && ArpRecords[i].protocol_address==destip) return i; + } + } + return -1; +} +int sgIP_GetArpSlot() { + int i,m,midle; + m=0; + midle=0; + for(i=0;i<SGIP_ARP_MAXENTRIES;i++) { + if(ArpRecords[i].flags&SGIP_ARP_FLAG_ACTIVE) { + if(ArpRecords[i].idletime>=midle) { + midle=ArpRecords[i].idletime; m=i; + } + } else { + return i; + } + } + // this slot *was* in use, so let's fix that situation. + if(ArpRecords[m].queued_packet) sgIP_memblock_free(ArpRecords[m].queued_packet); + ArpRecords[m].flags=0; + ArpRecords[m].retrycount=0; + ArpRecords[m].idletime=0; + ArpRecords[m].queued_packet=0; + return m; +} + +int sgIP_is_broadcast_address(sgIP_Hub_HWInterface * hw, unsigned long ipaddr) { + if((hw->snmask | ipaddr) == 0xFFFFFFFF) return 1; + return 0; +} + +// this function will protect against malformed packets that could cause internal problems. +int sgIP_ARP_Check_isok(sgIP_Hub_HWInterface * hw, sgIP_memblock * mb, sgIP_Header_ARP * arp) { + return 1; // doesn't do anything yet ;) +} + +void sgIP_ARP_Init() { + int i; + for(i=0;i<SGIP_ARP_MAXENTRIES;i++) { + ArpRecords[i].flags=0; + ArpRecords[i].idletime=0; + ArpRecords[i].queued_packet=0; + } +} +void sgIP_ARP_Timer100ms() { + int i; + for(i=0;i<SGIP_ARP_MAXENTRIES;i++) { + if(ArpRecords[i].flags & SGIP_ARP_FLAG_ACTIVE) { + ArpRecords[i].idletime++; + if(!(ArpRecords[i].flags&SGIP_ARP_FLAG_HAVEHWADDR)) { + ArpRecords[i].retrycount++; + if(ArpRecords[i].retrycount>125) { // it's a lost cause. + if(ArpRecords[i].queued_packet) { // if there is already a queued packet, kill it. + sgIP_memblock_free(ArpRecords[i].queued_packet); + } + ArpRecords[i].flags=0; + continue; + } + if((ArpRecords[i].retrycount&7)==7) { // attempt retransmit of ARP frame. + sgIP_ARP_SendARPRequest(ArpRecords[i].linked_interface, ArpRecords[i].linked_protocol, ArpRecords[i].protocol_address); + } + } + } + } +} + +void sgIP_ARP_FlushInterface(sgIP_Hub_HWInterface * hw) { + int i; + for(i=0;i<SGIP_ARP_MAXENTRIES;i++) { + if(ArpRecords[i].linked_interface==hw) ArpRecords[i].flags=0; + if(hw==0) ArpRecords[i].flags=0; // flush all interfaces + } +} + // don't *really* need to process this, but it helps. +int sgIP_ARP_ProcessIPFrame(sgIP_Hub_HWInterface * hw, sgIP_memblock * mb) { + + return 0; +} +int sgIP_ARP_ProcessARPFrame(sgIP_Hub_HWInterface * hw, sgIP_memblock * mb) { + int i, j, ip; + if(!hw || !mb) return 0; + sgIP_memblock_exposeheader(mb,-14); // hide 14 bytes at the start temporarily... + // look at arp frame... + sgIP_Header_ARP * arp = (sgIP_Header_ARP *) mb->datastart; + + if(!sgIP_ARP_Check_isok(hw,mb,arp)) { + sgIP_memblock_free(mb); + return 0; // error - arp header incorrect somehow. + } + sgIP_memblock_exposeheader(mb,14); // re-expose 14 bytes at the start... + + if(htons(arp->opcode)==1) { // request + // requested IP + ip = arp->addresses[arp->hw_addr_len*2+4+0]+(arp->addresses[arp->hw_addr_len*2+4+1]<<8)+(arp->addresses[arp->hw_addr_len*2+4+2]<<16)+(arp->addresses[arp->hw_addr_len*2+4+3]<<24); + SGIP_DEBUG_MESSAGE(("ARP: request IP %08X",ip)); + if(ip==hw->ipaddr) {// someone's asking for our info, toss them a reply. + sgIP_ARP_SendARPResponse(hw,mb); + return 0; + } + } + if(htons(arp->opcode)==2) { // response + // sender IP + ip = arp->addresses[arp->hw_addr_len+0]+(arp->addresses[arp->hw_addr_len+1]<<8)+(arp->addresses[arp->hw_addr_len+2]<<16)+(arp->addresses[arp->hw_addr_len+3]<<24); + i=sgIP_FindArpSlot(hw,ip); + if(i!=-1) { // we've been waiting for you... + for(j=0;j<arp->hw_addr_len;j++) ArpRecords[i].hw_address[j]=arp->addresses[j]; + ArpRecords[i].flags|=SGIP_ARP_FLAG_HAVEHWADDR; + sgIP_memblock * mb2; + mb2=ArpRecords[i].queued_packet; + ArpRecords[i].queued_packet=0; + if(mb2) sgIP_ARP_SendProtocolFrame(hw,mb2,ArpRecords[i].linked_protocol,ip); + } + } + + sgIP_memblock_free(mb); + return 0; +} +int sgIP_ARP_SendProtocolFrame(sgIP_Hub_HWInterface * hw, sgIP_memblock * mb, unsigned short protocol, unsigned long destaddr) { + int i,j; + int m; + sgIP_Header_Ethernet * ether; + if(!hw || !mb) return 0; + sgIP_memblock_exposeheader(mb,14); // add 14 bytes at the start for the header + + if(sgIP_is_broadcast_address(hw,destaddr)) { + // construct ethernet header + ether = (sgIP_Header_Ethernet *) mb->datastart; + for(j=0;j<6;j++) { + ether->src_mac[j] = hw->hwaddr[j]; + ether->dest_mac[j]= 0xFF; // broadcast destination + } + ether->protocol=protocol; + return sgIP_Hub_SendRawPacket(hw,mb); // this function will free the memory block when it's done. + } + + i=sgIP_FindArpSlot(hw,destaddr); + if(i!=-1) { + if(ArpRecords[i].flags & SGIP_ARP_FLAG_HAVEHWADDR) { // we have the adddress + ArpRecords[i].idletime=0; + // construct ethernet header + ether = (sgIP_Header_Ethernet *) mb->datastart; + for(j=0;j<6;j++) { + ether->src_mac[j] = hw->hwaddr[j]; + ether->dest_mac[j]= ArpRecords[i].hw_address[j]; + } + ether->protocol=protocol; + return sgIP_Hub_SendRawPacket(hw,mb); // this function will free the memory block when it's done. + } else { // we don't have the address, but are looking for it. + if(ArpRecords[i].queued_packet) { // if there is already a queued packet, reject the new one. + sgIP_memblock_free(mb); + return 0; // couldn't send. + } else { + sgIP_memblock_exposeheader(mb,-14); // re-hide ethernet header. + ArpRecords[i].queued_packet=mb; // queue packet. + ArpRecords[i].linked_protocol=protocol; // queue packet. + return 0; + } + } + } + m=sgIP_GetArpSlot(); // gets and cleans out an arp slot for us + // build new record + ArpRecords[m].flags=SGIP_ARP_FLAG_ACTIVE; + ArpRecords[m].idletime=0; + ArpRecords[m].retrycount=0; + ArpRecords[m].linked_interface=hw; + ArpRecords[m].protocol_address=destaddr; + sgIP_memblock_exposeheader(mb,-14); // re-hide ethernet header. + ArpRecords[m].queued_packet=mb; + ArpRecords[m].linked_protocol=protocol; + sgIP_ARP_SendARPRequest(hw,protocol,destaddr); + return 0; // queued, but not sent yet. +} + +int sgIP_ARP_SendARPResponse(sgIP_Hub_HWInterface * hw, sgIP_memblock * mb) { + int i; + if(!hw || !mb) return 0; + sgIP_memblock_exposeheader(mb,-14); // hide 14 bytes at the start temporarily... + + // Repurpose existing ARP packet + sgIP_Header_ARP * arp = (sgIP_Header_ARP *) mb->datastart; + if(!sgIP_ARP_Check_isok(hw,mb,arp)) { + sgIP_memblock_free(mb); + return 0; // error - arp header incorrect somehow. + } + + if(arp->hw_addr_len!=hw->hwaddrlen || arp->protocol_addr_len!=4) { + // eek! can't send it back in this sorry state! + sgIP_memblock_free(mb); + return 0; + } + + arp->opcode=htons(2); // response + for(i=0;i<hw->hwaddrlen;i++) arp->addresses[i+4+hw->hwaddrlen]=arp->addresses[i]; // copy src hw addr + for(i=0;i<4;i++) arp->addresses[i+(hw->hwaddrlen)*2+4]=arp->addresses[i+hw->hwaddrlen]; + for(i=0;i<hw->hwaddrlen;i++) arp->addresses[i]=hw->hwaddr[i]; + for(i=0;i<4;i++) arp->addresses[i+(hw->hwaddrlen)]=(hw->ipaddr>>(i*8))&255; + + // construct ethernet header + sgIP_memblock_exposeheader(mb,14); // add 14 bytes at the start for the header + sgIP_Header_Ethernet * ether = (sgIP_Header_Ethernet *) mb->datastart; + for(i=0;i<6;i++) { + ether->src_mac[i] = hw->hwaddr[i]; + ether->dest_mac[i]= arp->addresses[i+4+hw->hwaddrlen]; // requesting party + } + ether->protocol=htons(0x0806); // ARP protocol + + // Send ethernet packet + return sgIP_Hub_SendRawPacket(hw,mb); // this function will free the memory block when it's done. +} +int sgIP_ARP_SendGratARP(sgIP_Hub_HWInterface * hw) { + int i; + if(!hw) return 0; + sgIP_memblock * mb = sgIP_memblock_alloc(SGIP_HEADER_ARP_BASESIZE+2*4 + 2*hw->hwaddrlen); + if(!mb) return 0; + + // Construct ARP packet + sgIP_Header_ARP * arp = (sgIP_Header_ARP *) mb->datastart; + arp->hwspace=htons(1); // ethernet + arp->protocol=htons(0x0800); + arp->opcode=htons(2); // response + arp->hw_addr_len=hw->hwaddrlen; + arp->protocol_addr_len= 4; + for(i=0;i<hw->hwaddrlen;i++) arp->addresses[i]=hw->hwaddr[i]; + for(i=0;i<4;i++) arp->addresses[i+hw->hwaddrlen]=(hw->ipaddr>>(i*8))&255; + for(i=0;i<hw->hwaddrlen;i++) arp->addresses[i+4+hw->hwaddrlen]=hw->hwaddr[i]; + for(i=0;i<4;i++) arp->addresses[i+hw->hwaddrlen*2+4]=(hw->ipaddr>>(i*8))&255; + + // construct ethernet header + sgIP_memblock_exposeheader(mb,14); // add 14 bytes at the start for the header + sgIP_Header_Ethernet * ether = (sgIP_Header_Ethernet *) mb->datastart; + for(i=0;i<6;i++) { + ether->src_mac[i] = hw->hwaddr[i]; + ether->dest_mac[i]= 0xFF; // broadcast packet + } + ether->protocol=htons(0x0806); // ARP protocol + + // Send ethernet packet + return sgIP_Hub_SendRawPacket(hw,mb); // this function will free the memory block when it's done. +} +int sgIP_ARP_SendARPRequest(sgIP_Hub_HWInterface * hw, int protocol, unsigned long protocol_addr) { + int i; + if(!hw) return 0; + sgIP_memblock * mb = sgIP_memblock_alloc(SGIP_HEADER_ARP_BASESIZE+2*4 + 2*hw->hwaddrlen); + if(!mb) return 0; + + // Construct ARP packet + sgIP_Header_ARP * arp = (sgIP_Header_ARP *) mb->datastart; + arp->hwspace=htons(1); // 1=ethernet + arp->protocol=(protocol); + arp->opcode=htons(1); // 1=request + arp->hw_addr_len=hw->hwaddrlen; + arp->protocol_addr_len= 4; + for(i=0;i<hw->hwaddrlen;i++) arp->addresses[i]=hw->hwaddr[i]; + for(i=0;i<4;i++) arp->addresses[i+hw->hwaddrlen]=(hw->ipaddr>>(i*8))&255; + for(i=0;i<hw->hwaddrlen;i++) arp->addresses[i+4+hw->hwaddrlen]=0; + for(i=0;i<4;i++) arp->addresses[i+hw->hwaddrlen*2+4]=(protocol_addr>>(i*8))&255; + + // construct ethernet header + sgIP_memblock_exposeheader(mb,14); // add 14 bytes at the start for the header + sgIP_Header_Ethernet * ether = (sgIP_Header_Ethernet *) mb->datastart; + for(i=0;i<6;i++) { + ether->src_mac[i] = hw->hwaddr[i]; + ether->dest_mac[i]= 0xFF; // broadcast packet + } + ether->protocol=htons(0x0806); // ARP protocol + + // Send ethernet packet + return sgIP_Hub_SendRawPacket(hw,mb); // this function will free the memory block when it's done. +} diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ARP.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ARP.h new file mode 100644 index 0000000000..0c56747527 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ARP.h @@ -0,0 +1,80 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ +#ifndef SGIP_ARP_H +#define SGIP_ARP_H + +#include "sgIP_Config.h" +#include "sgIP_memblock.h" +#include "sgIP_Hub.h" + +#define SGIP_ARP_FLAG_ACTIVE 0x0001 +#define SGIP_ARP_FLAG_HAVEHWADDR 0x0002 + +typedef struct SGIP_ARP_RECORD { + unsigned short flags, retrycount; + unsigned long idletime; + sgIP_Hub_HWInterface * linked_interface; + sgIP_memblock * queued_packet; + int linked_protocol; + unsigned long protocol_address; + char hw_address[SGIP_MAXHWADDRLEN]; +} sgIP_ARP_Record; + + +typedef struct SGIP_HEADER_ARP { + unsigned short hwspace; // ethernet=1; + unsigned short protocol; + unsigned char hw_addr_len; + unsigned char protocol_addr_len; + unsigned short opcode; // request=1, reply=2 + unsigned char addresses[8+12]; // sender HW, sender Protocol, dest HW, dest Protocol +} sgIP_Header_ARP; + +#define SGIP_HEADER_ARP_BASESIZE 8 + +#ifdef __cplusplus +extern "C" { +#endif + + extern void sgIP_ARP_Init(); + extern void sgIP_ARP_Timer100ms(); + extern void sgIP_ARP_FlushInterface(sgIP_Hub_HWInterface * hw); + + extern int sgIP_ARP_ProcessIPFrame(sgIP_Hub_HWInterface * hw, sgIP_memblock * mb); + extern int sgIP_ARP_ProcessARPFrame(sgIP_Hub_HWInterface * hw, sgIP_memblock * mb); + extern int sgIP_ARP_SendProtocolFrame(sgIP_Hub_HWInterface * hw, sgIP_memblock * mb, unsigned short protocol, unsigned long destaddr); + + extern int sgIP_ARP_SendARPResponse(sgIP_Hub_HWInterface * hw, sgIP_memblock * mb); + extern int sgIP_ARP_SendGratARP(sgIP_Hub_HWInterface * hw); + extern int sgIP_ARP_SendARPRequest(sgIP_Hub_HWInterface * hw, int protocol, unsigned long protocol_addr); + + + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Config.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Config.h new file mode 100644 index 0000000000..5be7166890 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Config.h @@ -0,0 +1,274 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + + +#ifndef SGIP_CONFIG_H +#define SGIP_CONFIG_H + +#include <errno.h> + +////////////////////////////////////////////////////////////////////////// +// General options - these control the core functionality of the stack. + +// SGIP_USEDYNAMICMEMORY: Allows the stack to use memory as it needs it, via malloc()/free() +// This option is extremely useful in environments where it can be used, as it prevents the +// overhead of allocating per-connection memory in advance, and allows an unlimited number +// of connections, provided the memory space. This option requires the implementation of +// two C functions, "void * sgIP_malloc(int)" and "void sgIP_free(void *)", which behave +// similarly to the malloc and free functions commonly used in C. +#define SGIP_USEDYNAMICMEMORY + +// SGIP_INTERRUPT_THREADING_MODEL: Provides memory protection in a system that can allow +// multiple processing "threads" by way of interrupts. This is not required on single +// threaded systems, and not adequate on multithreaded systems, but provides a way to +// allow protection against contention on interrupt-driven systems. This option requires +// the system to implement two C functions "int sgIP_DisableInterrupts()" and additionally +// "void sgIP_RestoreInterrupts(int)" that takes as a parameter the value returned by +// sgIP_DisableInterrupts(). Interrupts are disabled upon beginning work with sensitive +// memory areas or allocation/deallocation of memory, and are restored afterwards. +#define SGIP_INTERRUPT_THREADING_MODEL + +// SGIP_MULTITHREADED_THREADING_MODEL: Standard memory protection for large multithreaded +// systems, such as operating systems and the like. This kind of memory protection is +// useful for true multithreaded systems but useless in a single-threaded system and +// harmful in an interrupt-based multiprocess system. +//#define SGIP_MULTITHREADED_THREADING_MODEL + +#define SGIP_LITTLEENDIAN + +////////////////////////////////////////////////////////////////////////// +// Temporary memory system settings + +// SGIP_MEMBLOCK_DATASIZE: This is the maximum data size contained in a single sgIP_memblock. +// for best performance ensure this value is larger than any packet that is expected to be +// received, however, in a memory-tight situation, much smaller values can be used. +#define SGIP_MEMBLOCK_DATASIZE 1600 + +// SGIP_MEMBLOCK_BASENUM: The starting number of memblocks that will be allocated. This is +// also the total number of memblocks that will be allocated if sgIP is not configured to use +// dynamic memory allocation. +#define SGIP_MEMBLOCK_BASENUM 12 + +// SGIP_MEMBLOCK_STEPNUM: In the case that all memblocks are full, and dynamic memory is +// enabled, this many additional memblocks will be allocated in an attempt to satasfy the +// memory usage demands of the stack. +#define SGIP_MEMBLOCK_STEPNUM 6 + +// SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL: Who cares what the other memblock defines say, let's +// Generate all memblocks by mallocing 'em. +#define SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL + +////////////////////////////////////////////////////////////////////////// +// Hardware layer settings + +// SGIP_MAXHWADDRLEN: The maximum usable hardware address length. Ethernet is 6 bytes. +#define SGIP_MAXHWADDRLEN 8 + +// SGIP_MAXHWHEADER: The maximum allocated size for hardware headers. +#define SGIP_MAXHWHEADER 16 + +// SGIP_MTU_OVERRIDE: This is the maximum MTU that will be accepted. By default it is being +// set to 1460 bytes in order to be courteous to Ethernet and it's ridiculously low MTU. +// This value will allow you to prevent fragmentation of IP packets by not using the full +// MTU available to your network interface when the IP packet will just be sliced and diced +// at the next smaller MTU. (the stack will still use HW mtu if it's lower.) +#define SGIP_MTU_OVERRIDE 1460 + + +////////////////////////////////////////////////////////////////////////// +// Connection settings - can be tuned to change memory usage and performance + +// SGIP_TCP_STATELESS_LISTEN: Uses a technique to prevent syn-flooding from blocking listen +// ports by using all the connection blocks/memory. +#define SGIP_TCP_STATELESS_LISTEN + +// SGIP_TCP_STEALTH: Only sends packets in response to connections to active ports. Doing so +// causes ports to appear not as closed, but as if the deviced does not exist when probing +// ports that are not in use. +//#define SGIP_TCP_STEALTH + +// SGIP_TCP_TTL: Time-to-live value given to outgoing packets, in the absence of a reason to +// manually override this value. +#define SGIP_IP_TTL 128 + +// SGIP_TCPRECEIVEBUFFERLENGTH: The size (in bytes) of the receive FIFO in a TCP connection +#define SGIP_TCP_RECEIVEBUFFERLENGTH 8192 + +// SGIP_TCPTRANSMITBUFFERLENGTH: The size (in bytes) of the transmit FIFO in a TCP connection +#define SGIP_TCP_TRANSMITBUFFERLENGTH 8192 + +// SGIP_TCPOOBBUFFERLENGTH: The size (in bytes) of the receive OOB data FIFO in a TCP connection +#define SGIP_TCP_OOBBUFFERLENGTH 256 + +// SGIP_ARP_MAXENTRIES: The maximum number of cached ARP entries - this is defined staticly +// because it's somewhat impractical to dynamicly allocate memory for such a small structure +// (at least on most smaller systems) +#define SGIP_ARP_MAXENTRIES 32 + +// SGIP_HUB_MAXHWINTERFACES: The maximum number of hardware interfaces the sgIP hub will +// connect to. A hardware interface being some port (ethernet, wifi, etc) that will relay +// packets to the outside world. +#define SGIP_HUB_MAXHWINTERFACES 1 + +// SGIP_HUB_MAXPROTOCOLINTERFACES: The maximum number of protocol interfaces the sgIP hub will +// connect to. A protocol interface being a software handler for a certain protocol type +// (such as IP) +#define SGIP_HUB_MAXPROTOCOLINTERFACES 1 + +#define SGIP_TCP_FIRSTOUTGOINGPORT 40000 +#define SGIP_TCP_LASTOUTGOINGPORT 65000 +#define SGIP_UDP_FIRSTOUTGOINGPORT 40000 +#define SGIP_UDP_LASTOUTGOINGPORT 65000 + +#define SGIP_TCP_GENTIMEOUTMS 6000 +#define SGIP_TCP_TRANSMIT_DELAY 25 +#define SGIP_TCP_TRANSMIT_IMMTHRESH 40 +#define SGIP_TCP_TIMEMS_2MSL 1000*60*2 +#define SGIP_TCP_MAXRETRY 7 +#define SGIP_TCP_MAXSYNS 64 +#define SGIP_TCP_REACK_THRESH 1000 + +#define SGIP_TCP_SYNRETRYMS 250 +#define SGIP_TCP_GENRETRYMS 500 +#define SGIP_TCP_BACKOFFMAX 6000 + +#define SGIP_SOCKET_MAXSOCKETS 32 + +//#define SGIP_SOCKET_DEFAULT_NONBLOCK 1 + + +////////////////////////////////////////////////////////////////////////// +// DNS settings + +#define SGIP_DNS_MAXRECORDSCACHE 16 +#define SGIP_DNS_MAXRECORDADDRS 4 +#define SGIP_DNS_MAXALIASES 4 +#define SGIP_DNS_TIMEOUTMS 5000 +#define SGIP_DNS_MAXRETRY 3 +#define SGIP_DNS_MAXSERVERRETRY 4 + +////////////////////////////////////////////////////////////////////////// + +#define SGIP_DHCP_ERRORTIMEOUT 45000 +#define SGIP_DHCP_RESENDTIMEOUT 3000 +#define SGIP_DHCP_DEFAULTHOSTNAME "NintendoDS" +#define SGIP_DHCP_CLASSNAME "sgIP 0.3" + +////////////////////////////////////////////////////////////////////////// +// Static memory settings - only used if SGIP_USEDYNAMICMEMORY is NOT defined. + +// SGIP_TCP_MAXCONNECTIONS: In the case dynamic memory is not used, this value gives the max +// number of TCP blocks available for inbound/outbound connections via TCP. +#define SGIP_TCP_MAXCONNECTIONS 10 + + + + +////////////////////////////////////////////////////////////////////////// +// Debugging options + + +// SGIP_DEBUG: Enable debug logging. +// requires external function "void sgIP_dbgprint(char *, ...);" +//#define SGIP_DEBUG + +#ifdef SGIP_DEBUG +#define SGIP_DEBUG_MESSAGE(param) sgIP_dbgprint param +#define SGIP_DEBUG_ERROR(param) sgIP_dbgprint param; while(1); +#else +#define SGIP_DEBUG_MESSAGE(param) +#define SGIP_DEBUG_ERROR(param) +#endif + + +////////////////////////////////////////////////////////////////////////// +// Error handling +extern int sgIP_errno; +#define SGIP_ERROR(a) ((errno=(a)), -1) +#define SGIP_ERROR0(a) ((errno=(a)), 0) + +////////////////////////////////////////////////////////////////////////// +// Error checking + + +#ifdef SGIP_MULTITHREADED_THREADING_MODEL +#ifdef SGIP_INTERRUPT_THREADING_MODEL +#error SGIP_INTERRUPT_THREADING_MODEL and SGIP_MULTITHREADED_THREADING_MODEL cannot be used together! +#endif +#endif + + +////////////////////////////////////////////////////////////////////////// +// External option-based dependencies + + +#ifdef SGIP_INTERRUPT_THREADING_MODEL +#ifdef __cplusplus +extern "C" { +#endif + extern int sgIP_DisableInterrupts(); + extern void sgIP_RestoreInterrupts(int); + extern void sgIP_IntrWaitEvent(); +#ifdef __cplusplus +}; +#endif +#define SGIP_INTR_PROTECT() \ + int tIME; \ + tIME=sgIP_DisableInterrupts() +#define SGIP_INTR_REPROTECT() \ + tIME=sgIP_DisableInterrupts() +#define SGIP_INTR_UNPROTECT() \ + sgIP_RestoreInterrupts(tIME) +#define SGIP_WAITEVENT() \ + sgIP_IntrWaitEvent() +#else // !SGIP_INTERRUPT_THREADING_MODEL +#define SGIP_INTR_PROTECT() +#define SGIP_INTR_REPROTECT() +#define SGIP_INTR_UNPROTECT() +#define SGIP_WAITEVENT(); +#endif // SGIP_INTERRUPT_THREADING_MODEL + +#ifdef SGIP_DEBUG +#ifdef __cplusplus +extern "C" { +#endif + extern void sgIP_dbgprint(char *, ...); +#ifdef __cplusplus +}; +#endif +#endif // SGIP_DEBUG + +#ifdef SGIP_USEDYNAMICMEMORY +#ifdef __cplusplus +extern "C" { +#endif + extern void * sgIP_malloc(int); + extern void sgIP_free(void *); +#ifdef __cplusplus +}; +#endif +#endif // SGIP_USEDYNAMICMEMORY + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DHCP.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DHCP.c new file mode 100644 index 0000000000..8f6fa6d1ed --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DHCP.c @@ -0,0 +1,375 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "sgIP_DHCP.h" +#include "sgIP_DNS.h" +#include <string.h> +#include "sys/socket.h" +#include "netinet/in.h" + +extern unsigned long volatile sgIP_timems; +int dhcp_socket; +char dhcp_hostname[64]; +int dhcp_tid; +unsigned long dhcp_timestart, dhcp_timelastaction; +sgIP_DHCP_Packet * dhcp_p; +sgIP_Hub_HWInterface * dhcp_int; +int dhcp_optionptr; +int dhcp_requestDNS; +int dhcp_status; +int dhcp_state; // 0== send DHCPDISCOVER wait for DHCPOFFER, 1== send DHCPREQUEST wait for DHCPACK +unsigned long dhcp_rcvd_ip, dhcp_rcvd_gateway, dhcp_rcvd_snmask, dhcp_rcvd_dns[3], dhcp_serverip; + + +void sgIP_DHCP_Init() { + dhcp_socket=0; + dhcp_p=0; + dhcp_int=0; + dhcp_rcvd_ip=0; + strcpy(dhcp_hostname,SGIP_DHCP_DEFAULTHOSTNAME); + dhcp_status=SGIP_DHCP_STATUS_IDLE; +} +void sgIP_DHCP_SetHostName(char * s) { + strncpy(dhcp_hostname,s,63); + dhcp_hostname[63]=0; +} +int sgIP_DHCP_IsDhcpIp(unsigned long ip) { // check if the IP address was assigned via dhcp. + return ip==dhcp_rcvd_ip; +} + +void sgIP_DHCP_SendDgram() { + struct sockaddr_in sain; + int len_dhcp; + sain.sin_port=htons(67); // bootp server port + sain.sin_addr.s_addr=0xFFFFFFFF; // broadcast + dhcp_p->options[dhcp_optionptr++]=0xFF; // terminate options list. + //sendto(dhcp_socket,dhcp_p,sizeof(sgIP_DHCP_Packet)-312+dhcp_optionptr,0,(struct sockaddr *)&sain,sizeof(sain)); + len_dhcp = sizeof(sgIP_DHCP_Packet)-312+dhcp_optionptr; + if(len_dhcp<300) len_dhcp=300; + sendto(dhcp_socket,dhcp_p,len_dhcp,0,(struct sockaddr *)&sain,sizeof(sain)); + sgIP_free(dhcp_p); + dhcp_p=0; + dhcp_timelastaction=sgIP_timems; +} + +void sgIP_DHCP_BeginDgram(int dgramtype) { + int i; + if(dhcp_p) sgIP_free(dhcp_p); + dhcp_p = (sgIP_DHCP_Packet *) sgIP_malloc(sizeof(sgIP_DHCP_Packet)); + if(!dhcp_p) return; + + // ensure packet is zero'd.. seems to pacify some routers. malloc doesn't initialise the memory returned. + memset(dhcp_p,0,sizeof(sgIP_DHCP_Packet)); + + dhcp_p->op=1; // 1==BOOTREQUEST + dhcp_p->htype=1; // 1== ethernet address type + dhcp_p->hlen=6; // hardware address length + dhcp_p->hops=0; // client sets to zero + dhcp_p->xid=dhcp_tid; // DHCP transaction ID + dhcp_p->secs=(sgIP_timems-dhcp_timestart)/1000; // seconds since DHCP start + dhcp_p->flags=htons(0x0000); // top bit set = request broadcast response + dhcp_p->ciaddr=0; + dhcp_p->yiaddr=0; + dhcp_p->siaddr=0; + dhcp_p->giaddr=0; + + memcpy(dhcp_p->chaddr,dhcp_int->hwaddr,6); + + dhcp_optionptr=0; + dhcp_p->options[dhcp_optionptr++]=0x63; + dhcp_p->options[dhcp_optionptr++]=0x82; + dhcp_p->options[dhcp_optionptr++]=0x53; + dhcp_p->options[dhcp_optionptr++]=0x63; // 4-byte "magic cookie" (bleh!) + // add some necessary options... - by default add the dhcp message type, host name, class id, and parameter request list + dhcp_p->options[dhcp_optionptr++]=0x35; // DHCP Message type + dhcp_p->options[dhcp_optionptr++]=0x01; + dhcp_p->options[dhcp_optionptr++]=dgramtype; + + dhcp_p->options[dhcp_optionptr++]=0x3D; // DHCP client identifier + dhcp_p->options[dhcp_optionptr++]=0x07; // length + dhcp_p->options[dhcp_optionptr++]=0x01; // hw type + for(i=0;i<6;i++) dhcp_p->options[dhcp_optionptr++]=dhcp_int->hwaddr[i]; + + dhcp_p->options[dhcp_optionptr++]=0x0C; // DHCP host name + dhcp_p->options[dhcp_optionptr++]=strlen(dhcp_hostname); + for(i=0;i<strlen(dhcp_hostname);i++) { + dhcp_p->options[dhcp_optionptr++]=dhcp_hostname[i]; + } + + dhcp_p->options[dhcp_optionptr++]=0x37; // DHCP Parameter request list + dhcp_p->options[dhcp_optionptr++]=2+dhcp_requestDNS; + dhcp_p->options[dhcp_optionptr++]=1; // subnet mask + dhcp_p->options[dhcp_optionptr++]=3; // router + if(dhcp_requestDNS) dhcp_p->options[dhcp_optionptr++]=6; // dns server + + if(dgramtype==DHCP_TYPE_REQUEST) { + dhcp_p->options[dhcp_optionptr++]=0x32; // DHCP Requested IP address + dhcp_p->options[dhcp_optionptr++]=0x04; + dhcp_p->options[dhcp_optionptr++]=(dhcp_rcvd_ip)&255; + dhcp_p->options[dhcp_optionptr++]=(dhcp_rcvd_ip>>8)&255; + dhcp_p->options[dhcp_optionptr++]=(dhcp_rcvd_ip>>16)&255; + dhcp_p->options[dhcp_optionptr++]=(dhcp_rcvd_ip>>24)&255; + + dhcp_p->options[dhcp_optionptr++]=0x36; // DHCP Server identifier + dhcp_p->options[dhcp_optionptr++]=0x04; + dhcp_p->options[dhcp_optionptr++]=(dhcp_serverip)&255; + dhcp_p->options[dhcp_optionptr++]=(dhcp_serverip>>8)&255; + dhcp_p->options[dhcp_optionptr++]=(dhcp_serverip>>16)&255; + dhcp_p->options[dhcp_optionptr++]=(dhcp_serverip>>24)&255; + } + + dhcp_p->options[dhcp_optionptr++]=0x3C; // DHCP Vendor Class ID + dhcp_p->options[dhcp_optionptr++]=strlen(SGIP_DHCP_CLASSNAME); + for(i=0;i<strlen(SGIP_DHCP_CLASSNAME);i++) { + dhcp_p->options[dhcp_optionptr++]=(SGIP_DHCP_CLASSNAME)[i]; + } + + // reason we don't send it immediately is in case the calling code wants to modify some data or add some options. +} + + + +void sgIP_DHCP_Start(sgIP_Hub_HWInterface * interface, int getDNS) { // begin dhcp transaction to get IP and maybe DNS data. + struct sockaddr_in sain; + int i; + SGIP_DEBUG_MESSAGE(("sgIP_DHCP_Start()")); + sgIP_DHCP_Terminate(); + dhcp_requestDNS=getDNS?1:0; + dhcp_int=interface; + dhcp_timestart=sgIP_timems; + dhcp_timelastaction=sgIP_timems; + dhcp_tid=sgIP_timems; + dhcp_status=SGIP_DHCP_STATUS_WORKING; + dhcp_state=0; + + dhcp_rcvd_ip = 0; + dhcp_rcvd_gateway=0; + dhcp_rcvd_snmask=0; + dhcp_rcvd_dns[0]=0; + dhcp_rcvd_dns[1]=0; + dhcp_rcvd_dns[2]=0; + + dhcp_socket=socket(AF_INET,SOCK_DGRAM,0); + sain.sin_addr.s_addr=0; + sain.sin_port=htons(68); // BOOTP client + bind(dhcp_socket,(struct sockaddr *)&sain,sizeof(sain)); + i=1; + ioctl(dhcp_socket,FIONBIO,&i); + + sgIP_DHCP_BeginDgram(DHCP_TYPE_DISCOVER); + sgIP_DHCP_SendDgram(); +} +void sgIP_DHCP_Release() { // call to dump our DHCP address and leave. + if(dhcp_status==SGIP_DHCP_STATUS_WORKING) { + sgIP_DHCP_Terminate(); + } else { + sgIP_DHCP_BeginDgram(DHCP_TYPE_RELEASE); + dhcp_p->ciaddr=dhcp_int->ipaddr; + sgIP_DHCP_SendDgram(); + + } +} +int sgIP_DHCP_Update() { // MUST be called periodicly; returns status - call until it returns SGIP_DHCP_STATUS_SUCCESS or _FAILED. + sgIP_DHCP_Packet * p; + struct sockaddr_in * sain; + int i,j,n,l; + if(dhcp_status!=SGIP_DHCP_STATUS_WORKING) return dhcp_status; + int send = 0; + + p=(sgIP_DHCP_Packet *)sgIP_malloc(sizeof(sgIP_DHCP_Packet)); + if(p) { + + while(1) { + l=recvfrom(dhcp_socket,p,sizeof(sgIP_DHCP_Packet),0,(struct sockaddr *)&sain,&n); + if(l==-1) break; + if(p->op!=2 || p->htype!=1 || p->hlen!=6 || p->xid!=dhcp_tid ) continue; + // check magic cookie + if(p->options[0]!=0x63 || p->options[1]!=0x82 || p->options[2]!=0x53 || p->options[3]!=0x63) continue; + i=4; // yay, the cookie is valid. + l -= (sizeof(sgIP_DHCP_Packet)-312); // number of bytes remaining in the options + while(i<l) { + n=p->options[i++]; + switch(n) { + case 0: // ignore + break; + case 255: // end-of-options marker. + l=0; + break; + case 53: // message type, variable length, 2+n + j=p->options[i++]; + if(dhcp_state==0) { + if(p->options[i]!=DHCP_TYPE_OFFER) l=-1; + } else { + if(p->options[i]==DHCP_TYPE_ACK) { + sgIP_free(p); + sgIP_DHCP_Terminate(); + dhcp_int->ipaddr=dhcp_rcvd_ip; + dhcp_int->gateway=dhcp_rcvd_gateway; + dhcp_int->snmask=dhcp_rcvd_snmask; + SGIP_DEBUG_MESSAGE(("DHCP Configured!")); + SGIP_DEBUG_MESSAGE(("IP%08X SM%08X GW%08X",dhcp_rcvd_ip,dhcp_rcvd_snmask,dhcp_rcvd_gateway)); + if(dhcp_requestDNS) { + dhcp_int->dns[0]=dhcp_rcvd_dns[0]; + dhcp_int->dns[1]=dhcp_rcvd_dns[1]; + dhcp_int->dns[2]=dhcp_rcvd_dns[2]; + SGIP_DEBUG_MESSAGE(("DNS %08X %08X %08X",dhcp_rcvd_dns[0],dhcp_rcvd_dns[1],dhcp_rcvd_dns[2])); + } + + dhcp_status=SGIP_DHCP_STATUS_SUCCESS; + return dhcp_status; + } else { + l=-1; + } + } + i+=j; + + break; + case 1: // subnet mask field, variable length 2+n + j=p->options[i++]; + if(dhcp_state==1 || j<4) {i+=j; break; } + dhcp_rcvd_snmask = (dhcp_rcvd_snmask>>8) | (p->options[i++]<<24); + dhcp_rcvd_snmask = (dhcp_rcvd_snmask>>8) | (p->options[i++]<<24); + dhcp_rcvd_snmask = (dhcp_rcvd_snmask>>8) | (p->options[i++]<<24); + dhcp_rcvd_snmask = (dhcp_rcvd_snmask>>8) | (p->options[i++]<<24); + i+=j-4; + break; + case 3: // gateway, variable length 2+n + j=p->options[i++]; + if(dhcp_state==1 || j<4) {i+=j; break; } + dhcp_rcvd_gateway = (dhcp_rcvd_gateway>>8) | (p->options[i++]<<24); + dhcp_rcvd_gateway = (dhcp_rcvd_gateway>>8) | (p->options[i++]<<24); + dhcp_rcvd_gateway = (dhcp_rcvd_gateway>>8) | (p->options[i++]<<24); + dhcp_rcvd_gateway = (dhcp_rcvd_gateway>>8) | (p->options[i++]<<24); + i+=j-4; + break; + case 54: // server ID, variable length 2+n + j=p->options[i++]; + if(dhcp_state==1 || j<4) {i+=j; break; } + dhcp_serverip = (dhcp_serverip>>8) | (p->options[i++]<<24); + dhcp_serverip = (dhcp_serverip>>8) | (p->options[i++]<<24); + dhcp_serverip = (dhcp_serverip>>8) | (p->options[i++]<<24); + dhcp_serverip = (dhcp_serverip>>8) | (p->options[i++]<<24); + i+=j-4; + break; + case 6: // dns servers, variable length 2+n + if(dhcp_requestDNS && !dhcp_state) { + j=p->options[i++]; + n=0; + while(n<3 && 4*n+3<j) { + dhcp_rcvd_dns[n] = (dhcp_rcvd_dns[n]>>8) | (p->options[i++]<<24); + dhcp_rcvd_dns[n] = (dhcp_rcvd_dns[n]>>8) | (p->options[i++]<<24); + dhcp_rcvd_dns[n] = (dhcp_rcvd_dns[n]>>8) | (p->options[i++]<<24); + dhcp_rcvd_dns[n] = (dhcp_rcvd_dns[n]>>8) | (p->options[i++]<<24); + n++; + } + i+=j-4*n; + break; + } + default: + j=p->options[i++]; + i+=j; + } + } + if(l==-1) continue; + dhcp_rcvd_ip=(p->yiaddr); + + // discover succeeded. increment transaction id. force sending REQUEST message next. + dhcp_state=1; + dhcp_tid += ( sgIP_timems-dhcp_timestart ) + 1; + send = 1; + break; + } + + sgIP_free(p); + // has timeout expired? + if( (sgIP_timems-dhcp_timestart) > SGIP_DHCP_ERRORTIMEOUT) { + SGIP_DEBUG_MESSAGE(("sgIP DHCP error timeout!")); + sgIP_DHCP_Terminate(); + dhcp_status=SGIP_DHCP_STATUS_FAILED; + return dhcp_status; + } + if( send || (sgIP_timems-dhcp_timelastaction) > SGIP_DHCP_RESENDTIMEOUT ) + { + if(dhcp_state==0) sgIP_DHCP_BeginDgram(DHCP_TYPE_DISCOVER); else sgIP_DHCP_BeginDgram(DHCP_TYPE_REQUEST); + sgIP_DHCP_SendDgram(); + } + } else { + SGIP_DEBUG_MESSAGE(("sgIP DHCP alloc failed!")); + sgIP_DHCP_Terminate(); + dhcp_status=SGIP_DHCP_STATUS_FAILED; + } + + return dhcp_status; +} +void sgIP_DHCP_Terminate() { // kill the process where it stands; deallocate all DHCP resources. + if(dhcp_socket) closesocket(dhcp_socket); + dhcp_socket=0; + if(dhcp_p) sgIP_free(dhcp_p); + dhcp_p=0; + dhcp_status=SGIP_DHCP_STATUS_IDLE; +} + +int gethostname(char *name, size_t len) +{ + int size = sizeof(dhcp_hostname); + if (name == NULL) + return SGIP_ERROR(EFAULT); + + if ( len <= size ) + return SGIP_ERROR(EINVAL); + + strncpy(name, dhcp_hostname, size); + name[size]=0; + return 0; +} + +int sethostname(const char *name, size_t len) +{ + sgIP_DNS_Record *rec; + + int size = sizeof(dhcp_hostname); + if (name == NULL) + return SGIP_ERROR(EFAULT); + + if ( len > size - 1) + return SGIP_ERROR(EINVAL); + + rec = sgIP_DNS_FindDNSRecord(dhcp_hostname); + + strncpy(dhcp_hostname, name, len); + dhcp_hostname[len]=0; + strncpy(rec->aliases[0], name, len); + rec->aliases[0][len]=0; + strncpy(rec->name, name, len); + rec->name[len]=0; + + return 0; +} + + + + + + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DHCP.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DHCP.h new file mode 100644 index 0000000000..1f5f5f0b8b --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DHCP.h @@ -0,0 +1,86 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ +#ifndef SGIP_DHCP_H +#define SGIP_DHCP_H + +#include "sgIP_Config.h" +#include "sgIP_Hub.h" + +// "DHCP Server" port is 67, "DHCP Client" port is 68 +// DHCP messages broadcast by a client prior to that client obtaining its IP address must have the source address field in the IP header set to 0. + + + +typedef struct SGIP_DHCP_PACKET { // yes, freaking big endian prevails here too. + unsigned char op; // opcode/message type (1=BOOTREQUEST, 2=BOOTREPLY) + unsigned char htype; // hardware address type + unsigned char hlen; // Hardware address length (should be 6, for ethernet/wifi) + unsigned char hops; // set to 0 + unsigned long xid; // 4-byte client specified transaction ID + unsigned short secs; // seconds elapsed since client started trying to boot + unsigned short flags; // flags + unsigned long ciaddr; // client IP address, filled in by client if verifying previous params + unsigned long yiaddr; // "your" (client) IP address + unsigned long siaddr; // IP addr of next server to use in bootstrap. + unsigned long giaddr; // Relay agent IP address + unsigned char chaddr[16]; // client hardware address + char sname[64]; // optional server hostname (null terminated string) + char file[128]; // boot file name, null terminated string + char options[312]; // optional parameters +} sgIP_DHCP_Packet; + +enum SGIP_DHCP_STATUS { + SGIP_DHCP_STATUS_IDLE, + SGIP_DHCP_STATUS_WORKING, + SGIP_DHCP_STATUS_FAILED, + SGIP_DHCP_STATUS_SUCCESS +}; + +#define DHCP_TYPE_DISCOVER 1 +#define DHCP_TYPE_OFFER 2 +#define DHCP_TYPE_REQUEST 3 +#define DHCP_TYPE_ACK 5 +#define DHCP_TYPE_RELEASE 7 + + +#ifdef __cplusplus +extern "C" { +#endif + + void sgIP_DHCP_Init(); + + void sgIP_DHCP_SetHostName(char * s); // just for the fun of it. + int sgIP_DHCP_IsDhcpIp(unsigned long ip); // check if the IP address was assigned via dhcp. + void sgIP_DHCP_Start(sgIP_Hub_HWInterface * interface, int getDNS); // begin dhcp transaction to get IP and maybe DNS data. + void sgIP_DHCP_Release(); // call to dump our DHCP address and leave. + int sgIP_DHCP_Update(); // MUST be called periodicly after _Start; returns status - call until it returns something other than SGIP_DHCP_STATUS_WORKING + void sgIP_DHCP_Terminate(); // kill the process where it stands; deallocate all DHCP resources. + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DNS.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DNS.c new file mode 100644 index 0000000000..cbc5ac8f6b --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DNS.c @@ -0,0 +1,492 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "sgIP_DNS.h" +#include "sgIP_Hub.h" +#include "netinet/in.h" +#include "sys/socket.h" + +int dns_sock; +int time_count; +int last_id; +int query_time_start; +extern unsigned long volatile sgIP_timems; + +// cache record data +sgIP_DNS_Record dnsrecords[SGIP_DNS_MAXRECORDSCACHE]; + +// data to return via hostent +volatile sgIP_DNS_Record dnsrecord_return; +volatile char * alias_list[SGIP_DNS_MAXALIASES+1]; +volatile char * addr_list[SGIP_DNS_MAXRECORDADDRS+1]; +char ipaddr_alias[256]; +unsigned long ipaddr_ip; +volatile sgIP_DNS_Hostent dnsrecord_hostent; + +unsigned char querydata[512]; +unsigned char responsedata[512]; + +void sgIP_DNS_Init() { + int i; + for(i=0;i<SGIP_DNS_MAXRECORDSCACHE;i++) dnsrecords[i].flags=0; + dns_sock=-1; + time_count=0; +} + +void sgIP_DNS_Timer1000ms() { + int i; + time_count++; + for(i=0;i<SGIP_DNS_MAXRECORDSCACHE;i++) { + if(dnsrecords[i].flags & SGIP_DNS_FLAG_RESOLVED) { + dnsrecords[i].TTL-=1; + if(dnsrecords[i].TTL<=0) { + dnsrecords[i].flags=0; + } + } + } +} + +int sgIP_DNS_isipaddress(const char * name, unsigned long * ipdest) { + int i,j,t,ndot; + unsigned long out_addr, g[4]; + const char * c; + + ndot=0; + c=name; + while(*c) { // scan for invalid characters + if(!((*c>='0' && *c<='9') || (*c>='A' && *c<='F') || (*c>='a' && *c<='f') || *c=='.' || *c=='x' || *c=='X')) return 0; + if(*c=='.') ndot++; + c++; + } + if(ndot>3) return 0; + c=name; + for(i=0;i<=ndot;i++) { + g[i]=0; + t=0; + j=0; + while(*c && *c!='.') { + if(j==0 && *c=='0') { t++; } + else if(j==1 && t==1 && (*c=='x' || *c=='X')) { t++; } + else { + switch(t) { + case 0: // decimal + if(*c=='x' || *c=='X' || (*c>='A' && *c<='F') || (*c>='a' && *c<='f')) return 0; + g[i]=(g[i]*10)+(*c-'0'); + break; + case 1: // octal + if(*c=='x' || *c=='X' || (*c>='A' && *c<='F') || (*c>='a' && *c<='f') || *c=='8' || *c=='9') return 0; + g[i]=(g[i]<<3)+(*c-'0'); + break; + case 2: // hex + if(*c=='x' || *c=='X') return 0; + if(*c>='0' && *c<='9') { + g[i]=(g[i]<<4)+(*c-'0'); + } else { + g[i]=(g[i]<<4)+(*c&0xDF)+9; + } + break; + } + } + j++; c++; + } + if(*c) c++; else break; + } + out_addr=0; + switch(ndot) { + case 0: + out_addr=g[0]; + break; + case 1: + if(g[0]>=0x100 || g[1]>=0x1000000) return 0; + out_addr= (g[0]<<24) | g[1]; + break; + case 2: + if(g[0]>=0x100 || g[1]>=0x100 || g[2]>=0x10000) return 0; + out_addr= (g[0]<<24) | (g[1]<<16) | g[2]; + break; + case 3: + if(g[0]>=0x100 || g[1]>=0x100 || g[2]>=0x100 || g[3]>=0x100) return 0; + out_addr= (g[0]<<24) | (g[1]<<16) | (g[2]<<8) | g[3]; + break; + } + *ipdest=htonl(out_addr); + return 1; +} + +sgIP_DNS_Record * sgIP_DNS_FindDNSRecord(const char * name) { + int i,j,k,n,c,c2; + SGIP_INTR_PROTECT(); + for(i=0;i<SGIP_DNS_MAXRECORDSCACHE;i++) { + if((dnsrecords[i].flags&(SGIP_DNS_FLAG_ACTIVE|SGIP_DNS_FLAG_RESOLVED)) == (SGIP_DNS_FLAG_ACTIVE|SGIP_DNS_FLAG_RESOLVED)) { + for(j=0;j<dnsrecords[i].numalias;j++) { + k=0; + for(n=0;name[n] && dnsrecords[i].aliases[j][n]; n++) { // obscure and complex case-insensitive string compare. + c=name[n]; + c2=dnsrecords[i].aliases[j][n]; + if(c>='a' && c<='z') c+='A'-'a'; + if(c2>='a' && c2<='z') c2+='A'-'a'; + if(c==c2) { + k++; + } else { + k=0; break; + } + } + if(name[n] || dnsrecords[i].aliases[j][n]) k=0; + if(k) { + SGIP_INTR_UNPROTECT(); + return dnsrecords+i; + } + } + } + } + + SGIP_INTR_UNPROTECT(); + return 0; +} + +sgIP_DNS_Record * sgIP_DNS_GetUnusedRecord() { + int i,j,minttl; + SGIP_INTR_PROTECT(); + for(i=0;i<SGIP_DNS_MAXRECORDSCACHE;i++) { + if(!(dnsrecords[i].flags&SGIP_DNS_FLAG_ACTIVE)) { + SGIP_INTR_UNPROTECT(); + return dnsrecords+i; + } + } + minttl=dnsrecords[0].TTL; j=0; + for(i=1;i<SGIP_DNS_MAXRECORDSCACHE;i++) { + if(dnsrecords[i].TTL<minttl && !(dnsrecords[i].flags&SGIP_DNS_FLAG_BUSY)) { + j=i; + minttl=dnsrecords[i].TTL; + } + } + dnsrecords[j].flags=0; + SGIP_INTR_UNPROTECT(); + return dnsrecords+j; +} + +static +void sgIP_ntoa(unsigned long ipaddr) { + int c,i,j,n; + c=0; + for(j=0;j<4;j++) { + if(j) ipaddr_alias[c++]='.'; + n=(ipaddr>>(j*8))&255; + i=0; + if(n>=100) { i=n/100; ipaddr_alias[c++]='0'+i; n-=i*100; } + if(n>=10 || i) { i=n/10; ipaddr_alias[c++]='0'+i; n-=i*10; } + ipaddr_alias[c++]='0'+n; + } + ipaddr_alias[c]=0; +} + +static +sgIP_DNS_Hostent * sgIP_DNS_GenerateHostentIP(unsigned long ipaddr) { + + sgIP_ntoa(ipaddr); + + alias_list[0]=ipaddr_alias; + alias_list[1]=0; + ipaddr_ip=ipaddr; + addr_list[0]=(char *)&ipaddr_ip; + addr_list[1]=0; + + dnsrecord_hostent.h_addr_list=(char **)addr_list; + dnsrecord_hostent.h_addrtype=1; + dnsrecord_hostent.h_aliases=(char **)alias_list; + dnsrecord_hostent.h_length=4; + dnsrecord_hostent.h_name=ipaddr_alias; + return (sgIP_DNS_Hostent *)&dnsrecord_hostent; +} + +sgIP_DNS_Hostent * sgIP_DNS_GenerateHostent(sgIP_DNS_Record * dnsrec) { + volatile int i; + dnsrecord_return = *dnsrec; // copy struct + for(i=0;i<dnsrecord_return.numalias;i++) { + alias_list[i]=dnsrecord_return.aliases[i]; + } + alias_list[i]=0; + for(i=0;i<dnsrecord_return.numaddr;i++) { + addr_list[i]=(char *)&(dnsrecord_return.addrdata[i*dnsrecord_return.addrlen]); + } + addr_list[i]=0; + dnsrecord_hostent.h_addr_list=(char **)addr_list; + dnsrecord_hostent.h_addrtype=dnsrecord_return.addrclass; + dnsrecord_hostent.h_aliases=(char **)alias_list; + dnsrecord_hostent.h_length=dnsrecord_return.addrlen; + dnsrecord_hostent.h_name=(char *)dnsrecord_return.name; + return (sgIP_DNS_Hostent *)&dnsrecord_hostent; +} + +static +int sgIP_DNS_genquery(const char * name) { + int i,j,c,l; + unsigned short * querydata_s = (unsigned short *) querydata; + unsigned char * querydata_c = querydata; + // header section + querydata_s[0]=htons(time_count&0xFFFF); + last_id=querydata_s[0]; + querydata_s[1]=htons(0x0100); // recursion desired, standard query + querydata_s[2]=htons(1); // one QD (question) + querydata_s[3]=0; // no resource records + querydata_s[4]=0; // no nameserver records + querydata_s[5]=0; // no additional records + // question section + + querydata_c+=12; + querydata_s+=6; + j=0; + i=0; + while(1) { + l=j; + j++; + c=0; + while(name[i]!=0 && name[i]!='.' && i<255) { + querydata_c[j++]=name[i++]; c++; + } + querydata_c[l]=c; + if(name[i]==0 || i>=255) break; + if(c==0) return 0; // this should never happen (unless there's really invalid input with 2 dots next to each other.) + i++; + } + querydata_c[j++]=0; // terminating zero length + // qtype + querydata_c[j++]=0; + querydata_c[j++]=1; // 00 01 "A" (address) + // qclass + querydata_c[j++]=0; + querydata_c[j++]=1; // 00 01 "IN" (internet) + + return j+12; // length +} + +void sgIP_DNS_CopyAliasAt(char * deststr,int offset) { + char * c; + int i,j; + i=0; + c=(char *)responsedata+offset; + do { + j=c[0]; + if(j>63) { + j=((j&63)<<8) | c[1]; + c=(char *)responsedata+j; + continue; + } + if(!j) break; + c++; + for(;j>0;j--) { + deststr[i++]= *(c++); + } + deststr[i++]='.'; + } while(1); + if(i>0) i--; + deststr[i]=0; +} + + +sgIP_DNS_Hostent * sgIP_DNS_gethostbyname(const char * name) { + sgIP_DNS_Record * rec; + sgIP_DNS_Hostent * he; + sgIP_Hub_HWInterface * hw; + int len,i,sainlen; + int retries,dtime; + unsigned long serverip; + struct sockaddr_in sain; + unsigned long IP; + SGIP_INTR_PROTECT(); + + // is name an IP address? + if(sgIP_DNS_isipaddress(name,&IP)) { + SGIP_INTR_UNPROTECT(); + return sgIP_DNS_GenerateHostentIP(IP); + } + + // check cache, return if value required is in cache... + rec=sgIP_DNS_FindDNSRecord(name); + if(rec) { + he=sgIP_DNS_GenerateHostent(rec); + SGIP_INTR_UNPROTECT(); + return he; + } + + // not in cache? generate a query... + len=sgIP_DNS_genquery(name); + + // send off the query, handle retransmit and trying other dns servers. + if(dns_sock==-1) { + hw=sgIP_Hub_GetDefaultInterface(); + serverip=hw->dns[0]; + + dns_sock=socket(AF_INET,SOCK_DGRAM,0); + i=1; + i=ioctl(dns_sock,FIONBIO,&i); // set non-blocking + + retries=0; + do { + query_time_start=sgIP_timems; + sain.sin_addr.s_addr=serverip; + sain.sin_port=htons(53); + i=sendto(dns_sock,querydata,len,0,(struct sockaddr *)&sain,sizeof(sain)); +dns_listenonly: + + do { + i=recvfrom(dns_sock,responsedata,512,0,(struct sockaddr *)&sain,&sainlen); + if(i!=-1) break; + dtime=sgIP_timems-query_time_start; + if(dtime>SGIP_DNS_TIMEOUTMS) break; + SGIP_INTR_UNPROTECT(); + SGIP_WAITEVENT(); + SGIP_INTR_REPROTECT(); + } while(1); + + if(i==-1) { // no reply, retry + retries++; + if(retries>=SGIP_DNS_MAXRETRY) { // maybe try another server? for now just quit. + closesocket(dns_sock); + dns_sock=-1; + SGIP_INTR_UNPROTECT(); + + return NULL; + } + continue; // send again + } + + // got something, is it what we want? + if(i<12 || sain.sin_addr.s_addr!=serverip || sain.sin_port!=htons(53)) { // suspicious. + goto dns_listenonly; // yay! a goto! - go back and see if we can get a more official response. + } + + // parse response. + { + const unsigned short * resdata_s = (unsigned short *) responsedata; + const unsigned char * resdata_c = responsedata; + const char * c; + int j,q,a, nalias,naddr; + if(last_id!=resdata_s[0]) { // bad. + goto dns_listenonly; + } + q=htons(resdata_s[2]); + a=htons(resdata_s[3]); + // no answer. + if (a == 0) + { + closesocket(dns_sock); + dns_sock=-1; + SGIP_INTR_UNPROTECT(); + + return NULL; + } + + resdata_c+=12; + while(q) { // ignore questions + do { + j=resdata_c[0]; + if(j>63) { resdata_c+=2; break; } + resdata_c += j+1; + } while(j); + resdata_c+=4; + q--; + } + + nalias=0; + naddr=0; + rec=sgIP_DNS_GetUnusedRecord(); + rec->flags=SGIP_DNS_FLAG_ACTIVE | SGIP_DNS_FLAG_BUSY; + while(a) { + if(nalias<SGIP_DNS_MAXALIASES) sgIP_DNS_CopyAliasAt(rec->aliases[nalias++],resdata_c-responsedata); + do { + j=resdata_c[0]; + if(j>63) { resdata_c+=2; break; } + resdata_c += j+1; + } while(j); + // CNAME=5, A=1 + j=resdata_c[1]; + rec->addrclass=(resdata_c[2]<<8)|resdata_c[3]; + rec->TTL = (resdata_c[4]<<24)|(resdata_c[5]<<16)|(resdata_c[6]<<8)|resdata_c[7]; + if(j==1) { // A + if(naddr<SGIP_DNS_MAXRECORDADDRS) { + rec->addrdata[naddr*4] = resdata_c[10]; + rec->addrdata[naddr*4+1] = resdata_c[11]; + rec->addrdata[naddr*4+2] = resdata_c[12]; + rec->addrdata[naddr*4+3] = resdata_c[13]; + naddr++; + } + } + j=(resdata_c[8]<<8)|resdata_c[9]; + resdata_c+=10+j; + a--; + } + + // likely we have all the data we care for now. + rec->addrlen=4; + rec->numaddr=naddr; + rec->numalias=nalias; + for(c=name,i=0;*c;c++,i++) rec->name[i]=*c; + rec->name[i]=0; + rec->flags=SGIP_DNS_FLAG_ACTIVE | SGIP_DNS_FLAG_RESOLVED; + break; // we got our answer, let's get out of here! + } + } while(1); + + closesocket(dns_sock); + dns_sock=-1; + } else { + SGIP_INTR_UNPROTECT(); + return NULL; + } + + // received response, return data + he=sgIP_DNS_GenerateHostent(rec); + SGIP_INTR_UNPROTECT(); + return he; +} + +unsigned long inet_addr(const char *cp) { + unsigned long IP; + if(sgIP_DNS_isipaddress(cp,&IP)) { + return IP; + } + return 0xFFFFFFFF; +} + +int inet_aton(const char *cp, struct in_addr *inp) { + unsigned long IP; + + if(sgIP_DNS_isipaddress(cp,&IP)) { + inp->s_addr = IP; + return 1; + } + + return 0; +} + + +char *inet_ntoa(struct in_addr in) { + sgIP_ntoa(in.s_addr); + return (char *)ipaddr_alias; +} + + + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DNS.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DNS.h new file mode 100644 index 0000000000..2922579a7f --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DNS.h @@ -0,0 +1,69 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ +#ifndef SGIP_DNS_H +#define SGIP_DNS_H + +#include "sgIP_Config.h" + +#define SGIP_DNS_FLAG_ACTIVE 1 +#define SGIP_DNS_FLAG_RESOLVED 2 +#define SGIP_DNS_FLAG_BUSY 4 + +typedef struct SGIP_DNS_RECORD { + char name [256]; + char aliases[SGIP_DNS_MAXALIASES][256]; + unsigned char addrdata[SGIP_DNS_MAXRECORDADDRS*4]; + short addrlen; + short addrclass; + int numaddr,numalias; + int TTL; + int flags; +} sgIP_DNS_Record; + +typedef struct SGIP_DNS_HOSTENT { + char * h_name; + char ** h_aliases; + int h_addrtype; // class - 1=IN (internet) + int h_length; + char ** h_addr_list; +} sgIP_DNS_Hostent; + +#ifdef __cplusplus +extern "C" { +#endif + +extern void sgIP_DNS_Init(); +extern void sgIP_DNS_Timer1000ms(); + +extern sgIP_DNS_Hostent * sgIP_DNS_gethostbyname(const char * name); +extern sgIP_DNS_Record * sgIP_DNS_GetUnusedRecord(); +extern sgIP_DNS_Record * sgIP_DNS_FindDNSRecord(const char * name); + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Hub.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Hub.c new file mode 100644 index 0000000000..1b141b7129 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Hub.c @@ -0,0 +1,211 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ +#include "sgIP_Hub.h" +#include "sgIP_ARP.h" + +////////////////////////////////////////////////////////////////////////// +// Global vars + +int NumHWInterfaces; +int NumProtocolInterfaces; +sgIP_Hub_Protocol ProtocolInterfaces[SGIP_HUB_MAXPROTOCOLINTERFACES]; +sgIP_Hub_HWInterface HWInterfaces[SGIP_HUB_MAXHWINTERFACES]; + + + +////////////////////////////////////////////////////////////////////////// +// Private functions + + + + + + +////////////////////////////////////////////////////////////////////////// +// Public functions + + +void sgIP_Hub_Init() { + NumHWInterfaces=0; + NumProtocolInterfaces=0; + +} + +sgIP_Hub_Protocol * sgIP_Hub_AddProtocolInterface(int protocolID, int (*ReceivePacket)(sgIP_memblock *), int (*InterfaceInit)(sgIP_Hub_Protocol *)) { + int n; + if(NumProtocolInterfaces>=SGIP_HUB_MAXPROTOCOLINTERFACES) return 0; + for(n=0;n<SGIP_HUB_MAXPROTOCOLINTERFACES;n++) { + if(!(ProtocolInterfaces[n].flags&SGIP_FLAG_PROTOCOL_IN_USE)) break; + } + if(n==SGIP_HUB_MAXPROTOCOLINTERFACES) return 0; + + ProtocolInterfaces[n].flags=SGIP_FLAG_PROTOCOL_IN_USE | SGIP_FLAG_PROTOCOL_ENABLED; + ProtocolInterfaces[n].protocol=protocolID; + ProtocolInterfaces[n].ReceivePacket=ReceivePacket; + if(InterfaceInit) InterfaceInit(ProtocolInterfaces+n); + NumProtocolInterfaces++; + return ProtocolInterfaces+n; +} + + +sgIP_Hub_HWInterface * sgIP_Hub_AddHardwareInterface(int (*TransmitFunction)(sgIP_Hub_HWInterface *, sgIP_memblock *), int (*InterfaceInit)(sgIP_Hub_HWInterface *)) { + int n; + if(NumHWInterfaces>=SGIP_HUB_MAXHWINTERFACES) return 0; + for(n=0;n<SGIP_HUB_MAXHWINTERFACES;n++) { + if(!(HWInterfaces[n].flags&SGIP_FLAG_HWINTERFACE_IN_USE)) break; + } + if(n==SGIP_HUB_MAXHWINTERFACES) return 0; + + HWInterfaces[n].flags = SGIP_FLAG_HWINTERFACE_IN_USE | SGIP_FLAG_HWINTERFACE_ENABLED; + HWInterfaces[n].TransmitFunction=TransmitFunction; + if(InterfaceInit) InterfaceInit(HWInterfaces+n); + NumHWInterfaces++; + return HWInterfaces+n; +} + +extern void sgIP_Hub_RemoveProtocolInterface(sgIP_Hub_Protocol * protocol) { + int n; + for(n=0;n<SGIP_HUB_MAXPROTOCOLINTERFACES;n++) { + if(ProtocolInterfaces+n ==protocol) break; + } + if(n==SGIP_HUB_MAXPROTOCOLINTERFACES) return; + protocol->flags=0; + NumProtocolInterfaces--; +} +extern void sgIP_Hub_RemoveHardwareInterface(sgIP_Hub_HWInterface * hw) { + int n; + for(n=0;n<SGIP_HUB_MAXHWINTERFACES;n++) { + if(HWInterfaces+n == hw) break; + } + if(n==SGIP_HUB_MAXHWINTERFACES) return; + hw->flags=0; + NumHWInterfaces--; +} + +int sgIP_Hub_ReceiveHardwarePacket(sgIP_Hub_HWInterface * hw, sgIP_memblock * packet) { + if(!hw || !packet) return 0; + if(hw->flags & SGIP_FLAG_HWINTERFACE_ENABLED) { + int n; + int protocol; + + protocol = ((unsigned short *)packet->datastart)[6]; +// SGIP_DEBUG_MESSAGE(("hub: rx packet %04X %X",protocol,packet->totallength)); + if(protocol==PROTOCOL_ETHER_ARP) { // arp + sgIP_ARP_ProcessARPFrame(hw,packet); + return 0; + } + if(protocol==PROTOCOL_ETHER_IP) { // IP, forward to the ARP system. + + } + + // hide ethernet header for higher-level protocols + sgIP_memblock_exposeheader(packet,-14); + for(n=0;n<SGIP_HUB_MAXPROTOCOLINTERFACES;n++) { + if(ProtocolInterfaces[n].flags&SGIP_FLAG_PROTOCOL_ENABLED && ProtocolInterfaces[n].protocol==protocol) { // this protocol handler + return ProtocolInterfaces[n].ReceivePacket(packet); + } + } + } + // hrmm, packet is unhandled. Ignore it for now. + sgIP_memblock_free(packet); + return 0; +} +// send packet from a protocol interface, resolve the requisite hardware interface addresses and send it. +int sgIP_Hub_SendProtocolPacket(int protocol, sgIP_memblock * packet, unsigned long dest_address, unsigned long src_address) { + if(!packet) return 0; + sgIP_Hub_HWInterface * hw; + int i; + hw=0; + // figure out what hardware interface is in use. + for(i=0;i<SGIP_HUB_MAXHWINTERFACES;i++) if(HWInterfaces[i].ipaddr==src_address) {hw=HWInterfaces+i; break;} + if(!hw) { + sgIP_memblock_free(packet); + return 0; + } + // resolve protocol address to hardware address & send packet + if( (src_address & hw->snmask) == (dest_address & hw->snmask) // on same network + || dest_address == 0xFFFFFFFF ) // or broadcast address, send directly. + { + return sgIP_ARP_SendProtocolFrame(hw,packet,protocol,dest_address); + } else { // eek, on different network. Send to gateway + return sgIP_ARP_SendProtocolFrame(hw,packet,protocol,hw->gateway); + } +} +// send packet on a hardware interface. +int sgIP_Hub_SendRawPacket(sgIP_Hub_HWInterface * hw, sgIP_memblock * packet) { + if(!hw || !packet) return 0; + if(hw->flags&SGIP_FLAG_HWINTERFACE_ENABLED) { + return hw->TransmitFunction(hw,packet); + } + sgIP_memblock_free(packet); + return 0; +} + +int sgIP_Hub_IPMaxMessageSize(unsigned long ipaddr) { + return SGIP_MTU_OVERRIDE; // hack - make this more accurate soon! +} + +unsigned long sgIP_Hub_GetCompatibleIP(unsigned long destIP) { + int n; + for(n=0;n<SGIP_HUB_MAXHWINTERFACES;n++) { + if((HWInterfaces[n].flags&SGIP_FLAG_HWINTERFACE_IN_USE)) { + if((HWInterfaces[n].ipaddr & HWInterfaces[n].snmask) == (destIP & HWInterfaces[n].snmask)) return HWInterfaces[n].ipaddr; + } + } + for(n=0;n<SGIP_HUB_MAXHWINTERFACES;n++) { + if((HWInterfaces[n].flags&SGIP_FLAG_HWINTERFACE_IN_USE)) { + return HWInterfaces[n].ipaddr; + } + } + return 0; +} + +extern sgIP_Hub_HWInterface * sgIP_Hub_GetDefaultInterface() { + int n; + for(n=0;n<SGIP_HUB_MAXHWINTERFACES;n++) { + if((HWInterfaces[n].flags&SGIP_FLAG_HWINTERFACE_IN_USE)) { + return HWInterfaces+n; + } + } + return 0; +} + + +#ifdef SGIP_LITTLEENDIAN +unsigned short htons(unsigned short num) { + return ((num<<8)&0xFF00) | (num>>8); +} +unsigned long htonl(unsigned long num) { + return (num<<24) | ((num&0xFF00)<<8) | ((num&0xFF0000)>>8) | (num>>24); +} +#else +unsigned short htons(unsigned short num) { + return num; +} +unsigned long htonl(unsigned long num) { + return num; +} +#endif + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Hub.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Hub.h new file mode 100644 index 0000000000..edfa4472db --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Hub.h @@ -0,0 +1,109 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ +#ifndef SGIP_HUB_H +#define SGIP_HUB_H + +#include "sgIP_Config.h" +#include "sgIP_memblock.h" + + + +#define SGIP_FLAG_PROTOCOL_IN_USE 0x0001 +#define SGIP_FLAG_PROTOCOL_ENABLED 0x8000 + +#define SGIP_FLAG_HWINTERFACE_IN_USE 0x0001 +#define SGIP_FLAG_HWINTERFACE_CONNECTED 0x0002 +#define SGIP_FLAG_HWINTERFACE_USEDHCP 0x0004 +#define SGIP_FLAG_HWINTERFACE_CHANGENETWORK 0x0008 +#define SGIP_FLAG_HWINTERFACE_ENABLED 0x8000 + +#ifdef SGIP_LITTLEENDIAN +#define PROTOCOL_ETHER_ARP 0x0608 +#define PROTOCOL_ETHER_IP 0x0008 +#else +#define PROTOCOL_ETHER_ARP 0x0806 +#define PROTOCOL_ETHER_IP 0x0800 +#endif + + +// structure sgIP_Hub_Protocol: Used to record the interface between the sgIP Hub and a protocol handler +typedef struct SGIP_HUB_PROTOCOL { + unsigned short flags; + unsigned short protocol; + int (*ReceivePacket)(sgIP_memblock *); + +} sgIP_Hub_Protocol; + +typedef struct SGIP_HUB_HWINTERFACE { + unsigned short flags; + unsigned short hwaddrlen; + int MTU; + int (*TransmitFunction)(struct SGIP_HUB_HWINTERFACE *, sgIP_memblock *); + void * userdata; + unsigned long ipaddr, gateway, snmask, dns[3]; + unsigned char hwaddr[SGIP_MAXHWADDRLEN]; +} sgIP_Hub_HWInterface; + +typedef struct SGIP_HEADER_ETHERNET { + unsigned char dest_mac[6]; + unsigned char src_mac[6]; + unsigned short protocol; +} sgIP_Header_Ethernet; + +#define ntohs(num) htons(num) +#define ntohl(num) htonl(num) + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern void sgIP_Hub_Init(); + + +extern sgIP_Hub_Protocol * sgIP_Hub_AddProtocolInterface(int protocolID, int (*ReceivePacket)(sgIP_memblock *), int (*InterfaceInit)(sgIP_Hub_Protocol *)); +extern sgIP_Hub_HWInterface * sgIP_Hub_AddHardwareInterface(int (*TransmitFunction)(sgIP_Hub_HWInterface *, sgIP_memblock *), int (*InterfaceInit)(sgIP_Hub_HWInterface *)); +extern void sgIP_Hub_RemoveProtocolInterface(sgIP_Hub_Protocol * protocol); +extern void sgIP_Hub_RemoveHardwareInterface(sgIP_Hub_HWInterface * hw); + +extern int sgIP_Hub_ReceiveHardwarePacket(sgIP_Hub_HWInterface * hw, sgIP_memblock * packet); +extern int sgIP_Hub_SendProtocolPacket(int protocol, sgIP_memblock * packet, unsigned long dest_address, unsigned long src_address); +extern int sgIP_Hub_SendRawPacket(sgIP_Hub_HWInterface * hw, sgIP_memblock * packet); + +extern int sgIP_Hub_IPMaxMessageSize(unsigned long ipaddr); +unsigned long sgIP_Hub_GetCompatibleIP(unsigned long destIP); + +extern sgIP_Hub_HWInterface * sgIP_Hub_GetDefaultInterface(); + +unsigned short htons(unsigned short num); +unsigned long htonl(unsigned long num); + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ICMP.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ICMP.c new file mode 100644 index 0000000000..57143c5efe --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ICMP.c @@ -0,0 +1,56 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "sgIP_ICMP.h" +#include "sgIP_IP.h" +#include "sgIP_Hub.h" + +void sgIP_ICMP_Init() { + +} + +int sgIP_ICMP_ReceivePacket(sgIP_memblock * mb, unsigned long srcip, unsigned long destip) { + if(!mb) return 0; + sgIP_Header_ICMP * icmp; + icmp = (sgIP_Header_ICMP *) mb->datastart; + if(icmp->checksum!=0 && sgIP_memblock_IPChecksum(mb,0,mb->totallength)!=0xFFFF) { + SGIP_DEBUG_MESSAGE(("ICMP receive checksum incorrect")); + sgIP_memblock_free(mb); + return 0; + } + switch(icmp->type) { + case 8: // echo request + icmp->type=0; // change to echo reply + // mod checksum + icmp->checksum=0; + icmp->checksum=~sgIP_memblock_IPChecksum(mb,0,mb->totallength); + return sgIP_IP_SendViaIP(mb,PROTOCOL_IP_ICMP,destip,srcip); + case 0: // echo reply (ignore for now) + default: // others (ignore for now) + break; + } + sgIP_memblock_free(mb); + return 0; +} diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ICMP.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ICMP.h new file mode 100644 index 0000000000..815b35ce5f --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ICMP.h @@ -0,0 +1,52 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ +#ifndef SGIP_ICMP_H +#define SGIP_ICMP_H + +#include "sgIP_Config.h" +#include "sgIP_memblock.h" + +typedef struct SGIP_HEADER_ICMP { + unsigned char type,code; + unsigned short checksum; + unsigned long xtra; +} sgIP_Header_ICMP; + +#ifdef __cplusplus +extern "C" { +#endif + + extern void sgIP_ICMP_Init(); + + extern int sgIP_ICMP_ReceivePacket(sgIP_memblock * mb, unsigned long srcip, unsigned long destip); + + + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_IP.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_IP.c new file mode 100644 index 0000000000..595516b4da --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_IP.c @@ -0,0 +1,124 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "sgIP_IP.h" +#include "sgIP_TCP.h" +#include "sgIP_UDP.h" +#include "sgIP_ICMP.h" +#include "sgIP_Hub.h" + +int idnum_count; + +int sgIP_IP_ReceivePacket(sgIP_memblock * mb) { + sgIP_Header_IP * iphdr; + unsigned short * chksum_calc; + int chksum_temp; + int hdrlen; + + iphdr=(sgIP_Header_IP *)mb->datastart; + chksum_calc=(unsigned short *)mb->datastart; + // check that header is valid: + hdrlen=iphdr->version_ihl&15; + // check length... + if(mb->totallength<htons(iphdr->tot_length)) { + SGIP_DEBUG_MESSAGE(("IP: bad length!")); + SGIP_DEBUG_MESSAGE(("-%i/%i",mb->totallength,htons(iphdr->tot_length))); + sgIP_memblock_free(mb); + return 0; // bad size. + } + sgIP_memblock_trimsize(mb,htons(iphdr->tot_length)); + // check version + if((iphdr->version_ihl>>4)!=4) { + SGIP_DEBUG_MESSAGE(("IP: bad version!")); + sgIP_memblock_free(mb); + return 0; // bad version. + } + + // check checksum + chksum_temp=sgIP_memblock_IPChecksum(mb,0,hdrlen*4); + if(chksum_temp!=0xFFFF) { // bad chksum! kill packet. + SGIP_DEBUG_MESSAGE(("IP: bad checksum!")); + sgIP_memblock_free(mb); + return 0; // bad checksum. + } + if(htons(iphdr->fragment_offset)&0x3FFF) { // fragmented! oh noes! We can't deal with this! + SGIP_DEBUG_MESSAGE(("IP: fragmented!")); + sgIP_memblock_free(mb); + return 0; // fragmented. + } + + sgIP_memblock_exposeheader(mb,-hdrlen*4); + switch(iphdr->protocol) { + case PROTOCOL_IP_ICMP: // ICMP + sgIP_ICMP_ReceivePacket(mb,iphdr->src_address,iphdr->dest_address); + break; + case PROTOCOL_IP_TCP: // TCP + sgIP_TCP_ReceivePacket(mb,iphdr->src_address,iphdr->dest_address); + break; + case PROTOCOL_IP_UDP: // UDP + sgIP_UDP_ReceivePacket(mb,iphdr->src_address,iphdr->dest_address); + break; + default: + sgIP_memblock_free(mb); + } + + return 0; +} +int sgIP_IP_MaxContentsSize(unsigned long destip) { + return sgIP_Hub_IPMaxMessageSize(destip)-sgIP_IP_RequiredHeaderSize(); +} +int sgIP_IP_RequiredHeaderSize() { + return 5*4; // we'll not include zeroed options. +} +int sgIP_IP_SendViaIP(sgIP_memblock * mb, int protocol, unsigned long srcip, unsigned long destip) { + sgIP_Header_IP * iphdr; + unsigned short * chksum_calc; + int chksum_temp,i; + sgIP_memblock_exposeheader(mb,20); + iphdr=(sgIP_Header_IP *)mb->datastart; + chksum_calc=(unsigned short *)mb->datastart; + iphdr->dest_address=destip; + iphdr->fragment_offset=0; + iphdr->header_checksum=0; + iphdr->identification=idnum_count++; + iphdr->protocol=protocol; + iphdr->src_address=srcip; + iphdr->tot_length=htons(mb->totallength); + iphdr->TTL=SGIP_IP_TTL; + iphdr->type_of_service=0; + iphdr->version_ihl=0x45; + chksum_temp=0; + for(i=0;i<10;i++) chksum_temp+=chksum_calc[i]; + chksum_temp += chksum_temp>>16; + chksum_temp &= 0xFFFF; + chksum_temp = ~chksum_temp; + if(chksum_temp==0) chksum_temp=0xFFFF; + iphdr->header_checksum=chksum_temp; + return sgIP_Hub_SendProtocolPacket(htons(0x0800),mb,destip,srcip); +} +unsigned long sgIP_IP_GetLocalBindAddr(unsigned long srcip, unsigned long destip) { + if(srcip) return srcip; + return sgIP_Hub_GetCompatibleIP(destip); +} diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_IP.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_IP.h new file mode 100644 index 0000000000..4935acd846 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_IP.h @@ -0,0 +1,64 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ +#ifndef SGIP_IP_H +#define SGIP_IP_H + +#include "sgIP_memblock.h" + +#define PROTOCOL_IP_ICMP 1 +#define PROTOCOL_IP_TCP 6 +#define PROTOCOL_IP_UDP 17 + +typedef struct SGIP_HEADER_IP { + unsigned char version_ihl; // version = top 4 bits == 4, IHL = header length in 32bit increments = bottom 4 bits + unsigned char type_of_service; // [3bit prescidence][ D ][ T ][ R ][ 0 0 ] - D=low delya, T=high thoroughput, R= high reliability + unsigned short tot_length; // total length of packet including header + unsigned short identification; // value assigned by sender to aid in packet reassembly + unsigned short fragment_offset; // top 3 bits are flags [0][DF][MF] (Don't Fragment / More Fragments Exist) - offset is in 8-byte chunks. + unsigned char TTL; // time to live, measured in hops + unsigned char protocol; // protocols: ICMP=1, TCP=6, UDP=17 + unsigned short header_checksum; // checksum: + unsigned long src_address; // src address is 32bit IP address + unsigned long dest_address; // dest address is 32bit IP address + unsigned char options[4]; // optional options come here. +} sgIP_Header_IP; + + +#ifdef __cplusplus +extern "C" { +#endif + + extern int sgIP_IP_ReceivePacket(sgIP_memblock * mb); + extern int sgIP_IP_MaxContentsSize(unsigned long destip); + extern int sgIP_IP_RequiredHeaderSize(); + extern int sgIP_IP_SendViaIP(sgIP_memblock * mb, int protocol, unsigned long srcip, unsigned long destip); + extern unsigned long sgIP_IP_GetLocalBindAddr(unsigned long srcip, unsigned long destip); + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_TCP.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_TCP.c new file mode 100644 index 0000000000..a513735645 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_TCP.c @@ -0,0 +1,915 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "sgIP_TCP.h" +#include "sgIP_IP.h" +#include "sgIP_Hub.h" +#include "sys/socket.h" + +sgIP_Record_TCP * tcprecords; +int port_counter; +unsigned long lasttime; +extern unsigned long volatile sgIP_timems; +sgIP_TCP_SYNCookie synlist[SGIP_TCP_MAXSYNS]; + +int numsynlist; // number of active entries in synlist (earliest first) + +void sgIP_TCP_Init() { + tcprecords=0; + numsynlist=0; + port_counter=SGIP_TCP_FIRSTOUTGOINGPORT; + lasttime=sgIP_timems; +} + +void sgIP_TCP_Timer() { // scan through tcp records and resend anything necessary + sgIP_Record_TCP * rec; + int time,i,j; + time=sgIP_timems-lasttime; + lasttime=sgIP_timems; + for(i=0;i<numsynlist;i++) { + if(synlist[i].timenext<=time) { + j=time-synlist[i].timenext; + synlist[i].timebackoff*=2; + if(synlist[i].timebackoff>SGIP_TCP_BACKOFFMAX) synlist[i].timebackoff=SGIP_TCP_BACKOFFMAX; + if(j>synlist[i].timebackoff) synlist[i].timenext=0; else synlist[i].timenext=synlist[i].timebackoff-j; + // resend SYN + sgIP_TCP_SendSynReply(SGIP_TCP_FLAG_SYN|SGIP_TCP_FLAG_ACK,synlist[i].localseq,synlist[i].remoteseq,synlist[i].localip,synlist[i].remoteip,synlist[i].localport,synlist[i].remoteport,-1); + } else { + synlist[i].timenext-=time; + } + } + rec=tcprecords; + while(rec) { + time=sgIP_timems-rec->time_last_action; + switch(rec->tcpstate) { + case SGIP_TCP_STATE_NODATA: // newly allocated [do nothing] + case SGIP_TCP_STATE_UNUSED: // allocated & BINDed [do nothing] + case SGIP_TCP_STATE_CLOSED: // Block is unused. [do nothing] + case SGIP_TCP_STATE_LISTEN: // listening [do nothing] + case SGIP_TCP_STATE_FIN_WAIT_2: // got ACK for our FIN, haven't got FIN yet. [do nothing] + break; + case SGIP_TCP_STATE_SYN_SENT: // connect initiated [resend syn] + if(time>rec->time_backoff) { + rec->retrycount++; + if(rec->retrycount>=SGIP_TCP_MAXRETRY) { + //error + rec->errorcode=ECONNABORTED; + rec->tcpstate=SGIP_TCP_STATE_CLOSED; + break; + } + j=rec->time_backoff; + j*=2; + if(j>SGIP_TCP_BACKOFFMAX) j=SGIP_TCP_BACKOFFMAX; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_SYN,0); + rec->time_backoff=j; // preserve backoff + } + break; + case SGIP_TCP_STATE_CLOSE_WAIT: // got FIN, wait for user code to close socket & send FIN [do nothing] + case SGIP_TCP_STATE_ESTABLISHED: // syns have been exchanged [check for data in buffer, send] + if(rec->want_shutdown==1 && rec->buf_tx_out==rec->buf_tx_in) { // oblige & shutdown + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_FIN | SGIP_TCP_FLAG_ACK,0); + if(rec->tcpstate==SGIP_TCP_STATE_CLOSE_WAIT) { + rec->tcpstate=SGIP_TCP_STATE_CLOSING; + } else { + rec->tcpstate=SGIP_TCP_STATE_FIN_WAIT_1; + } + rec->want_shutdown=2; + break; + } + j=rec->buf_tx_out-rec->buf_tx_in; + if(j<0) j+=SGIP_TCP_TRANSMITBUFFERLENGTH; + j+=(int)(rec->sequence-rec->sequence_next); + if(j>0) {// never-sent bytes + if(time>SGIP_TCP_TRANSMIT_DELAY) { // 1000 is an arbitrary constant. + j=rec->buf_tx_out-rec->buf_tx_in; + if(j<0) j+=SGIP_TCP_TRANSMITBUFFERLENGTH; + i=(int)(rec->txwindow-rec->sequence); + if(j>i) j=i; + i=sgIP_IP_MaxContentsSize(rec->destip)-20; // max tcp data size + if(j>i) j=i; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,i); + break; + } + } + if(time>rec->time_backoff && rec->buf_tx_out!=rec->buf_tx_in) { // resend last packet + j=rec->buf_tx_out-rec->buf_tx_in; + if(j<0) j+=SGIP_TCP_TRANSMITBUFFERLENGTH; + i=(int)(rec->txwindow-rec->sequence); + if(j>i) j=i; + i=sgIP_IP_MaxContentsSize(rec->destip)-20; // max tcp data size + if(j>i) j=i; + j=rec->time_backoff; + j*=2; + if(j>SGIP_TCP_BACKOFFMAX) j=SGIP_TCP_BACKOFFMAX; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,i); + rec->time_backoff=j; // preserve backoff + break; + } + break; + case SGIP_TCP_STATE_FIN_WAIT_1: // sent a FIN, haven't got FIN or ACK yet. [resend fin] + if(time>rec->time_backoff) { + rec->retrycount++; + if(rec->retrycount>=SGIP_TCP_MAXRETRY) { + //error + rec->errorcode=ETIMEDOUT; + rec->tcpstate=SGIP_TCP_STATE_CLOSED; + break; + } + j=rec->time_backoff; + j*=2; + if(j>SGIP_TCP_BACKOFFMAX) j=SGIP_TCP_BACKOFFMAX; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_FIN,0); + rec->time_backoff=j; // preserve backoff + } + break; + case SGIP_TCP_STATE_CLOSING: // got FIN, waiting for ACK of our FIN [resend FINACK] + if(time>rec->time_backoff) { + rec->retrycount++; + if(rec->retrycount>=SGIP_TCP_MAXRETRY) { + //error + rec->errorcode=ETIMEDOUT; + rec->tcpstate=SGIP_TCP_STATE_CLOSED; + break; + } + j=rec->time_backoff; + j*=2; + if(j>SGIP_TCP_BACKOFFMAX) j=SGIP_TCP_BACKOFFMAX; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_FIN | SGIP_TCP_FLAG_ACK,0); + rec->time_backoff=j; // preserve backoff + } + break; + case SGIP_TCP_STATE_LAST_ACK: // wait for ACK of our last FIN [resend FIN] + if(time>rec->time_backoff) { + rec->retrycount++; + if(rec->retrycount>=SGIP_TCP_MAXRETRY) { + //error + rec->errorcode=ETIMEDOUT; + rec->tcpstate=SGIP_TCP_STATE_CLOSED; + break; + } + j=rec->time_backoff; + j*=2; + if(j>SGIP_TCP_BACKOFFMAX) j=SGIP_TCP_BACKOFFMAX; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_FIN,0); + rec->time_backoff=j; // preserve backoff + } + break; + case SGIP_TCP_STATE_TIME_WAIT: // wait to ensure remote tcp knows it's been terminated. [reset in 2MSL] + if(time>SGIP_TCP_TIMEMS_2MSL) { + rec->errorcode=ESHUTDOWN; + rec->tcpstate=SGIP_TCP_STATE_CLOSED; + } + break; + } + + + rec=rec->next; + } +} + + +unsigned long sgIP_TCP_support_seqhash(unsigned long srcip, unsigned long destip, unsigned short srcport, unsigned short destport) { + unsigned long hash; + hash=destip; + hash ^= destport * (0x02041089+sgIP_timems); + hash ^= srcport * (0x080810422+(sgIP_timems<<1)); + hash ^= srcip * (0x48841221+(sgIP_timems<<3)); + hash ^= destip * (0x04020108+(sgIP_timems<<5)); + return hash; +} +int sgIP_TCP_GetUnusedOutgoingPort() { + int myport,clear; + sgIP_Record_TCP * rec; + port_counter+=(sgIP_timems&1023); // semi-random + if(port_counter>SGIP_TCP_LASTOUTGOINGPORT) port_counter=SGIP_TCP_FIRSTOUTGOINGPORT; + while(1) { + rec = tcprecords; + myport=port_counter++; + if(port_counter>SGIP_TCP_LASTOUTGOINGPORT) port_counter=SGIP_TCP_FIRSTOUTGOINGPORT; + clear=1; + while(rec) { + if(rec->srcport==myport && rec->tcpstate!=SGIP_TCP_STATE_CLOSED && rec->tcpstate!=SGIP_TCP_STATE_NODATA) { clear=0; break; } + rec=rec->next; + } + if(clear) return myport; + } +} + +int sgIP_TCP_CalcChecksum(sgIP_memblock * mb, unsigned long srcip, unsigned long destip, int totallength) { + int checksum; + if(!mb) return 0; + if(mb->totallength&1) mb->datastart[mb->totallength]=0; + checksum=sgIP_memblock_IPChecksum(mb,0,mb->totallength); + // add in checksum of "faux header" + checksum+=(destip&0xFFFF); + checksum+=(destip>>16); + checksum+=(srcip&0xFFFF); + checksum+=(srcip>>16); + checksum+=htons(totallength); + checksum+=(6)<<8; + checksum= (checksum&0xFFFF) +(checksum>>16); + checksum= (checksum&0xFFFF) +(checksum>>16); + + return checksum; +} + + +int sgIP_TCP_ReceivePacket(sgIP_memblock * mb, unsigned long srcip, unsigned long destip) { + if(!mb) return 0; + sgIP_Header_TCP * tcp; + int delta1,delta2, delta3,datalen, shouldReply; + unsigned long tcpack,tcpseq; + tcp = (sgIP_Header_TCP *) mb->datastart; + // 01234567890123456789012345678901 + // TCPxxxxxxxx-xxxxxxxx,xxxx-xxxx + //SGIP_DEBUG_MESSAGE(("TCP%08X-%08X,%04X-%04X",srcip,destip,tcp->srcport,tcp->destport)); + // -Lxxxx,Cxxxx,Fxx,hx,Axxxxxxxx + //SGIP_DEBUG_MESSAGE(("-L%04X,C%04X,F%02X,h%X,A%08X",mb->totallength,tcp->checksum,tcp->tcpflags,tcp->dataofs_>>4,tcp->acknum)); + if(tcp->checksum!=0x0000 && sgIP_TCP_CalcChecksum(mb,srcip,destip,mb->totallength)!=0xFFFF) { // checksum is invalid! + SGIP_DEBUG_MESSAGE(("TCP receive checksum incorrect")); + sgIP_memblock_free(mb); + return 0; + } + sgIP_Record_TCP * rec; + rec=tcprecords; + // find associated block. + while(rec) { + if(rec->srcport==tcp->destport && (rec->srcip==destip || rec->srcip==0)) { + if((rec->tcpstate==SGIP_TCP_STATE_LISTEN && (tcp->tcpflags&SGIP_TCP_FLAG_SYN)) || rec->destport==tcp->srcport) break; + } + rec=rec->next; + } + if(!rec) { // could be completion of an incoming connection? + tcpack=htonl(tcp->acknum); + if(tcp->tcpflags&SGIP_TCP_FLAG_ACK) { + int i,j; + for(i=0;i<numsynlist;i++) { + if(synlist[i].localseq+1==tcpack) { // oki! this is probably legit ;) + rec=synlist[i].linked; // we have the data we need. + // remove entry from synlist + numsynlist--; + i*=3; + for(;i<numsynlist;i++) { + synlist[i]=synlist[i+1]; // assume struct copy + } + for(j=0;j<rec->maxlisten;j++) if(!rec->listendata[j]) break; // find last entry in listen queue + if(j==rec->maxlisten) { rec=0; break; } // discard this connection! we have no space in the listen queue. + + rec->listendata[j]=sgIP_TCP_AllocRecord(); + j++; + if(j!=rec->maxlisten) rec->listendata[j]=0; + + rec=rec->listendata[j-1]; + + // fill in data about the connection. + rec->tcpstate=SGIP_TCP_STATE_ESTABLISHED; + rec->time_last_action=sgIP_timems; + rec->time_backoff=SGIP_TCP_GENRETRYMS; // backoff timer + rec->srcip=destip; + rec->destip=srcip; + rec->srcport=tcp->destport; + rec->destport=tcp->srcport; + rec->sequence=htonl(tcp->acknum); + rec->ack=htonl(tcp->seqnum); + rec->sequence_next=rec->sequence; + rec->rxwindow=rec->ack+1400; // last byte in receive window + rec->txwindow=rec->sequence+htons(tcp->window); + + sgIP_memblock_free(mb); + return 0; + } + } + } + } + if(!rec) { // we don't have a clue what this one is. +#ifndef SGIP_TCP_STEALTH + // send a RST + sgIP_TCP_SendSynReply(SGIP_TCP_FLAG_RST,ntohl(tcp->acknum),0,destip,srcip,tcp->destport,tcp->srcport,0); +#endif + sgIP_memblock_free(mb); + return 0; + } + // check sequence and ACK numbers, to ensure they're in range. + tcpack=htonl(tcp->acknum); + tcpseq=htonl(tcp->seqnum); + datalen=mb->totallength-(tcp->dataofs_>>4)*4; + shouldReply=0; + if(tcp->tcpflags&SGIP_TCP_FLAG_RST) { // verify if rst is legit, and act on it. + // check seq against receive window + delta1=(int)(tcpseq-rec->ack); + delta2=(int)(rec->rxwindow-tcpseq); + if(delta1<0 || delta2<0 || rec->tcpstate==SGIP_TCP_STATE_LISTEN) { + // out of range, ignore + } else { + // in range! reset connection. + rec->errorcode=ECONNRESET; + rec->tcpstate=SGIP_TCP_STATE_CLOSED; + } + sgIP_memblock_free(mb); + return 0; + } + + if((tcp->tcpflags&SGIP_TCP_FLAG_ACK) && !(tcp->tcpflags&SGIP_TCP_FLAG_SYN)) { // doesn't work very well with SYN. + // verify ack value (checking ack sequence vs transmit window) + delta1=(int)(tcpack-rec->sequence); + delta2=(int)(rec->txwindow-tcpack); + if(delta1<0 || delta2<0) { // invalid ack range, discard packet + sgIP_memblock_free(mb); + return 0; + } + delta2=tcpack-rec->sequence; + rec->sequence=tcpack; + delta2+=rec->buf_tx_in; + if(delta2>=SGIP_TCP_TRANSMITBUFFERLENGTH) delta2-=SGIP_TCP_TRANSMITBUFFERLENGTH; + rec->buf_tx_in=delta2; + if(delta1>0) shouldReply=1; + } + rec->txwindow=rec->sequence+htons(tcp->window); + + // now, decide what to do with our nice new shiny memblock... + + // for most states, receive data + switch(rec->tcpstate) { + case SGIP_TCP_STATE_NODATA: // newly allocated + case SGIP_TCP_STATE_UNUSED: // allocated & BINDed + case SGIP_TCP_STATE_CLOSED: // Block is unused. + case SGIP_TCP_STATE_LISTEN: // listening + case SGIP_TCP_STATE_TIME_WAIT: // wait to ensure remote tcp knows it's been terminated. + case SGIP_TCP_STATE_SYN_SENT: // connect initiated + case SGIP_TCP_STATE_CLOSE_WAIT: // got FIN, wait for user code to close socket & send FIN + case SGIP_TCP_STATE_CLOSING: // got FIN, waiting for ACK of our FIN + case SGIP_TCP_STATE_LAST_ACK: // wait for ACK of our last FIN + break; + case SGIP_TCP_STATE_SYN_RECEIVED: // spawned from listen socket; or from syn sent. + case SGIP_TCP_STATE_ESTABLISHED: // syns have been exchanged + case SGIP_TCP_STATE_FIN_WAIT_1: // sent a FIN, haven't got FIN or ACK yet. + case SGIP_TCP_STATE_FIN_WAIT_2: // got ACK for our FIN, haven't got FIN yet. + if(tcp->tcpflags&SGIP_TCP_FLAG_ACK) { + // check end of incoming data against receive window + delta1=(int)(tcpseq+datalen-rec->ack); // check end of data vs start of window (>=0, end of data is equal to or after start of unreceived data) + delta2=(int)(rec->rxwindow-tcpseq-datalen); // check end of data vs end of window (>=0, end of data is equal to or before end of rx window) + delta3=(int)(rec->ack-tcpseq); // check start of data vs start of window (>=0, start of data is equal or before the next expected byte) + if(delta1<0 || delta2<0 || delta3<0) { + if(delta1>-SGIP_TCP_RECEIVEBUFFERLENGTH) { // ack it anyway, they got lost on the retard bus. + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); + } + break; // out of range, they should know better. + } + { + int datastart=(tcp->dataofs_>>4)*4; + delta1=(int)(tcpseq-rec->ack); + if(delta1<0) { // data is partly ack'd...just copy what we need. + datastart-=delta1; + datalen+=delta1; + } + // copy data into the fifo + rec->ack+=datalen; + delta1=datalen; + while(datalen>0) { // don't actually need to check the rx buffer length, if the ack check approved it, it will be in range (not overflow) by default + delta2=SGIP_TCP_RECEIVEBUFFERLENGTH-rec->buf_rx_out; // number of bytes til the end of the buffer + if(datalen<delta2) delta2=datalen; + sgIP_memblock_CopyToLinear(mb,rec->buf_rx+rec->buf_rx_out,datastart,delta2); + datalen-=delta2; + datastart+=delta2; + rec->buf_rx_out += delta2; + if(rec->buf_rx_out>=SGIP_TCP_RECEIVEBUFFERLENGTH) rec->buf_rx_out-=SGIP_TCP_RECEIVEBUFFERLENGTH; + } + if(rec->tcpstate==SGIP_TCP_STATE_FIN_WAIT_1 || rec->tcpstate==SGIP_TCP_STATE_FIN_WAIT_2) break; + if(shouldReply || delta1>=0) { // send a packet in reply, ha! + delta1=rec->buf_tx_out-rec->buf_tx_in; + if(delta1<0) delta1+=SGIP_TCP_TRANSMITBUFFERLENGTH; + delta2=(int)(rec->txwindow-rec->sequence); + if(delta1>delta2) delta1=delta2; + delta2=sgIP_IP_MaxContentsSize(rec->destip)-20; // max tcp data size + if(delta1>delta2) delta1=delta2; + if(delta1>=0) { // could be less than 0, but very odd. + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,delta1); + } + } + } + } + } + + // decide what to do with the others + switch(rec->tcpstate) { + case SGIP_TCP_STATE_NODATA: // newly allocated + case SGIP_TCP_STATE_UNUSED: // allocated & BINDed + case SGIP_TCP_STATE_CLOSED: // Block is unused. + break; // can't do anything in these states. + case SGIP_TCP_STATE_LISTEN: // listening + if(tcp->tcpflags&SGIP_TCP_FLAG_SYN) { // other end requesting a connection + if(numsynlist==SGIP_TCP_MAXSYNS) { + numsynlist--; + for(delta1=0;delta1<numsynlist;delta1++) { + synlist[delta1]=synlist[delta1+1]; // assume struct copy + } + } + { + unsigned long myseq,myport; + myport=tcp->destport; + myseq=sgIP_TCP_support_seqhash(srcip,destip,tcp->srcport,myport); + // send relevant synack + sgIP_TCP_SendSynReply(SGIP_TCP_FLAG_SYN|SGIP_TCP_FLAG_ACK,myseq,tcpseq+1,destip,srcip,myport,tcp->srcport,-1); + synlist[numsynlist].localseq=myseq; + synlist[numsynlist].timebackoff=SGIP_TCP_SYNRETRYMS; + synlist[numsynlist].timenext=SGIP_TCP_SYNRETRYMS; + synlist[numsynlist].linked=rec; + synlist[numsynlist].remoteseq=tcpseq+1; + synlist[numsynlist].remoteip=srcip; + synlist[numsynlist].localip=destip; + synlist[numsynlist].localport=myport; + synlist[numsynlist].remoteport=tcp->srcport; + numsynlist++; + } + } + break; + case SGIP_TCP_STATE_SYN_SENT: // connect initiated + switch(tcp->tcpflags&(SGIP_TCP_FLAG_SYN|SGIP_TCP_FLAG_ACK)) { + case SGIP_TCP_FLAG_SYN | SGIP_TCP_FLAG_ACK: // both flags set + rec->ack=tcpseq+1; + rec->sequence=tcpack; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); + rec->tcpstate=SGIP_TCP_STATE_ESTABLISHED; + rec->retrycount=0; + break; + case SGIP_TCP_FLAG_SYN: // just got a syn... + rec->ack=tcpseq+1; + rec->sequence=tcpack; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); + rec->tcpstate=SGIP_TCP_STATE_SYN_RECEIVED; + rec->retrycount=0; + break; + } + break; + case SGIP_TCP_STATE_SYN_RECEIVED: // spawned from listen socket; or from syn sent. + if(tcp->tcpflags&SGIP_TCP_FLAG_ACK) { + rec->tcpstate=SGIP_TCP_STATE_ESTABLISHED; + rec->retrycount=0; + } + break; + case SGIP_TCP_STATE_ESTABLISHED: // syns have been exchanged + if(tcp->tcpflags&SGIP_TCP_FLAG_FIN) { + // check sequence against next ack number + delta1=(int)(tcpseq-rec->ack); + //delta2=(int)(rec->rxwindow-tcpseq); + if(delta1<0 || delta1>0) break; // out of range, they should know better. + // this is the end... + rec->tcpstate=SGIP_TCP_STATE_CLOSE_WAIT; + rec->ack=tcpseq+datalen+1; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); + + } + break; + case SGIP_TCP_STATE_FIN_WAIT_1: // sent a FIN, haven't got FIN or ACK yet. + switch(tcp->tcpflags&(SGIP_TCP_FLAG_FIN|SGIP_TCP_FLAG_ACK)) { + case SGIP_TCP_FLAG_FIN: + // check sequence against next ack number + delta1=(int)(tcpseq-rec->ack); + //delta2=(int)(rec->rxwindow-tcpseq); + if(delta1<0 || delta1>0) break; // out of range, they should know better. + + rec->tcpstate=SGIP_TCP_STATE_CLOSING; + rec->ack=tcpseq+datalen+1; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); + break; + case SGIP_TCP_FLAG_ACK: // already checked ack against appropriate window + rec->tcpstate=SGIP_TCP_STATE_FIN_WAIT_2; + break; + case (SGIP_TCP_FLAG_FIN | SGIP_TCP_FLAG_ACK): // already checked ack, check sequence though + // check sequence against next ack number + delta1=(int)(tcpseq-rec->ack); + //delta2=(int)(rec->rxwindow-tcpseq); + if(delta1<0 || delta1>0) break; // out of range, they should know better. + rec->tcpstate=SGIP_TCP_STATE_TIME_WAIT; + rec->ack=tcpseq+datalen+1; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); + break; + } + break; + case SGIP_TCP_STATE_FIN_WAIT_2: // got ACK for our FIN, haven't got FIN yet. + if(tcp->tcpflags&SGIP_TCP_FLAG_FIN) { + // check sequence against next ack number + delta1=(int)(tcpseq-rec->ack); + //delta2=(int)(rec->rxwindow-tcpseq); + if(delta1<0 || delta1>0) break; // out of range, they should know better. + + rec->tcpstate=SGIP_TCP_STATE_TIME_WAIT; + rec->ack=tcpseq+datalen+1; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); + } + break; + case SGIP_TCP_STATE_CLOSE_WAIT: // got FIN, wait for user code to close socket & send FIN + if(tcp->tcpflags&SGIP_TCP_FLAG_FIN) { + // check sequence against next ack number + delta1=(int)(tcpseq-rec->ack); + //delta2=(int)(rec->rxwindow-tcpseq); + if(delta1<0 || delta1>0) break; // out of range, they should know better. + + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); // they still don't seem to have got our ack, we'll send it again. + } + break; + case SGIP_TCP_STATE_CLOSING: // got FIN, waiting for ACK of our FIN + switch(tcp->tcpflags&(SGIP_TCP_FLAG_FIN|SGIP_TCP_FLAG_ACK)) { + case SGIP_TCP_FLAG_FIN: + // check sequence against receive window + delta1=(int)(tcpseq-rec->ack); + delta2=(int)(rec->rxwindow-tcpseq); + if(delta1<1 || delta2<0) break; // out of range, they should know better. + + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); // resend their ack. + break; + case SGIP_TCP_FLAG_ACK: // already checked ack against appropriate window + rec->tcpstate=SGIP_TCP_STATE_TIME_WAIT; + break; + case (SGIP_TCP_FLAG_FIN | SGIP_TCP_FLAG_ACK): // already checked ack, check sequence though + // check sequence against receive window + delta1=(int)(tcpseq-rec->ack); + delta2=(int)(rec->rxwindow-tcpseq); + if(delta1<1 || delta2<0) break; // out of range, they should know better. + rec->tcpstate=SGIP_TCP_STATE_TIME_WAIT; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); + break; + } + break; + + case SGIP_TCP_STATE_LAST_ACK: // wait for ACK of our last FIN + if(tcp->tcpflags&SGIP_TCP_FLAG_ACK) { + rec->tcpstate=SGIP_TCP_STATE_TIME_WAIT; + } + break; + case SGIP_TCP_STATE_TIME_WAIT: // wait to ensure remote tcp knows it's been terminated. + if(tcp->tcpflags&SGIP_TCP_FLAG_FIN) { + // check sequence against receive window + delta1=(int)(tcpseq-rec->ack); + delta2=(int)(rec->rxwindow-tcpseq); + if(delta1<1 || delta2<0) break; // out of range, they should know better. + + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); // send 'em a grat ACK + } + break; + } + sgIP_memblock_free(mb); + return 0; +} + +sgIP_memblock * sgIP_TCP_GenHeader(sgIP_Record_TCP * rec, int flags, int datalength) { + sgIP_memblock * mb = sgIP_memblock_alloc(datalength+20+sgIP_IP_RequiredHeaderSize()); + int windowlen; + if(!mb) return 0; + sgIP_memblock_exposeheader(mb,-sgIP_IP_RequiredHeaderSize()); // hide IP header space for later + sgIP_Header_TCP * tcp = (sgIP_Header_TCP *) mb->datastart; + tcp->srcport=rec->srcport; + tcp->destport=rec->destport; + tcp->seqnum=htonl(rec->sequence); + tcp->acknum=htonl(rec->ack); + tcp->tcpflags=flags; + tcp->urg_ptr=0; // no support for URG data atm. + tcp->checksum=0; + tcp->dataofs_=5<<4; // header length == 20 (5*32bit) + windowlen=rec->buf_rx_out-rec->buf_rx_in; + if(windowlen<0) windowlen+=SGIP_TCP_RECEIVEBUFFERLENGTH; // we now have the amount in the buffer + windowlen = SGIP_TCP_RECEIVEBUFFERLENGTH-windowlen-1; + if(windowlen<0) windowlen=0; + if(flags&SGIP_TCP_FLAG_ACK) rec->want_reack = windowlen<SGIP_TCP_REACK_THRESH; // indicate an additional ack should be sent when we have more space in the buffer. + if(windowlen>65535) windowlen=65535; + if(windowlen>1400) windowlen=1400; // don't want to deal with IP fragmentation. + rec->rxwindow=rec->ack+windowlen; // last byte in receive window + tcp->window=htons(windowlen); + return mb; +} +void sgIP_TCP_FixChecksum(unsigned long srcip, unsigned long destip, sgIP_memblock * mb) { + int checksum; + if(!mb) return; + sgIP_Header_TCP * tcp; + tcp = (sgIP_Header_TCP *) mb->datastart; + tcp->checksum=0; + checksum=sgIP_memblock_IPChecksum(mb,0,mb->totallength); + + // add in checksum of "faux header" + checksum+=(destip&0xFFFF); + checksum+=(destip>>16); + checksum+=(srcip&0xFFFF); + checksum+=(srcip>>16); + checksum+=htons(mb->totallength); + checksum+=(6)<<8; + checksum=(checksum&0xFFFF) + (checksum>>16); + checksum=(checksum&0xFFFF) + (checksum>>16); + + checksum = ~checksum; + if(checksum==0) checksum=0xFFFF; + tcp->checksum=checksum; +} + +int sgIP_TCP_SendPacket(sgIP_Record_TCP * rec, int flags, int datalength) { // data sent is taken directly from the TX fifo. + int i,j,k; + if(!rec) return 0; + SGIP_INTR_PROTECT(); + + j=rec->buf_tx_out-rec->buf_tx_in; + if(j<0) j+=SGIP_TCP_TRANSMITBUFFERLENGTH; + if(datalength>j) datalength=j; + sgIP_memblock * mb =sgIP_TCP_GenHeader(rec,flags,datalength); + if(!mb) { + SGIP_INTR_UNPROTECT(); + return 0; + } + j=20; // destination offset in memblock for data + rec->sequence_next=rec->sequence+datalength; + k=rec->buf_tx_in; + while(datalength>0) { + i=SGIP_TCP_TRANSMITBUFFERLENGTH-rec->buf_tx_in; + if(i>datalength)i=datalength; + sgIP_memblock_CopyFromLinear(mb,rec->buf_tx+k,j,i); + k+=i; + if(k>=SGIP_TCP_TRANSMITBUFFERLENGTH) k-=SGIP_TCP_TRANSMITBUFFERLENGTH; + j+=i; + datalength-=i; + } + + sgIP_TCP_FixChecksum(rec->srcip,rec->destip,mb); + sgIP_IP_SendViaIP(mb,6,rec->srcip,rec->destip); + + rec->time_last_action=sgIP_timems; // semi-generic timer. + rec->time_backoff=SGIP_TCP_GENRETRYMS; // backoff timer + SGIP_INTR_UNPROTECT(); + return 0; +} + +int sgIP_TCP_SendSynReply(int flags,unsigned long seq, unsigned long ack, unsigned long srcip, unsigned long destip, int srcport, int destport, int windowlen) { + SGIP_INTR_PROTECT(); + + sgIP_memblock * mb = sgIP_memblock_alloc(20+sgIP_IP_RequiredHeaderSize()); + if(!mb) { + SGIP_INTR_UNPROTECT(); + return 0; + } + sgIP_memblock_exposeheader(mb,-sgIP_IP_RequiredHeaderSize()); // hide IP header space for later + sgIP_Header_TCP * tcp = (sgIP_Header_TCP *) mb->datastart; + tcp->srcport=srcport; + tcp->destport=destport; + tcp->seqnum=htonl(seq); + tcp->acknum=htonl(ack); + tcp->tcpflags=flags; + tcp->urg_ptr=0; // no support for URG data atm. + tcp->checksum=0; + tcp->dataofs_=5<<4; // header length == 20 (5*32bit) + + if(windowlen<0 || windowlen>1400) windowlen=1400; // don't want to deal with IP fragmentation. + tcp->window=htons(windowlen); + + sgIP_TCP_FixChecksum(srcip,destip,mb); + sgIP_IP_SendViaIP(mb,6,srcip,destip); + + SGIP_INTR_UNPROTECT(); + return 0; +} + +sgIP_Record_TCP * sgIP_TCP_AllocRecord() { + SGIP_INTR_PROTECT(); + sgIP_Record_TCP * rec; + rec = sgIP_malloc(sizeof(sgIP_Record_TCP)); + if(rec) { + rec->buf_oob_in=0; + rec->buf_oob_out=0; + rec->buf_rx_in=0; + rec->buf_rx_out=0; + rec->buf_tx_in=0; + rec->buf_tx_out=0; + rec->tcpstate=0; + rec->next=tcprecords; + tcprecords=rec; + rec->maxlisten=0; + rec->srcip=0; + rec->retrycount=0; + rec->errorcode=0; + rec->listendata=0; + rec->want_shutdown=0; + rec->want_reack=0; + } + SGIP_INTR_UNPROTECT(); + return rec; +} +void sgIP_TCP_FreeRecord(sgIP_Record_TCP * rec) { + if(!rec) return; + SGIP_INTR_PROTECT(); + sgIP_Record_TCP * t; + int i,j; + rec->tcpstate=0; + if(tcprecords==rec) { + tcprecords=rec->next; + } else { + t=tcprecords; + while(t) { + if(t->next==rec) { + t->next=rec->next; + break; + } + t=t->next; + } + } + if(rec->listendata) { + for(i=0;i<rec->maxlisten;i++) { + if(!rec->listendata[i]) break; + sgIP_TCP_FreeRecord(rec->listendata[i]); + } + // kill any possible waiting elements in the SYN chain. + j=0; + for(i=0;i<numsynlist;i++) { + if(j!=i) { + synlist[j]=synlist[i]; + } + if(synlist[i].linked==rec) j--; + j++; + } + numsynlist=j; + sgIP_free(rec->listendata); + } + sgIP_free(rec); + + SGIP_INTR_UNPROTECT(); +} + +int sgIP_TCP_Bind(sgIP_Record_TCP * rec, int srcport, unsigned long srcip) { + if(!rec) return 0; + SGIP_INTR_PROTECT(); + if(rec->tcpstate==SGIP_TCP_STATE_NODATA) { + rec->srcip=srcip; + rec->srcport=srcport; + rec->tcpstate=SGIP_TCP_STATE_UNUSED; + } + SGIP_INTR_UNPROTECT(); + return 0; +} +int sgIP_TCP_Listen(sgIP_Record_TCP * rec, int maxlisten) { + if(!rec) return SGIP_ERROR(EINVAL); + if(rec->tcpstate!=SGIP_TCP_STATE_UNUSED) return SGIP_ERROR(EINVAL); + int err; + SGIP_INTR_PROTECT(); + if(rec->maxlisten!=0) { // we're *already* listening. + err=0; + } else { + err=0; + if(maxlisten<=0) maxlisten=1; + rec->maxlisten=maxlisten; + rec->listendata = (sgIP_Record_TCP **) sgIP_malloc(maxlisten*4); // pointers to TCP records, 0-terminated list. + if(!rec->listendata) { rec->maxlisten=0; err=0; } else {rec->tcpstate=SGIP_TCP_STATE_LISTEN; rec->listendata[0]=0;} + } + SGIP_INTR_UNPROTECT(); + return err; +} + +sgIP_Record_TCP * sgIP_TCP_Accept(sgIP_Record_TCP * rec) { + if(!rec) return (sgIP_Record_TCP *)SGIP_ERROR0(EINVAL); + if(rec->tcpstate!=SGIP_TCP_STATE_LISTEN) return (sgIP_Record_TCP *)SGIP_ERROR0(EINVAL); + int err,i; + sgIP_Record_TCP * t; + SGIP_INTR_PROTECT(); + if(!rec->listendata) err=SGIP_ERROR0(EINVAL); + else { + if(!rec->listendata[0]) { + err=SGIP_ERROR0(EWOULDBLOCK); + } else { + t=rec->listendata[0]; + for(i=1;i<rec->maxlisten;i++) { + rec->listendata[i-1]=rec->listendata[i]; + } + rec->listendata[i-1]=0; + SGIP_INTR_UNPROTECT(); + return t; + } + } + + SGIP_INTR_UNPROTECT(); + return 0; +} + +int sgIP_TCP_Close(sgIP_Record_TCP * rec) { + if(!rec) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + if(rec->want_shutdown==0) rec->want_shutdown=1; + SGIP_INTR_UNPROTECT(); + return 0; +} +int sgIP_TCP_Connect(sgIP_Record_TCP * rec, unsigned long destip, int destport) { + if(!rec) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + if(rec->tcpstate==SGIP_TCP_STATE_NODATA) { // need to bind a local address + rec->srcip=sgIP_IP_GetLocalBindAddr(0,destip); + rec->srcport=htons(sgIP_TCP_GetUnusedOutgoingPort()); + rec->destip=destip; + rec->destport=destport; + } else if(rec->tcpstate==SGIP_TCP_STATE_UNUSED) { // already bound to a local address. + rec->srcip=sgIP_IP_GetLocalBindAddr(rec->srcip,destip); + rec->destip=destip; + rec->destport=destport; + } else { + SGIP_INTR_UNPROTECT(); + return SGIP_ERROR(EINVAL); + } + + // send a SYN packet, and advance the state of the connection + rec->sequence=sgIP_TCP_support_seqhash(rec->srcip,rec->destip,rec->srcport,rec->destport); + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_SYN,0); + rec->retrycount=0; + rec->tcpstate=SGIP_TCP_STATE_SYN_SENT; + + SGIP_INTR_UNPROTECT(); + return 0; +} +int sgIP_TCP_Send(sgIP_Record_TCP * rec, const char * datatosend, int datalength, int flags) { + if(!rec || !datatosend) return SGIP_ERROR(EINVAL); + if(rec->want_shutdown) return SGIP_ERROR(ESHUTDOWN); + SGIP_INTR_PROTECT(); + int bufsize; + bufsize=rec->buf_tx_out-rec->buf_tx_in; + if(bufsize<0) bufsize+=SGIP_TCP_TRANSMITBUFFERLENGTH; + if(bufsize==0) { rec->time_last_action=sgIP_timems; rec->time_backoff=SGIP_TCP_GENRETRYMS; } // first byte sent, set up delay before sending + bufsize=SGIP_TCP_TRANSMITBUFFERLENGTH-bufsize-1; // space left in buffer + if(datalength>bufsize) datalength=bufsize; + int i,j; + j=rec->buf_tx_out; + for(i=0;i<datalength;i++) { + rec->buf_tx[j++]=datatosend[i]; + if(j==SGIP_TCP_TRANSMITBUFFERLENGTH) j=0; + } + rec->buf_tx_out = j; + // check for immediate transmit + j=rec->buf_tx_out-rec->buf_tx_in; + if(j<0) j+=SGIP_TCP_TRANSMITBUFFERLENGTH; + j+=(int)(rec->sequence-rec->sequence_next); + if(j>SGIP_TCP_TRANSMIT_IMMTHRESH && rec->tcpstate==SGIP_TCP_STATE_ESTABLISHED) { + j=(int)(rec->sequence_next-rec->sequence); + if(j<1000) { // arbitrary constant. + j=rec->buf_tx_out-rec->buf_tx_in; + if(j<0) j+=SGIP_TCP_TRANSMITBUFFERLENGTH; + i=(int)(rec->txwindow-rec->sequence); + if(j>i) j=i; + i=sgIP_IP_MaxContentsSize(rec->destip)-20; // max tcp data size + if(j>i) j=i; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,i); + rec->retrycount=0; + } + } + SGIP_INTR_UNPROTECT(); + if(datalength==0) return SGIP_ERROR(EWOULDBLOCK); + return datalength; +} +int sgIP_TCP_Recv(sgIP_Record_TCP * rec, char * databuf, int buflength, int flags) { + if(!rec || !databuf) return SGIP_ERROR(EINVAL); //error + if(rec->buf_rx_in==rec->buf_rx_out) { + if(rec->tcpstate==SGIP_TCP_STATE_CLOSED || rec->tcpstate==SGIP_TCP_STATE_CLOSE_WAIT) { + if(rec->errorcode) return SGIP_ERROR(rec->errorcode); + return SGIP_ERROR0(ESHUTDOWN); + } + return SGIP_ERROR(EWOULDBLOCK); //error no data + } + SGIP_INTR_PROTECT(); + int rxlen = rec->buf_rx_out - rec->buf_rx_in; + if(rxlen<0) rxlen+=SGIP_TCP_RECEIVEBUFFERLENGTH; + if(buflength>rxlen) buflength=rxlen; + int i,j; + j=rec->buf_rx_in; + for(i=0;i<buflength;i++) { + databuf[i]=rec->buf_rx[j++]; + if(j==SGIP_TCP_RECEIVEBUFFERLENGTH) j=0; + } + + if(!(flags&MSG_PEEK)) { + rec->buf_rx_in=j; + + if(rec->want_reack) { + i=rec->buf_rx_out-rec->buf_rx_in; + if(i<0) i+=SGIP_TCP_RECEIVEBUFFERLENGTH; // we now have the amount in the buffer + i = SGIP_TCP_RECEIVEBUFFERLENGTH-i-1; + if(i<0) i=0; + if(i>SGIP_TCP_REACK_THRESH) { + rec->want_reack=0; + sgIP_TCP_SendPacket(rec,SGIP_TCP_FLAG_ACK,0); + } + } + } + SGIP_INTR_UNPROTECT(); + return buflength; +} diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_TCP.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_TCP.h new file mode 100644 index 0000000000..2c84551e2b --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_TCP.h @@ -0,0 +1,134 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ +#ifndef SGIP_TCP_H +#define SGIP_TCP_H + +#include "sgIP_Config.h" +#include "sgIP_memblock.h" + +enum SGIP_TCP_STATE { + SGIP_TCP_STATE_NODATA, // newly allocated + SGIP_TCP_STATE_UNUSED, // allocated & BINDed + SGIP_TCP_STATE_LISTEN, // listening + SGIP_TCP_STATE_SYN_SENT, // connect initiated + SGIP_TCP_STATE_SYN_RECEIVED, // spawned from listen socket; + SGIP_TCP_STATE_ESTABLISHED, // syns have been exchanged + SGIP_TCP_STATE_FIN_WAIT_1, // sent a FIN, haven't got FIN or ACK yet. + SGIP_TCP_STATE_FIN_WAIT_2, // got ACK for our FIN, haven't got FIN yet. + SGIP_TCP_STATE_CLOSE_WAIT, // got FIN, wait for user code to close socket & send FIN + SGIP_TCP_STATE_CLOSING, // got FIN, waiting for ACK of our FIN + SGIP_TCP_STATE_LAST_ACK, // wait for ACK of our last FIN + SGIP_TCP_STATE_TIME_WAIT, // wait to ensure remote tcp knows it's been terminated. + SGIP_TCP_STATE_CLOSED, // Block is unused. +}; + + +#define SGIP_TCP_FLAG_FIN 1 +#define SGIP_TCP_FLAG_SYN 2 +#define SGIP_TCP_FLAG_RST 4 +#define SGIP_TCP_FLAG_PSH 8 +#define SGIP_TCP_FLAG_ACK 16 +#define SGIP_TCP_FLAG_URG 32 + +typedef struct SGIP_HEADER_TCP { + unsigned short srcport,destport; + unsigned long seqnum; + unsigned long acknum; + unsigned char dataofs_; + unsigned char tcpflags; + unsigned short window; + unsigned short checksum; + unsigned short urg_ptr; + unsigned char options[4]; +} sgIP_Header_TCP; + + +// sgIP_Record_TCP - a TCP record, to store data for an active TCP connection. +typedef struct SGIP_RECORD_TCP { + struct SGIP_RECORD_TCP * next; // operate as a linked list + // TCP state information + int tcpstate; + unsigned long sequence; // sequence number of first byte not acknowledged by remote system + unsigned long ack; // external sequence number of next byte to receive + unsigned long sequence_next; // sequence number of first unsent byte + unsigned long rxwindow; // sequence of last byte in receive window + unsigned long txwindow; // sequence of last byte allowed to send + int time_last_action; // used for retransmission and etc. + int time_backoff; + int retrycount; + unsigned long srcip; + unsigned long destip; + unsigned short srcport,destport; + struct SGIP_RECORD_TCP ** listendata; + int maxlisten; + int errorcode; + int want_shutdown; // 0= don't want shutdown, 1= want shutdown, 2= being shutdown + int want_reack; + // TCP buffer information: + int buf_rx_in, buf_rx_out; + int buf_tx_in, buf_tx_out; + int buf_oob_in, buf_oob_out; + unsigned char buf_rx[SGIP_TCP_RECEIVEBUFFERLENGTH]; + unsigned char buf_tx[SGIP_TCP_TRANSMITBUFFERLENGTH]; + unsigned char buf_oob[SGIP_TCP_OOBBUFFERLENGTH]; +} sgIP_Record_TCP; + +typedef struct SGIP_TCP_SYNCOOKIE { + unsigned long localseq, remoteseq; + unsigned long localip, remoteip; + unsigned short localport, remoteport; + unsigned long timenext,timebackoff; + sgIP_Record_TCP * linked; // parent listening connection +} sgIP_TCP_SYNCookie; + + + +#ifdef __cplusplus +extern "C" { +#endif + + extern void sgIP_TCP_Init(); + extern void sgIP_TCP_Timer(); + + extern int sgIP_TCP_ReceivePacket(sgIP_memblock * mb, unsigned long srcip, unsigned long destip); + extern int sgIP_TCP_SendPacket(sgIP_Record_TCP * rec, int flags, int datalength); // data sent is taken directly from the TX fifo. + extern int sgIP_TCP_SendSynReply(int flags,unsigned long seq, unsigned long ack, unsigned long srcip, unsigned long destip, int srcport, int destport, int windowlen); + + extern sgIP_Record_TCP * sgIP_TCP_AllocRecord(); + extern void sgIP_TCP_FreeRecord(sgIP_Record_TCP * rec); + extern int sgIP_TCP_Bind(sgIP_Record_TCP * rec, int srcport, unsigned long srcip); + extern int sgIP_TCP_Listen(sgIP_Record_TCP * rec, int maxlisten); + extern sgIP_Record_TCP * sgIP_TCP_Accept(sgIP_Record_TCP * rec); + extern int sgIP_TCP_Close(sgIP_Record_TCP * rec); + extern int sgIP_TCP_Connect(sgIP_Record_TCP * rec, unsigned long destip, int destport); + extern int sgIP_TCP_Send(sgIP_Record_TCP * rec, const char * datatosend, int datalength, int flags); + extern int sgIP_TCP_Recv(sgIP_Record_TCP * rec, char * databuf, int buflength, int flags); + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_UDP.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_UDP.c new file mode 100644 index 0000000000..2e3be7fc19 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_UDP.c @@ -0,0 +1,245 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "sgIP_Hub.h" +#include "sgIP_UDP.h" +#include "sgIP_IP.h" + +sgIP_Record_UDP * udprecords; +int udpport_counter; +extern unsigned long volatile sgIP_timems; + +void sgIP_UDP_Init() { + udprecords=0; + udpport_counter=SGIP_UDP_FIRSTOUTGOINGPORT; +} + + +int sgIP_UDP_GetUnusedOutgoingPort() { + int myport,clear; + sgIP_Record_UDP * rec; + udpport_counter+=(sgIP_timems&1023); // semi-random + if(udpport_counter>SGIP_UDP_LASTOUTGOINGPORT) udpport_counter=SGIP_UDP_FIRSTOUTGOINGPORT; + while(1) { + rec = udprecords; + myport=udpport_counter++; + if(udpport_counter>SGIP_UDP_LASTOUTGOINGPORT) udpport_counter=SGIP_UDP_FIRSTOUTGOINGPORT; + clear=1; + while(rec) { + if(rec->srcport==myport) { clear=0; break; } + rec=rec->next; + } + if(clear) return myport; + } +} + +int sgIP_UDP_CalcChecksum(sgIP_memblock * mb, unsigned long srcip, unsigned long destip, int totallength) { + int checksum; + if(!mb) return 0; + if(mb->totallength&1) mb->datastart[mb->totallength]=0; + checksum=sgIP_memblock_IPChecksum(mb,0,mb->totallength); + // add in checksum of "faux header" + checksum+=(destip&0xFFFF); + checksum+=(destip>>16); + checksum+=(srcip&0xFFFF); + checksum+=(srcip>>16); + checksum+=htons(totallength); + checksum+=(17)<<8; + checksum=(checksum&0xFFFF) + (checksum>>16); + checksum=(checksum&0xFFFF) + (checksum>>16); + + checksum = (~checksum)&0xFFFF; + if(checksum==0) checksum=0xFFFF; + return checksum; +} + +int sgIP_UDP_ReceivePacket(sgIP_memblock * mb, unsigned long srcip, unsigned long destip) { + if(!mb) return 0; + int chk = sgIP_UDP_CalcChecksum(mb,srcip,destip,mb->totallength); + if(chk!=0xFFFF) { + SGIP_DEBUG_MESSAGE(("UDP receive checksum incorrect")); + sgIP_memblock_free(mb); + return 0; // checksum error + } + sgIP_Header_UDP * udp; + udp=(sgIP_Header_UDP *)mb->datastart; + sgIP_Record_UDP * rec; + sgIP_memblock *tmb; + SGIP_INTR_PROTECT(); + rec=udprecords; + + while(rec) { + if((rec->srcip==destip || rec->srcip==0) && rec->srcport==udp->destport && rec->state!=SGIP_UDP_STATE_UNUSED) break; // a match! + rec=rec->next; + } + if(!rec) { // no matching records + sgIP_memblock_free(mb); + SGIP_INTR_UNPROTECT(); + return 0; + } + // we have a record and a packet for it; add some data to the record and stuff it into the record queue. + sgIP_memblock_exposeheader(mb,4); + *((unsigned long *)mb->datastart)=srcip; // keep srcip around. + if(rec->incoming_queue==0) { + rec->incoming_queue=mb; + } else { + rec->incoming_queue_end->next=mb; + } + + tmb=mb; + while(tmb->next) tmb=tmb->next; + rec->incoming_queue_end=tmb; + // ok, data added to queue - yay! + // that means... we're done. + + SGIP_INTR_UNPROTECT(); + return 0; +} + +int sgIP_UDP_SendPacket(sgIP_Record_UDP * rec, const char * data, int datalen, unsigned long destip, int destport) { + if(!rec || !data) return SGIP_ERROR(EINVAL); + if(rec->state!=SGIP_UDP_STATE_BOUND) { + rec->srcip=0; + rec->srcport=sgIP_UDP_GetUnusedOutgoingPort(); + rec->state=SGIP_UDP_STATE_BOUND; + } + sgIP_memblock * mb = sgIP_memblock_alloc(sgIP_IP_RequiredHeaderSize()+8+datalen); + if(!mb) return SGIP_ERROR(ENOMEM); + sgIP_memblock_exposeheader(mb,-sgIP_IP_RequiredHeaderSize()); // hide IP header space for later + + SGIP_INTR_PROTECT(); + unsigned long srcip = sgIP_IP_GetLocalBindAddr(rec->srcip,destip); + sgIP_Header_UDP * udp = (sgIP_Header_UDP *) mb->datastart; + udp->srcport=rec->srcport; + udp->destport=destport; + udp->length=htons(datalen+8); + udp->checksum=0; + int i; + for(i=0;i<datalen;i++) { + mb->datastart[i+8]=data[i]; + } + udp->checksum=sgIP_UDP_CalcChecksum(mb,srcip,destip,mb->totallength); + sgIP_IP_SendViaIP(mb,17,srcip,destip); + + SGIP_INTR_UNPROTECT(); + return datalen; +} + +sgIP_Record_UDP * sgIP_UDP_AllocRecord() { + SGIP_INTR_PROTECT(); + sgIP_Record_UDP * rec; + rec = (sgIP_Record_UDP *)sgIP_malloc(sizeof(sgIP_Record_UDP)); + if(rec) { + rec->destip=0; + rec->destport=0; + rec->incoming_queue=0; + rec->incoming_queue_end=0; + rec->srcip=0; + rec->srcport=0; + rec->state=0; + rec->next=udprecords; + udprecords=rec; + } + SGIP_INTR_UNPROTECT(); + return rec; +} +void sgIP_UDP_FreeRecord(sgIP_Record_UDP * rec) { + if(!rec) return; + SGIP_INTR_PROTECT(); + sgIP_Record_UDP * t; + // incoming queue is all clumped together as a single memblock, so, time to free it all in one call :) + if(rec->incoming_queue) sgIP_memblock_free(rec->incoming_queue); // woohoo! + rec->state=0; + if(udprecords==rec) { + udprecords=rec->next; + } else { + t=udprecords; + while(t) { + if(t->next==rec) { + t->next=rec->next; + break; + } + t=t->next; + } + } + sgIP_free(rec); + + SGIP_INTR_UNPROTECT(); +} + +int sgIP_UDP_Bind(sgIP_Record_UDP * rec, int srcport, unsigned long srcip) { + if(!rec) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + if(rec->state!=SGIP_UDP_STATE_UNUSED) { + rec->srcip=srcip; + rec->srcport=srcport; + if(rec->state==SGIP_UDP_STATE_UNBOUND) rec->state=SGIP_UDP_STATE_BOUND; + } + SGIP_INTR_UNPROTECT(); + return 0; +} + +int sgIP_UDP_RecvFrom(sgIP_Record_UDP * rec, char * destbuf, int buflength, int flags, unsigned long * sender_ip, unsigned short * sender_port) { + if(!rec || !destbuf || !sender_ip || !sender_port || buflength==0) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + if(rec->incoming_queue==0) { + SGIP_INTR_UNPROTECT(); + return SGIP_ERROR(EWOULDBLOCK); + } + int packetlen=rec->incoming_queue->totallength-12; + if(packetlen>buflength) { + SGIP_INTR_UNPROTECT(); + return SGIP_ERROR(EMSGSIZE); + } + sgIP_memblock * mb; + *sender_ip=*((unsigned long *)rec->incoming_queue->datastart); + *sender_port=((unsigned short *)rec->incoming_queue->datastart)[2]; + int totlen,first, buf_start,i; + totlen=rec->incoming_queue->totallength; + first=12; + buf_start=0; + + while(totlen>0 && rec->incoming_queue) { + totlen-=rec->incoming_queue->thislength; + for(i=first;i<rec->incoming_queue->thislength;i++) { + destbuf[buf_start+i-first]=rec->incoming_queue->datastart[i]; + } + buf_start+=rec->incoming_queue->thislength-first; + first=0; + mb=rec->incoming_queue; + rec->incoming_queue=rec->incoming_queue->next; + mb->next=0; + sgIP_memblock_free(mb); + } + if(!(rec->incoming_queue)) rec->incoming_queue_end=0; + + SGIP_INTR_UNPROTECT(); + return buf_start; +} + +int sgIP_UDP_SendTo(sgIP_Record_UDP * rec, const char * buf, int buflength, int flags, unsigned long dest_ip, int dest_port) { + return sgIP_UDP_SendPacket(rec,buf,buflength,dest_ip,dest_port); +} + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_UDP.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_UDP.h new file mode 100644 index 0000000000..496cd0ada7 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_UDP.h @@ -0,0 +1,81 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + + +#ifndef SGIP_UDP_H +#define SGIP_UDP_H + +#include "sgIP_Config.h" +#include "sgIP_memblock.h" + + +enum SGIP_UDP_STATE { + SGIP_UDP_STATE_UNBOUND, // newly allocated + SGIP_UDP_STATE_BOUND, // got a source address/port + SGIP_UDP_STATE_UNUSED, // no longer in use. +}; + + +typedef struct SGIP_HEADER_UDP { + unsigned short srcport,destport; + unsigned short length,checksum; +} sgIP_Header_UDP; + +typedef struct SGIP_RECORD_UDP { + struct SGIP_RECORD_UDP * next; + + int state; + unsigned long srcip; + unsigned long destip; + unsigned short srcport,destport; + + sgIP_memblock * incoming_queue; + sgIP_memblock * incoming_queue_end; + +} sgIP_Record_UDP; + +#ifdef __cplusplus +extern "C" { +#endif + + void sgIP_UDP_Init(); + + int sgIP_UDP_CalcChecksum(sgIP_memblock * mb, unsigned long srcip, unsigned long destip, int totallength); + int sgIP_UDP_ReceivePacket(sgIP_memblock * mb, unsigned long srcip, unsigned long destip); + int sgIP_UDP_SendPacket(sgIP_Record_UDP * rec, const char * data, int datalen, unsigned long destip, int destport); + + sgIP_Record_UDP * sgIP_UDP_AllocRecord(); + void sgIP_UDP_FreeRecord(sgIP_Record_UDP * rec); + + int sgIP_UDP_Bind(sgIP_Record_UDP * rec, int srcport, unsigned long srcip); + int sgIP_UDP_RecvFrom(sgIP_Record_UDP * rec, char * destbuf, int buflength, int flags, unsigned long * sender_ip, unsigned short * sender_port); + int sgIP_UDP_SendTo(sgIP_Record_UDP * rec, const char * buf, int buflength, int flags, unsigned long dest_ip, int dest_port); + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_memblock.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_memblock.c new file mode 100644 index 0000000000..474b9f2192 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_memblock.c @@ -0,0 +1,295 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "sgIP_memblock.h" + +#include <stdlib.h> +#include <string.h> + +#ifndef SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL + +#ifndef SGIP_USEDYNAMICMEMORY +sgIP_memblock memblock_pool[SGIP_MEMBLOCK_BASENUM]; +#else +sgIP_memblock * memblock_pool; +#endif + +sgIP_memblock * memblock_poolfree; +int numused, numfree; +void * pool_link; + + +sgIP_memblock * sgIP_memblock_getunused() { + int i; + sgIP_memblock * mb; + SGIP_INTR_PROTECT(); + if(memblock_poolfree) { // we still have free memblocks! + mb=memblock_poolfree; + memblock_poolfree=mb->next; + numfree--; + numused++; + } else { // oh noes, we have no more free memblocks. + mb = 0; // eventually alloc new blocks, but for now just stop. + } + + SGIP_INTR_UNPROTECT(); + return mb; +} +#endif //SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL + +void sgIP_memblock_Init() { +#ifndef SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL + int i; +#ifdef SGIP_USEDYNAMICMEMORY + pool_link = sgIP_malloc(sizeof(sgIP_memblock)*SGIP_MEMBLOCK_BASENUM+4); + ((long *)pool_link)[0]=0; + memblock_pool = (sgIP_memblock *) (((char *)pool_link)+4); +#endif + numused=numfree=0; + memblock_poolfree=0; + for(i=0;i<SGIP_MEMBLOCK_BASENUM;i++) { + memblock_pool[i].totallength=0; + memblock_pool[i].next=memblock_poolfree; + memblock_poolfree=memblock_pool+i; + numfree++; + } +#endif //SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL +} + +#ifdef SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL + +sgIP_memblock * sgIP_memblock_allocHW(int headersize, int packetsize) { + sgIP_memblock * mb; + mb = (sgIP_memblock *) sgIP_malloc(SGIP_MEMBLOCK_HEADERSIZE+SGIP_MAXHWHEADER+packetsize); + if(!mb) return 0; + mb->totallength=headersize+packetsize; + mb->thislength=mb->totallength; + mb->datastart=mb->reserved+SGIP_MAXHWHEADER-headersize; + mb->next=0; + return mb; +} + +#else //SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL + +sgIP_memblock * sgIP_memblock_allocHW(int headersize, int packetsize) { + sgIP_memblock * mb, * tmb, *t; + int totlen; + mb = sgIP_memblock_getunused(); + if(!mb) return 0; + mb->totallength=headersize+packetsize; + mb->datastart=mb->reserved+SGIP_MAXHWHEADER-headersize; + mb->next=0; + mb->thislength=headersize+SGIP_MEMBLOCK_FIRSTINTERNALSIZE; + if(mb->thislength>=mb->totallength) { + mb->thislength = mb->totallength; +// SGIP_DEBUG_MESSAGE(("memblock_alloc: %i free, %i used",numfree,numused)); + return mb; + } else { // need more blocks + totlen=mb->thislength; + tmb=mb; + while(totlen<mb->totallength) { + t=sgIP_memblock_getunused(); + if(!t) { // we're skrewed. + sgIP_memblock_free(mb); + return 0; + } + tmb->next=t; + t->totallength=mb->totallength; + t->datastart=mb->reserved; // no header on blocks after the first. + t->next=0; + t->thislength=SGIP_MEMBLOCK_INTERNALSIZE; + if(t->thislength+totlen>=mb->totallength) { + t->thislength=mb->totallength-totlen; +// SGIP_DEBUG_MESSAGE(("memblock_alloc: %i free, %i used",numfree,numused)); + return mb; + } else { // need YET more blocks. + totlen+=t->thislength; + tmb=t; + } // the cycle contiues. + } + sgIP_memblock_free(mb); // should never get here. + } + return 0; +} +#endif //SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL + +sgIP_memblock * sgIP_memblock_alloc(int packetsize) { + return sgIP_memblock_allocHW(0,packetsize); +} + +#ifdef SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL + +void sgIP_memblock_free(sgIP_memblock * mb) { + sgIP_memblock * f; + + SGIP_INTR_PROTECT(); + while(mb) { + mb->totallength=0; + mb->thislength=0; + f=mb; + mb = mb->next; + + sgIP_free(f); + } + + SGIP_INTR_UNPROTECT(); +} + +#else //SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL + +void sgIP_memblock_free(sgIP_memblock * mb) { + sgIP_memblock * f; + + SGIP_INTR_PROTECT(); + while(mb) { + mb->totallength=0; + mb->thislength=0; + f=mb; + mb = mb->next; + + numfree++; // reinstate memblock into the pool! + numused--; + f->next=memblock_poolfree; + memblock_poolfree=f; + } +// SGIP_DEBUG_MESSAGE(("memblock_free: %i free, %i used",numfree,numused)); + + SGIP_INTR_UNPROTECT(); + +} + +#endif //SGIP_MEMBLOCK_DYNAMIC_MALLOC_ALL + +// positive to expose, negative to hide. +void sgIP_memblock_exposeheader(sgIP_memblock * mb, int change) { + if(mb) { + mb->thislength+=change; + mb->totallength+=change; + mb->datastart-=change; + while(mb->next) { + mb->next->totallength=mb->totallength; + mb=mb->next; + } + } +} +void sgIP_memblock_trimsize(sgIP_memblock * mb, int newsize) { + int lentot; + if(mb) { + mb->totallength=newsize; + lentot=0; + while(mb) { + lentot+=mb->thislength; + if(lentot>newsize) { + mb->thislength-=(lentot-newsize); + if(mb->next) sgIP_memblock_free(mb->next); + mb->next=0; + return; + } else { + mb=mb->next; + } + } + } +} + + +int sgIP_memblock_IPChecksum(sgIP_memblock * mb, int startbyte, int chksum_length) { + int chksum_temp,offset; + // check checksum + chksum_temp=0; + offset=0; + while(mb && startbyte>mb->thislength) { startbyte-=mb->thislength; mb=mb->next; } + if(!mb) return 0; + while(chksum_length) { + while(startbyte+offset+1<mb->thislength && chksum_length>1) { + chksum_temp+= ((unsigned char *)mb->datastart)[startbyte+offset] + (((unsigned char *)mb->datastart)[startbyte+offset+1]<<8); + offset+=2; + chksum_length-=2; + } + chksum_temp= (chksum_temp&0xFFFF) +(chksum_temp>>16); + if(startbyte+offset<mb->thislength && chksum_length>0) { + chksum_temp+= ((unsigned char *)mb->datastart)[startbyte+offset]; + if(chksum_length==1) break; + chksum_length--; + offset=0; + startbyte=0; + mb=mb->next; + if(!mb) break; + if(mb->thislength==0) break; + chksum_temp+= ((unsigned char *)mb->datastart)[startbyte+offset]<<8; + if(chksum_length==1) break; + offset++; + chksum_length--; + } + } + chksum_temp= (chksum_temp&0xFFFF) +(chksum_temp>>16); + chksum_temp= (chksum_temp&0xFFFF) +(chksum_temp>>16); + return chksum_temp; +} +int sgIP_memblock_CopyToLinear(sgIP_memblock * mb, void * dest_buf, int startbyte, int copy_length) { + int copylen,ofs_src, tot_copy; + ofs_src=startbyte; + while(mb && ofs_src>=mb->thislength) { ofs_src-=mb->thislength; mb=mb->next; } + if(!mb) return 0; + if(startbyte+copy_length>mb->totallength) copy_length=mb->totallength-startbyte; + if(copy_length<0) copy_length=0; + tot_copy=0; + while(copy_length>0) { + copylen=copy_length; + if(copylen>mb->thislength-ofs_src) copylen=mb->thislength-ofs_src; + memcpy(((char *)dest_buf)+tot_copy,mb->datastart+ofs_src,copylen); + copy_length-=copylen; + tot_copy+=copylen; + ofs_src=0; + mb=mb->next; + if(!mb) break; + } + return tot_copy; +} +int sgIP_memblock_CopyFromLinear(sgIP_memblock * mb, void * src_buf, int startbyte, int copy_length) { + int copylen,ofs_src, tot_copy; + ofs_src=startbyte; + while(mb && ofs_src>=mb->thislength) { ofs_src-=mb->thislength; mb=mb->next; } + if(!mb) return 0; + if(startbyte+copy_length>mb->totallength) copy_length=mb->totallength-startbyte; + if(copy_length<0) copy_length=0; + tot_copy=0; + while(copy_length>0) { + copylen=copy_length; + if(copylen>mb->thislength-ofs_src) copylen=mb->thislength-ofs_src; + memcpy(mb->datastart+ofs_src,((char *)src_buf)+tot_copy,copylen); + copy_length-=copylen; + tot_copy+=copylen; + ofs_src=0; + mb=mb->next; + if(!mb) break; + } + return tot_copy; + +} +int sgIP_memblock_CopyBlock(sgIP_memblock * mb_src, sgIP_memblock * mb_dest, int start_src, int start_dest, int copy_length) { + + return 0; +} + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_memblock.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_memblock.h new file mode 100644 index 0000000000..3b262932a8 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_memblock.h @@ -0,0 +1,65 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + + +#ifndef SGIP_MEMBLOCK_H +#define SGIP_MEMBLOCK_H + +#include "sgIP_Config.h" + + +typedef struct SGIP_MEMBLOCK { + int totallength; + int thislength; + struct SGIP_MEMBLOCK * next; + char * datastart; + char reserved[SGIP_MEMBLOCK_DATASIZE-16]; // assume the other 4 values are 16 bytes total in length. +} sgIP_memblock; + +#define SGIP_MEMBLOCK_HEADERSIZE 16 +#define SGIP_MEMBLOCK_INTERNALSIZE (SGIP_MEMBLOCK_DATASIZE-16) +#define SGIP_MEMBLOCK_FIRSTINTERNALSIZE (SGIP_MEMBLOCK_DATASIZE-16-SGIP_MAXHWHEADER) + +#ifdef __cplusplus +extern "C" { +#endif + + extern void sgIP_memblock_Init(); + extern sgIP_memblock * sgIP_memblock_alloc(int packetsize); + extern sgIP_memblock * sgIP_memblock_allocHW(int headersize, int packetsize); + extern void sgIP_memblock_free(sgIP_memblock * mb); + extern void sgIP_memblock_exposeheader(sgIP_memblock * mb, int change); + extern void sgIP_memblock_trimsize(sgIP_memblock * mb, int newsize); + + extern int sgIP_memblock_IPChecksum(sgIP_memblock * mb, int startbyte, int chksum_length); + extern int sgIP_memblock_CopyToLinear(sgIP_memblock * mb, void * dest_buf, int startbyte, int copy_length); + extern int sgIP_memblock_CopyFromLinear(sgIP_memblock * mb, void * src_buf, int startbyte, int copy_length); + extern int sgIP_memblock_CopyBlock(sgIP_memblock * mb_src, sgIP_memblock * mb_dest, int start_src, int start_dest, int copy_length); +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_sockets.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_sockets.c new file mode 100644 index 0000000000..026dbd2d25 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_sockets.c @@ -0,0 +1,520 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "sgIP_sockets.h" +#include "sgIP_TCP.h" +#include "sgIP_UDP.h" +#include "sgIP_ICMP.h" +#include "sgIP_DNS.h" + + +sgIP_socket_data socketlist[SGIP_SOCKET_MAXSOCKETS]; +extern unsigned long sgIP_timems; + + +void sgIP_sockets_Init() { + int i; + for(i=0;i<SGIP_SOCKET_MAXSOCKETS;i++) { + socketlist[i].conn_ptr=0; + socketlist[i].flags = 0; + } +} + + // spawn/kill socket for internal use ONLY. +int spawn_socket(int flags) { + int s; + SGIP_INTR_PROTECT(); + for(s=0;s<SGIP_SOCKET_MAXSOCKETS;s++) if(!(socketlist[s].flags&SGIP_SOCKET_FLAG_ACTIVE)) break; + if(s==SGIP_SOCKET_MAXSOCKETS) { + SGIP_INTR_UNPROTECT(); + return SGIP_ERROR(ENOMEM); + } + socketlist[s].flags=SGIP_SOCKET_FLAG_ACTIVE | flags; + socketlist[s].conn_ptr=0; + SGIP_INTR_UNPROTECT(); + return s+1; +} +int kill_socket(int s) { + if(s<1 || s>SGIP_SOCKET_MAXSOCKETS) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + s--; + socketlist[s].conn_ptr=0; + socketlist[s].flags=0; + SGIP_INTR_UNPROTECT(); + return 0; +} + +int socket(int domain, int type, int protocol) { + int s; + if(domain!=AF_INET) return SGIP_ERROR(EINVAL); + if(protocol!=0) return SGIP_ERROR(EINVAL); + if(type!=SOCK_DGRAM && type!=SOCK_STREAM) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + for(s=0;s<SGIP_SOCKET_MAXSOCKETS;s++) if(!(socketlist[s].flags&SGIP_SOCKET_FLAG_ACTIVE)) break; + if(s==SGIP_SOCKET_MAXSOCKETS) { + SGIP_INTR_UNPROTECT(); + return SGIP_ERROR(ENOMEM); + } + if(type==SOCK_STREAM) { + socketlist[s].flags=SGIP_SOCKET_FLAG_ACTIVE | SGIP_SOCKET_FLAG_TYPE_TCP; + socketlist[s].conn_ptr=sgIP_TCP_AllocRecord(); + } else if(type==SOCK_DGRAM) { + socketlist[s].flags=SGIP_SOCKET_FLAG_ACTIVE | SGIP_SOCKET_FLAG_TYPE_UDP; + socketlist[s].conn_ptr=sgIP_UDP_AllocRecord(); + } else { + SGIP_INTR_UNPROTECT(); + return SGIP_ERROR(EINVAL); + } +#ifdef SGIP_SOCKET_DEFAULT_NONBLOCK + socketlist[s].flags|=SGIP_SOCKET_FLAG_NONBLOCKING; +#endif + SGIP_INTR_UNPROTECT(); + return s+1; +} + + +int closesocket(int socket) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + socket--; + if(!(socketlist[socket].flags&SGIP_SOCKET_FLAG_ACTIVE)) { SGIP_INTR_UNPROTECT(); return 0; } + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + sgIP_TCP_FreeRecord((sgIP_Record_TCP *)socketlist[socket].conn_ptr); + } else if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_UDP) { + sgIP_UDP_FreeRecord((sgIP_Record_UDP *)socketlist[socket].conn_ptr); + } + socketlist[socket].conn_ptr=0; + socketlist[socket].flags=0; + SGIP_INTR_UNPROTECT(); + return 0; +} + +int bind(int socket, const struct sockaddr * addr, int addr_len) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return SGIP_ERROR(EINVAL); + if(addr_len!=sizeof(struct sockaddr_in)) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + int retval=SGIP_ERROR(EINVAL); + socket--; + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + retval=sgIP_TCP_Bind((sgIP_Record_TCP *)socketlist[socket].conn_ptr,((struct sockaddr_in *)addr)->sin_port,((struct sockaddr_in *)addr)->sin_addr.s_addr); + } else if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_UDP) { + retval=sgIP_UDP_Bind((sgIP_Record_UDP *)socketlist[socket].conn_ptr,((struct sockaddr_in *)addr)->sin_port,((struct sockaddr_in *)addr)->sin_addr.s_addr); + } + SGIP_INTR_UNPROTECT(); + return retval; +} +int connect(int socket, const struct sockaddr * addr, int addr_len) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return SGIP_ERROR(EINVAL); + if(addr_len!=sizeof(struct sockaddr_in)) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + int i; + int retval=SGIP_ERROR(EINVAL); + socket--; + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + retval=sgIP_TCP_Connect((sgIP_Record_TCP *)socketlist[socket].conn_ptr,((struct sockaddr_in *)addr)->sin_addr.s_addr,((struct sockaddr_in *)addr)->sin_port); + if(retval==0) { + do { + i=((sgIP_Record_TCP *)socketlist[socket].conn_ptr)->tcpstate; + if(i==SGIP_TCP_STATE_ESTABLISHED || i==SGIP_TCP_STATE_CLOSE_WAIT) {retval=0; break;} + if(i==SGIP_TCP_STATE_CLOSED || i==SGIP_TCP_STATE_UNUSED || i==SGIP_TCP_STATE_LISTEN || i==SGIP_TCP_STATE_NODATA) + { retval=SGIP_ERROR(((sgIP_Record_TCP *)socketlist[socket].conn_ptr)->errorcode); break; } + if(socketlist[socket].flags&SGIP_SOCKET_FLAG_NONBLOCKING) break; + SGIP_INTR_UNPROTECT(); + SGIP_WAITEVENT(); + SGIP_INTR_REPROTECT(); + } while(1); + } + } + SGIP_INTR_UNPROTECT(); + return retval; +} +int send(int socket, const void * data, int sendlength, int flags) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return -1; + SGIP_INTR_PROTECT(); + int retval=SGIP_ERROR(EINVAL); + socket--; + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + do { + retval=sgIP_TCP_Send((sgIP_Record_TCP *)socketlist[socket].conn_ptr,data,sendlength,flags); + if(retval!=-1) break; + if(errno!=EWOULDBLOCK) break; + if(socketlist[socket].flags&SGIP_SOCKET_FLAG_NONBLOCKING) break; + SGIP_INTR_UNPROTECT(); + SGIP_WAITEVENT(); + SGIP_INTR_REPROTECT(); + } while(1); + } + SGIP_INTR_UNPROTECT(); + return retval; +} +int recv(int socket, void * data, int recvlength, int flags) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return -1; + SGIP_INTR_PROTECT(); + int retval=SGIP_ERROR(EINVAL); + socket--; + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + do { + retval=sgIP_TCP_Recv((sgIP_Record_TCP *)socketlist[socket].conn_ptr,data,recvlength,flags); + if(retval!=-1) break; + if(errno!=EWOULDBLOCK) break; + if(socketlist[socket].flags&SGIP_SOCKET_FLAG_NONBLOCKING) break; + SGIP_INTR_UNPROTECT(); + SGIP_WAITEVENT(); + SGIP_INTR_REPROTECT(); + } while(1); + } + SGIP_INTR_UNPROTECT(); + return retval; +} +int sendto(int socket, const void * data, int sendlength, int flags, const struct sockaddr * addr, int addr_len) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return -1; + if(!addr) return -1; + SGIP_INTR_PROTECT(); + int retval=SGIP_ERROR(EINVAL); + socket--; + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + } else if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_UDP) { + retval=sgIP_UDP_SendTo((sgIP_Record_UDP *)socketlist[socket].conn_ptr,data,sendlength,flags,((struct sockaddr_in *)addr)->sin_addr.s_addr,((struct sockaddr_in *)addr)->sin_port); + } + SGIP_INTR_UNPROTECT(); + return retval; +} +int recvfrom(int socket, void * data, int recvlength, int flags, struct sockaddr * addr, int * addr_len) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return -1; + if(!addr) return -1; + SGIP_INTR_PROTECT(); + int retval=SGIP_ERROR(EINVAL); + socket--; + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + } else if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_UDP) { + do { + retval=sgIP_UDP_RecvFrom((sgIP_Record_UDP *)socketlist[socket].conn_ptr,data,recvlength,flags,&(((struct sockaddr_in *)addr)->sin_addr.s_addr),&(((struct sockaddr_in *)addr)->sin_port)); + if(retval!=-1) break; + if(errno!=EWOULDBLOCK) break; + if(socketlist[socket].flags&SGIP_SOCKET_FLAG_NONBLOCKING) break; + SGIP_INTR_UNPROTECT(); // give interrupts a chance to occur. + SGIP_WAITEVENT(); // don't just try again immediately + SGIP_INTR_REPROTECT(); + } while(1); + *addr_len = sizeof(struct sockaddr_in); + } + SGIP_INTR_UNPROTECT(); + return retval; +} +int listen(int socket, int max_connections) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + int retval=SGIP_ERROR(EINVAL); + socket--; + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + retval=sgIP_TCP_Listen((sgIP_Record_TCP *)socketlist[socket].conn_ptr,max_connections); + } + SGIP_INTR_UNPROTECT(); + return retval; +} +int accept(int socket, struct sockaddr * addr, int * addr_len) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS || !addr || !addr_len) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + sgIP_Record_TCP * ret; + int retval,s; + retval=SGIP_ERROR0(EINVAL); + ret=0; + socket--; + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + s=spawn_socket((socketlist[socket].flags&SGIP_SOCKET_FLAG_NONBLOCKING) | SGIP_SOCKET_FLAG_TYPE_TCP); + if(s>0) { + do { + ret=sgIP_TCP_Accept((sgIP_Record_TCP *)socketlist[socket].conn_ptr); + if(ret!=0) break; + if(errno!=EWOULDBLOCK) break; + if(socketlist[socket].flags&SGIP_SOCKET_FLAG_NONBLOCKING) break; + SGIP_INTR_UNPROTECT(); // give interrupts a chance to occur. + SGIP_WAITEVENT(); // don't just try again immediately + SGIP_INTR_REPROTECT(); + } while(1); + } + if(ret==0) { + kill_socket(s); + retval=-1; + } else { + *addr_len=sizeof(struct sockaddr_in); + ((struct sockaddr_in *)addr)->sin_family=AF_INET; + ((struct sockaddr_in *)addr)->sin_port=ret->destport; + ((struct sockaddr_in *)addr)->sin_addr.s_addr=ret->destip; + socketlist[s-1].conn_ptr=ret; + retval=s; + } + } + SGIP_INTR_UNPROTECT(); + return retval; +} +int shutdown(int socket, int shutdown_type) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return SGIP_ERROR(EINVAL); + SGIP_INTR_PROTECT(); + int retval=SGIP_ERROR(EINVAL); + socket--; + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + retval=sgIP_TCP_Close((sgIP_Record_TCP *)socketlist[socket].conn_ptr); + } + SGIP_INTR_UNPROTECT(); + return retval; +} + +int ioctl(int socket, long cmd, void * arg) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return SGIP_ERROR(EBADF); + socket--; + int retval,i; + retval=0; + SGIP_INTR_PROTECT(); + switch(cmd) { + case FIONBIO: + if(!arg){ + retval=SGIP_ERROR(EINVAL); + } else { + socketlist[socket].flags &= ~SGIP_SOCKET_FLAG_NONBLOCKING; + if(*((unsigned long *)arg)) socketlist[socket].flags |= SGIP_SOCKET_FLAG_NONBLOCKING; + } + break; + case FIONREAD: + if(!arg) { + retval=SGIP_ERROR(EINVAL); + } else { + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + i=((sgIP_Record_TCP *)socketlist[socket].conn_ptr)->buf_rx_out-((sgIP_Record_TCP *)socketlist[socket].conn_ptr)->buf_rx_in; + if(i<0) i+=SGIP_TCP_RECEIVEBUFFERLENGTH; + *((int *)arg)=i; + } else { + retval=SGIP_ERROR(EINVAL); + } + } + } + SGIP_INTR_UNPROTECT(); + return retval; +} + +int setsockopt(int socket, int level, int option_name, const void * data, int data_len) { + return 0; +} +int getsockopt(int socket, int level, int option_name, void * data, int * data_len) { + return 0; +} + +int getpeername(int socket, struct sockaddr *addr, int * addr_len) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return SGIP_ERROR(EBADF); + if(!addr || !addr_len) return SGIP_ERROR(EFAULT); + if(*addr_len<sizeof(struct sockaddr_in)) return SGIP_ERROR(EFAULT); + socket--; + SGIP_INTR_PROTECT(); + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + { + struct sockaddr_in * sain = (struct sockaddr_in *)addr; + sgIP_Record_TCP * rec = (sgIP_Record_TCP *)socketlist[socket].conn_ptr; + if(rec->tcpstate!=SGIP_TCP_STATE_ESTABLISHED) { + SGIP_INTR_UNPROTECT(); + return SGIP_ERROR(ENOTCONN); + } else { + sain->sin_addr.s_addr=rec->destip; + sain->sin_family=AF_INET; + sain->sin_port=rec->destport; + *addr_len=sizeof(struct sockaddr_in); + } + } + } else { + SGIP_INTR_UNPROTECT(); + return SGIP_ERROR(EOPNOTSUPP); + } + SGIP_INTR_UNPROTECT(); + return 0; +} +int getsockname(int socket, struct sockaddr *addr, int * addr_len) { + if(socket<1 || socket>SGIP_SOCKET_MAXSOCKETS) return SGIP_ERROR(EBADF); + if(!addr || !addr_len) return SGIP_ERROR(EFAULT); + if(*addr_len<sizeof(struct sockaddr_in)) return SGIP_ERROR(EFAULT); + socket--; + SGIP_INTR_PROTECT(); + if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + { + struct sockaddr_in * sain = (struct sockaddr_in *)addr; + sgIP_Record_TCP * rec = (sgIP_Record_TCP *)socketlist[socket].conn_ptr; + if(rec->tcpstate==SGIP_TCP_STATE_UNUSED || rec->tcpstate==SGIP_TCP_STATE_CLOSED) { + SGIP_INTR_UNPROTECT(); + return SGIP_ERROR(EINVAL); + } else { + sain->sin_addr.s_addr=rec->srcip; + sain->sin_family=AF_INET; + sain->sin_port=rec->srcport; + *addr_len=sizeof(struct sockaddr_in); + } + } + } else if((socketlist[socket].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_UDP) { + { + struct sockaddr_in * sain = (struct sockaddr_in *)addr; + sgIP_Record_UDP * rec = (sgIP_Record_UDP *)socketlist[socket].conn_ptr; + if(rec->state==SGIP_UDP_STATE_UNUSED) { + SGIP_INTR_UNPROTECT(); + return SGIP_ERROR(EINVAL); + } else { + sain->sin_addr.s_addr=rec->srcip; + sain->sin_family=AF_INET; + sain->sin_port=rec->srcport; + *addr_len=sizeof(struct sockaddr_in); + } + } + } else { + SGIP_INTR_UNPROTECT(); + return SGIP_ERROR(EOPNOTSUPP); + } + SGIP_INTR_UNPROTECT(); + return 0; +} + + +struct hostent * gethostbyname(const char * name) { + return (struct hostent *)sgIP_DNS_gethostbyname(name); +}; + + +extern int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout) { + // 31 days = 2678400 seconds + unsigned long timeout_ms, lasttime, temp; + sgIP_Record_TCP * rec; + sgIP_Record_UDP * urec; + lasttime=sgIP_timems; + if(!timeout) timeout_ms=2678400000UL; + else { + if(timeout->tv_sec>=2678400) { + timeout_ms=2678400000UL; + } else { + timeout_ms=timeout->tv_sec*1000 + (timeout->tv_usec/1000); + } + } + SGIP_INTR_PROTECT(); + nfds=SGIP_SOCKET_MAXSOCKETS; + + int i,j,retval; + while(timeout_ms>0) { // check all fd sets + // readfds + if(readfds) { + for(i=0;i<nfds;i++) { + if(FD_ISSET(i+1,readfds)) { + if((socketlist[i].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + rec = (sgIP_Record_TCP *)socketlist[i].conn_ptr; + if(rec->buf_rx_in!=rec->buf_rx_out) { timeout_ms=0; break; } + } else if((socketlist[i].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_UDP) { + urec = (sgIP_Record_UDP *)socketlist[i].conn_ptr; + if(urec->incoming_queue) { timeout_ms=0; break; } + } + } + } + if(timeout_ms==0) break; + } + if(writefds) { + // writefds + for(i=0;i<nfds;i++) { + if(FD_ISSET(i+1,writefds)) { + if((socketlist[i].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + rec = (sgIP_Record_TCP *)socketlist[i].conn_ptr; + j=rec->buf_tx_in-1; + if(j<0) j=SGIP_TCP_TRANSMITBUFFERLENGTH-1; + if(rec->buf_tx_in!=j) { timeout_ms=0; break; } + } + } + } + if(timeout_ms==0) break; + } + // errorfds + // ignore errorfds for now. + + temp=sgIP_timems-lasttime; + if(timeout_ms<temp) timeout_ms=0; else timeout_ms -= temp; + lasttime+=temp; + SGIP_INTR_UNPROTECT(); // give interrupts a chance to occur. + SGIP_WAITEVENT(); // don't just try again immediately + SGIP_INTR_REPROTECT(); + } + // markup fd sets and return + // readfds + retval=0; + if(readfds) { + for(i=0;i<nfds;i++) { + if(FD_ISSET(i+1,readfds)) { + if((socketlist[i].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + rec = (sgIP_Record_TCP *)socketlist[i].conn_ptr; + if(rec->buf_rx_in==rec->buf_rx_out) { FD_CLR(i+1,readfds);} else retval++; + } else if((socketlist[i].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_UDP) { + urec = (sgIP_Record_UDP *)socketlist[i].conn_ptr; + if(!urec->incoming_queue) { FD_CLR(i+1,readfds);} else retval++; + } + } + } + } + + // writefds + if(writefds) { + for(i=0;i<nfds;i++) { + if(FD_ISSET(i+1,writefds)) { + if((socketlist[i].flags&SGIP_SOCKET_FLAG_TYPEMASK)==SGIP_SOCKET_FLAG_TYPE_TCP) { + rec = (sgIP_Record_TCP *)socketlist[i].conn_ptr; + j=rec->buf_tx_in-1; + if(j<0) j=SGIP_TCP_TRANSMITBUFFERLENGTH-1; + if(rec->buf_tx_in==j) { FD_CLR(i+1,writefds); } else retval++; + } + } + } + } + + if(errorfds) { FD_ZERO(errorfds); } + + SGIP_INTR_UNPROTECT(); + return retval; +} + + +/* +extern void FD_CLR(int fd, fd_set * fdset) { + if(fd<1 || fd>FD_SETSIZE || !fdset) return; + fd--; + fdset->fdbits[fd>>5] &= ~(1<<(fd&31)); +} +extern int FD_ISSET(int fd, fd_set * fdset) { + if(fd<1 || fd>FD_SETSIZE || !fdset) return 0; + fd--; + return (fdset->fdbits[fd>>5] & 1<<(fd&31))?1:0; +} +extern void FD_SET(int fd, fd_set * fdset) { + if(fd<1 || fd>FD_SETSIZE || !fdset) return; + fd--; + fdset->fdbits[fd>>5] |= 1<<(fd&31); +} +extern void FD_ZERO(fd_set * fdset) { + int i; + if(!fdset) return; + for(i=0;i<(FD_SETSIZE+31)/32;i++) { + fdset->fdbits[i]=0; + } +} +*/ + + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_sockets.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_sockets.h new file mode 100644 index 0000000000..8ec6055b44 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_sockets.h @@ -0,0 +1,83 @@ +// DSWifi Project - sgIP Internet Protocol Stack Implementation +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef SGIP_SOCKETS_H +#define SGIP_SOCKETS_H + +#include "sgIP_Config.h" +#include "sys/socket.h" +#include "netinet/in.h" +#include "netdb.h" + +#define SGIP_SOCKET_FLAG_ACTIVE 0x8000 +#define SGIP_SOCKET_FLAG_NONBLOCKING 0x4000 +#define SGIP_SOCKET_FLAG_TYPEMASK 0x0001 +#define SGIP_SOCKET_FLAG_TYPE_TCP 0x0001 +#define SGIP_SOCKET_FLAG_TYPE_UDP 0x0000 + +typedef struct SGIP_SOCKET_DATA { + unsigned int flags; + void * conn_ptr; +} sgIP_socket_data; + +#ifdef __cplusplus +extern "C" { +#endif + + extern void sgIP_sockets_Init(); + + // sys/socket.h + extern int socket(int domain, int type, int protocol); + extern int bind(int socket, const struct sockaddr * addr, int addr_len); + extern int connect(int socket, const struct sockaddr * addr, int addr_len); + extern int send(int socket, const void * data, int sendlength, int flags); + extern int recv(int socket, void * data, int recvlength, int flags); + extern int sendto(int socket, const void * data, int sendlength, int flags, const struct sockaddr * addr, int addr_len); + extern int recvfrom(int socket, void * data, int recvlength, int flags, struct sockaddr * addr, int * addr_len); + extern int listen(int socket, int max_connections); + extern int accept(int socket, struct sockaddr * addr, int * addr_len); + extern int shutdown(int socket, int shutdown_type); + extern int closesocket(int socket); + + extern int ioctl(int socket, long cmd, void * arg); + + extern int setsockopt(int socket, int level, int option_name, const void * data, int data_len); + extern int getsockopt(int socket, int level, int option_name, void * data, int * data_len); + + extern int getpeername(int socket, struct sockaddr *addr, int * addr_len); + extern int getsockname(int socket, struct sockaddr *addr, int * addr_len); + + // sys/time.h (actually intersects partly with libnds, so I'm letting libnds handle fd_set for the time being) + extern int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout); + + // arpa/inet.h + extern unsigned long inet_addr(const char *cp); + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/wifi_arm9.c b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/wifi_arm9.c new file mode 100644 index 0000000000..4fc5de963e --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/wifi_arm9.c @@ -0,0 +1,995 @@ +// DS Wifi interface code +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +// wifi_arm9.c - arm9 wifi support code +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + + +#include <nds.h> +#include "dsregs.h" + +#include "wifi_arm9.h" +#include <stdarg.h> +#include <stdlib.h> +#include <sys/socket.h> + + + + + + + + + +#ifdef WIFI_USE_TCP_SGIP + +#include "sgIP.h" + + +sgIP_Hub_HWInterface * wifi_hw; + + +int sgIP_DisableInterrupts() { + int a; + a=REG_IME; + REG_IME=0; + return a; +} +void sgIP_RestoreInterrupts(int old_ime) { + REG_IME=old_ime; +} + +void sgIP_IntrWaitEvent() { + // __asm( ".ARM\n swi 0x060000\n" ); + int i,j; + j=0; + for(i=0;i<20000;i++) { + j+=i; + } +} + +void * sgIP_malloc(int size) __attribute__((weak)); +void sgIP_free(void * ptr) __attribute__((weak)); + + + +////////////////////////////////////////////////////////////////////////// +// wifi heap allocator system + +#define WHEAP_RECORD_FLAG_INUSE 0 +#define WHEAP_RECORD_FLAG_UNUSED 1 +#define WHEAP_RECORD_FLAG_FREED 2 + +typedef struct WHEAP_RECORD { + struct WHEAP_RECORD * next; + unsigned short flags, unused; + int size; +} wHeapRecord; + +#ifdef SGIP_DEBUG +#define WHEAP_FILL_START 0xAA +#define WHEAP_FILL_END 0xBB +#define WHEAP_PAD_START 4 +#define WHEAP_PAD_END 4 +#define WHEAP_DO_PAD +#else +#define WHEAP_PAD_START 0 +#define WHEAP_PAD_END 0 +#undef WHEAP_DO_PAD +#endif +#define WHEAP_RECORD_SIZE (sizeof(wHeapRecord)) +#define WHEAP_PAD_SIZE ((WHEAP_PAD_START)+(WHEAP_PAD_END)) +#define WHEAP_SIZE_CUTOFF ((WHEAP_RECORD_SIZE)+64) + + +int wHeapsize; +wHeapRecord * wHeapStart; // start of heap +wHeapRecord * wHeapFirst; // first free block +void wHeapAllocInit(int size) { + wHeapStart=(wHeapRecord *)malloc(size); + wHeapFirst=wHeapStart; + wHeapStart->flags=WHEAP_RECORD_FLAG_UNUSED; + wHeapStart->next=0; + wHeapStart->size=size-sizeof(wHeapRecord); +} + + +void * wHeapAlloc(int size) { + wHeapRecord * rec = wHeapFirst; + void * voidptr; + int n; + size=(size+3)&(~3); + if(size==0) size=4; + size+=WHEAP_PAD_SIZE; + if(!rec) { SGIP_DEBUG_MESSAGE(("wHeapAlloc: heap full!")); return 0; } // should not happen given normal use. + while(rec->size<size) { + if(!rec->next) { SGIP_DEBUG_MESSAGE(("wHeapAlloc: heap too full!")); return 0; } // cannot alloc + if(rec->next->flags!=WHEAP_RECORD_FLAG_INUSE) { // try to merge with next one + rec->size+=rec->next->size+WHEAP_RECORD_SIZE; + rec->next=rec->next->next; + } else { // skip ahead to more friendly waters + rec=rec->next; + while(rec->next) { + if(rec->flags!=WHEAP_RECORD_FLAG_INUSE) break; + rec=rec->next; + } + if(rec->flags==WHEAP_RECORD_FLAG_INUSE) { SGIP_DEBUG_MESSAGE(("wHeapAlloc: heap too full!")); return 0; } // no empty slots :( + } + } + rec->flags=WHEAP_RECORD_FLAG_INUSE; + n=rec->size-size; + voidptr = ((char *)rec)+WHEAP_RECORD_SIZE+WHEAP_PAD_START; + if(n<WHEAP_SIZE_CUTOFF) { // pad to include unused portion + rec->unused=n; + } else { // chop block into 2 + wHeapRecord * rec2; + rec2=(wHeapRecord *)(((char *)rec)+WHEAP_RECORD_SIZE+size); + rec2->flags=WHEAP_RECORD_FLAG_UNUSED; + rec2->size=rec->size-size-WHEAP_RECORD_SIZE; + rec->size=size; + rec2->next=rec->next; + rec->next=rec2; + rec->unused=0; + } + if(rec==wHeapFirst) { + while(wHeapFirst->next && wHeapFirst->flags==WHEAP_RECORD_FLAG_INUSE) wHeapFirst=wHeapFirst->next; + if(wHeapFirst->flags==WHEAP_RECORD_FLAG_INUSE) wHeapFirst=0; + } +#ifdef WHEAP_DO_PAD + { + int i; + for(i=0;i<WHEAP_PAD_START;i++) { + (((unsigned char *)rec)+WHEAP_RECORD_SIZE)[i]=WHEAP_FILL_START; + } + for(i=0;i<WHEAP_PAD_END;i++) { + (((unsigned char *)rec)+WHEAP_RECORD_SIZE+size-WHEAP_PAD_END)[i]=WHEAP_FILL_END; + } + } +#endif + return voidptr; +} + +void wHeapFree(void * data) { + wHeapRecord * rec = (wHeapRecord *)(((char *)data)-WHEAP_RECORD_SIZE-WHEAP_PAD_START); +#ifdef WHEAP_DO_PAD + { + int size=rec->size-rec->unused; + int i; + for(i=0;i<WHEAP_PAD_START;i++) { + if((((unsigned char *)rec)+WHEAP_RECORD_SIZE)[i]!=WHEAP_FILL_START) break; + } + if(i!=WHEAP_PAD_START) { // note heap error + SGIP_DEBUG_MESSAGE(("wHeapFree: Corruption found before allocated data! 0x%X",data)); + } + for(i=0;i<WHEAP_PAD_END;i++) { + if((((unsigned char *)rec)+WHEAP_RECORD_SIZE+size-WHEAP_PAD_END)[i]!=WHEAP_FILL_END) break; + } + if(i!=WHEAP_PAD_END) { // note heap error + SGIP_DEBUG_MESSAGE(("wHeapFree: Corruption found after allocated data! 0x%x",data)); + } + } +#endif + if(rec->flags!=WHEAP_RECORD_FLAG_INUSE) { // note heap error + SGIP_DEBUG_MESSAGE(("wHeapFree: Data already freed! 0x%X",data)); + } + rec->flags=WHEAP_RECORD_FLAG_FREED; + if(rec<wHeapFirst || !wHeapFirst) wHeapFirst=rec; // reposition the "starting" pointer. +} + + +////////////////////////////////////////////////////////////////////////// + + + + + +void * sgIP_malloc(int size) { return wHeapAlloc(size); } +void sgIP_free(void * ptr) { wHeapFree(ptr); } + + +#endif + + + + + +void ethhdr_print(char f, void * d) { + char buffer[33]; + int i; + int t,c; + buffer[0]=f; + buffer[1]=':'; + buffer[14]=' '; + buffer[27]=' '; + buffer[32]=0; + for(i=0;i<6;i++) { + t=((u8 *)d)[i]; + c=t&15; + if(c>9) c+='A'-10; else c+='0'; + buffer[3+i*2]=c; + c=(t>>4)&15; + if(c>9) c+='A'-10; else c+='0'; + buffer[2+i*2]=c; + + t=((u8 *)d)[i+6]; + c=t&15; + if(c>9) c+='A'-10; else c+='0'; + buffer[16+i*2]=c; + c=(t>>4)&15; + if(c>9) c+='A'-10; else c+='0'; + buffer[15+i*2]=c; + } + for(i=0;i<2;i++) { + t=((u8 *)d)[i+12]; + c=t&15; + if(c>9) c+='A'-10; else c+='0'; + buffer[29+i*2]=c; + c=(t>>4)&15; + if(c>9) c+='A'-10; else c+='0'; + buffer[28+i*2]=c; + } + SGIP_DEBUG_MESSAGE((buffer)); +} + + + + +Wifi_MainStruct Wifi_Data_Struct; + +volatile Wifi_MainStruct * WifiData = 0; + +WifiPacketHandler packethandler = 0; +WifiSyncHandler synchandler = 0; + +void erasemem(void * mem, int length) { + int i; + char * m = (char *)mem; + for(i=0;i<length;i++) + m[i]=0; +} + +void Wifi_CopyMacAddr(volatile void * dest, volatile void * src) { + ((u16 *)dest)[0]=((u16 *)src)[0]; + ((u16 *)dest)[1]=((u16 *)src)[1]; + ((u16 *)dest)[2]=((u16 *)src)[2]; +} + +int Wifi_CmpMacAddr(volatile void * mac1,volatile void * mac2) { + return (((u16 *)mac1)[0]==((u16 *)mac2)[0]) && (((u16 *)mac1)[1]==((u16 *)mac2)[1]) && (((u16 *)mac1)[2]==((u16 *)mac2)[2]); +} + + + +u32 Wifi_TxBufferWordsAvailable() { + s32 size=WifiData->txbufIn-WifiData->txbufOut-1; + if(size<0) size += WIFI_TXBUFFER_SIZE/2; + return size; +} +void Wifi_TxBufferWrite(s32 start, s32 len, u16 * data) { + int writelen; + while(len>0) { + writelen=len; + if(writelen>(WIFI_TXBUFFER_SIZE/2)-start) writelen=(WIFI_TXBUFFER_SIZE/2)-start; + len-=writelen; + while(writelen) { + WifiData->txbufData[start++]=*(data++); + writelen--; + } + start=0; + } +} + +int Wifi_RxRawReadPacket(s32 packetID, s32 readlength, u16 * data) { + int readlen,read_data; + readlength= (readlength+1)/2; + read_data=0; + while(readlength>0) { + readlen=readlength; + if(readlen>(WIFI_RXBUFFER_SIZE/2)-packetID) readlen=(WIFI_RXBUFFER_SIZE/2)-packetID; + readlength-=readlen; + read_data+=readlen; + while(readlen>0) { + *(data++) = WifiData->rxbufData[packetID++]; + readlen--; + } + packetID=0; + } + return read_data; +} + +u16 Wifi_RxReadOffset(s32 base, s32 offset) { + base+=offset; + if(base>=(WIFI_RXBUFFER_SIZE/2)) base -= (WIFI_RXBUFFER_SIZE/2); + return WifiData->rxbufData[base]; +} + +// datalen = size of packet from beginning of 802.11 header to end, but not including CRC. +int Wifi_RawTxFrame(u16 datalen, u16 rate, u16 * data) { + Wifi_TxHeader txh; + int sizeneeded; + int base; + sizeneeded=((datalen+12+4+3)/4)*2; + if(sizeneeded>Wifi_TxBufferWordsAvailable()) {WifiData->stats[WSTAT_TXQUEUEDREJECTED]++; return -1; } + txh.tx_rate=rate; + txh.tx_length=datalen+4; + base = WifiData->txbufOut; + Wifi_TxBufferWrite(base,6,(u16 *)&txh); + base += 6; + if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; + Wifi_TxBufferWrite(base,((datalen+3)/4)*2,data); + base += ((datalen+3)/4)*2; + if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; + WifiData->txbufOut=base; + WifiData->stats[WSTAT_TXQUEUEDPACKETS]++; + WifiData->stats[WSTAT_TXQUEUEDBYTES]+=sizeneeded; + if(synchandler) synchandler(); + return 0; +} + + +void Wifi_RawSetPacketHandler(WifiPacketHandler wphfunc) { + packethandler=wphfunc; +} +void Wifi_SetSyncHandler(WifiSyncHandler wshfunc) { + synchandler=wshfunc; +} + +void Wifi_DisableWifi() { + WifiData->reqMode=WIFIMODE_DISABLED; + WifiData->reqReqFlags &= ~WFLAG_REQ_APCONNECT; +} +void Wifi_EnableWifi() { + WifiData->reqMode=WIFIMODE_NORMAL; + WifiData->reqReqFlags &= ~WFLAG_REQ_APCONNECT; +} +void Wifi_SetPromiscuousMode(int enable) { + if(enable) WifiData->reqReqFlags |= WFLAG_REQ_PROMISC; + else WifiData->reqReqFlags &= ~WFLAG_REQ_PROMISC; +} + +void Wifi_ScanMode() { + WifiData->reqMode=WIFIMODE_SCAN; + WifiData->reqReqFlags &= ~WFLAG_REQ_APCONNECT; +} +void Wifi_SetChannel(int channel) { + if(channel<1 || channel>13) return; + if(WifiData->reqMode==WIFIMODE_NORMAL || WifiData->reqMode==WIFIMODE_SCAN) { + WifiData->reqChannel=channel; + } +} + + +int Wifi_GetNumAP() { + int i,j; + j=0; + for(i=0;i<WIFI_MAX_AP;i++) if(WifiData->aplist[i].flags&WFLAG_APDATA_ACTIVE) j++; + return j; +} + +int Wifi_GetAPData(int apnum, Wifi_AccessPoint * apdata) { + int i,j; + if(!apdata) return WIFI_RETURN_PARAMERROR; + j=0; + for(i=0;i<WIFI_MAX_AP;i++){ + if(WifiData->aplist[i].flags&WFLAG_APDATA_ACTIVE) { + if(j==apnum) { + while(Spinlock_Acquire(WifiData->aplist[i])!=SPINLOCK_OK); + { + // additionally calculate average RSSI here + WifiData->aplist[i].rssi=0; + for(j=0;j<8;j++) { + WifiData->aplist[i].rssi+=WifiData->aplist[i].rssi_past[j]; + } + WifiData->aplist[i].rssi = WifiData->aplist[i].rssi >> 3; + *apdata = WifiData->aplist[i]; // yay for struct copy! + Spinlock_Release(WifiData->aplist[i]); + return WIFI_RETURN_OK; + } + } + j++; + } + } + return WIFI_RETURN_ERROR; +} + +int Wifi_FindMatchingAP(int numaps, Wifi_AccessPoint * apdata, Wifi_AccessPoint * match_dest) { + int ap_match,i,j,n; + Wifi_AccessPoint ap; + u16 macaddrzero[3] = {0,0,0}; // check for empty mac addr + ap_match=-1; + for(i=0;i<Wifi_GetNumAP();i++){ + Wifi_GetAPData(i,&ap); + for(j=0;j<numaps;j++) { + if(apdata[j].ssid_len>32 || ((signed char)apdata[j].ssid_len)<0) continue; + if(apdata[j].ssid_len>0) { // compare SSIDs + if(apdata[j].ssid_len!=ap.ssid_len) continue; + for(n=0;n<apdata[j].ssid_len;n++) { + if(apdata[j].ssid[n]!=ap.ssid[n]) break; + } + if(n!=apdata[j].ssid_len) continue; + } + if(!Wifi_CmpMacAddr(apdata[j].macaddr,macaddrzero)) { // compare mac addr + if(!Wifi_CmpMacAddr(apdata[j].macaddr,ap.macaddr)) continue; + } + if(apdata[j].channel!=0) { // compare channels + if(apdata[j].channel!=ap.channel) continue; + } + if(j<ap_match || ap_match==-1) { + ap_match=j; + if(match_dest) *match_dest = ap; + } + if(ap_match==0) return ap_match; + } + } + return ap_match; +} + +int wifi_connect_state = 0; // -1==error, 0==searching, 1==associating, 2==dhcp'ing, 3==done, 4=searching wfc data +Wifi_AccessPoint wifi_connect_point; +int Wifi_ConnectAP(Wifi_AccessPoint * apdata, int wepmode, int wepkeyid, u8 * wepkey) { + int i; + Wifi_AccessPoint ap; + wifi_connect_state=-1; + if(!apdata) return -1; + if(((signed char)apdata->ssid_len)<0 || apdata->ssid_len>32) return -1; + + Wifi_DisconnectAP(); + + wifi_connect_state=0; + WifiData->wepmode9=wepmode; // copy data + WifiData->wepkeyid9=wepkeyid; + for(i=0;i<20;i++) { + WifiData->wepkey9[i]=wepkey[i]; + } + + + i=Wifi_FindMatchingAP(1,apdata,&ap); + if(i==0) { + Wifi_CopyMacAddr(WifiData->bssid9, ap.bssid); + Wifi_CopyMacAddr(WifiData->apmac9, ap.bssid); + WifiData->ssid9[0]=ap.ssid_len; + for(i=0;i<32;i++) { + WifiData->ssid9[i+1]=ap.ssid[i]; + } + WifiData->apchannel9=ap.channel; + for(i=0;i<16;i++) WifiData->baserates9[i]=ap.base_rates[i]; + WifiData->reqMode=WIFIMODE_NORMAL; + WifiData->reqReqFlags |= WFLAG_REQ_APCONNECT | WFLAG_REQ_APCOPYVALUES; + wifi_connect_state=1; + } else { + WifiData->reqMode=WIFIMODE_SCAN; + wifi_connect_point = *apdata; + } + return 0; +} +void Wifi_AutoConnect() { + if(!(WifiData->wfc_enable[0]&0x80)) { + wifi_connect_state=ASSOCSTATUS_CANNOTCONNECT; + } else { + wifi_connect_state=4; + WifiData->reqMode=WIFIMODE_SCAN; + } +} + +static +void sgIP_DNS_Record_Localhost() +{ + sgIP_DNS_Record *rec; + const unsigned char * resdata_c = (unsigned char *)&(wifi_hw->ipaddr); + rec = sgIP_DNS_GetUnusedRecord(); + rec->flags=SGIP_DNS_FLAG_ACTIVE | SGIP_DNS_FLAG_BUSY; + + rec->addrlen = 4; + rec->numalias = 1; + gethostname(rec->aliases[0], 256); + gethostname(rec->name, 256); + rec->numaddr = 1; + rec->addrdata[0] = resdata_c[0]; + rec->addrdata[1] = resdata_c[1]; + rec->addrdata[2] = resdata_c[2]; + rec->addrdata[3] = resdata_c[3]; + rec->addrclass = AF_INET; + rec->TTL = 0; + + rec->flags=SGIP_DNS_FLAG_ACTIVE | SGIP_DNS_FLAG_BUSY|SGIP_DNS_FLAG_RESOLVED; +} + +int Wifi_AssocStatus() { + switch(wifi_connect_state) { + case -1: // error + return ASSOCSTATUS_CANNOTCONNECT; + case 0: // searching + { + int i; + Wifi_AccessPoint ap; + i=Wifi_FindMatchingAP(1,&wifi_connect_point,&ap); + if(i==0) { + Wifi_CopyMacAddr(WifiData->bssid9, ap.bssid); + Wifi_CopyMacAddr(WifiData->apmac9, ap.bssid); + WifiData->ssid9[0]=ap.ssid_len; + for(i=0;i<32;i++) { + WifiData->ssid9[i+1]=ap.ssid[i]; + } + WifiData->apchannel9=ap.channel; + for(i=0;i<16;i++) WifiData->baserates9[i]=ap.base_rates[i]; + WifiData->reqMode=WIFIMODE_NORMAL; + WifiData->reqReqFlags |= WFLAG_REQ_APCONNECT | WFLAG_REQ_APCOPYVALUES; + wifi_connect_state=1; + } + } + return ASSOCSTATUS_SEARCHING; + case 1: // associating + switch(WifiData->curMode) { + case WIFIMODE_DISABLED: + case WIFIMODE_NORMAL: + case WIFIMODE_DISASSOCIATE: + return ASSOCSTATUS_DISCONNECTED; + case WIFIMODE_SCAN: + if(WifiData->reqReqFlags&WFLAG_REQ_APCONNECT) return ASSOCSTATUS_AUTHENTICATING; + return ASSOCSTATUS_DISCONNECTED; + case WIFIMODE_ASSOCIATE: + switch(WifiData->authlevel) { + case WIFI_AUTHLEVEL_DISCONNECTED: + return ASSOCSTATUS_AUTHENTICATING; + case WIFI_AUTHLEVEL_AUTHENTICATED: + case WIFI_AUTHLEVEL_DEASSOCIATED: + return ASSOCSTATUS_ASSOCIATING; + case WIFI_AUTHLEVEL_ASSOCIATED: +#ifdef WIFI_USE_TCP_SGIP + if(wifi_hw) { + if(!(wifi_hw->ipaddr)) { + sgIP_DHCP_Start(wifi_hw,wifi_hw->dns[0]==0); + wifi_connect_state=2; + return ASSOCSTATUS_ACQUIRINGDHCP; + } + } + sgIP_ARP_SendGratARP(wifi_hw); +#endif + wifi_connect_state=3; + WifiData->flags9|=WFLAG_ARM9_NETREADY; + return ASSOCSTATUS_ASSOCIATED; + } + break; + case WIFIMODE_ASSOCIATED: +#ifdef WIFI_USE_TCP_SGIP + if(wifi_hw) { + if(!(wifi_hw->ipaddr)) { + sgIP_DHCP_Start(wifi_hw,wifi_hw->dns[0]==0); + wifi_connect_state=2; + return ASSOCSTATUS_ACQUIRINGDHCP; + } + } + sgIP_ARP_SendGratARP(wifi_hw); +#endif + wifi_connect_state=3; + WifiData->flags9|=WFLAG_ARM9_NETREADY; + return ASSOCSTATUS_ASSOCIATED; + case WIFIMODE_CANNOTASSOCIATE: + return ASSOCSTATUS_CANNOTCONNECT; + } + return ASSOCSTATUS_DISCONNECTED; + case 2: // dhcp'ing +#ifdef WIFI_USE_TCP_SGIP + { + int i; + i=sgIP_DHCP_Update(); + if(i!=SGIP_DHCP_STATUS_WORKING) { + switch(i) { + case SGIP_DHCP_STATUS_SUCCESS: + wifi_connect_state=3; + WifiData->flags9|=WFLAG_ARM9_NETREADY; + sgIP_ARP_SendGratARP(wifi_hw); + sgIP_DNS_Record_Localhost(); + return ASSOCSTATUS_ASSOCIATED; + default: + case SGIP_DHCP_STATUS_IDLE: + case SGIP_DHCP_STATUS_FAILED: + Wifi_DisconnectAP(); + wifi_connect_state=-1; + return ASSOCSTATUS_CANNOTCONNECT; + + } + } + } +#else + // should never get here (dhcp state) without sgIP! + Wifi_DisconnectAP(); + wifi_connect_state=-1; + return ASSOCSTATUS_CANNOTCONNECT; +#endif + return ASSOCSTATUS_ACQUIRINGDHCP; + case 3: // connected! + return ASSOCSTATUS_ASSOCIATED; + case 4: // search nintendo WFC data for a suitable AP + { + int n,i; + for(n=0;n<3;n++) if(!(WifiData->wfc_enable[n]&0x80)) break; + Wifi_AccessPoint ap; + n=Wifi_FindMatchingAP(n,WifiData->wfc_ap,&ap); + if(n!=-1) { +#ifdef WIFI_USE_TCP_SGIP + Wifi_SetIP(WifiData->wfc_config[n][0],WifiData->wfc_config[n][1],WifiData->wfc_config[n][2],WifiData->wfc_config[n][3],WifiData->wfc_config[n][4]); +#endif + WifiData->wepmode9=WifiData->wfc_enable[n]&0x03; // copy data + WifiData->wepkeyid9=(WifiData->wfc_enable[n]>>4)&7; + for(i=0;i<16;i++) { + WifiData->wepkey9[i]=WifiData->wfc_wepkey[n][i]; + } + + Wifi_CopyMacAddr(WifiData->bssid9, ap.bssid); + Wifi_CopyMacAddr(WifiData->apmac9, ap.bssid); + WifiData->ssid9[0]=ap.ssid_len; + for(i=0;i<32;i++) { + WifiData->ssid9[i+1]=ap.ssid[i]; + } + WifiData->apchannel9=ap.channel; + for(i=0;i<16;i++) WifiData->baserates9[i]=ap.base_rates[i]; + WifiData->reqMode=WIFIMODE_NORMAL; + WifiData->reqReqFlags |= WFLAG_REQ_APCONNECT | WFLAG_REQ_APCOPYVALUES; + wifi_connect_state=1; + return ASSOCSTATUS_SEARCHING; + + } + + } + return ASSOCSTATUS_SEARCHING; + } + return ASSOCSTATUS_CANNOTCONNECT; +} + + +int Wifi_DisconnectAP() { + WifiData->reqMode=WIFIMODE_NORMAL; + WifiData->reqReqFlags &= ~WFLAG_REQ_APCONNECT; + WifiData->flags9&=~WFLAG_ARM9_NETREADY; + + wifi_connect_state=-1; + return 0; +} + + +#ifdef WIFI_USE_TCP_SGIP + + + +int Wifi_TransmitFunction(sgIP_Hub_HWInterface * hw, sgIP_memblock * mb) { + // convert ethernet frame into wireless frame and output. + // ethernet header: 6byte dest, 6byte src, 2byte protocol_id + // assumes individual pbuf len is >=14 bytes, it's pretty likely ;) - also hopes pbuf len is a multiple of 2 :| + int base,framelen, hdrlen, writelen; + int copytotal, copyexpect; + u16 framehdr[6+12+2]; + sgIP_memblock * t; + framelen=mb->totallength-14+8 + (WifiData->wepmode7?4:0); + + if(!(WifiData->flags9&WFLAG_ARM9_NETUP)) { + SGIP_DEBUG_MESSAGE(("Transmit:err_netdown")); + sgIP_memblock_free(mb); + return 0; //? + } + if(framelen+40>Wifi_TxBufferWordsAvailable()*2) { // error, can't send this much! + SGIP_DEBUG_MESSAGE(("Transmit:err_space")); + sgIP_memblock_free(mb); + return 0; //? + } + + ethhdr_print('T',mb->datastart); + framehdr[0]=0; + framehdr[1]=0; + framehdr[2]=0; + framehdr[3]=0; + framehdr[4]=0; // rate, will be filled in by the arm7. + hdrlen=18; + framehdr[7]=0; + + if(WifiData->curReqFlags&WFLAG_REQ_APADHOC) { // adhoc mode + framehdr[6]=0x0008; + Wifi_CopyMacAddr(framehdr+14,WifiData->bssid7); + Wifi_CopyMacAddr(framehdr+11,WifiData->MacAddr); + Wifi_CopyMacAddr(framehdr+8,((u8 *)mb->datastart)); + } else { + framehdr[6]=0x0108; + Wifi_CopyMacAddr(framehdr+8,WifiData->bssid7); + Wifi_CopyMacAddr(framehdr+11,WifiData->MacAddr); + Wifi_CopyMacAddr(framehdr+14,((u8 *)mb->datastart)); + } + if(WifiData->wepmode7) { framehdr[6] |=0x4000; hdrlen=20; } + framehdr[17] = 0; + framehdr[18] = 0; // wep IV, will be filled in if needed on the arm7 side. + framehdr[19] = 0; + + framehdr[5]=framelen+hdrlen*2-12+4; + copyexpect= ((framelen+hdrlen*2-12+4) +12 -4 +1)/2; + copytotal=0; + + WifiData->stats[WSTAT_TXQUEUEDPACKETS]++; + WifiData->stats[WSTAT_TXQUEUEDBYTES]+=framelen+hdrlen*2; + + base = WifiData->txbufOut; + Wifi_TxBufferWrite(base,hdrlen,framehdr); + base += hdrlen; + copytotal+=hdrlen; + if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; + + // add LLC header + framehdr[0]=0xAAAA; + framehdr[1]=0x0003; + framehdr[2]=0x0000; + framehdr[3]=((u16 *)mb->datastart)[6]; // frame type + + Wifi_TxBufferWrite(base,4,framehdr); + base += 4; + copytotal+=4; + if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; + + t=mb; + writelen=(mb->thislength-14); + if(writelen) { + Wifi_TxBufferWrite(base,(writelen+1)/2,((u16 *)mb->datastart)+7); + base+=(writelen+1)/2; + copytotal+=(writelen+1)/2; + if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; + } + while(mb->next) { + mb=mb->next; + writelen=mb->thislength; + Wifi_TxBufferWrite(base,(writelen+1)/2,((u16 *)mb->datastart)); + base+=(writelen+1)/2; + copytotal+=(writelen+1)/2; + if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; + } + if(WifiData->wepmode7) { // add required extra bytes + base+=2; + copytotal+=2; + if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; + } + WifiData->txbufOut=base; // update fifo out pos, done sending packet. + + sgIP_memblock_free(t); // free packet, as we're the last stop on this chain. + + if(copytotal!=copyexpect) { + SGIP_DEBUG_MESSAGE(("Tx exp:%i que:%i",copyexpect,copytotal)); + } + if(synchandler) synchandler(); + return 0; +} + +int Wifi_Interface_Init(sgIP_Hub_HWInterface * hw) { + hw->MTU=2300; + hw->ipaddr=(192)|(168<<8)|(1<<16)|(151<<24); + hw->snmask=0x00FFFFFF; + hw->gateway=(192)|(168<<8)|(1<<16)|(1<<24); + hw->dns[0]=(192)|(168<<8)|(1<<16)|(1<<24); + hw->hwaddrlen=6; + Wifi_CopyMacAddr(hw->hwaddr,WifiData->MacAddr); + hw->userdata=0; + return 0; +} + +void Wifi_Timer(int num_ms) { + Wifi_Update(); + sgIP_Timer(num_ms); +} + +#endif + +unsigned long Wifi_Init(int initflags) { + erasemem(&Wifi_Data_Struct,sizeof(Wifi_Data_Struct)); + DC_FlushAll(); + WifiData = (Wifi_MainStruct *) (((u32)&Wifi_Data_Struct)| 0x00400000); // should prevent the cache from eating us alive. + +#ifdef WIFI_USE_TCP_SGIP + switch(initflags & WIFIINIT_OPTION_HEAPMASK) { + case WIFIINIT_OPTION_USEHEAP_128: + wHeapAllocInit(128*1024); + break; + case WIFIINIT_OPTION_USEHEAP_64: + wHeapAllocInit(64*1024); + break; + case WIFIINIT_OPTION_USEHEAP_256: + wHeapAllocInit(256*1024); + break; + case WIFIINIT_OPTION_USEHEAP_512: + wHeapAllocInit(512*1024); + break; + case WIFIINIT_OPTION_USECUSTOMALLOC: + break; + } + sgIP_Init(); + +#endif + + WifiData->flags9 = WFLAG_ARM9_ACTIVE | (initflags & WFLAG_ARM9_INITFLAGMASK) ; + return (u32) &Wifi_Data_Struct; +} + +int Wifi_CheckInit() { + if(!WifiData) return 0; + return ((WifiData->flags7 & WFLAG_ARM7_ACTIVE) && (WifiData->flags9 & WFLAG_ARM9_ARM7READY)); +} + + +void Wifi_Update() { + int cnt; + int base, base2, len, fulllen; + if(!WifiData) return; + +#ifdef WIFI_USE_TCP_SGIP + + if(!(WifiData->flags9&WFLAG_ARM9_ARM7READY)) { + if(WifiData->flags7 & WFLAG_ARM7_ACTIVE) { + WifiData->flags9 |=WFLAG_ARM9_ARM7READY; + // add network interface. + wifi_hw = sgIP_Hub_AddHardwareInterface(&Wifi_TransmitFunction,&Wifi_Interface_Init); + sgIP_timems=WifiData->random; //hacky! but it should work just fine :) + } + } + if(WifiData->authlevel!=WIFI_AUTHLEVEL_ASSOCIATED && WifiData->flags9&WFLAG_ARM9_NETUP) { + WifiData->flags9 &= ~(WFLAG_ARM9_NETUP); + } else if(WifiData->authlevel==WIFI_AUTHLEVEL_ASSOCIATED && !(WifiData->flags9&WFLAG_ARM9_NETUP)) { + WifiData->flags9 |= (WFLAG_ARM9_NETUP); + } + +#endif + + // check for received packets, forward to whatever wants them. + cnt=0; + while(WifiData->rxbufIn!=WifiData->rxbufOut) { + base = WifiData->rxbufIn; + len=Wifi_RxReadOffset(base,4); + fulllen=((len+3)&(~3))+12; +#ifdef WIFI_USE_TCP_SGIP + // Do lwIP interfacing for rx here + if((Wifi_RxReadOffset(base,6)&0x01CF)==0x0008) // if it is a non-null data packet coming from the AP (toDS==0) + { + u16 framehdr[6+12+2+4]; + sgIP_memblock * mb; + int hdrlen; + base2=base; + Wifi_RxRawReadPacket(base,22*2,framehdr); + + // ethhdr_print('!',framehdr+8); + if((framehdr[8]==((u16 *)WifiData->MacAddr)[0] && framehdr[9]==((u16 *)WifiData->MacAddr)[1] && framehdr[10]==((u16 *)WifiData->MacAddr)[2]) || + (framehdr[8]==0xFFFF && framehdr[9]==0xFFFF && framehdr[10]==0xFFFF)) { + // destination matches our mac address, or the broadcast address. + //if(framehdr[6]&0x4000) { // wep enabled (when receiving WEP packets, the IV is stripped for us! how nice :| + // base2+=24; hdrlen=28; // base2+=[wifi hdr 12byte]+[802 header hdrlen]+[slip hdr 8byte] + //} else { + base2+=22; hdrlen=24; + //} + // SGIP_DEBUG_MESSAGE(("%04X %04X %04X %04X %04X",Wifi_RxReadOffset(base2-8,0),Wifi_RxReadOffset(base2-7,0),Wifi_RxReadOffset(base2-6,0),Wifi_RxReadOffset(base2-5,0),Wifi_RxReadOffset(base2-4,0))); + // check for LLC/SLIP header... + if(Wifi_RxReadOffset(base2-4,0)==0xAAAA && Wifi_RxReadOffset(base2-4,1)==0x0003 && Wifi_RxReadOffset(base2-4,2)==0) { + mb = sgIP_memblock_allocHW(14,len-8-hdrlen); + if(mb) { + if(base2>=(WIFI_RXBUFFER_SIZE/2)) base2-=(WIFI_RXBUFFER_SIZE/2); + Wifi_RxRawReadPacket(base2,(len-8-hdrlen)&(~1),((u16 *)mb->datastart)+7); + if(len&1) ((u8 *)mb->datastart)[len+14-1-8-hdrlen]=Wifi_RxReadOffset(base2,((len-8-hdrlen)/2))&255; + Wifi_CopyMacAddr(mb->datastart,framehdr+8); // copy dest + if(Wifi_RxReadOffset(base,6)&0x0200) { // from DS set? + Wifi_CopyMacAddr(((u8 *)mb->datastart)+6,framehdr+14); // copy src from adrs3 + } else { + Wifi_CopyMacAddr(((u8 *)mb->datastart)+6,framehdr+11); // copy src from adrs2 + } + ((u16 *)mb->datastart)[6]=framehdr[(hdrlen/2)+6+3]; // assume LLC exists and is 8 bytes. + + ethhdr_print('R',mb->datastart); + + // Done generating recieved data packet... now distribute it. + sgIP_Hub_ReceiveHardwarePacket(wifi_hw,mb); + + } + } + } + } + +#endif + + // check if we have a handler + if(packethandler) { + base2=base+6; + if(base2>=(WIFI_RXBUFFER_SIZE/2)) base2-=(WIFI_RXBUFFER_SIZE/2); + (*packethandler)(base2,len); + } + + base+=fulllen/2; + if(base>=(WIFI_RXBUFFER_SIZE/2)) base-=(WIFI_RXBUFFER_SIZE/2); + WifiData->rxbufIn=base; + + if(cnt++>80) break; + } +} + + +////////////////////////////////////////////////////////////////////////// +// Ip addr get/set functions +#ifdef WIFI_USE_TCP_SGIP + +u32 Wifi_GetIP() { + if(wifi_hw) return wifi_hw->ipaddr; + return 0; +} + +unsigned long Wifi_GetIPInfo(unsigned long * pGateway,unsigned long * pSnmask,unsigned long * pDns1,unsigned long * pDns2) { + if(wifi_hw) { + if(pGateway) *pGateway=wifi_hw->gateway; + if(pSnmask) *pSnmask=wifi_hw->snmask; + if(pDns1) *pDns1=wifi_hw->dns[0]; + if(pDns2) *pDns2=wifi_hw->dns[1]; + return wifi_hw->ipaddr; + } + return 0; +} + + +void Wifi_SetIP(u32 IPaddr, u32 gateway, u32 subnetmask, u32 dns1, u32 dns2) { + if(wifi_hw) { + SGIP_DEBUG_MESSAGE(("SetIP%08X %08X %08X",IPaddr,gateway,subnetmask)); + wifi_hw->ipaddr=IPaddr; + wifi_hw->gateway=gateway; + wifi_hw->snmask=subnetmask; + wifi_hw->dns[0]=dns1; + wifi_hw->dns[1]=dns2; + // reset arp cache... + sgIP_ARP_FlushInterface(wifi_hw); + } +} + +void Wifi_SetDHCP() { + + +} + +#endif + + +int Wifi_GetData(int datatype, int bufferlen, unsigned char * buffer) { + int i; + if(datatype<0 || datatype>=MAX_WIFIGETDATA) return -1; + switch(datatype) { + case WIFIGETDATA_MACADDRESS: + if(bufferlen<6 || !buffer) return -1; + for(i=0;i<6;i++) { + buffer[i]=WifiData->MacAddr[i]; + } + return 6; + case WIFIGETDATA_NUMWFCAPS: + for(i=0;i<3;i++) if(!(WifiData->wfc_enable[i]&0x80)) break; + return i; + } + return -1; +} + +u32 Wifi_GetStats(int statnum) { + if(statnum<0 || statnum>=NUM_WIFI_STATS) return 0; + return WifiData->stats[statnum]; +} + + +////////////////////////////////////////////////////////////////////////// +// sync functions + +void Wifi_Sync() { + Wifi_Update(); +} + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/wifi_arm9.h b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/wifi_arm9.h new file mode 100644 index 0000000000..d975a01813 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/wifi_arm9.h @@ -0,0 +1,122 @@ +// DS Wifi interface code +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +// wifi_arm9.c - arm9 wifi support header +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + + +#ifndef WIFI_ARM9_H +#define WIFI_ARM9_H + +#include "wifi_shared.h" + + + +// default option is to use 128k heap +#define WIFIINIT_OPTION_USEHEAP_128 0x0000 +#define WIFIINIT_OPTION_USEHEAP_64 0x1000 +#define WIFIINIT_OPTION_USEHEAP_256 0x2000 +#define WIFIINIT_OPTION_USEHEAP_512 0x3000 +#define WIFIINIT_OPTION_USECUSTOMALLOC 0x4000 +#define WIFIINIT_OPTION_HEAPMASK 0xF000 + +#ifdef WIFI_USE_TCP_SGIP + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +}; +#endif + + +#endif + +extern volatile Wifi_MainStruct * WifiData; + +enum WIFIGETDATA { + WIFIGETDATA_MACADDRESS, // MACADDRESS: returns data in the buffer, requires at least 6 bytes + WIFIGETDATA_NUMWFCAPS, // NUM WFC APS: returns number between 0 and 3, doesn't use buffer. + + MAX_WIFIGETDATA +}; + +// Wifi Packet Handler function: (int packetID, int packetlength) - packetID is only valid while the called function is executing. +// call Wifi_RxRawReadPacket while in the packet handler function, to retreive the data to a local buffer. +typedef void (*WifiPacketHandler)(int, int); + +// Wifi Sync Handler function: Callback function that is called when the arm7 needs to be told to synchronize with new fifo data. +// If this callback is used (see Wifi_SetSyncHandler()), it should send a message via the fifo to the arm7, which will call Wifi_Sync() on arm7. +typedef void (*WifiSyncHandler)(); + + +#ifdef __cplusplus +extern "C" { +#endif + +extern void Wifi_CopyMacAddr(volatile void * dest, volatile void * src); +extern int Wifi_CmpMacAddr(volatile void * mac1, volatile void * mac2); + +extern unsigned long Wifi_Init(int initflags); +extern int Wifi_CheckInit(); + +extern int Wifi_RawTxFrame(u16 datalen, u16 rate, u16 * data); +extern void Wifi_SetSyncHandler(WifiSyncHandler wshfunc); +extern void Wifi_RawSetPacketHandler(WifiPacketHandler wphfunc); +extern int Wifi_RxRawReadPacket(s32 packetID, s32 readlength, u16 * data); + +extern void Wifi_DisableWifi(); +extern void Wifi_EnableWifi(); +extern void Wifi_SetPromiscuousMode(int enable); +extern void Wifi_ScanMode(); +extern void Wifi_SetChannel(int channel); + +extern int Wifi_GetNumAP(); +extern int Wifi_GetAPData(int apnum, Wifi_AccessPoint * apdata); +extern int Wifi_FindMatchingAP(int numaps, Wifi_AccessPoint * apdata, Wifi_AccessPoint * match_dest); +extern int Wifi_ConnectAP(Wifi_AccessPoint * apdata, int wepmode, int wepkeyid, u8 * wepkey); +extern void Wifi_AutoConnect(); + +extern int Wifi_AssocStatus(); +extern int Wifi_DisconnectAP(); +extern int Wifi_GetData(int datatype, int bufferlen, unsigned char * buffer); + + +extern void Wifi_Update(); +extern void Wifi_Sync(); + +#ifdef WIFI_USE_TCP_SGIP +extern void Wifi_Timer(int num_ms); +extern void Wifi_SetIP(u32 IPaddr, u32 gateway, u32 subnetmask, u32 dns1, u32 dns2); +extern u32 Wifi_GetIP(); + +#endif + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/common/source/dsregs.h b/c/src/lib/libbsp/arm/nds/dswifi/common/source/dsregs.h new file mode 100644 index 0000000000..4faf61e525 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/common/source/dsregs.h @@ -0,0 +1,179 @@ +////////////////////////////////////////////////////////////////////////// +// DSRegs.h - (c) 2005-2006 Stephen Stair +// General reference mumbo jumbo to give me easy access to the regs I like. +////////////////////////////////////////////////////////////////////////// +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef DSREGS_H +#define DSREGS_H + +#include <nds.h> + + +////////////////////////////////////////////////////////////////////////// +// General registers + + +// general memory range defines +#define PAL ((u16 *) 0x05000000) +#define VRAM1 ((u16 *) 0x06000000) +#define VRAM2 ((u16 *) 0x06200000) + +//#define OAM ((u16 *) 0x07000000) +#define CART ((u16 *) 0x08000000) + + +// video registers +#define DISPCNT (*((u32 volatile *) 0x04000000)) +#define DISPSTAT (*((u16 volatile *) 0x04000004)) +#define VCOUNT (*((u16 volatile *) 0x04000006)) +#define BG0CNT (*((u16 volatile *) 0x04000008)) +#define BG1CNT (*((u16 volatile *) 0x0400000A)) +#define BG2CNT (*((u16 volatile *) 0x0400000C)) +#define BG3CNT (*((u16 volatile *) 0x0400000E)) +#define BG0HOFS (*((u16 volatile *) 0x04000010)) +#define BG0VOFS (*((u16 volatile *) 0x04000012)) +#define BG1HOFS (*((u16 volatile *) 0x04000014)) +#define BG1VOFS (*((u16 volatile *) 0x04000016)) +#define BG2HOFS (*((u16 volatile *) 0x04000018)) +#define BG2VOFS (*((u16 volatile *) 0x0400001A)) +#define BG3HOFS (*((u16 volatile *) 0x0400001C)) +#define BG3VOFS (*((u16 volatile *) 0x0400001E)) +#define BG2PA (*((u16 volatile *) 0x04000020)) +#define BG2PB (*((u16 volatile *) 0x04000022)) +#define BG2PC (*((u16 volatile *) 0x04000024)) +#define BG2PD (*((u16 volatile *) 0x04000026)) +#define BG2X (*((u32 volatile *) 0x04000028)) +#define BG2Y (*((u32 volatile *) 0x0400002C)) +#define BG3PA (*((u16 volatile *) 0x04000030)) +#define BG3PB (*((u16 volatile *) 0x04000032)) +#define BG3PC (*((u16 volatile *) 0x04000034)) +#define BG3PD (*((u16 volatile *) 0x04000036)) +#define BG3X (*((u32 volatile *) 0x04000038)) +#define BG3Y (*((u32 volatile *) 0x0400003C)) +#define WIN0H (*((u16 volatile *) 0x04000040)) +#define WIN1H (*((u16 volatile *) 0x04000042)) +#define WIN0V (*((u16 volatile *) 0x04000044)) +#define WIN1V (*((u16 volatile *) 0x04000046)) +#define WININ (*((u16 volatile *) 0x04000048)) +#define WINOUT (*((u16 volatile *) 0x0400004A)) +#define MOSAIC (*((u16 volatile *) 0x0400004C)) +#define BLDCNT (*((u16 volatile *) 0x04000050)) +#define BLDALPHA (*((u16 volatile *) 0x04000052)) +#define BLDY (*((u16 volatile *) 0x04000054)) + +#define DISPCNT2 (*((u32 volatile *) 0x04001000)) +#define DISPSTAT2 (*((u16 volatile *) 0x04001004)) +#define VCOUNT2 (*((u16 volatile *) 0x04001006)) +#define BG0CNT2 (*((u16 volatile *) 0x04001008)) +#define BG1CNT2 (*((u16 volatile *) 0x0400100A)) +#define BG2CNT2 (*((u16 volatile *) 0x0400100C)) +#define BG3CNT2 (*((u16 volatile *) 0x0400100E)) +#define BG0HOFS2 (*((u16 volatile *) 0x04001010)) +#define BG0VOFS2 (*((u16 volatile *) 0x04001012)) +#define BG1HOFS2 (*((u16 volatile *) 0x04001014)) +#define BG1VOFS2 (*((u16 volatile *) 0x04001016)) +#define BG2HOFS2 (*((u16 volatile *) 0x04001018)) +#define BG2VOFS2 (*((u16 volatile *) 0x0400101A)) +#define BG3HOFS2 (*((u16 volatile *) 0x0400101C)) +#define BG3VOFS2 (*((u16 volatile *) 0x0400101E)) +#define BG2PA2 (*((u16 volatile *) 0x04001020)) +#define BG2PB2 (*((u16 volatile *) 0x04001022)) +#define BG2PC2 (*((u16 volatile *) 0x04001024)) +#define BG2PD2 (*((u16 volatile *) 0x04001026)) +#define BG2X2 (*((u32 volatile *) 0x04001028)) +#define BG2Y2 (*((u32 volatile *) 0x0400102C)) +#define BG3PA2 (*((u16 volatile *) 0x04001030)) +#define BG3PB2 (*((u16 volatile *) 0x04001032)) +#define BG3PC2 (*((u16 volatile *) 0x04001034)) +#define BG3PD2 (*((u16 volatile *) 0x04001036)) +#define BG3X2 (*((u32 volatile *) 0x04001038)) +#define BG3Y2 (*((u32 volatile *) 0x0400103C)) +#define WIN0H2 (*((u16 volatile *) 0x04001040)) +#define WIN1H2 (*((u16 volatile *) 0x04001042)) +#define WIN0V2 (*((u16 volatile *) 0x04001044)) +#define WIN1V2 (*((u16 volatile *) 0x04001046)) +#define WININ2 (*((u16 volatile *) 0x04001048)) +#define WINOUT2 (*((u16 volatile *) 0x0400104A)) +#define MOSAIC2 (*((u16 volatile *) 0x0400104C)) +#define BLDCNT2 (*((u16 volatile *) 0x04001050)) +#define BLDALPHA2 (*((u16 volatile *) 0x04001052)) +#define BLDY2 (*((u16 volatile *) 0x04001054)) + +// video memory defines +#define PAL_BG1 ((u16 *) 0x05000000) +#define PAL_FG1 ((u16 *) 0x05000200) +#define PAL_BG2 ((u16 *) 0x05000400) +#define PAL_FG2 ((u16 *) 0x05000600) + +// other video defines +#define VRAMBANKCNT (((u16 volatile *) 0x04000240)) + +#define RGB(r,g,b) ( ((r)&31) | (((g)&31)<<5) | (((b)&31)<<10) ) +#define VRAM_SETBANK(bank, set) \ + if((bank)&1) { VRAMBANKCNT[(bank)>>1] = (VRAMBANKCNT[(bank)>>1]&0x00ff) | (((set)&0xff)<<8); } else \ + { VRAMBANKCNT[(bank)>>1] = (VRAMBANKCNT[(bank)>>1]&0xff00) | ((set)&0xff); } + +// joypad input +#define KEYINPUT (*((u16 volatile *) 0x04000130)) +#define KEYCNT (*((u16 volatile *) 0x04000132)) + + +// System registers +#define WAITCNT (*((u16 volatile *) 0x04000204)) +//#define IME (*((u16 volatile *) 0x04000208)) +//#define IE (*((u32 volatile *) 0x04000210)) +//#define IF (*((u32 volatile *) 0x04000214)) +#define HALTCNT (*((u16 volatile *) 0x04000300)) + + + + + + +////////////////////////////////////////////////////////////////////////// +// ARM7 specific registers +#ifdef ARM7 +#define POWERCNT7 (*((u16 volatile *) 0x04000304)) + +#define SPI_CR (*((u16 volatile *) 0x040001C0)) +#define SPI_DATA (*((u16 volatile *) 0x040001C2)) + + + +#endif + +////////////////////////////////////////////////////////////////////////// +// ARM9 specific registers +#ifdef ARM9 +#define POWERCNT (*((u16 volatile *) 0x04000308)) + + + +#endif +// End of file! +#endif + + + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/common/source/spinlock.h b/c/src/lib/libbsp/arm/nds/dswifi/common/source/spinlock.h new file mode 100644 index 0000000000..ef89e475b8 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/common/source/spinlock.h @@ -0,0 +1,63 @@ +// DS Wifi interface code +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +// spinlock.h - code for spinlocking for basic wifi structure memory protection +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + + + +/* + +__asm ( +".GLOBL SLasm_Acquire, SLasm_Release \n" +".ARM \n" +"SLasm_Acquire: \n" +" ldr r2,[r0] \n" +" cmp r2,#0 \n" +" movne r0,#1 \n" +" bxne lr \n" +" mov r2,r1 \n" +" swp r2,r2,[r0] \n" +" cmp r2,#0 \n" +" cmpne r2,r1 \n" +" moveq r0,#0 \n" +" bxeq lr \n" +" swp r2,r2,[r0] \n" +" mov r0,#1 \n" +" bx lr \n" +"\n\n" +"SLasm_Release: \n" +" ldr r2,[r0] \n" +" cmp r2,r1 \n" +" movne r0,#2 \n" +" bxne lr \n" +" mov r2,#0 \n" +" swp r2,r2,[r0] \n" +" cmp r2,r1 \n" +" moveq r0,#0 \n" +" movne r0,#2 \n" +" bx lr \n" +); + +*/ + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/common/source/spinlock.s b/c/src/lib/libbsp/arm/nds/dswifi/common/source/spinlock.s new file mode 100644 index 0000000000..e2f36ef81e --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/common/source/spinlock.s @@ -0,0 +1,42 @@ + + .text + + .code 32 + + +.GLOBL SLasm_Acquire, SLasm_Release +.ARM +SLasm_Acquire: + ldr r2,[r0] + cmp r2,#0 + movne r0,#1 + bxne lr + mov r2,r1 + swp r2,r2,[r0] + cmp r2,#0 + cmpne r2,r1 + moveq r0,#0 + bxeq lr + swp r2,r2,[r0] + mov r0,#1 + bx lr + + + +SLasm_Release: + ldr r2,[r0] + cmp r2,r1 + movne r0,#2 + bxne lr + mov r2,#0 + swp r2,r2,[r0] + cmp r2,r1 + moveq r0,#0 + movne r0,#2 + bx lr + + + + .pool + .end + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/common/source/wifi_shared.h b/c/src/lib/libbsp/arm/nds/dswifi/common/source/wifi_shared.h new file mode 100644 index 0000000000..9c83af9502 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/common/source/wifi_shared.h @@ -0,0 +1,284 @@ +// DS Wifi interface code +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +// wifi_shared.h - Shared structures to be used by arm9 and arm7 +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef WIFI_SHARED_H +#define WIFI_SHARED_H + + +#include <nds.h> + + + +// on spinlock contention, the side unsuccessfully attempting the lock reverts the lock. +// if the unlocking side sees the lock incorrectly set, the unlocking side will delay until it has reverted to the correct value, then continue unlocking. +// there should be a delay of at least about ~10-20 cycles between a lock and unlock, to prevent contention. +#define SPINLOCK_NOBODY 0x0000 +#define SPINLOCK_ARM7 0x0001 +#define SPINLOCK_ARM9 0x0002 + +#define SPINLOCK_OK 0x0000 +#define SPINLOCK_INUSE 0x0001 +#define SPINLOCK_ERROR 0x0002 + +#ifdef ARM7 +#define SPINLOCK_VALUE SPINLOCK_ARM7 +#endif +#ifdef ARM9 +#define SPINLOCK_VALUE SPINLOCK_ARM9 +#endif + + +#define Spinlock_Acquire(structtolock) SLasm_Acquire(&((structtolock).spinlock),SPINLOCK_VALUE) +#define Spinlock_Release(structtolock) SLasm_Release(&((structtolock).spinlock),SPINLOCK_VALUE) +#define Spinlock_Check(structtolock) (((structtolock).spinlock)!=SPINLOCK_NOBODY) + +#ifdef __cplusplus +extern "C" { +#endif + +extern u32 SLasm_Acquire(volatile u32 * lockaddr, u32 lockvalue); +extern u32 SLasm_Release(volatile u32 * lockaddr, u32 lockvalue); + +#ifdef __cplusplus +}; +#endif + +// If for whatever reason you want to ditch SGIP and use your own stack, comment out the following line. +#define WIFI_USE_TCP_SGIP 1 + +#define WIFI_RXBUFFER_SIZE (1024*12) +#define WIFI_TXBUFFER_SIZE (1024*24) +#define WIFI_MAX_AP 32 +#define WIFI_MAX_ASSOC_RETRY 30 +#define WIFI_PS_POLL_CONST 2 + +#define WIFI_MAX_PROBE 4 + +#define WIFI_AP_TIMEOUT 40 + +#define WFLAG_PACKET_DATA 0x0001 +#define WFLAG_PACKET_MGT 0x0002 +#define WFLAG_PACKET_BEACON 0x0004 +#define WFLAG_PACKET_CTRL 0x0008 + + +#define WFLAG_PACKET_ALL 0xFFFF + +#define WFLAG_ARM7_ACTIVE 0x0001 +#define WFLAG_ARM7_RUNNING 0x0002 + +#define WFLAG_ARM9_ACTIVE 0x0001 +#define WFLAG_ARM9_USELED 0x0002 +#define WFLAG_ARM9_ARM7READY 0x0004 +#define WFLAG_ARM9_NETUP 0x0008 +#define WFLAG_ARM9_NETREADY 0x0010 + +#define WFLAG_ARM9_INITFLAGMASK 0x0002 + +#define WFLAG_IP_GOTDHCP 0x0001 + +// request - request flags +#define WFLAG_REQ_APCONNECT 0x0001 +#define WFLAG_REQ_APCOPYVALUES 0x0002 +#define WFLAG_REQ_APADHOC 0x0008 +#define WFLAG_REQ_PROMISC 0x0010 +#define WFLAG_REQ_USEWEP 0x0020 + +// request - informational flags +#define WFLAG_REQ_APCONNECTED 0x8000 + +#define WFLAG_APDATA_ADHOC 0x0001 +#define WFLAG_APDATA_WEP 0x0002 +#define WFLAG_APDATA_WPA 0x0004 +#define WFLAG_APDATA_COMPATIBLE 0x0008 +#define WFLAG_APDATA_EXTCOMPATIBLE 0x0010 +#define WFLAG_APDATA_SHORTPREAMBLE 0x0020 +#define WFLAG_APDATA_ACTIVE 0x8000 + + +enum WIFI_RETURN { + WIFI_RETURN_OK = 0, // Everything went ok + WIFI_RETURN_LOCKFAILED = 1, // the spinlock attempt failed (it wasn't retried cause that could lock both cpus- retry again after a delay. + WIFI_RETURN_ERROR = 2, // There was an error in attempting to complete the requested task. + WIFI_RETURN_PARAMERROR = 3, // There was an error in the parameters passed to the function. +}; + +enum WIFI_STATS { + // software stats + WSTAT_RXQUEUEDPACKETS, // number of packets queued into the rx fifo + WSTAT_TXQUEUEDPACKETS, // number of packets queued into the tx fifo + WSTAT_RXQUEUEDBYTES, // number of bytes queued into the rx fifo + WSTAT_TXQUEUEDBYTES, // number of bytes queued into the tx fifo + WSTAT_RXQUEUEDLOST, // number of packets lost due to space limitations in queuing + WSTAT_TXQUEUEDREJECTED, // number of packets rejected due to space limitations in queuing + WSTAT_RXPACKETS, + WSTAT_RXBYTES, + WSTAT_RXDATABYTES, + WSTAT_TXPACKETS, + WSTAT_TXBYTES, + WSTAT_TXDATABYTES, + WSTAT_ARM7_UPDATES, + WSTAT_DEBUG, + // harware stats (function mostly unknown.) + WSTAT_HW_1B0,WSTAT_HW_1B1,WSTAT_HW_1B2,WSTAT_HW_1B3,WSTAT_HW_1B4,WSTAT_HW_1B5,WSTAT_HW_1B6,WSTAT_HW_1B7, + WSTAT_HW_1B8,WSTAT_HW_1B9,WSTAT_HW_1BA,WSTAT_HW_1BB,WSTAT_HW_1BC,WSTAT_HW_1BD,WSTAT_HW_1BE,WSTAT_HW_1BF, + WSTAT_HW_1C0,WSTAT_HW_1C1,WSTAT_HW_1C4,WSTAT_HW_1C5, + WSTAT_HW_1D0,WSTAT_HW_1D1,WSTAT_HW_1D2,WSTAT_HW_1D3,WSTAT_HW_1D4,WSTAT_HW_1D5,WSTAT_HW_1D6,WSTAT_HW_1D7, + WSTAT_HW_1D8,WSTAT_HW_1D9,WSTAT_HW_1DA,WSTAT_HW_1DB,WSTAT_HW_1DC,WSTAT_HW_1DD,WSTAT_HW_1DE,WSTAT_HW_1DF, + + NUM_WIFI_STATS +}; + + +enum WIFI_MODE { + WIFIMODE_DISABLED, + WIFIMODE_NORMAL, + WIFIMODE_SCAN, + WIFIMODE_ASSOCIATE, + WIFIMODE_ASSOCIATED, + WIFIMODE_DISASSOCIATE, + WIFIMODE_CANNOTASSOCIATE, +}; +enum WIFI_AUTHLEVEL { + WIFI_AUTHLEVEL_DISCONNECTED, + WIFI_AUTHLEVEL_AUTHENTICATED, + WIFI_AUTHLEVEL_ASSOCIATED, + WIFI_AUTHLEVEL_DEASSOCIATED, +}; + +enum WEPMODES { + WEPMODE_NONE = 0, + WEPMODE_40BIT = 1, + WEPMODE_128BIT = 2 +}; + +enum WIFI_ASSOCSTATUS { + ASSOCSTATUS_DISCONNECTED, // not *trying* to connect + ASSOCSTATUS_SEARCHING, // data given does not completely specify an AP, looking for AP that matches the data. + ASSOCSTATUS_AUTHENTICATING, // connecting... + ASSOCSTATUS_ASSOCIATING, // connecting... + ASSOCSTATUS_ACQUIRINGDHCP, // connected to AP, but getting IP data from DHCP + ASSOCSTATUS_ASSOCIATED, // Connected! (COMPLETE if Wifi_ConnectAP was called to start) + ASSOCSTATUS_CANNOTCONNECT, // error in connecting... (COMPLETE if Wifi_ConnectAP was called to start) +}; + +typedef struct WIFI_TXHEADER { + u16 enable_flags; + u16 unknown; + u16 countup; + u16 beaconfreq; + u16 tx_rate; + u16 tx_length; +} Wifi_TxHeader; + +typedef struct WIFI_RXHEADER { + u16 a; + u16 b; + u16 c; + u16 d; + u16 byteLength; + u16 rssi_; +} Wifi_RxHeader; + +typedef struct WIFI_ACCESSPOINT { + char ssid[33]; // 0-32byte data, zero + char ssid_len; + u8 bssid[6]; + u8 macaddr[6]; + u16 maxrate; // max rate is measured in steps of 1/2Mbit - 5.5Mbit will be represented as 11, or 0x0B + u32 timectr; + u16 rssi; + u16 flags; + u32 spinlock; + u8 channel; + u8 rssi_past[8]; + u8 base_rates[16]; // terminated by a 0 entry +} Wifi_AccessPoint; + +typedef struct WIFI_MAINSTRUCT { + unsigned long dummy1[8]; + // wifi status + u16 curChannel, reqChannel; + u16 curMode, reqMode; + u16 authlevel,authctr; + u32 flags9, flags7, reqPacketFlags; + u16 curReqFlags, reqReqFlags; + u32 counter7,bootcounter7; + char MacAddr[6]; + u16 authtype; + u16 iptype,ipflags; + u32 ip,snmask,gateway; + + // current AP data + char ssid7[34],ssid9[34]; + u8 bssid7[6], bssid9[6]; + u8 apmac7[6], apmac9[6]; + char wepmode7, wepmode9; + char wepkeyid7, wepkeyid9; + u8 wepkey7[20],wepkey9[20]; + u8 baserates7[16], baserates9[16]; + u8 apchannel7, apchannel9; + u8 maxrate7; + u16 ap_rssi; + u16 pspoll_period; + + // AP data + Wifi_AccessPoint aplist[WIFI_MAX_AP]; + + // probe stuff + u8 probe9_numprobe; + u8 probe9_ssidlen[WIFI_MAX_PROBE]; + char probe9_ssid[WIFI_MAX_PROBE][32]; + + // WFC data + u8 wfc_enable[4]; // wep mode, or 0x80 for "enabled" + Wifi_AccessPoint wfc_ap[3]; + unsigned long wfc_config[3][5]; // ip, snmask, gateway, primarydns, 2nddns + u8 wfc_wepkey[3][16]; + + + // wifi data + u32 rxbufIn, rxbufOut; // bufIn/bufOut have 2-byte granularity. + u16 rxbufData[WIFI_RXBUFFER_SIZE/2]; // send raw 802.11 data through! rxbuffer is for rx'd data, arm7->arm9 transfer + + u32 txbufIn, txbufOut; + u16 txbufData[WIFI_TXBUFFER_SIZE/2]; // tx buffer is for data to tx, arm9->arm7 transfer + + // stats data + u32 stats[NUM_WIFI_STATS]; + + u16 debug[30]; + + u32 random; // semirandom number updated at the convenience of the arm7. use for initial seeds & such. + + unsigned long dummy2[8]; + +} Wifi_MainStruct; + + + +#endif + diff --git a/c/src/lib/libbsp/arm/nds/dswifi/dswifi_license.txt b/c/src/lib/libbsp/arm/nds/dswifi/dswifi_license.txt new file mode 100644 index 0000000000..2ab66f783e --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/dswifi_license.txt @@ -0,0 +1,27 @@ + DSWifi Project - sgIP Internet Protocol Stack Implementation + + Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org + + http://www.akkit.org + + +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/c/src/lib/libbsp/arm/nds/dswifi/include/dswifi7.h b/c/src/lib/libbsp/arm/nds/dswifi/include/dswifi7.h new file mode 100644 index 0000000000..2f784ccf48 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/include/dswifi7.h @@ -0,0 +1,89 @@ +// DSWifi Project - Arm7 Library Header file (dswifi7.h) +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef DSWIFI7_H +#define DSWIFI7_H + +#include "dswifi_version.h" + +// Wifi Sync Handler function: Callback function that is called when the arm9 needs to be told to synchronize with new fifo data. +// If this callback is used (see Wifi_SetSyncHandler()), it should send a message via the fifo to the arm9, which will call Wifi_Sync() on arm9. +typedef void (*WifiSyncHandler)(); + + +#ifdef __cplusplus +extern "C" { +#endif + +// Read_Flash: Reads an arbitrary amount of data from the firmware flash chip +// int address: Offset to start reading from in the flash chip +// char * destination: Pointer to a memory buffer to hold incoming data +// int length: The number of bytes to read +extern void Read_Flash(int address, char * destination, int length); + +// PowerChip_ReadWrite: Reads or writes a value to the DS's power chip +// int cmp: The byte-long command to send to the chip (top bit 1=read, 0=write - other bits = register ID to read/write) +// int data: The data to write to the chip (if sending a read command, this should be zero) +// Returns: The data read returned by the serial connection; only really useful when reading. +extern int PowerChip_ReadWrite(int cmd, int data); + +// Wifi_Interrupt: Handler for the arm7 wifi interrupt. Should be called by the +// interrupt handler on arm7, and should *not* have multiple interrupts enabled. +extern void Wifi_Interrupt(); + +// Wifi_Update: Sync function to ensure data continues to flow between the two +// CPUs smoothly. Should be called at a periodic interval, such as in vblank. +extern void Wifi_Update(); + +// Wifi_Init: Requires the data returned by the arm9 wifi init call. The arm9 +// init call's returned data must be passed to the arm7 and then given to this +// function. (or else very bad things happen) +// This function also enables power to the wifi system, which will shorten +// battery life. +// unsigned long WifiData: You must pass the 32bit value returned by the call to +// Wifi_Init on the ARM9. +extern void Wifi_Init(unsigned long WifiData); + +// Wifi_Deinit: In the case that it is necessary, this function cuts power to +// the wifi system. After this the wifi will be unusable until Wifi_Init is +// called again. +extern void Wifi_Deinit(); + +// Wifi_Sync: Call this function when requested to sync by the arm9 side of the +// wifi lib +extern void Wifi_Sync(); + +// Wifi_SetSyncHandler: Call this function to request notification of when the +// ARM9-side Wifi_Sync function should be called. +// WifiSyncHandler sh: Pointer to the function to be called for notification. +extern void Wifi_SetSyncHandler(WifiSyncHandler sh); + + +#ifdef __cplusplus +}; +#endif + + +#endif // DSWIFI7_H diff --git a/c/src/lib/libbsp/arm/nds/dswifi/include/dswifi9.h b/c/src/lib/libbsp/arm/nds/dswifi/include/dswifi9.h new file mode 100644 index 0000000000..532169d39d --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/include/dswifi9.h @@ -0,0 +1,337 @@ +// DSWifi Project - Arm9 Library Header File (dswifi9.h) +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef DSWIFI9_H +#define DSWIFI9_H + +#include "dswifi_version.h" + +// well, some flags and stuff are just stuffed in here and not documented very well yet... Most of the important stuff is documented though. +// Next version should clean up some of this a lot more :) + +#define WIFIINIT_OPTION_USELED 0x0002 + +// default option is to use 128k heap +#define WIFIINIT_OPTION_USEHEAP_128 0x0000 +#define WIFIINIT_OPTION_USEHEAP_64 0x1000 +#define WIFIINIT_OPTION_USEHEAP_256 0x2000 +#define WIFIINIT_OPTION_USEHEAP_512 0x3000 +#define WIFIINIT_OPTION_USECUSTOMALLOC 0x4000 +#define WIFIINIT_OPTION_HEAPMASK 0xF000 + +#define WFLAG_PACKET_DATA 0x0001 +#define WFLAG_PACKET_MGT 0x0002 +#define WFLAG_PACKET_BEACON 0x0004 +#define WFLAG_PACKET_CTRL 0x0008 + +#define WFLAG_PACKET_ALL 0xFFFF + + +#define WFLAG_APDATA_ADHOC 0x0001 +#define WFLAG_APDATA_WEP 0x0002 +#define WFLAG_APDATA_WPA 0x0004 +#define WFLAG_APDATA_COMPATIBLE 0x0008 +#define WFLAG_APDATA_EXTCOMPATIBLE 0x0010 +#define WFLAG_APDATA_SHORTPREAMBLE 0x0020 +#define WFLAG_APDATA_ACTIVE 0x8000 + +enum WIFI_RETURN { + WIFI_RETURN_OK = 0, // Everything went ok + WIFI_RETURN_LOCKFAILED = 1, // the spinlock attempt failed (it wasn't retried cause that could lock both cpus- retry again after a delay. + WIFI_RETURN_ERROR = 2, // There was an error in attempting to complete the requested task. + WIFI_RETURN_PARAMERROR = 3, // There was an error in the parameters passed to the function. +}; + +enum WIFI_STATS { + // software stats + WSTAT_RXQUEUEDPACKETS, // number of packets queued into the rx fifo + WSTAT_TXQUEUEDPACKETS, // number of packets queued into the tx fifo + WSTAT_RXQUEUEDBYTES, // number of bytes queued into the rx fifo + WSTAT_TXQUEUEDBYTES, // number of bytes queued into the tx fifo + WSTAT_RXQUEUEDLOST, // number of packets lost due to space limitations in queuing + WSTAT_TXQUEUEDREJECTED, // number of packets rejected due to space limitations in queuing + WSTAT_RXPACKETS, + WSTAT_RXBYTES, + WSTAT_RXDATABYTES, + WSTAT_TXPACKETS, + WSTAT_TXBYTES, + WSTAT_TXDATABYTES, + // harware stats (function mostly unknown.) + WSTAT_HW_1B0,WSTAT_HW_1B1,WSTAT_HW_1B2,WSTAT_HW_1B3,WSTAT_HW_1B4,WSTAT_HW_1B5,WSTAT_HW_1B6,WSTAT_HW_1B7, + WSTAT_HW_1B8,WSTAT_HW_1B9,WSTAT_HW_1BA,WSTAT_HW_1BB,WSTAT_HW_1BC,WSTAT_HW_1BD,WSTAT_HW_1BE,WSTAT_HW_1BF, + WSTAT_HW_1C0,WSTAT_HW_1C1,WSTAT_HW_1C4,WSTAT_HW_1C5, + WSTAT_HW_1D0,WSTAT_HW_1D1,WSTAT_HW_1D2,WSTAT_HW_1D3,WSTAT_HW_1D4,WSTAT_HW_1D5,WSTAT_HW_1D6,WSTAT_HW_1D7, + WSTAT_HW_1D8,WSTAT_HW_1D9,WSTAT_HW_1DA,WSTAT_HW_1DB,WSTAT_HW_1DC,WSTAT_HW_1DD,WSTAT_HW_1DE,WSTAT_HW_1DF, + + NUM_WIFI_STATS +}; + +// user code should NEVER have to use the WIFI_MODE or WIFI_AUTHLEVEL enums... is here in case I want to have some debug code... +enum WIFI_MODE { + WIFIMODE_DISABLED, + WIFIMODE_NORMAL, + WIFIMODE_SCAN, + WIFIMODE_ASSOCIATE, + WIFIMODE_ASSOCIATED, + WIFIMODE_DISASSOCIATE, + WIFIMODE_CANNOTASSOCIATE, +}; +enum WIFI_AUTHLEVEL { + WIFI_AUTHLEVEL_DISCONNECTED, + WIFI_AUTHLEVEL_AUTHENTICATED, + WIFI_AUTHLEVEL_ASSOCIATED, + WIFI_AUTHLEVEL_DEASSOCIATED, +}; + +// user code uses members of the WIFIGETDATA structure in calling Wifi_GetData to retreive miscellaneous odd information +enum WIFIGETDATA { + WIFIGETDATA_MACADDRESS, // MACADDRESS: returns data in the buffer, requires at least 6 bytes + WIFIGETDATA_NUMWFCAPS, // NUM WFC APS: returns number between 0 and 3, doesn't use buffer. + + MAX_WIFIGETDATA +}; + + +enum WEPMODES { + WEPMODE_NONE = 0, + WEPMODE_40BIT = 1, + WEPMODE_128BIT = 2 +}; +// WIFI_ASSOCSTATUS - returned by Wifi_AssocStatus() after calling Wifi_ConnectAPk +enum WIFI_ASSOCSTATUS { + ASSOCSTATUS_DISCONNECTED, // not *trying* to connect + ASSOCSTATUS_SEARCHING, // data given does not completely specify an AP, looking for AP that matches the data. + ASSOCSTATUS_AUTHENTICATING, // connecting... + ASSOCSTATUS_ASSOCIATING, // connecting... + ASSOCSTATUS_ACQUIRINGDHCP, // connected to AP, but getting IP data from DHCP + ASSOCSTATUS_ASSOCIATED, // Connected! (COMPLETE if Wifi_ConnectAP was called to start) + ASSOCSTATUS_CANNOTCONNECT, // error in connecting... (COMPLETE if Wifi_ConnectAP was called to start) +}; + +// most user code will never need to know about the WIFI_TXHEADER or WIFI_RXHEADER +typedef struct WIFI_TXHEADER { + u16 enable_flags; + u16 unknown; + u16 countup; + u16 beaconfreq; + u16 tx_rate; + u16 tx_length; +} Wifi_TxHeader; + +typedef struct WIFI_RXHEADER { + u16 a; + u16 b; + u16 c; + u16 d; + u16 byteLength; + u16 rssi_; +} Wifi_RxHeader; + +// WIFI_ACCESSPOINT is an important structure in that it defines how to connect to an access point. +// listed inline are information about the members and their function +// if a field is not necessary for Wifi_ConnectAP it will be marked as such +// *only* 4 fields are absolutely required to be filled in correctly for the connection to work, they are: +// ssid, ssid_len, bssid, and channel - all others can be ignored (though flags should be set to 0) +typedef struct WIFI_ACCESSPOINT { + char ssid[33]; // the AP's SSID - zero terminated is not necessary.. if ssid[0] is zero, the ssid will be ignored in trying to find an AP to connect to. [REQUIRED] + char ssid_len; // number of valid bytes in the ssid field (0-32) [REQUIRED] + u8 bssid[6]; // BSSID is the AP's SSID - setting it to all 00's indicates this is not known and it will be ignored [REQUIRED] + u8 macaddr[6]; // mac address of the "AP" is only necessary in ad-hoc mode. [generally not required to connect] + u16 maxrate; // max rate is measured in steps of 1/2Mbit - 5.5Mbit will be represented as 11, or 0x0B [not required to connect] + u32 timectr; // internal information about how recently a beacon has been received [not required to connect] + u16 rssi; // running average of the recent RSSI values for this AP, will be set to 0 after not receiving beacons for a while. [not required to connect] + u16 flags; // flags indicating various parameters for the AP [not required, but the WFLAG_APDATA_ADHOC flag will be used] + u32 spinlock; // internal data word used to lock the record to guarantee data coherence [not required to connect] + u8 channel; // valid channels are 1-13, setting the channel to 0 will indicate the system should search. [REQUIRED] + u8 rssi_past[8]; // rssi_past indicates the RSSI values for the last 8 beacons received ([7] is the most recent) [not required to connect] + u8 base_rates[16]; // list of the base rates "required" by the AP (same format as maxrate) - zero-terminated list [not required to connect] +} Wifi_AccessPoint; + +// Wifi Packet Handler function: (int packetID, int packetlength) - packetID is only valid while the called function is executing. +// call Wifi_RxRawReadPacket while in the packet handler function, to retreive the data to a local buffer. +typedef void (*WifiPacketHandler)(int, int); + +// Wifi Sync Handler function: Callback function that is called when the arm7 needs to be told to synchronize with new fifo data. +// If this callback is used (see Wifi_SetSyncHandler()), it should send a message via the fifo to the arm7, which will call Wifi_Sync() on arm7. +typedef void (*WifiSyncHandler)(); + + +#ifdef __cplusplus +extern "C" { +#endif + +////////////////////////////////////////////////////////////////////////// +// Init/update/state management functions + +// Wifi_Init: Initializes the wifi library (arm9 side) and the sgIP library. +// int initflags: set up some optional things, like controlling the LED blinking. +// Returns: a 32bit value that *must* be passed to arm7. +extern unsigned long Wifi_Init(int initflags); + +// Wifi_CheckInit: Verifies when the ARM7 has been successfully initialized +// Returns: 1 if the arm7 is ready for wifi, 0 otherwise +extern int Wifi_CheckInit(); + +// Wifi_DisableWifi: Instructs the ARM7 to disengage wireless and stop receiving or +// transmitting. +extern void Wifi_DisableWifi(); + +// Wifi_EnableWifi: Instructs the ARM7 to go into a basic "active" mode, not actually +// associated to an AP, but actively receiving and potentially transmitting +extern void Wifi_EnableWifi(); + +// Wifi_SetPromiscuousMode: Allows the DS to enter or leave a "promsicuous" mode, in which +// all data that can be received is forwarded to the arm9 for user processing. +// Best used with Wifi_RawSetPacketHandler, to allow user code to use the data +// (well, the lib won't use 'em, so they're just wasting CPU otherwise.) +// int enable: 0 to disable promiscuous mode, nonzero to engage +extern void Wifi_SetPromiscuousMode(int enable); + +// Wifi_ScanMode: Instructs the ARM7 to periodically rotate through the channels to +// pick up and record information from beacons given off by APs +extern void Wifi_ScanMode(); + +// Wifi_SetChannel: If the wifi system is not connected or connecting to an access point, instruct +// the chipset to change channel +// int channel: the channel to change to, in the range of 1-13 +extern void Wifi_SetChannel(int channel); + +// Wifi_GetNumAP: +// Returns: the current number of APs that are known about and tracked internally +extern int Wifi_GetNumAP(); + +// Wifi_GetAPData: Grabs data from internal structures for user code (always succeeds) +// int apnum: the 0-based index of the access point record to fetch +// Wifi_AccessPoint * apdata: Pointer to the location where the retrieved data should be stored +extern int Wifi_GetAPData(int apnum, Wifi_AccessPoint * apdata); + +// Wifi_FindMatchingAP: determines whether various APs exist in the local area. You provide a +// list of APs, and it will return the index of the first one in the list that can be found +// in the internal list of APs that are being tracked +// int numaps: number of records in the list +// Wifi_AccessPoint * apdata: pointer to an array of structures with information about the APs to find +// Wifi_AccessPoint * match_dest: OPTIONAL pointer to a record to receive the matching AP record. +// Returns: -1 for none found, or a positive/zero integer index into the array +extern int Wifi_FindMatchingAP(int numaps, Wifi_AccessPoint * apdata, Wifi_AccessPoint * match_dest); + +// Wifi_ConnectAP: Connect to an access point +// Wifi_AccessPoint * apdata: basic data on the AP +// int wepmode: indicates whether wep is used, and what kind +// int wepkeyid: indicates which wep key ID to use for transmitting +// unsigned char * wepkey: the wep key, to be used in all 4 key slots (should make this more flexible in the future) +// Returns: 0 for ok, -1 for error with input data +extern int Wifi_ConnectAP(Wifi_AccessPoint * apdata, int wepmode, int wepkeyid, unsigned char * wepkey); + +// Wifi_AutoConnect: Connect to an access point specified by the WFC data in the firmware +extern void Wifi_AutoConnect(); + +// Wifi_AssocStatus: Returns information about the status of connection to an AP +// Returns: a value from the WIFI_ASSOCSTATUS enum, continue polling until you +// receive ASSOCSTATUS_CONNECTED or ASSOCSTATUS_CANNOTCONNECT +extern int Wifi_AssocStatus(); + +// Wifi_DisconnectAP: Disassociate from the Access Point +extern int Wifi_DisconnectAP(); + +// Wifi_Timer: This function should be called in a periodic interrupt. It serves as the basis +// for all updating in the sgIP library, all retransmits, timeouts, and etc are based on this +// function being called. It's not timing critical but it is rather essential. +// int num_ms: The number of milliseconds since the last time this function was called. +extern void Wifi_Timer(int num_ms); + +// Wifi_GetIP: +// Returns: The current IP address of the DS (may not be valid before connecting to an AP, or setting the IP manually.) +extern unsigned long Wifi_GetIP(); // get local ip + +// Wifi_GetIPInfo: (values may not be valid before connecting to an AP, or setting the IP manually.) +// unsigned long * pGateway: pointer to receive the currently configured gateway IP +// unsigned long * pSnmask: pointer to receive the currently configured subnet mask +// unsigned long * pDns1: pointer to receive the currently configured primary DNS server IP +// unsigned long * pDns2: pointer to receive the currently configured secondary DNS server IP +// Returns: The current IP address of the DS +extern unsigned long Wifi_GetIPInfo(unsigned long * pGateway,unsigned long * pSnmask,unsigned long * pDns1,unsigned long * pDns2); + +// Wifi_SetIP: Set the DS's IP address and other IP configuration information. +// unsigned long IPaddr: The new IP address (NOTE! if this value is zero, the IP, the gateway, and the subnet mask will be allocated via DHCP) +// unsigned long gateway: The new gateway (example: 192.168.1.1 is 0xC0A80101) +// unsigned long subnetmask: The new subnet mask (example: 255.255.255.0 is 0xFFFFFF00) +// unsigned long dns1: The new primary dns server (NOTE! if this value is zero AND the IPaddr value is zero, dns1 and dns2 will be allocated via DHCP) +// unsigned long dns2: The new secondary dns server +extern void Wifi_SetIP(unsigned long IPaddr, unsigned long gateway, unsigned long subnetmask, unsigned long dns1, unsigned long dns2); + +// Wifi_GetData: Retrieve an arbitrary or misc. piece of data from the wifi hardware. see WIFIGETDATA enum. +// int datatype: element from the WIFIGETDATA enum specifing what kind of data to get +// int bufferlen: length of the buffer to copy data to (not always used) +// unsigned char * buffer: buffer to copy element data to (not always used) +// Returns: -1 for failure, the number of bytes written to the buffer, or the value requested if the buffer isn't used. +extern int Wifi_GetData(int datatype, int bufferlen, unsigned char * buffer); + +// Wifi_GetStats: Retreive an element of the wifi statistics gathered +// int statnum: Element from the WIFI_STATS enum, indicating what statistic to return +// Returns: the requested stat, or 0 for failure +extern u32 Wifi_GetStats(int statnum); +////////////////////////////////////////////////////////////////////////// +// Raw Send/Receive functions + +// Wifi_RawTxFrame: Send a raw 802.11 frame at a specified rate +// unsigned short datalen: The length in bytes of the frame to send +// unsigned short rate: The rate to transmit at (Specified as mbits/10, 1mbit=0x000A, 2mbit=0x0014) +// unsigned short * data: Pointer to the data to send (should be halfword-aligned) +// Returns: Nothing of interest. +extern int Wifi_RawTxFrame(unsigned short datalen, unsigned short rate, unsigned short * data); + +// Wifi_RawSetPacketHandler: Set a handler to process all raw incoming packets +// WifiPacketHandler wphfunc: Pointer to packet handler (see WifiPacketHandler definition for more info) +extern void Wifi_RawSetPacketHandler(WifiPacketHandler wphfunc); + +// Wifi_RxRawReadPacket: Allows user code to read a packet from within the WifiPacketHandler function +// long packetID: a non-unique identifier which locates the packet specified in the internal buffer +// long readlength: number of bytes to read (actually reads (number+1)&~1 bytes) +// unsigned short * data: location for the data to be read into +extern int Wifi_RxRawReadPacket(long packetID, long readlength, unsigned short * data); + +////////////////////////////////////////////////////////////////////////// +// Fast transfer support - update functions + +// Wifi_Update: Checks for new data from the arm7 and initiates routing if data +// is available. +extern void Wifi_Update(); + +// Wifi_Sync: Call this function when requested to sync by the arm7 side of the +// wifi lib +extern void Wifi_Sync(); + +// Wifi_SetSyncHandler: Call this function to request notification of when the +// ARM7-side Wifi_Sync function should be called. +// WifiSyncHandler sh: Pointer to the function to be called for notification. +extern void Wifi_SetSyncHandler(WifiSyncHandler sh); + + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/include/dswifi_version.h b/c/src/lib/libbsp/arm/nds/dswifi/include/dswifi_version.h new file mode 100644 index 0000000000..7a82b91323 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/include/dswifi_version.h @@ -0,0 +1,10 @@ +#ifndef _dswifi_version_h_ +#define _dswifi_version_h_ + +#define DSWIFI_MAJOR 0 +#define DSWIFI_MINOR 3 +#define DSWIFI_REVISION 4 + +#define DSWIFI_VERSION "0.3.4" + +#endif // _dswifi_version_h_ diff --git a/c/src/lib/libbsp/arm/nds/dswifi/include/netdb.h b/c/src/lib/libbsp/arm/nds/dswifi/include/netdb.h new file mode 100644 index 0000000000..3bff579020 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/include/netdb.h @@ -0,0 +1,49 @@ +// DSWifi Project - socket emulation layer defines/prototypes (netdb.h) +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef NETDB_H +#define NETDB_H + +struct hostent { + char * h_name; + char ** h_aliases; + int h_addrtype; + int h_length; + char ** h_addr_list; +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + extern struct hostent * gethostbyname(const char * name); + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/include/netinet/in.h b/c/src/lib/libbsp/arm/nds/dswifi/include/netinet/in.h new file mode 100644 index 0000000000..6d6e442bd8 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/include/netinet/in.h @@ -0,0 +1,61 @@ +// DSWifi Project - socket emulation layer defines/prototypes (netinet/in.h) +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef NETINET_IN_H +#define NETINET_IN_H + +#include "sys/socket.h" + +#define INADDR_ANY 0x00000000 +#define INADDR_BROADCAST 0xFFFFFFFF +#define INADDR_NONE 0xFFFFFFFF + + +struct in_addr { + unsigned long s_addr; +}; + +struct sockaddr_in { + unsigned short sin_family; + unsigned short sin_port; + struct in_addr sin_addr; + unsigned char sin_zero[8]; +}; + +#ifdef __cplusplus +extern "C" { +#endif + + // actually from arpa/inet.h - but is included through netinet/in.h + unsigned long inet_addr(const char *cp); + int inet_aton(const char *cp, struct in_addr *inp); + char *inet_ntoa(struct in_addr in);
+ +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/include/sgIP_errno.h b/c/src/lib/libbsp/arm/nds/dswifi/include/sgIP_errno.h new file mode 100644 index 0000000000..dcd4deead8 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/include/sgIP_errno.h @@ -0,0 +1,165 @@ +// DSWifi Project - socket emulation layer defines/prototypes (sgIP_errno.h) +// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org +/****************************************************************************** +DSWifi Lib and test materials are licenced under the MIT open source licence: +Copyright (c) 2005-2006 Stephen Stair + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +/**** Note: This file is unused unless you need to build in an environment without newlib ****/ + +#ifndef SGIP_ERRNO_H +#define SGIP_ERRNO_H + +#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 */ + + +#ifndef errno +extern int sgIP_errno; +#define errno sgIP_errno +#endif + +#endif diff --git a/c/src/lib/libbsp/arm/nds/dswifi/makefile b/c/src/lib/libbsp/arm/nds/dswifi/makefile new file mode 100644 index 0000000000..bdd88a2607 --- /dev/null +++ b/c/src/lib/libbsp/arm/nds/dswifi/makefile @@ -0,0 +1,69 @@ +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitPro) +endif + +export TOPDIR := $(CURDIR) + +export DSWIFI_MAJOR := 0 +export DSWIFI_MINOR := 3 +export DSWIFI_REVISION := 4 + +VERSION := $(DSWIFI_MAJOR).$(DSWIFI_MINOR).$(DSWIFI_REVISION) + +.PHONEY: release debug clean all + +all: include/dswifi_version.h release debug + +include/dswifi_version.h : makefile + @echo "#ifndef _dswifi_version_h_" > $@ + @echo "#define _dswifi_version_h_" >> $@ + @echo >> $@ + @echo "#define DSWIFI_MAJOR $(DSWIFI_MAJOR)" >> $@ + @echo "#define DSWIFI_MINOR $(DSWIFI_MINOR)" >> $@ + @echo "#define DSWIFI_REVISION $(DSWIFI_REVISION)" >> $@ + @echo >> $@ + @echo '#define DSWIFI_VERSION "'$(DSWIFI_MAJOR).$(DSWIFI_MINOR).$(DSWIFI_REVISION)'"' >> $@ + @echo >> $@ + @echo "#endif // _dswifi_version_h_" >> $@ + + +#------------------------------------------------------------------------------- +release: lib +#------------------------------------------------------------------------------- + $(MAKE) -C arm9 BUILD=release + $(MAKE) -C arm7 BUILD=release + +#------------------------------------------------------------------------------- +debug: lib +#------------------------------------------------------------------------------- + $(MAKE) -C arm9 BUILD=debug + $(MAKE) -C arm7 BUILD=debug + +#------------------------------------------------------------------------------- +lib: +#------------------------------------------------------------------------------- + mkdir lib + +#------------------------------------------------------------------------------- +clean: +#------------------------------------------------------------------------------- + @$(MAKE) -C arm9 clean + @$(MAKE) -C arm7 clean + +#------------------------------------------------------------------------------- +dist-src: clean +#------------------------------------------------------------------------------- + @tar --exclude=*CVS* -cvjf dswifi-src-$(VERSION).tar.bz2 arm7 arm9 common include makefile dswifi_license.txt + +#------------------------------------------------------------------------------- +dist-bin: all +#------------------------------------------------------------------------------- + @tar --exclude=*CVS* -cvjf dswifi-$(VERSION).tar.bz2 include lib dswifi_license.txt + +dist: dist-bin dist-src + +#------------------------------------------------------------------------------- +install: dist-bin +#------------------------------------------------------------------------------- + bzip2 -cd dswifi-$(VERSION).tar.bz2 | tar -xv -C $(DEVKITPRO)/libnds + |