summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/nds/dswifi
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2008-04-16 18:37:33 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2008-04-16 18:37:33 +0000
commit311dfa65d823ebb1448a12e9a24d09c7ca7a9e2a (patch)
tree47eaf22ca7bb8cc68486ffe964abd54b535902ad /c/src/lib/libbsp/arm/nds/dswifi
parent2008-04-16 Matthieu Bucchianeri <mbucchia@gmail.com> (diff)
downloadrtems-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')
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm7/makefile145
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm7/source/wifi_arm7.c1637
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm7/source/wifi_arm7.h136
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/makefile150
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP.c63
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP.h56
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ARP.c304
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ARP.h80
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Config.h274
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DHCP.c375
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DHCP.h86
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DNS.c492
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_DNS.h69
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Hub.c211
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_Hub.h109
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ICMP.c56
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_ICMP.h52
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_IP.c124
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_IP.h64
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_TCP.c915
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_TCP.h134
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_UDP.c245
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_UDP.h81
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_memblock.c295
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_memblock.h65
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_sockets.c520
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/sgIP_sockets.h83
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/wifi_arm9.c995
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/arm9/source/wifi_arm9.h122
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/common/source/dsregs.h179
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/common/source/spinlock.h63
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/common/source/spinlock.s42
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/common/source/wifi_shared.h284
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/dswifi_license.txt27
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/include/dswifi7.h89
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/include/dswifi9.h337
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/include/dswifi_version.h10
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/include/netdb.h49
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/include/netinet/in.h61
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/include/sgIP_errno.h165
-rw-r--r--c/src/lib/libbsp/arm/nds/dswifi/makefile69
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
+