From 200c494a5559b9f94a40593f63714bbdde436589 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 4 Jun 2020 15:15:09 +0200 Subject: get this little experiment started for now all it does is crash --- src/frontend/qt_sdl/CMakeLists.txt | 4 +- src/frontend/qt_sdl/LAN_Socket.cpp | 96 +++++++++++++++++++++++++++++++++++--- src/frontend/qt_sdl/main.cpp | 4 +- 3 files changed, 93 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 62d6e60..75dfbe2 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -88,14 +88,14 @@ if (UNIX) --generate-header "${CMAKE_SOURCE_DIR}/melon_grc.xml") if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - target_link_libraries(melonDS dl Qt5::Core Qt5::Gui Qt5::Widgets) + target_link_libraries(melonDS dl slirp Qt5::Core Qt5::Gui Qt5::Widgets) endif () target_sources(melonDS PUBLIC melon_grc.c) elseif (WIN32) target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") - target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) + target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32 slirp.dll) if (BUILD_STATIC) target_link_libraries(melonDS imm32 winmm version setupapi -static Qt5::Core Qt5::Gui Qt5::Widgets z zstd) else() diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp index c6fbd4b..110c443 100644 --- a/src/frontend/qt_sdl/LAN_Socket.cpp +++ b/src/frontend/qt_sdl/LAN_Socket.cpp @@ -25,6 +25,8 @@ #include "LAN_Socket.h" #include "../Config.h" +#include + #ifdef __WIN32__ #include #include @@ -105,13 +107,58 @@ UDPSocket UDPSocketList[4]; int UDPSocketID = 0; +Slirp* Ctx; + + +struct timespec { long tv_sec; long tv_nsec; }; //header part +#define CLOCK_MONOTONIC 1312 +int clock_gettime(int, struct timespec *spec) //C-file part +{ __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); + wintime -=116444736000000000LL; //1jan1601 to 1jan1970 + spec->tv_sec =wintime / 10000000LL; //seconds + spec->tv_nsec =wintime % 10000000LL *100; //nano-seconds + return 0; +} + + +ssize_t fart(const void *buf, size_t len, void *opaque) +{ + printf("slirp fart %d\n", len); +} + +void fart_guest_error(const char *msg, void *opaque){printf("guesterror %s\n", msg);} +/* Return the virtual clock value in nanoseconds */ +int64_t fart_clock_get_ns(void *opaque) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec * 1000000000LL + ts.tv_nsec; +} +/* Create a new timer with the given callback and opaque data */ +void *fart_timer_new(SlirpTimerCb cb, void *cb_opaque, void *opaque) +{ + printf("TIMER SHITO!!\n");return nullptr; +} +/* Remove and free a timer */ +void fart_timer_free(void *timer, void *opaque){printf("timerfree\n");} +/* Modify a timer to expire at @expire_time */ +void fart_timer_mod(void *timer, int64_t expire_time, void *opaque){printf("timermod\n");} +/* Register a fd for future polling */ +void fart_register_poll_fd(int fd, void *opaque){printf("registerpoll\n");} +/* Unregister a fd */ +void fart_unregister_poll_fd(int fd, void *opaque){printf("unregisterpoll\n");} +/* Kick the io-thread, to signal that new events may be processed */ +void fart_notify(void *opaque){printf("nofiy\n");} + +SlirpCb cb; + bool Init() { // TODO: how to deal with cases where an adapter is unplugged or changes config?? //if (PCapLib) return true; //Lib = NULL; - PacketLen = 0; + /*PacketLen = 0; RXNum = 0; IPv4ID = 1; @@ -121,12 +168,40 @@ bool Init() UDPSocketID = 0; + return true;*/ + + SlirpConfig cfg; + memset(&cfg, 0, sizeof(cfg)); + cfg.version = 1; + + cfg.in_enabled = true; + *(u32*)&cfg.vnetwork = kClientIP; + *(u32*)&cfg.vnetmask = 0xFFFFFF00; + *(u32*)&cfg.vhost = kServerIP; + cfg.vhostname = "melon"; + //cfg.vdhcp_start.S_addr = kServerIP; + + + memset(&cb, 0, sizeof(cb)); + + cb.send_packet = fart; + cb.guest_error = fart_guest_error; + cb.clock_get_ns = fart_clock_get_ns; + cb.timer_new = fart_timer_new; + cb.timer_free = fart_timer_free; + cb.timer_mod = fart_timer_mod; + cb.register_poll_fd = fart_register_poll_fd; + cb.unregister_poll_fd = fart_unregister_poll_fd; + cb.notify = fart_notify; + + Ctx = slirp_new(&cfg, &cb, nullptr); + return true; } void DeInit() { - for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) + /*for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) { TCPSocket* sock = &TCPSocketList[i]; if (sock->Backend) closesocket(sock->Backend); @@ -136,7 +211,9 @@ void DeInit() { UDPSocket* sock = &UDPSocketList[i]; if (sock->Backend) closesocket(sock->Backend); - } + }*/ + + slirp_cleanup(Ctx); } @@ -1041,13 +1118,17 @@ int SendPacket(u8* data, int len) return 0; } - HandlePacket(data, len); + u16 ethertype = ntohs(*(u16*)&data[0xC]); + printf("packet of type %04X\n", ethertype); + + //HandlePacket(data, len); + slirp_input(Ctx, data, len); return len; } int RecvPacket(u8* data) { - int ret = 0; + /*int ret = 0; if (RXNum > 0) { memcpy(data, PacketBuffer, PacketLen); @@ -1100,7 +1181,7 @@ int RecvPacket(u8* data) printf("%02X ", recvbuf[k+j]); } printf("\n"); - }*/ + }*-/ //recvlen = recv(sock->Backend, (char*)recvbuf, 1024, 0); //if (recvlen == 0) printf("it closed immediately after\n"); @@ -1137,8 +1218,9 @@ int RecvPacket(u8* data) printf("UDP: socket %d receiving %d bytes\n", i, recvlen); UDP_BuildIncomingFrame(sock, recvbuf, recvlen); - } + }*/ + int ret = 0; return ret; } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index fa542ad..f1b31b3 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -2071,12 +2071,12 @@ int CALLBACK WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdsho if (argv_w) LocalFree(argv_w); - if (AttachConsole(ATTACH_PARENT_PROCESS)) + /*if (AttachConsole(ATTACH_PARENT_PROCESS)) { freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); printf("\n"); - } + }*/ int ret = main(argc, argv); -- cgit v1.2.3 From a29e64534073fa670447958729207f78071ecce5 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 5 Jun 2020 19:12:03 +0200 Subject: get somewhere --- src/frontend/qt_sdl/LAN_Socket.cpp | 286 +++++++++++++++++++++++++++++++------ 1 file changed, 239 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp index 110c443..97a36e4 100644 --- a/src/frontend/qt_sdl/LAN_Socket.cpp +++ b/src/frontend/qt_sdl/LAN_Socket.cpp @@ -25,6 +25,8 @@ #include "LAN_Socket.h" #include "../Config.h" +#include + #include #ifdef __WIN32__ @@ -109,48 +111,131 @@ int UDPSocketID = 0; Slirp* Ctx; +const int FDListMax = 64; +struct pollfd FDList[FDListMax]; +int FDListSize; + + +#ifdef __WIN32__ + +#define poll WSAPoll + +// https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows -struct timespec { long tv_sec; long tv_nsec; }; //header part +struct timespec { long tv_sec; long tv_nsec; }; #define CLOCK_MONOTONIC 1312 -int clock_gettime(int, struct timespec *spec) //C-file part -{ __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); - wintime -=116444736000000000LL; //1jan1601 to 1jan1970 - spec->tv_sec =wintime / 10000000LL; //seconds - spec->tv_nsec =wintime % 10000000LL *100; //nano-seconds - return 0; + +int clock_gettime(int, struct timespec *spec) +{ + __int64 wintime; + GetSystemTimeAsFileTime((FILETIME*)&wintime); + wintime -=116444736000000000LL; //1jan1601 to 1jan1970 + spec->tv_sec = wintime / 10000000LL; //seconds + spec->tv_nsec = wintime % 10000000LL * 100; //nano-seconds + return 0; } +#endif // __WIN32__ + + +ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque) +{ + if (len > 2048) + { + printf("slirp: packet too big (%d)\n", len); + return 0; + } + + printf("slirp: response packet of %d bytes, type %04X\n", len, ntohs(((u16*)buf)[6])); -ssize_t fart(const void *buf, size_t len, void *opaque) + PacketLen = len; + memcpy(PacketBuffer, buf, PacketLen); + RXNum = 1; + + return len; +} + +void SlirpCbGuestError(const char* msg, void* opaque) { - printf("slirp fart %d\n", len); + printf("SLIRP: error: %s\n", msg); } -void fart_guest_error(const char *msg, void *opaque){printf("guesterror %s\n", msg);} -/* Return the virtual clock value in nanoseconds */ -int64_t fart_clock_get_ns(void *opaque) +int64_t SlirpCbClockGetNS(void* opaque) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec * 1000000000LL + ts.tv_nsec; } -/* Create a new timer with the given callback and opaque data */ -void *fart_timer_new(SlirpTimerCb cb, void *cb_opaque, void *opaque) + +void* SlirpCbTimerNew(SlirpTimerCb cb, void* cb_opaque, void* opaque) +{ + return nullptr; +} + +void SlirpCbTimerFree(void* timer, void* opaque) +{ +} + +void SlirpCbTimerMod(void* timer, int64_t expire_time, void* opaque) { - printf("TIMER SHITO!!\n");return nullptr; } -/* Remove and free a timer */ -void fart_timer_free(void *timer, void *opaque){printf("timerfree\n");} -/* Modify a timer to expire at @expire_time */ -void fart_timer_mod(void *timer, int64_t expire_time, void *opaque){printf("timermod\n");} -/* Register a fd for future polling */ -void fart_register_poll_fd(int fd, void *opaque){printf("registerpoll\n");} -/* Unregister a fd */ -void fart_unregister_poll_fd(int fd, void *opaque){printf("unregisterpoll\n");} -/* Kick the io-thread, to signal that new events may be processed */ -void fart_notify(void *opaque){printf("nofiy\n");} - -SlirpCb cb; + +void SlirpCbRegisterPollFD(int fd, void* opaque) +{ + printf("Slirp: register poll FD %d\n", fd); + + if (FDListSize >= FDListMax) + { + printf("!! SLIRP FD LIST FULL\n"); + return; + } + + for (int i = 0; i < FDListSize; i++) + { + if (FDList[i].fd == fd) return; + } + + FDList[FDListSize].fd = fd; + FDListSize++; +} + +void SlirpCbUnregisterPollFD(int fd, void* opaque) +{ + printf("Slirp: unregister poll FD %d\n", fd); + + if (FDListSize < 1) + { + printf("!! SLIRP FD LIST EMPTY\n"); + return; + } + + for (int i = 0; i < FDListSize; i++) + { + if (FDList[i].fd == fd) + { + FDListSize--; + FDList[i] = FDList[FDListSize]; + } + } +} + +void SlirpCbNotify(void* opaque) +{ + // +} + +SlirpCb cb = +{ + .send_packet = SlirpCbSendPacket, + .guest_error = SlirpCbGuestError, + .clock_get_ns = SlirpCbClockGetNS, + .timer_new = SlirpCbTimerNew, + .timer_free = SlirpCbTimerFree, + .timer_mod = SlirpCbTimerMod, + .register_poll_fd = SlirpCbRegisterPollFD, + .unregister_poll_fd = SlirpCbUnregisterPollFD, + .notify = SlirpCbNotify +}; bool Init() { @@ -170,30 +255,22 @@ bool Init() return true;*/ + FDListSize = 0; + memset(FDList, 0, sizeof(FDList)); + SlirpConfig cfg; memset(&cfg, 0, sizeof(cfg)); cfg.version = 1; cfg.in_enabled = true; - *(u32*)&cfg.vnetwork = kClientIP; - *(u32*)&cfg.vnetmask = 0xFFFFFF00; - *(u32*)&cfg.vhost = kServerIP; - cfg.vhostname = "melon"; + *(u32*)&cfg.vnetwork = htonl(kSubnet); + *(u32*)&cfg.vnetmask = htonl(0xFFFFFF00); + *(u32*)&cfg.vhost = htonl(kServerIP); + cfg.vhostname = "melonServer"; + *(u32*)&cfg.vdhcp_start = htonl(kClientIP); + *(u32*)&cfg.vnameserver = htonl(kDNSIP); //cfg.vdhcp_start.S_addr = kServerIP; - - memset(&cb, 0, sizeof(cb)); - - cb.send_packet = fart; - cb.guest_error = fart_guest_error; - cb.clock_get_ns = fart_clock_get_ns; - cb.timer_new = fart_timer_new; - cb.timer_free = fart_timer_free; - cb.timer_mod = fart_timer_mod; - cb.register_poll_fd = fart_register_poll_fd; - cb.unregister_poll_fd = fart_unregister_poll_fd; - cb.notify = fart_notify; - Ctx = slirp_new(&cfg, &cb, nullptr); return true; @@ -1121,14 +1198,130 @@ int SendPacket(u8* data, int len) u16 ethertype = ntohs(*(u16*)&data[0xC]); printf("packet of type %04X\n", ethertype); + if (ethertype == 0x0806) + { + u16 protocol = ntohs(*(u16*)&data[0x10]); + u16 op = ntohs(*(u16*)&data[0x14]); + u32 sourceip = ntohl(*(u32*)&data[0x26-4-6]); + u32 targetip = ntohl(*(u32*)&data[0x26]); + printf("ARP: protocol=%04X, op=%04X, source=%08X, target=%08X\n", protocol, op, sourceip, targetip); + } + else if (ethertype == 0x800) + { + u8 protocol = data[0x17]; + if (protocol == 0x11) // UDP + { + u16 srcport = ntohs(*(u16*)&data[0x22]); + u16 dstport = ntohs(*(u16*)&data[0x24]); + if (srcport == 68 && dstport == 67) // DHCP + { + printf("LANMAGIC: DHCP packet\n"); + } + else if (dstport == 53 && htonl(*(u32*)&data[0x1E]) == kDNSIP) // DNS + { + printf("LANMAGIC: DNS packet\n"); + HandleDNSFrame(data, len); + return len; + } + + printf("LANMAGIC: UDP packet %08X->%08X %d->%d\n", htonl(*(u32*)&data[0x1A]), htonl(*(u32*)&data[0x1E]), srcport, dstport); + } + else if (protocol == 0x06) // TCP + { + printf("LANMAGIC: TCP packet\n"); + + for (int i = 0; i < len; i++) + { + printf("%02X ", data[i]); + if ((i&0xF)==0xF) printf("\n"); + } + printf("\n"); + } + else + printf("LANMAGIC: unsupported IP protocol %02X\n", protocol); + } + //HandlePacket(data, len); slirp_input(Ctx, data, len); return len; } +int SlirpCbAddPoll(int fd, int events, void* opaque) +{ + int idx = -1; + for (int i = 0; i < FDListSize; i++) + { + if (FDList[i].fd == fd) + { + idx = i; + break; + } + } + + if (idx == -1) + { + printf("SLIRP: ERROR! FD %d NOT REGISTERED\n", fd); + return -1; + } + + //printf("Slirp: add poll: fd=%d, idx=%d, events=%08X\n", fd, idx, events); + + u16 evt = 0; + + if (events & SLIRP_POLL_IN) evt |= POLLIN; + if (events & SLIRP_POLL_OUT) evt |= POLLWRNORM; + +#ifndef __WIN32__ + if (events & SLIRP_POLL_PRI) evt |= POLLPRI; + if (events & SLIRP_POLL_ERR) evt |= POLLERR; + if (events & SLIRP_POLL_HUP) evt |= POLLHUP; +#endif // !__WIN32__ + + FDList[idx].events = evt; + return idx; +} + +int SlirpCbGetREvents(int idx, void* opaque) +{ + if (idx < 0 || idx >= FDListSize) + { + printf("SLIRP: !! BAD FD INDEX %d (MAX %d)\n", idx, FDListSize); + return 0; + } + + //printf("Slirp: get revents, idx=%d, res=%04X\n", idx, FDList[idx].revents); + + u16 evt = FDList[idx].revents; + int ret = 0; + + if (evt & POLLIN) ret |= SLIRP_POLL_IN; + if (evt & POLLWRNORM) ret |= SLIRP_POLL_OUT; + if (evt & POLLPRI) ret |= SLIRP_POLL_PRI; + if (evt & POLLERR) ret |= SLIRP_POLL_ERR; + if (evt & POLLHUP) ret |= SLIRP_POLL_HUP; + + return ret; +} + int RecvPacket(u8* data) { - /*int ret = 0; + int ret = 0; + + if (FDListSize > 0) + { + u32 timeout = 0; + slirp_pollfds_fill(Ctx, &timeout, SlirpCbAddPoll, nullptr); + int res = poll(FDList, FDListSize, timeout); + slirp_pollfds_poll(Ctx, res<0, SlirpCbGetREvents, nullptr); + + /*struct pollfd derp = {0};; + derp.fd = FDList[0]; + derp.events = POLLIN | POLLWRNORM;//POLLPRI | POLLIN | POLLWRNORM; + int res = poll(&derp, 1, 0); + if (res==SOCKET_ERROR) printf("fart: %d / %d\n", WSAGetLastError(), FDList[0]); + if(derp.revents) printf("derp: %04X\n", derp.revents);*/ + } + if (RXNum > 0) { memcpy(data, PacketBuffer, PacketLen); @@ -1136,7 +1329,7 @@ int RecvPacket(u8* data) RXNum = 0; } - for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) + /*for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) { TCPSocket* sock = &TCPSocketList[i]; if (sock->Status != 1) continue; @@ -1220,7 +1413,6 @@ int RecvPacket(u8* data) UDP_BuildIncomingFrame(sock, recvbuf, recvlen); }*/ - int ret = 0; return ret; } -- cgit v1.2.3 From 4b73f81ee001115a0b59a3fe939f16181a9bde05 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 5 Jun 2020 20:20:03 +0200 Subject: clean it up --- src/frontend/qt_sdl/LAN_Socket.cpp | 910 +------------------------------------ 1 file changed, 5 insertions(+), 905 deletions(-) (limited to 'src') diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp index 97a36e4..6a3fa74 100644 --- a/src/frontend/qt_sdl/LAN_Socket.cpp +++ b/src/frontend/qt_sdl/LAN_Socket.cpp @@ -21,34 +21,17 @@ #include #include #include +#include #include "../Wifi.h" #include "LAN_Socket.h" #include "../Config.h" -#include - #include #ifdef __WIN32__ - #include #include - #define socket_t SOCKET - #define sockaddr_t SOCKADDR #else - #include - #include - #include - #include - #include #include - #include - #define socket_t int - #define sockaddr_t struct sockaddr - #define closesocket close -#endif - -#ifndef INVALID_SOCKET -#define INVALID_SOCKET (socket_t)-1 #endif @@ -67,47 +50,7 @@ u8 PacketBuffer[2048]; int PacketLen; volatile int RXNum; -u16 IPv4ID; - - -// TODO: UDP sockets -// * use FIFO list -// * assign new socket when seeing new IP/port - - -typedef struct -{ - u8 DestIP[4]; - u16 SourcePort; - u16 DestPort; - - u32 SeqNum; // sequence number for incoming frames - u32 AckNum; - - // 0: unused - // 1: connected - u8 Status; - - socket_t Backend; - -} TCPSocket; - -typedef struct -{ - u8 DestIP[4]; - u16 SourcePort; - u16 DestPort; - - socket_t Backend; - struct sockaddr_in BackendAddr; - -} UDPSocket; - -TCPSocket TCPSocketList[16]; -UDPSocket UDPSocketList[4]; - -int UDPSocketID = 0; - +u32 IPv4ID; Slirp* Ctx; @@ -221,7 +164,6 @@ void SlirpCbUnregisterPollFD(int fd, void* opaque) void SlirpCbNotify(void* opaque) { - // } SlirpCb cb = @@ -239,21 +181,7 @@ SlirpCb cb = bool Init() { - // TODO: how to deal with cases where an adapter is unplugged or changes config?? - //if (PCapLib) return true; - - //Lib = NULL; - /*PacketLen = 0; - RXNum = 0; - - IPv4ID = 1; - - memset(TCPSocketList, 0, sizeof(TCPSocketList)); - memset(UDPSocketList, 0, sizeof(UDPSocketList)); - - UDPSocketID = 0; - - return true;*/ + IPv4ID = 0; FDListSize = 0; memset(FDList, 0, sizeof(FDList)); @@ -269,7 +197,6 @@ bool Init() cfg.vhostname = "melonServer"; *(u32*)&cfg.vdhcp_start = htonl(kClientIP); *(u32*)&cfg.vnameserver = htonl(kDNSIP); - //cfg.vdhcp_start.S_addr = kServerIP; Ctx = slirp_new(&cfg, &cb, nullptr); @@ -278,18 +205,6 @@ bool Init() void DeInit() { - /*for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) - { - TCPSocket* sock = &TCPSocketList[i]; - if (sock->Backend) closesocket(sock->Backend); - } - - for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++) - { - UDPSocket* sock = &UDPSocketList[i]; - if (sock->Backend) closesocket(sock->Backend); - }*/ - slirp_cleanup(Ctx); } @@ -333,165 +248,6 @@ void FinishUDPFrame(u8* data, int len) *(u16*)&udpheader[6] = htons(tmp); } -void FinishTCPFrame(u8* data, int len) -{ - u8* ipheader = &data[0xE]; - u8* tcpheader = &data[0x22]; - - // lengths - *(u16*)&ipheader[2] = htons(len - 0xE); - - // IP checksum - u32 tmp = 0; - - for (int i = 0; i < 20; i += 2) - tmp += ntohs(*(u16*)&ipheader[i]); - while (tmp >> 16) - tmp = (tmp & 0xFFFF) + (tmp >> 16); - tmp ^= 0xFFFF; - *(u16*)&ipheader[10] = htons(tmp); - - u32 tcplen = ntohs(*(u16*)&ipheader[2]) - 0x14; - - // TCP checksum - tmp = 0; - tmp += ntohs(*(u16*)&ipheader[12]); - tmp += ntohs(*(u16*)&ipheader[14]); - tmp += ntohs(*(u16*)&ipheader[16]); - tmp += ntohs(*(u16*)&ipheader[18]); - tmp += ntohs(0x0600); - tmp += tcplen; - for (u8* i = tcpheader; i < &tcpheader[tcplen-1]; i += 2) - tmp += ntohs(*(u16*)i); - if (tcplen & 1) - tmp += ntohs((u_short)tcpheader[tcplen-1]); - while (tmp >> 16) - tmp = (tmp & 0xFFFF) + (tmp >> 16); - tmp ^= 0xFFFF; - *(u16*)&tcpheader[16] = htons(tmp); -} - - -void HandleDHCPFrame(u8* data, int len) -{ - u8 type = 0xFF; - - u32 transid = *(u32*)&data[0x2E]; - - u8* options = &data[0x11A]; - for (;;) - { - if (options >= &data[len]) break; - u8 opt = *options++; - if (opt == 255) break; - - u8 len = *options++; - switch (opt) - { - case 53: // frame type - type = options[0]; - break; - } - - options += len; - } - - if (type == 0xFF) - { - printf("DHCP: bad frame\n"); - return; - } - - printf("DHCP: frame type %d, transid %08X\n", type, transid); - - if (type == 1 || // discover - type == 3) // request - { - u8 resp[512]; - u8* out = &resp[0]; - - // ethernet - memcpy(out, &data[6], 6); out += 6; - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0800); out += 2; - - // IP - u8* ipheader = out; - *out++ = 0x45; - *out++ = 0x00; - *(u16*)out = 0; out += 2; // total length - *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; - *out++ = 0x00; - *out++ = 0x00; - *out++ = 0x80; // TTL - *out++ = 0x11; // protocol (UDP) - *(u16*)out = 0; out += 2; // checksum - *(u32*)out = htonl(kServerIP); out += 4; // source IP - if (type == 1) - { - *(u32*)out = htonl(0xFFFFFFFF); out += 4; // destination IP - } - else if (type == 3) - { - *(u32*)out = htonl(kClientIP); out += 4; // destination IP - } - - // UDP - u8* udpheader = out; - *(u16*)out = htons(67); out += 2; // source port - *(u16*)out = htons(68); out += 2; // destination port - *(u16*)out = 0; out += 2; // length - *(u16*)out = 0; out += 2; // checksum - - // DHCP - u8* body = out; - *out++ = 0x02; - *out++ = 0x01; - *out++ = 0x06; - *out++ = 0x00; - *(u32*)out = transid; out += 4; - *(u16*)out = 0; out += 2; // seconds elapsed - *(u16*)out = 0; out += 2; - *(u32*)out = htonl(0x00000000); out += 4; // client IP - *(u32*)out = htonl(kClientIP); out += 4; // your IP - *(u32*)out = htonl(kServerIP); out += 4; // server IP - *(u32*)out = htonl(0x00000000); out += 4; // gateway IP - memcpy(out, &data[6], 6); out += 6; - memset(out, 0, 10); out += 10; - memset(out, 0, 192); out += 192; - *(u32*)out = 0x63538263; out += 4; // DHCP magic - - // DHCP options - *out++ = 53; *out++ = 1; - *out++ = (type==1) ? 2 : 5; // DHCP type: offer/ack - *out++ = 1; *out++ = 4; - *(u32*)out = htonl(0xFFFFFF00); out += 4; // subnet mask - *out++ = 3; *out++ = 4; - *(u32*)out = htonl(kServerIP); out += 4; // router - *out++ = 51; *out++ = 4; - *(u32*)out = htonl(442030); out += 4; // lease time - *out++ = 54; *out++ = 4; - *(u32*)out = htonl(kServerIP); out += 4; // DHCP server - *out++ = 6; *out++ = 4; - *(u32*)out = htonl(kDNSIP); out += 4; // DNS (hax) - - *out++ = 0xFF; - memset(out, 0, 20); out += 20; - - u32 framelen = (u32)(out - &resp[0]); - if (framelen & 1) { *out++ = 0; framelen++; } - FinishUDPFrame(resp, framelen); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; - } -} - void HandleDNSFrame(u8* data, int len) { u8* ipheader = &data[0xE]; @@ -653,540 +409,6 @@ void HandleDNSFrame(u8* data, int len) RXNum = 1; } -void UDP_BuildIncomingFrame(UDPSocket* sock, u8* data, int len) -{ - u8 resp[2048]; - u8* out = &resp[0]; - - if (len > 1536) return; - - // ethernet - memcpy(out, Wifi::GetMAC(), 6); out += 6; // hurf - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0800); out += 2; - - // IP - u8* resp_ipheader = out; - *out++ = 0x45; - *out++ = 0x00; - *(u16*)out = 0; out += 2; // total length - *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; - *out++ = 0x00; - *out++ = 0x00; - *out++ = 0x80; // TTL - *out++ = 0x11; // protocol (UDP) - *(u16*)out = 0; out += 2; // checksum - memcpy(out, sock->DestIP, 4); out += 4; // source IP - *(u32*)out = htonl(kClientIP); out += 4; // destination IP - - // UDP - u8* resp_tcpheader = out; - *(u16*)out = htons(sock->DestPort); out += 2; // source port - *(u16*)out = htons(sock->SourcePort); out += 2; // destination port - *(u16*)out = htons(len+8); out += 2; // length of header+data - *(u16*)out = 0; out += 2; // checksum - - memcpy(out, data, len); out += len; - - u32 framelen = (u32)(out - &resp[0]); - FinishUDPFrame(resp, framelen); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; -} - -void HandleUDPFrame(u8* data, int len) -{ - u8* ipheader = &data[0xE]; - u8* udpheader = &data[0x22]; - - // debug - /*for (int j = 0; j < len; j += 16) - { - int rem = len - j; - if (rem > 16) rem = 16; - for (int i = 0; i < rem; i++) - { - printf("%02X ", data[i+j]); - } - printf("\n"); - }*/ - - u16 srcport = ntohs(*(u16*)&udpheader[0]); - u16 dstport = ntohs(*(u16*)&udpheader[2]); - - int sockid = -1; - UDPSocket* sock; - for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++) - { - sock = &UDPSocketList[i]; - if (sock->Backend != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) && - sock->SourcePort == srcport && sock->DestPort == dstport) - { - sockid = i; - break; - } - } - - if (sockid == -1) - { - sockid = UDPSocketID; - sock = &UDPSocketList[sockid]; - - UDPSocketID++; - if (UDPSocketID >= (sizeof(UDPSocketList)/sizeof(UDPSocket))) - UDPSocketID = 0; - - if (sock->Backend != 0) - { - printf("LANMAGIC: closing previous UDP socket #%d\n", sockid); - closesocket(sock->Backend); - } - - sock->Backend = socket(AF_INET, SOCK_DGRAM, 0); - - memcpy(sock->DestIP, &ipheader[16], 4); - sock->SourcePort = srcport; - sock->DestPort = dstport; - - memset(&sock->BackendAddr, 0, sizeof(sock->BackendAddr)); - sock->BackendAddr.sin_family = AF_INET; - sock->BackendAddr.sin_port = htons(dstport); - memcpy(&sock->BackendAddr.sin_addr, &ipheader[16], 4); - /*if (bind(sock->Backend, (struct sockaddr*)&sock->BackendAddr, sizeof(sock->BackendAddr)) == -1) - { - printf("bind() shat itself :(\n"); - }*/ - - printf("LANMAGIC: opening UDP socket #%d to %d.%d.%d.%d:%d, srcport %d\n", - sockid, - ipheader[16], ipheader[17], ipheader[18], ipheader[19], - dstport, srcport); - } - - u16 udplen = ntohs(*(u16*)&udpheader[4]) - 8; - - printf("UDP: socket %d sending %d bytes\n", sockid, udplen); - sendto(sock->Backend, (char*)&udpheader[8], udplen, 0, - (struct sockaddr*)&sock->BackendAddr, sizeof(sock->BackendAddr)); -} - -void TCP_SYNACK(TCPSocket* sock, u8* data, int len) -{ - u8 resp[128]; - u8* out = &resp[0]; - - u8* ipheader = &data[0xE]; - u8* tcpheader = &data[0x22]; - - u32 seqnum = htonl(*(u32*)&tcpheader[4]); - seqnum++; - sock->AckNum = seqnum; - - //printf("SYNACK SEQ=%08X|%08X\n", sock->SeqNum, sock->AckNum); - - // ethernet - memcpy(out, &data[6], 6); out += 6; - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0800); out += 2; - - // IP - u8* resp_ipheader = out; - *out++ = 0x45; - *out++ = 0x00; - *(u16*)out = 0; out += 2; // total length - *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; - *out++ = 0x00; - *out++ = 0x00; - *out++ = 0x80; // TTL - *out++ = 0x06; // protocol (TCP) - *(u16*)out = 0; out += 2; // checksum - *(u32*)out = *(u32*)&ipheader[16]; out += 4; // source IP - *(u32*)out = *(u32*)&ipheader[12]; out += 4; // destination IP - - // TCP - u8* resp_tcpheader = out; - *(u16*)out = *(u16*)&tcpheader[2]; out += 2; // source port - *(u16*)out = *(u16*)&tcpheader[0]; out += 2; // destination port - *(u32*)out = htonl(sock->SeqNum); out += 4; sock->SeqNum++; // seq number - *(u32*)out = htonl(seqnum); out += 4; // ack seq number - *(u16*)out = htons(0x8012); out += 2; // flags (SYN+ACK) - *(u16*)out = htons(0x7000); out += 2; // window size (uuuh) - *(u16*)out = 0; out += 2; // checksum - *(u16*)out = 0; out += 2; // urgent pointer - - // TCP options - *out++ = 0x02; *out++ = 0x04; // max segment size - *(u16*)out = htons(0x05B4); out += 2; - *out++ = 0x01; - *out++ = 0x01; - *out++ = 0x04; *out++ = 0x02; // SACK permitted - *out++ = 0x01; - *out++ = 0x03; *out++ = 0x03; // window size - *out++ = 0x08; - - u32 framelen = (u32)(out - &resp[0]); - //if (framelen & 1) { *out++ = 0; framelen++; } - FinishTCPFrame(resp, framelen); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; -} - -void TCP_ACK(TCPSocket* sock, bool fin) -{ - u8 resp[64]; - u8* out = &resp[0]; - - u16 flags = 0x5010; - if (fin) flags |= 0x0001; - - //printf("%sACK SEQ=%08X|%08X\n", fin?"FIN":" ", sock->SeqNum, sock->AckNum); - - // ethernet - memcpy(out, Wifi::GetMAC(), 6); out += 6; - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0800); out += 2; - - // IP - u8* resp_ipheader = out; - *out++ = 0x45; - *out++ = 0x00; - *(u16*)out = 0; out += 2; // total length - *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; - *out++ = 0x00; - *out++ = 0x00; - *out++ = 0x80; // TTL - *out++ = 0x06; // protocol (TCP) - *(u16*)out = 0; out += 2; // checksum - *(u32*)out = *(u32*)&sock->DestIP; out += 4; // source IP - *(u32*)out = htonl(kClientIP); out += 4; // destination IP - - // TCP - u8* resp_tcpheader = out; - *(u16*)out = htonl(sock->DestPort); out += 2; // source port - *(u16*)out = htonl(sock->SourcePort); out += 2; // destination port - *(u32*)out = htonl(sock->SeqNum); out += 4; // seq number - *(u32*)out = htonl(sock->AckNum); out += 4; // ack seq number - *(u16*)out = htons(flags); out += 2; // flags - *(u16*)out = htons(0x7000); out += 2; // window size (uuuh) - *(u16*)out = 0; out += 2; // checksum - *(u16*)out = 0; out += 2; // urgent pointer - - u32 framelen = (u32)(out - &resp[0]); - //if (framelen & 1) { *out++ = 0; framelen++; } - FinishTCPFrame(resp, framelen); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; -} - -void TCP_BuildIncomingFrame(TCPSocket* sock, u8* data, int len) -{ - u8 resp[2048]; - u8* out = &resp[0]; - - if (len > 1536) return; -//printf("INCOMING SEQ=%08X|%08X\n", sock->SeqNum, sock->AckNum); - // ethernet - memcpy(out, Wifi::GetMAC(), 6); out += 6; // hurf - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0800); out += 2; - - // IP - u8* resp_ipheader = out; - *out++ = 0x45; - *out++ = 0x00; - *(u16*)out = 0; out += 2; // total length - *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++; - *out++ = 0x00; - *out++ = 0x00; - *out++ = 0x80; // TTL - *out++ = 0x06; // protocol (TCP) - *(u16*)out = 0; out += 2; // checksum - memcpy(out, sock->DestIP, 4); out += 4; // source IP - *(u32*)out = htonl(kClientIP); out += 4; // destination IP - - // TCP - u8* resp_tcpheader = out; - *(u16*)out = htons(sock->DestPort); out += 2; // source port - *(u16*)out = htons(sock->SourcePort); out += 2; // destination port - *(u32*)out = htonl(sock->SeqNum); out += 4; // seq number - *(u32*)out = htonl(sock->AckNum); out += 4; // ack seq number - *(u16*)out = htons(0x5018); out += 2; // flags (ACK, PSH) - *(u16*)out = htons(0x7000); out += 2; // window size (uuuh) - *(u16*)out = 0; out += 2; // checksum - *(u16*)out = 0; out += 2; // urgent pointer - - memcpy(out, data, len); out += len; - - u32 framelen = (u32)(out - &resp[0]); - FinishTCPFrame(resp, framelen); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; - - sock->SeqNum += len; -} - -void HandleTCPFrame(u8* data, int len) -{ - u8* ipheader = &data[0xE]; - u8* tcpheader = &data[0x22]; - - u16 srcport = ntohs(*(u16*)&tcpheader[0]); - u16 dstport = ntohs(*(u16*)&tcpheader[2]); - u16 flags = ntohs(*(u16*)&tcpheader[12]); - - u32 tcpheaderlen = 4 * (flags >> 12); - u32 tcplen = ntohs(*(u16*)&ipheader[2]) - 0x14; - u32 tcpdatalen = tcplen - tcpheaderlen; - - /*printf("tcpflags=%04X header=%d data=%d seq=%08X|%08X\n", - flags, tcpheaderlen, tcpdatalen, - ntohl(*(u32*)&tcpheader[4]), - ntohl(*(u32*)&tcpheader[8]));*/ - - if (flags & 0x002) // SYN - { - int sockid = -1; - TCPSocket* sock; - for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) - { - sock = &TCPSocketList[i]; - if (sock->Status != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) && - sock->SourcePort == srcport && sock->DestPort == dstport) - { - printf("LANMAGIC: duplicate TCP socket\n"); - sockid = i; - break; - } - } - - if (sockid == -1) - { - for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) - { - sock = &TCPSocketList[i]; - if (sock->Status == 0) - { - sockid = i; - break; - } - } - } - - if (sockid == -1) - { - printf("LANMAGIC: !! TCP SOCKET LIST FULL\n"); - return; - } - - printf("LANMAGIC: opening TCP socket #%d to %d.%d.%d.%d:%d, srcport %d\n", - sockid, - ipheader[16], ipheader[17], ipheader[18], ipheader[19], - dstport, srcport); - - // keep track of it - sock->Status = 1; - memcpy(sock->DestIP, &ipheader[16], 4); - sock->DestPort = dstport; - sock->SourcePort = srcport; - sock->SeqNum = 0x13370000; - sock->AckNum = 0; - - // open backend socket - if (!sock->Backend) - { - sock->Backend = socket(AF_INET, SOCK_STREAM, 0); - } - - struct sockaddr_in conn_addr; - memset(&conn_addr, 0, sizeof(conn_addr)); - conn_addr.sin_family = AF_INET; - memcpy(&conn_addr.sin_addr, &ipheader[16], 4); - conn_addr.sin_port = htons(dstport); - if (connect(sock->Backend, (sockaddr*)&conn_addr, sizeof(conn_addr)) == -1) - { - printf("connect() shat itself :(\n"); - } - else - { - // acknowledge it - TCP_SYNACK(sock, data, len); - } - } - else - { - int sockid = -1; - TCPSocket* sock; - for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) - { - sock = &TCPSocketList[i]; - if (sock->Status != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) && - sock->SourcePort == srcport && sock->DestPort == dstport) - { - sockid = i; - break; - } - } - - if (sockid == -1) - { - printf("LANMAGIC: bad TCP packet\n"); - return; - } - - // TODO: check those - u32 seqnum = ntohl(*(u32*)&tcpheader[4]); - u32 acknum = ntohl(*(u32*)&tcpheader[8]); - sock->SeqNum = acknum; - sock->AckNum = seqnum + tcpdatalen; - - // send data over the socket - if (tcpdatalen > 0) - { - u8* tcpdata = &tcpheader[tcpheaderlen]; - - printf("TCP: socket %d sending %d bytes (flags=%04X)\n", sockid, tcpdatalen, flags); - send(sock->Backend, (char*)tcpdata, tcpdatalen, 0); - - // kind of a hack, there - TCP_ACK(sock, false); - } - - if (flags & 0x001) // FIN - { - // TODO: timeout etc - printf("TCP: socket %d closing\n", sockid); - - sock->Status = 0; - closesocket(sock->Backend); - sock->Backend = 0; - } - } -} - -void HandleARPFrame(u8* data, int len) -{ - u16 protocol = ntohs(*(u16*)&data[0x10]); - if (protocol != 0x0800) return; - - u16 op = ntohs(*(u16*)&data[0x14]); - u32 targetip = ntohl(*(u32*)&data[0x26]); - - // TODO: handle ARP to the client - // this only handles ARP to the DHCP/router - - if (op == 1) - { - // opcode 1=req 2=reply - // sender MAC - // sender IP - // target MAC - // target IP - - const u8* targetmac; - if (targetip == kServerIP) targetmac = kServerMAC; - else if (targetip == kDNSIP) targetmac = kDNSMAC; - else return; - - u8 resp[64]; - u8* out = &resp[0]; - - // ethernet - memcpy(out, &data[6], 6); out += 6; - memcpy(out, kServerMAC, 6); out += 6; - *(u16*)out = htons(0x0806); out += 2; - - // ARP - *(u16*)out = htons(0x0001); out += 2; // hardware type - *(u16*)out = htons(0x0800); out += 2; // protocol - *out++ = 6; // MAC address size - *out++ = 4; // IP address size - *(u16*)out = htons(0x0002); out += 2; // opcode - memcpy(out, targetmac, 6); out += 6; - *(u32*)out = htonl(targetip); out += 4; - memcpy(out, &data[0x16], 6+4); out += 6+4; - - u32 framelen = (u32)(out - &resp[0]); - - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; - } - else - { - printf("wat??\n"); - } -} - -void HandlePacket(u8* data, int len) -{ - u16 ethertype = ntohs(*(u16*)&data[0xC]); - - if (ethertype == 0x0800) // IPv4 - { - u8 protocol = data[0x17]; - if (protocol == 0x11) // UDP - { - u16 srcport = ntohs(*(u16*)&data[0x22]); - u16 dstport = ntohs(*(u16*)&data[0x24]); - if (srcport == 68 && dstport == 67) // DHCP - { - printf("LANMAGIC: DHCP packet\n"); - return HandleDHCPFrame(data, len); - } - else if (dstport == 53 && htonl(*(u32*)&data[0x1E]) == kDNSIP) // DNS - { - printf("LANMAGIC: DNS packet\n"); - return HandleDNSFrame(data, len); - } - - printf("LANMAGIC: UDP packet %d->%d\n", srcport, dstport); - return HandleUDPFrame(data, len); - } - else if (protocol == 0x06) // TCP - { - printf("LANMAGIC: TCP packet\n"); - return HandleTCPFrame(data, len); - } - else - printf("LANMAGIC: unsupported IP protocol %02X\n", protocol); - } - else if (ethertype == 0x0806) // ARP - { - printf("LANMAGIC: ARP packet\n"); - return HandleARPFrame(data, len); - } - else - printf("LANMAGIC: unsupported ethernet type %04X\n", ethertype); -} - int SendPacket(u8* data, int len) { if (len > 2048) @@ -1196,52 +418,21 @@ int SendPacket(u8* data, int len) } u16 ethertype = ntohs(*(u16*)&data[0xC]); - printf("packet of type %04X\n", ethertype); - if (ethertype == 0x0806) - { - u16 protocol = ntohs(*(u16*)&data[0x10]); - u16 op = ntohs(*(u16*)&data[0x14]); - u32 sourceip = ntohl(*(u32*)&data[0x26-4-6]); - u32 targetip = ntohl(*(u32*)&data[0x26]); - printf("ARP: protocol=%04X, op=%04X, source=%08X, target=%08X\n", protocol, op, sourceip, targetip); - } - else if (ethertype == 0x800) + if (ethertype == 0x800) { u8 protocol = data[0x17]; if (protocol == 0x11) // UDP { - u16 srcport = ntohs(*(u16*)&data[0x22]); u16 dstport = ntohs(*(u16*)&data[0x24]); - if (srcport == 68 && dstport == 67) // DHCP - { - printf("LANMAGIC: DHCP packet\n"); - } - else if (dstport == 53 && htonl(*(u32*)&data[0x1E]) == kDNSIP) // DNS + if (dstport == 53 && htonl(*(u32*)&data[0x1E]) == kDNSIP) // DNS { - printf("LANMAGIC: DNS packet\n"); HandleDNSFrame(data, len); return len; } - - printf("LANMAGIC: UDP packet %08X->%08X %d->%d\n", htonl(*(u32*)&data[0x1A]), htonl(*(u32*)&data[0x1E]), srcport, dstport); - } - else if (protocol == 0x06) // TCP - { - printf("LANMAGIC: TCP packet\n"); - - for (int i = 0; i < len; i++) - { - printf("%02X ", data[i]); - if ((i&0xF)==0xF) printf("\n"); - } - printf("\n"); } - else - printf("LANMAGIC: unsupported IP protocol %02X\n", protocol); } - //HandlePacket(data, len); slirp_input(Ctx, data, len); return len; } @@ -1313,13 +504,6 @@ int RecvPacket(u8* data) slirp_pollfds_fill(Ctx, &timeout, SlirpCbAddPoll, nullptr); int res = poll(FDList, FDListSize, timeout); slirp_pollfds_poll(Ctx, res<0, SlirpCbGetREvents, nullptr); - - /*struct pollfd derp = {0};; - derp.fd = FDList[0]; - derp.events = POLLIN | POLLWRNORM;//POLLPRI | POLLIN | POLLWRNORM; - int res = poll(&derp, 1, 0); - if (res==SOCKET_ERROR) printf("fart: %d / %d\n", WSAGetLastError(), FDList[0]); - if(derp.revents) printf("derp: %04X\n", derp.revents);*/ } if (RXNum > 0) @@ -1329,90 +513,6 @@ int RecvPacket(u8* data) RXNum = 0; } - /*for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++) - { - TCPSocket* sock = &TCPSocketList[i]; - if (sock->Status != 1) continue; - - fd_set fd; - struct timeval tv; - - FD_ZERO(&fd); - FD_SET(sock->Backend, &fd); - tv.tv_sec = 0; - tv.tv_usec = 0; - - if (!select(sock->Backend+1, &fd, 0, 0, &tv)) - { - continue; - } - - u8 recvbuf[1024]; - int recvlen = recv(sock->Backend, (char*)recvbuf, 1024, 0); - if (recvlen < 1) - { - if (recvlen == 0) - { - // socket has closed from the other side - printf("TCP: socket %d closed from other side\n", i); - sock->Status = 2; - TCP_ACK(sock, true); - } - continue; - } - - printf("TCP: socket %d receiving %d bytes\n", i, recvlen); - TCP_BuildIncomingFrame(sock, recvbuf, recvlen); - - // debug - /*for (int j = 0; j < recvlen; j += 16) - { - int rem = recvlen - j; - if (rem > 16) rem = 16; - for (int k = 0; k < rem; k++) - { - printf("%02X ", recvbuf[k+j]); - } - printf("\n"); - }*-/ - - //recvlen = recv(sock->Backend, (char*)recvbuf, 1024, 0); - //if (recvlen == 0) printf("it closed immediately after\n"); - } - - for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++) - { - UDPSocket* sock = &UDPSocketList[i]; - if (sock->Backend == 0) continue; - - fd_set fd; - struct timeval tv; - - FD_ZERO(&fd); - FD_SET(sock->Backend, &fd); - tv.tv_sec = 0; - tv.tv_usec = 0; - - if (!select(sock->Backend+1, &fd, 0, 0, &tv)) - { - continue; - } - - u8 recvbuf[1024]; - sockaddr_t fromAddr; - socklen_t fromLen = sizeof(sockaddr_t); - int recvlen = recvfrom(sock->Backend, (char*)recvbuf, 1024, 0, &fromAddr, &fromLen); - if (recvlen < 1) continue; - - if (fromAddr.sa_family != AF_INET) continue; - struct sockaddr_in* fromAddrIn = (struct sockaddr_in*)&fromAddr; - if (memcmp(&fromAddrIn->sin_addr, sock->DestIP, 4)) continue; - if (ntohs(fromAddrIn->sin_port) != sock->DestPort) continue; - - printf("UDP: socket %d receiving %d bytes\n", i, recvlen); - UDP_BuildIncomingFrame(sock, recvbuf, recvlen); - }*/ - return ret; } -- cgit v1.2.3 From bbce434815c824f6bdec05b6b4eb980a4e4e8996 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 5 Jun 2020 20:22:55 +0200 Subject: pointless fix --- src/frontend/qt_sdl/LAN_Socket.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp index 6a3fa74..5477a7d 100644 --- a/src/frontend/qt_sdl/LAN_Socket.cpp +++ b/src/frontend/qt_sdl/LAN_Socket.cpp @@ -368,12 +368,12 @@ void HandleDNSFrame(u8* data, int len) while (p) { struct sockaddr_in* addr = (struct sockaddr_in*)p->ai_addr; - /*printf(" -> %d.%d.%d.%d", - addr->sin_addr.S_un.S_un_b.s_b1, addr->sin_addr.S_un.S_un_b.s_b2, - addr->sin_addr.S_un.S_un_b.s_b3, addr->sin_addr.S_un.S_un_b.s_b4);*/ - - //addr_res = addr->sin_addr.S_un.S_addr; addr_res = *(u32*)&addr->sin_addr; + + printf(" -> %d.%d.%d.%d", + addr_res & 0xFF, (addr_res >> 8) & 0xFF, + (addr_res >> 16) & 0xFF, addr_res >> 24); + p = p->ai_next; } } -- cgit v1.2.3 From 5cd1177e340d9ac81758c3edd951e3d4572a55dc Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 5 Jun 2020 20:44:18 +0200 Subject: huh. all DSi files had outdated copyright years --- src/DSi.cpp | 2 +- src/DSi.h | 2 +- src/DSi_AES.cpp | 2 +- src/DSi_AES.h | 2 +- src/DSi_Camera.cpp | 2 +- src/DSi_Camera.h | 2 +- src/DSi_I2C.cpp | 2 +- src/DSi_I2C.h | 2 +- src/DSi_NDMA.cpp | 2 +- src/DSi_NDMA.h | 2 +- src/DSi_NWifi.cpp | 2 +- src/DSi_NWifi.h | 2 +- src/DSi_SD.cpp | 2 +- src/DSi_SD.h | 2 +- src/DSi_SPI_TSC.cpp | 2 +- src/DSi_SPI_TSC.h | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/DSi.cpp b/src/DSi.cpp index 216f724..17649e4 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi.h b/src/DSi.h index 8cc8fd5..11d31a9 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_AES.cpp b/src/DSi_AES.cpp index 6a8ffad..c7c599e 100644 --- a/src/DSi_AES.cpp +++ b/src/DSi_AES.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_AES.h b/src/DSi_AES.h index 354c4a7..77ef464 100644 --- a/src/DSi_AES.h +++ b/src/DSi_AES.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_Camera.cpp b/src/DSi_Camera.cpp index 45061b2..cc44052 100644 --- a/src/DSi_Camera.cpp +++ b/src/DSi_Camera.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_Camera.h b/src/DSi_Camera.h index 78629b5..844a4d2 100644 --- a/src/DSi_Camera.h +++ b/src/DSi_Camera.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_I2C.cpp b/src/DSi_I2C.cpp index 9984f5e..ff755fb 100644 --- a/src/DSi_I2C.cpp +++ b/src/DSi_I2C.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_I2C.h b/src/DSi_I2C.h index d058be1..35f1ad8 100644 --- a/src/DSi_I2C.h +++ b/src/DSi_I2C.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_NDMA.cpp b/src/DSi_NDMA.cpp index 19c72b6..707c777 100644 --- a/src/DSi_NDMA.cpp +++ b/src/DSi_NDMA.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_NDMA.h b/src/DSi_NDMA.h index d7b7483..57da289 100644 --- a/src/DSi_NDMA.h +++ b/src/DSi_NDMA.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 79bc632..7bb91aa 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index e5fe637..462d7a8 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index 7fdba0f..35227e4 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_SD.h b/src/DSi_SD.h index 2862173..3b8ba56 100644 --- a/src/DSi_SD.h +++ b/src/DSi_SD.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_SPI_TSC.cpp b/src/DSi_SPI_TSC.cpp index 507005b..adff4a3 100644 --- a/src/DSi_SPI_TSC.cpp +++ b/src/DSi_SPI_TSC.cpp @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. diff --git a/src/DSi_SPI_TSC.h b/src/DSi_SPI_TSC.h index f3ffc32..c8e1164 100644 --- a/src/DSi_SPI_TSC.h +++ b/src/DSi_SPI_TSC.h @@ -1,5 +1,5 @@ /* - Copyright 2016-2019 Arisotura + Copyright 2016-2020 Arisotura This file is part of melonDS. -- cgit v1.2.3 From fc5eedc7169b38e9131ed125aa3e7db630b87804 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 15 Jun 2020 13:39:33 +0200 Subject: * take nwifi forward some * shut up CP15 printf's for Fx0 * fix bugs --- src/CP15.cpp | 8 +- src/DSi_NWifi.cpp | 310 +++++++++++++++++++++++++++++++++++++------ src/DSi_NWifi.h | 13 +- src/DSi_SD.cpp | 52 ++++++-- src/DSi_SD.h | 5 + src/NDS.cpp | 6 +- src/RTC.cpp | 1 - src/Wifi.cpp | 3 +- src/WifiAP.cpp | 12 ++ src/WifiAP.h | 1 + src/frontend/qt_sdl/main.cpp | 2 + 11 files changed, 352 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/CP15.cpp b/src/CP15.cpp index d340b9e..2a6489d 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -597,7 +597,10 @@ void ARMv5::CP15Write(u32 id, u32 val) return; } - if ((id&0xF00)!=0x700) + if ((id & 0xF00) == 0xF00) // test/debug shit? + return; + + if ((id & 0xF00) != 0x700) printf("unknown CP15 write op %03X %08X\n", id, val); } @@ -691,6 +694,9 @@ u32 ARMv5::CP15Read(u32 id) return ITCMSetting; } + if ((id & 0xF00) == 0xF00) // test/debug shit? + return 0; + printf("unknown CP15 read op %03X\n", id); return 0; } diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 7bb91aa..4843cfb 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -21,6 +21,7 @@ #include "DSi.h" #include "DSi_NWifi.h" #include "SPI.h" +#include "WifiAP.h" const u8 CIS0[256] = @@ -111,15 +112,31 @@ const u8 CIS1[256] = }; -// hax -DSi_NWifi* hax_wifi; -void triggerirq(u32 param) +DSi_NWifi* Ctx = nullptr; + + +DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) { - hax_wifi->SetIRQ_F1_Counter(0); + // TODO: check the actual mailbox size (presumably 0x200) + for (int i = 0; i < 8; i++) + Mailbox[i] = new FIFO(0x200); + + // this seems to control whether the firmware upload is done + EEPROMReady = 0; + + Ctx = this; } +DSi_NWifi::~DSi_NWifi() +{ + for (int i = 0; i < 8; i++) + delete Mailbox[i]; + + NDS::CancelEvent(NDS::Event_DSi_NWifi); + Ctx = nullptr; +} -DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) +void DSi_NWifi::Reset() { TransferCmd = 0xFFFFFFFF; RemSize = 0; @@ -136,7 +153,7 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) // TODO: check the actual mailbox size (presumably 0x200) for (int i = 0; i < 8; i++) - Mailbox[i] = new FIFO(0x200); + Mailbox[i]->Clear(); u8* mac = SPI_Firmware::GetWifiMAC(); printf("NWifi MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", @@ -158,15 +175,11 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) *(u16*)&EEPROM[0x004] = chk; - EEPROMReady = 0; - BootPhase = 0; -} -DSi_NWifi::~DSi_NWifi() -{ - for (int i = 0; i < 8; i++) - delete Mailbox[i]; + ErrorMask = 0; + + NDS::CancelEvent(NDS::Event_DSi_NWifi); } @@ -671,6 +684,7 @@ void DSi_NWifi::BMI_Command() { // HLE command handling stub u32 cmd = MB_Read32(0); + printf("BMI: cmd %08X\n", cmd); switch (cmd) { @@ -678,8 +692,8 @@ void DSi_NWifi::BMI_Command() { printf("BMI_DONE\n"); EEPROMReady = 1; // GROSS FUCKING HACK - u8 ready_msg[8] = {0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00}; - SendWMIFrame(ready_msg, 8, 0, 0x00, 0x0000); + u8 ready_msg[6] = {0x0A, 0x00, 0x08, 0x06, 0x16, 0x00}; + SendWMIEvent(0, 0x0001, ready_msg, 6); BootPhase = 1; } return; @@ -743,7 +757,7 @@ void DSi_NWifi::BMI_Command() { u32 len = MB_Read32(0); printf("BMI LZ write %08X\n", len); - //FILE* f = fopen("wififirm.bin", "ab"); + //FILE* f = fopen("debug/wififirm.bin", "ab"); for (int i = 0; i < len; i++) { @@ -770,7 +784,6 @@ void DSi_NWifi::WMI_Command() u16 h2 = MB_Read16(0); u16 cmd = MB_Read16(0); - printf("WMI: cmd %04X\n", cmd); switch (cmd) { @@ -778,50 +791,162 @@ void DSi_NWifi::WMI_Command() { u16 svc_id = MB_Read16(0); u16 conn_flags = MB_Read16(0); - - u8 svc_resp[10]; - *(u16*)&svc_resp[0] = 0x0003; - *(u16*)&svc_resp[2] = svc_id; - svc_resp[4] = 0; - svc_resp[5] = (svc_id & 0xFF) + 1; - *(u16*)&svc_resp[6] = 0x0001; - *(u16*)&svc_resp[8] = 0x0001; - SendWMIFrame(svc_resp, 10, 0, 0x00, 0x0000); + printf("service connect %04X %04X %04X\n", svc_id, conn_flags, MB_Read16(0)); + + u8 svc_resp[8]; + // responses from hardware: + // 0003 0100 00 01 0602 00 00 + // 0003 0101 00 02 0600 00 00 + // 0003 0102 00 03 0600 00 00 + // 0003 0103 00 04 0600 00 00 + // 0003 0104 00 05 0600 00 00 + *(u16*)&svc_resp[0] = svc_id; + svc_resp[2] = 0; + svc_resp[3] = (svc_id & 0xFF) + 1; + *(u16*)&svc_resp[4] = (svc_id==0x0100) ? 0x0602 : 0x0600; // max message size + *(u16*)&svc_resp[6] = 0x0000; + SendWMIEvent(0, 0x0003, svc_resp, 8); } break; case 0x0004: // setup complete { - u8 ready_evt[14]; - memset(ready_evt, 0, 14); - *(u16*)&ready_evt[0] = 0x1001; - memcpy(&ready_evt[2], SPI_Firmware::GetWifiMAC(), 6); - ready_evt[8] = 0x02; - *(u32*)&ready_evt[10] = 0x23000024; - // ctrl[0] = trailer size - // trailer[1] = trailer extra size - // trailer[0] = trailer type??? - SendWMIFrame(ready_evt, 14, 1, 0x00, 0x0000); + u8 ready_evt[12]; + memcpy(&ready_evt[0], SPI_Firmware::GetWifiMAC(), 6); + ready_evt[6] = 0x02; + ready_evt[7] = 0; + *(u32*)&ready_evt[8] = 0x2300006C; + SendWMIEvent(1, 0x1001, ready_evt, 12); + + u8 regdomain_evt[4]; + *(u32*)®domain_evt[0] = 0x80000000 | (*(u16*)&EEPROM[0x008] & 0x0FFF); + SendWMIEvent(1, 0x1006, regdomain_evt, 4); + + NDS::ScheduleEvent(NDS::Event_DSi_NWifi, true, 33611, MSTimer, 0); + } + break; + + case 0x0008: // set scan params + { + // TODO: do something with the params!! + + SendWMIAck(); + } + break; + + case 0x0009: // set BSS filter + { + // TODO: do something with the params!! + u8 bssfilter = Mailbox[0]->Read(); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + u32 iemask = MB_Read32(0); + + printf("WMI: set BSS filter, filter=%02X, iemask=%08X\n", bssfilter, iemask); + + SendWMIAck(); + } + break; + + case 0x000A: // set probed BSSID + { + u8 id = Mailbox[0]->Read(); + u8 flags = Mailbox[0]->Read(); + u8 len = Mailbox[0]->Read(); + + char ssid[33]; + for (int i = 0; i < len && i < 32; i++) + ssid[i] = Mailbox[0]->Read(); + ssid[32]= '\0'; + + // TODO: store it somewhere + printf("WMI: set probed SSID: id=%d, flags=%02X, len=%d, SSID=%s\n", id, flags, len, ssid); + + SendWMIAck(); + } + break; + + case 0x000E: // get channel list + { + int nchan = 11; // TODO: customize?? + u8 reply[2 + (nchan*2) + 2]; + + reply[0] = 0; + reply[1] = nchan; + for (int i = 0; i < nchan; i++) + *(u16*)&reply[2 + (i*2)] = 2412 + (i*5); + *(u16*)&reply[2 + (nchan*2)] = 0; + + SendWMIEvent(1, 0x000E, reply, 4+(nchan*2)); + + SendWMIAck(); + } + break; + + case 0x0011: // set channel params + { + Mailbox[0]->Read(); + u8 scan = Mailbox[0]->Read(); + u8 phymode = Mailbox[0]->Read(); + u8 len = Mailbox[0]->Read(); + + u16 channels[32]; + for (int i = 0; i < len && i < 32; i++) + channels[i] = MB_Read16(0); + + // TODO: store it somewhere + printf("WMI: set channel params: scan=%d, phymode=%d, len=%d, channels=", scan, phymode, len); + for (int i = 0; i < len && i < 32; i++) + printf("%d,", channels[i]); + printf("\n"); + + SendWMIAck(); + } + break; + + case 0x0022: // set error bitmask + { + ErrorMask = MB_Read32(0); + + SendWMIAck(); + } + break; + + case 0x0047: // cmd47 -- timer shenanigans?? + { + // + + SendWMIAck(); } break; default: printf("unknown WMI command %04X\n", cmd); + for (int i = 0; i < len; i++) + { + printf("%02X ", Mailbox[0]->Read()); + if ((i&0xF)==0xF) printf("\n"); + } + printf("\n"); break; } MB_Drain(0); } -void DSi_NWifi::SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl) +//void DSi_NWifi::SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl) +void DSi_NWifi::SendWMIEvent(u8 ep, u16 id, u8* data, u32 len) { u32 wlen = 0; - Mailbox[4]->Write(ep); // eid - Mailbox[4]->Write(flags); // flags - MB_Write16(4, len); // payload length - MB_Write16(4, ctrl); // ctrl - wlen += 6; + Mailbox[4]->Write(ep); // eid + Mailbox[4]->Write(0x02); // flags (trailer) + MB_Write16(4, len+2+8); // data length (plus event ID and trailer) + Mailbox[4]->Write(8); // trailer length + Mailbox[4]->Write(0); // + MB_Write16(4, id); // event ID + wlen += 8; for (int i = 0; i < len; i++) { @@ -829,6 +954,53 @@ void DSi_NWifi::SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl) wlen++; } + // trailer + Mailbox[4]->Write(0x02); + Mailbox[4]->Write(0x06); + Mailbox[4]->Write(0x00); + Mailbox[4]->Write(0x00); + Mailbox[4]->Write(0x00); + Mailbox[4]->Write(0x00); + Mailbox[4]->Write(0x00); + Mailbox[4]->Write(0x00); + wlen += 8; + + for (; wlen & 0x7F; wlen++) + Mailbox[4]->Write(0); +} + +void DSi_NWifi::SendWMIAck() +{ + u32 wlen = 0; + + Mailbox[4]->Write(0); // eid + Mailbox[4]->Write(0x02); // flags (trailer) + MB_Write16(4, 0xC); // data length (plus event ID and trailer) + Mailbox[4]->Write(0xC); // trailer length + Mailbox[4]->Write(0); // + wlen += 6; + + // trailer + Mailbox[4]->Write(0x01); + Mailbox[4]->Write(0x02); + Mailbox[4]->Write(0x01); + Mailbox[4]->Write(0x01); + Mailbox[4]->Write(0x02); + Mailbox[4]->Write(0x06); + + // observed trailer data: + // 00 06 00 00 02 00 (in the first few responses) + // 00 00 00 00 00 00 + // TODO: work out what that all means? + // does software even care? + Mailbox[4]->Write(0x00); + Mailbox[4]->Write(0x06); + Mailbox[4]->Write(0x00); + Mailbox[4]->Write(0x00); + Mailbox[4]->Write(0x02); + Mailbox[4]->Write(0x00); + wlen += 0xC; + for (; wlen & 0x7F; wlen++) Mailbox[4]->Write(0); } @@ -849,7 +1021,7 @@ u32 DSi_NWifi::WindowRead(u32 addr) // base address of EEPROM data // TODO find what the actual address is! return 0x1FFC00; - case 0x58: return EEPROMReady; // hax + case 0x58: return EEPROMReady; } return 0; @@ -879,3 +1051,55 @@ void DSi_NWifi::WindowWrite(u32 addr, u32 val) { printf("NWifi: window write %08X %08X\n", addr, val); } + + +void DSi_NWifi::CheckRX() +{return; + u16 framelen; + u16 framectl; + + for (;;) + { + int rxlen = WifiAP::RecvPacket(RXBuffer); + if (rxlen == 0) return; + if (rxlen < 12+24) continue; + + framelen = *(u16*)&RXBuffer[10]; + if (framelen != rxlen-12) + { + printf("bad frame length\n"); + continue; + } + framelen -= 4; + + framectl = *(u16*)&RXBuffer[12+0]; + if ((framectl & 0x00FC) == 0x0080) // beacon + { + printf("NWifi: got beacon\n"); + + u32 bodylen = framelen - 24; + if (bodylen > 256-16) bodylen = 256-16; + + u8 beacon_evt[256]; + memset(beacon_evt, 0, 256); + *(u16*)&beacon_evt[0] = 0x1004; // WMI_BSSINFO_EVENT + *(u16*)&beacon_evt[2] = 2442; // channel (in MHz???? welp) + beacon_evt[2] = 0x01; // frame type + beacon_evt[3] = 0x33; // 'snr' (???????) + *(u16*)&beacon_evt[4] = 0xFFD4; // 'rssi', 'snr'-95 (?????) + memcpy(&beacon_evt[6], &RXBuffer[12+16], 6); // BSSID + *(u32*)&beacon_evt[12] = 0; // ieMask (???????) + memcpy(&beacon_evt[16], &RXBuffer[12+24], bodylen); // frame body + //SendWMIFrame(beacon_evt, 16+bodylen, 1, 0, 0); + } + } +} + +void DSi_NWifi::MSTimer(u32 param) +{ + WifiAP::MSTimer(); + + Ctx->CheckRX(); + + NDS::ScheduleEvent(NDS::Event_DSi_NWifi, true, 33611, MSTimer, 0); +} diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index 462d7a8..8693b18 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -28,6 +28,8 @@ public: DSi_NWifi(DSi_SDHost* host); ~DSi_NWifi(); + void Reset(); + void SendCMD(u8 cmd, u32 param); void SendACMD(u8 cmd, u32 param); @@ -35,6 +37,10 @@ public: void SetIRQ_F1_Counter(u32 n); + void CheckRX(); + + static void MSTimer(u32 param); + private: u32 TransferCmd; u32 TransferAddr; @@ -62,7 +68,8 @@ private: void BMI_Command(); void WMI_Command(); - void SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl); + void SendWMIEvent(u8 ep, u16 id, u8* data, u32 len); + void SendWMIAck(); u32 WindowRead(u32 addr); void WindowWrite(u32 addr, u32 val); @@ -116,6 +123,10 @@ private: u32 EEPROMReady; u32 BootPhase; + + u32 ErrorMask; + + u8 RXBuffer[2048]; }; #endif // DSI_NWIFI_H diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index 35227e4..def7a33 100644 --- a/src/DSi_SD.cpp +++ b/src/DSi_SD.cpp @@ -112,8 +112,8 @@ void DSi_SDHost::Reset() if (Ports[0]) delete Ports[0]; if (Ports[1]) delete Ports[1]; - Ports[0] = NULL; - Ports[1] = NULL; + Ports[0] = nullptr; + Ports[1] = nullptr; if (Num == 0) { @@ -135,6 +135,9 @@ void DSi_SDHost::Reset() Ports[0] = nwifi; } + + if (Ports[0]) Ports[0]->Reset(); + if (Ports[1]) Ports[1]->Reset(); } void DSi_SDHost::DoSavestate(Savestate* file) @@ -205,6 +208,18 @@ void DSi_SDHost::SetCardIRQ() } } +void DSi_SDHost::UpdateCardIRQ(u16 oldmask) +{ + u16 oldflags = CardIRQStatus & ~oldmask; + u16 newflags = CardIRQStatus & ~CardIRQMask; + + if ((oldflags == 0) && (newflags != 0)) // checkme + { + NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC); + NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO_Data1 : NDS::IRQ2_DSi_SD_Data1); + } +} + void DSi_SDHost::SendResponse(u32 val, bool last) { *(u32*)&ResponseBuffer[6] = *(u32*)&ResponseBuffer[4]; @@ -448,6 +463,7 @@ u16 DSi_SDHost::Read(u32 addr) case 0x0F6: return 0; // MMC write protect (always 0) case 0x100: return Data32IRQ; + case 0x102: return 0; case 0x104: return BlockLen32; case 0x108: return BlockCount32; } @@ -549,8 +565,8 @@ void DSi_SDHost::Write(u32 addr, u16 val) u32 oldmask = IRQMask; IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16); UpdateIRQ(oldmask); - if (!DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(24); // checkme - if (DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(25); // checkme + //if (!DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(24); // checkme + //if (DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(25); // checkme } return; @@ -571,8 +587,13 @@ void DSi_SDHost::Write(u32 addr, u16 val) CardIRQStatus &= val; return; case 0x038: - CardIRQMask = val & 0xC007; - SetCardIRQ(); + { + u16 oldmask = CardIRQMask; + CardIRQMask = val & 0xC007; + UpdateCardIRQ(oldmask); + } + //CardIRQMask = val & 0xC007; + //SetCardIRQ(); return; case 0x0D8: @@ -592,6 +613,9 @@ void DSi_SDHost::Write(u32 addr, u16 val) SDOption = 0x40EE; // TODO: CARD_IRQ_STAT // TODO: FIFO16 shit + + if (Ports[0]) Ports[0]->Reset(); + if (Ports[1]) Ports[1]->Reset(); } SoftReset = 0x0006 | (val & 0x0001); return; @@ -601,6 +625,7 @@ void DSi_SDHost::Write(u32 addr, u16 val) if (val & (1<<10)) DataFIFO32->Clear(); DataMode = ((DataCtl >> 1) & 0x1) & ((Data32IRQ >> 1) & 0x1); return; + case 0x102: return; case 0x104: BlockLen32 = val & 0x03FF; return; case 0x108: BlockCount32 = val; return; } @@ -701,6 +726,16 @@ DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path File = Platform::OpenLocalFile(path, "w+b"); } } +} + +DSi_MMCStorage::~DSi_MMCStorage() +{ + if (File) fclose(File); +} + +void DSi_MMCStorage::Reset() +{ + // TODO: reset file access???? CSR = 0x00000100; // checkme @@ -723,11 +758,6 @@ DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path RWCommand = 0; } -DSi_MMCStorage::~DSi_MMCStorage() -{ - if (File) fclose(File); -} - void DSi_MMCStorage::SendCMD(u8 cmd, u32 param) { if (CSR & (1<<5)) diff --git a/src/DSi_SD.h b/src/DSi_SD.h index 3b8ba56..30da6c7 100644 --- a/src/DSi_SD.h +++ b/src/DSi_SD.h @@ -95,6 +95,7 @@ private: void ClearIRQ(u32 irq); void SetIRQ(u32 irq); void UpdateIRQ(u32 oldmask); + void UpdateCardIRQ(u16 oldmask); }; @@ -104,6 +105,8 @@ public: DSi_SDDevice(DSi_SDHost* host) { Host = host; IRQ = false; } ~DSi_SDDevice() {} + virtual void Reset() = 0; + virtual void SendCMD(u8 cmd, u32 param) = 0; virtual void ContinueTransfer() = 0; @@ -120,6 +123,8 @@ public: DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path); ~DSi_MMCStorage(); + void Reset(); + void SetCID(u8* cid) { memcpy(CID, cid, 16); } void SendCMD(u8 cmd, u32 param); diff --git a/src/NDS.cpp b/src/NDS.cpp index 22368ae..34a9da9 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1756,14 +1756,14 @@ void debug(u32 param) } fclose(shit);*/ FILE* - /*shit = fopen("debug/dump9.bin", "wb"); + shit = fopen("debug/dump9.bin", "wb"); for (u32 i = 0x02000000; i < 0x04000000; i+=4) { u32 val = DSi::ARM9Read32(i); fwrite(&val, 4, 1, shit); } - fclose(shit);*/ - shit = fopen("debug/dump7_2.bin", "wb"); + fclose(shit); + shit = fopen("debug/dump7.bin", "wb"); for (u32 i = 0x02000000; i < 0x04000000; i+=4) { u32 val = DSi::ARM7Read32(i); diff --git a/src/RTC.cpp b/src/RTC.cpp index 0d80b2c..fed63d5 100644 --- a/src/RTC.cpp +++ b/src/RTC.cpp @@ -106,7 +106,6 @@ u8 BCD(u8 val) void ByteIn(u8 val) { - //printf("RTC IN: %02X\n", val); if (InputPos == 0) { if ((val & 0xF0) == 0x60) diff --git a/src/Wifi.cpp b/src/Wifi.cpp index ab82724..54fbceb 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -966,7 +966,8 @@ void MSTimer() void USTimer(u32 param) { - WifiAP::USTimer(); + // FIXME!!! + //WifiAP::USTimer(); if (IOPORT(W_USCountCnt)) { diff --git a/src/WifiAP.cpp b/src/WifiAP.cpp index 3a5de37..122e9d3 100644 --- a/src/WifiAP.cpp +++ b/src/WifiAP.cpp @@ -130,6 +130,18 @@ void USTimer() } } +void MSTimer() +{ + USCounter += 0x400; + + u32 chk = (u32)USCounter; + if (!(chk & 0x1FC00)) + { + // send beacon every 128ms + BeaconDue = true; + } +} + int HandleManagementFrame(u8* data, int len) { diff --git a/src/WifiAP.h b/src/WifiAP.h index 97946a5..a2922bd 100644 --- a/src/WifiAP.h +++ b/src/WifiAP.h @@ -27,6 +27,7 @@ void DeInit(); void Reset(); void USTimer(); +void MSTimer(); // packet format: 12-byte TX header + original 802.11 frame int SendPacket(u8* data, int len); diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index f1b31b3..189581b 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -1285,6 +1285,8 @@ void MainWindow::keyPressEvent(QKeyEvent* event) { if (event->isAutoRepeat()) return; + if (event->key() == Qt::Key_F11) NDS::debug(0); + Input::KeyPress(event); } -- cgit v1.2.3 From 3fde8411a7484cd88877deaee38328eb573f5513 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 15 Jun 2020 13:40:54 +0200 Subject: fix ass-stupid RTC bug --- src/RTC.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/RTC.cpp b/src/RTC.cpp index fed63d5..ba51dff 100644 --- a/src/RTC.cpp +++ b/src/RTC.cpp @@ -174,7 +174,6 @@ void ByteIn(u8 val) case 0x70: Output[0] = FreeReg; break; } } - InputPos++; return; } @@ -220,8 +219,6 @@ void ByteIn(u8 val) if (InputPos == 1) FreeReg = val; break; } - - InputPos++; } -- cgit v1.2.3 From c6dc5dfc4b55f56abd8ee0d146728cccf1c45388 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 15 Jun 2020 14:35:02 +0200 Subject: get it to atleast finish a scan without shitting itself --- src/DSi_NWifi.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++++-------- src/DSi_NWifi.h | 3 ++- src/Wifi.cpp | 3 +-- 3 files changed, 69 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 4843cfb..a0778bb 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -21,7 +21,6 @@ #include "DSi.h" #include "DSi_NWifi.h" #include "SPI.h" -#include "WifiAP.h" const u8 CIS0[256] = @@ -178,6 +177,7 @@ void DSi_NWifi::Reset() BootPhase = 0; ErrorMask = 0; + ScanTimer = 0; NDS::CancelEvent(NDS::Event_DSi_NWifi); } @@ -826,6 +826,29 @@ void DSi_NWifi::WMI_Command() } break; + case 0x0007: // start scan + { + u32 forcefg = MB_Read32(0); + u32 legacy = MB_Read32(0); + u32 scantime = MB_Read32(0); + u32 forceinterval = MB_Read32(0); + u8 scantype = Mailbox[0]->Read(); + u8 nchannels = Mailbox[0]->Read(); + + printf("WMI: start scan, forceFG=%d, legacy=%d, scanTime=%d, interval=%d, scanType=%d, chan=%d\n", + forcefg, legacy, scantime, forceinterval, scantype, nchannels); + + if (ScanTimer > 0) + { + printf("!! CHECKME: START SCAN BUT WAS ALREADY SCANNING (%d)\n", ScanTimer); + } + + ScanTimer = scantime; + + SendWMIAck(); + } + break; + case 0x0008: // set scan params { // TODO: do something with the params!! @@ -913,6 +936,33 @@ void DSi_NWifi::WMI_Command() } break; + case 0x002E: // extension shit + { + u16 extcmd = MB_Read16(0); + switch (extcmd) + { + case 0x2008: // 'heartbeat'?? + { + u32 cookie = MB_Read32(0); + u32 source = MB_Read32(0); + + u8 reply[10]; + *(u16*)&reply[0] = 0x3007; + *(u32*)&reply[2] = cookie; + *(u32*)&reply[6] = source; + SendWMIEvent(1, 0x1010, reply, 10); + } + break; + + default: + printf("WMI: unknown ext cmd 002E:%04X\n", extcmd); + break; + } + + SendWMIAck(); + } + break; + case 0x0047: // cmd47 -- timer shenanigans?? { // @@ -1053,12 +1103,20 @@ void DSi_NWifi::WindowWrite(u32 addr, u32 val) } -void DSi_NWifi::CheckRX() -{return; - u16 framelen; - u16 framectl; +void DSi_NWifi::_MSTimer() +{ + if (ScanTimer > 0) + { + ScanTimer--; + + if (ScanTimer == 0) + { + u32 status = 0; + SendWMIEvent(1, 0x100A, (u8*)&status, 4); + } + } - for (;;) + /*for (;;) { int rxlen = WifiAP::RecvPacket(RXBuffer); if (rxlen == 0) return; @@ -1092,14 +1150,11 @@ void DSi_NWifi::CheckRX() memcpy(&beacon_evt[16], &RXBuffer[12+24], bodylen); // frame body //SendWMIFrame(beacon_evt, 16+bodylen, 1, 0, 0); } - } + }*/ } void DSi_NWifi::MSTimer(u32 param) { - WifiAP::MSTimer(); - - Ctx->CheckRX(); - + Ctx->_MSTimer(); NDS::ScheduleEvent(NDS::Event_DSi_NWifi, true, 33611, MSTimer, 0); } diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index 8693b18..68c3795 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -37,7 +37,7 @@ public: void SetIRQ_F1_Counter(u32 n); - void CheckRX(); + void _MSTimer(); static void MSTimer(u32 param); @@ -125,6 +125,7 @@ private: u32 BootPhase; u32 ErrorMask; + u32 ScanTimer; u8 RXBuffer[2048]; }; diff --git a/src/Wifi.cpp b/src/Wifi.cpp index 54fbceb..ab82724 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -966,8 +966,7 @@ void MSTimer() void USTimer(u32 param) { - // FIXME!!! - //WifiAP::USTimer(); + WifiAP::USTimer(); if (IOPORT(W_USCountCnt)) { -- cgit v1.2.3 From afbdd96a907e85849d67e14bf6c9217e20f666ea Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 15 Jun 2020 16:06:00 +0200 Subject: make it actually connect. hark hark hark --- src/DSi_NWifi.cpp | 282 ++++++++++++++++++++++++++++++++++++++++++++++-------- src/DSi_NWifi.h | 7 ++ src/WifiAP.cpp | 3 - src/WifiAP.h | 5 + 4 files changed, 252 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index a0778bb..af93cce 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -21,6 +21,7 @@ #include "DSi.h" #include "DSi_NWifi.h" #include "SPI.h" +#include "WifiAP.h" const u8 CIS0[256] = @@ -179,6 +180,9 @@ void DSi_NWifi::Reset() ErrorMask = 0; ScanTimer = 0; + BeaconTimer = 0x10A2220ULL; + ConnectionStatus = 0; + NDS::CancelEvent(NDS::Event_DSi_NWifi); } @@ -676,7 +680,8 @@ void DSi_NWifi::HandleCommand() switch (BootPhase) { case 0: return BMI_Command(); - case 1: return WMI_Command(); + case 1: return HTC_Command(); + case 2: return WMI_Command(); } } @@ -684,7 +689,6 @@ void DSi_NWifi::BMI_Command() { // HLE command handling stub u32 cmd = MB_Read32(0); - printf("BMI: cmd %08X\n", cmd); switch (cmd) { @@ -776,7 +780,7 @@ void DSi_NWifi::BMI_Command() } } -void DSi_NWifi::WMI_Command() +void DSi_NWifi::HTC_Command() { // HLE command handling stub u16 h0 = MB_Read16(0); @@ -822,10 +826,61 @@ void DSi_NWifi::WMI_Command() *(u32*)®domain_evt[0] = 0x80000000 | (*(u16*)&EEPROM[0x008] & 0x0FFF); SendWMIEvent(1, 0x1006, regdomain_evt, 4); + BootPhase = 2; NDS::ScheduleEvent(NDS::Event_DSi_NWifi, true, 33611, MSTimer, 0); } break; + default: + printf("unknown HTC command %04X\n", cmd); + for (int i = 0; i < len; i++) + { + printf("%02X ", Mailbox[0]->Read()); + if ((i&0xF)==0xF) printf("\n"); + } + printf("\n"); + break; + } + + MB_Drain(0); +} + +void DSi_NWifi::WMI_Command() +{ + // HLE command handling stub + u16 h0 = MB_Read16(0); + u16 len = MB_Read16(0); + u16 h2 = MB_Read16(0); + + u16 cmd = MB_Read16(0); + + switch (cmd) + { + case 0x0001: // connect to network + { + WMI_ConnectToNetwork(); + SendWMIAck(); + } + break; + + case 0x0004: // synchronize + { + Mailbox[0]->Read(); + // TODO?? + + SendWMIAck(); + } + break; + + case 0x0005: // create priority stream + { + // TODO??? + // there's a lot of crap in there. + + SendWMIAck(); + } + break; + case 0x0007: // start scan { u32 forcefg = MB_Read32(0); @@ -843,7 +898,8 @@ void DSi_NWifi::WMI_Command() printf("!! CHECKME: START SCAN BUT WAS ALREADY SCANNING (%d)\n", ScanTimer); } - ScanTimer = scantime; + // checkme + ScanTimer = scantime*5; SendWMIAck(); } @@ -878,10 +934,9 @@ void DSi_NWifi::WMI_Command() u8 flags = Mailbox[0]->Read(); u8 len = Mailbox[0]->Read(); - char ssid[33]; + char ssid[33] = {0}; for (int i = 0; i < len && i < 32; i++) ssid[i] = Mailbox[0]->Read(); - ssid[32]= '\0'; // TODO: store it somewhere printf("WMI: set probed SSID: id=%d, flags=%02X, len=%d, SSID=%s\n", id, flags, len, ssid); @@ -890,6 +945,15 @@ void DSi_NWifi::WMI_Command() } break; + case 0x000D: // set disconnect timeout + { + Mailbox[0]->Read(); + // TODO?? + + SendWMIAck(); + } + break; + case 0x000E: // get channel list { int nchan = 11; // TODO: customize?? @@ -928,6 +992,20 @@ void DSi_NWifi::WMI_Command() } break; + case 0x0012: // set power mode + { + Mailbox[0]->Read(); + // TODO?? + + SendWMIAck(); + } + break; + + case 0x0017: // dummy? + Mailbox[0]->Read(); + SendWMIAck(); + break; + case 0x0022: // set error bitmask { ErrorMask = MB_Read32(0); @@ -963,6 +1041,24 @@ void DSi_NWifi::WMI_Command() } break; + case 0x003D: // set keepalive interval + { + Mailbox[0]->Read(); + // TODO?? + + SendWMIAck(); + } + break; + + case 0x0041: // 'WMI_SET_WSC_STATUS_CMD' + { + Mailbox[0]->Read(); + // TODO?? + + SendWMIAck(); + } + break; + case 0x0047: // cmd47 -- timer shenanigans?? { // @@ -971,6 +1067,28 @@ void DSi_NWifi::WMI_Command() } break; + case 0x0048: // not supported by DSi?? + { + MB_Read32(0); + MB_Read32(0); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + + SendWMIAck(); + } + break; + + case 0xF000: // set bitrate + { + // TODO! + Mailbox[0]->Read(); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + + SendWMIAck(); + } + break; + default: printf("unknown WMI command %04X\n", cmd); for (int i = 0; i < len; i++) @@ -985,6 +1103,64 @@ void DSi_NWifi::WMI_Command() MB_Drain(0); } +void DSi_NWifi::WMI_ConnectToNetwork() +{ + u8 type = Mailbox[0]->Read(); + u8 auth11 = Mailbox[0]->Read(); + u8 auth = Mailbox[0]->Read(); + u8 pCryptoType = Mailbox[0]->Read(); + u8 pCryptoLen = Mailbox[0]->Read(); + u8 gCryptoType = Mailbox[0]->Read(); + u8 gCryptoLen = Mailbox[0]->Read(); + u8 ssidLen = Mailbox[0]->Read(); + + char ssid[33] = {0}; + for (int i = 0; i < 32; i++) + ssid[i] = Mailbox[0]->Read(); + if (ssidLen <= 32) + ssid[ssidLen] = '\0'; + + u16 channel = MB_Read16(0); + + u8 bssid[6]; + *(u32*)&bssid[0] = MB_Read32(0); + *(u16*)&bssid[4] = MB_Read16(0); + + u32 flags = MB_Read32(0); + + if ((type != 0x01) || + (auth11 != 0x01) || + (auth != 0x01) || + (pCryptoType != 0x01) || + (gCryptoType != 0x01) || + (memcmp(bssid, WifiAP::APMac, 6))) + { + printf("WMI_Connect: bad parameters\n"); + // TODO: send disconnect?? + return; + } + + printf("WMI: connecting to network %s\n", ssid); + + u8 reply[20]; + + // hope this is right! + *(u16*)&reply[0] = 2437; // channel + memcpy(&reply[2], WifiAP::APMac, 6); // BSSID + *(u16*)&reply[8] = 128; // listen interval + *(u16*)&reply[10] = 128; // beacon interval + *(u32*)&reply[12] = 0x01; // network type + + reply[16] = 0x16; // beaconIeLen ??? + reply[17] = 0x2F; // assocReqLen + reply[18] = 0x16; // assocRespLen + reply[19] = 0; // ????? + + SendWMIEvent(1, 0x1002, reply, 20); + + ConnectionStatus = 1; +} + //void DSi_NWifi::SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl) void DSi_NWifi::SendWMIEvent(u8 ep, u16 id, u8* data, u32 len) { @@ -1055,6 +1231,44 @@ void DSi_NWifi::SendWMIAck() Mailbox[4]->Write(0); } +void DSi_NWifi::SendWMIBSSInfo(u8 type, u8* data, u32 len) +{ + u32 wlen = 0; + + // TODO: what is the trailer about????? + // on hardware I observed one frame with trailer and another without + // plus it's different from other frames + + // TODO: check when version>=2 frame type is used? + // I observed the version<2 variant on my DSi + + Mailbox[4]->Write(1); // eid + Mailbox[4]->Write(0x00); // flags + MB_Write16(4, len+2+16); // data length (plus event ID and trailer) + Mailbox[4]->Write(0xFF); // trailer length + Mailbox[4]->Write(0xFF); // + MB_Write16(4, 0x1004); // event ID + wlen += 8; + + MB_Write16(4, 2437); // channel (6) (checkme!) + Mailbox[4]->Write(type); + Mailbox[4]->Write(0x1B); // 'snr' + MB_Write16(4, 0xFFBC); // RSSI + MB_Write32(4, *(u32*)&WifiAP::APMac[0]); + MB_Write16(4, *(u16*)&WifiAP::APMac[4]); + MB_Write32(4, 0); // ieMask + wlen += 16; + + for (int i = 0; i < len; i++) + { + Mailbox[4]->Write(data[i]); + wlen++; + } + + for (; wlen & 0x7F; wlen++) + Mailbox[4]->Write(0); +} + u32 DSi_NWifi::WindowRead(u32 addr) { @@ -1105,52 +1319,36 @@ void DSi_NWifi::WindowWrite(u32 addr, u32 val) void DSi_NWifi::_MSTimer() { + BeaconTimer++; + if (ScanTimer > 0) { ScanTimer--; + // send a beacon + if (!(BeaconTimer & 0x7F)) + { + u8 beacon[] = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // timestamp + 0x80, 0x00, // beacon interval + 0x21, 0x00, // capability, + 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x0C, 0x12, 0x18, 0x24, // rates + 0x03, 0x01, 0x06, // channel + 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, // TIM + 0x00, 0x07, 'm', 'e', 'l', 'o', 'n', 'A', 'P', // SSID + }; + + SendWMIBSSInfo(0x01, beacon, sizeof(beacon)); + printf("send beacon\n"); + } + if (ScanTimer == 0) { u32 status = 0; SendWMIEvent(1, 0x100A, (u8*)&status, 4); } } - - /*for (;;) - { - int rxlen = WifiAP::RecvPacket(RXBuffer); - if (rxlen == 0) return; - if (rxlen < 12+24) continue; - - framelen = *(u16*)&RXBuffer[10]; - if (framelen != rxlen-12) - { - printf("bad frame length\n"); - continue; - } - framelen -= 4; - - framectl = *(u16*)&RXBuffer[12+0]; - if ((framectl & 0x00FC) == 0x0080) // beacon - { - printf("NWifi: got beacon\n"); - - u32 bodylen = framelen - 24; - if (bodylen > 256-16) bodylen = 256-16; - - u8 beacon_evt[256]; - memset(beacon_evt, 0, 256); - *(u16*)&beacon_evt[0] = 0x1004; // WMI_BSSINFO_EVENT - *(u16*)&beacon_evt[2] = 2442; // channel (in MHz???? welp) - beacon_evt[2] = 0x01; // frame type - beacon_evt[3] = 0x33; // 'snr' (???????) - *(u16*)&beacon_evt[4] = 0xFFD4; // 'rssi', 'snr'-95 (?????) - memcpy(&beacon_evt[6], &RXBuffer[12+16], 6); // BSSID - *(u32*)&beacon_evt[12] = 0; // ieMask (???????) - memcpy(&beacon_evt[16], &RXBuffer[12+24], bodylen); // frame body - //SendWMIFrame(beacon_evt, 16+bodylen, 1, 0, 0); - } - }*/ } void DSi_NWifi::MSTimer(u32 param) diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index 68c3795..46cf714 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -66,10 +66,14 @@ private: void HandleCommand(); void BMI_Command(); + void HTC_Command(); void WMI_Command(); + void WMI_ConnectToNetwork(); + void SendWMIEvent(u8 ep, u16 id, u8* data, u32 len); void SendWMIAck(); + void SendWMIBSSInfo(u8 type, u8* data, u32 len); u32 WindowRead(u32 addr); void WindowWrite(u32 addr, u32 val); @@ -127,6 +131,9 @@ private: u32 ErrorMask; u32 ScanTimer; + u64 BeaconTimer; + u32 ConnectionStatus; + u8 RXBuffer[2048]; }; diff --git a/src/WifiAP.cpp b/src/WifiAP.cpp index 122e9d3..ae9664c 100644 --- a/src/WifiAP.cpp +++ b/src/WifiAP.cpp @@ -30,9 +30,6 @@ namespace WifiAP { -#define AP_MAC 0x00, 0xF0, 0x77, 0x77, 0x77, 0x77 -#define AP_NAME "melonAP" - const u8 APMac[6] = {AP_MAC}; #define PWRITE_8(p, v) *p++ = v; diff --git a/src/WifiAP.h b/src/WifiAP.h index a2922bd..130383e 100644 --- a/src/WifiAP.h +++ b/src/WifiAP.h @@ -22,6 +22,11 @@ namespace WifiAP { +#define AP_MAC 0x00, 0xF0, 0x77, 0x77, 0x77, 0x77 +#define AP_NAME "melonAP" + +extern const u8 APMac[6]; + bool Init(); void DeInit(); void Reset(); -- cgit v1.2.3 From 1101ed773bd9ed0b8024b987cc9e6621d58f8fea Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 16 Jun 2020 02:52:53 +0200 Subject: make it get further --- src/DSi_NWifi.cpp | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++--- src/DSi_NWifi.h | 7 ++- 2 files changed, 171 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index af93cce..99da932 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -22,6 +22,7 @@ #include "DSi_NWifi.h" #include "SPI.h" #include "WifiAP.h" +#include "Platform.h" const u8 CIS0[256] = @@ -117,9 +118,17 @@ DSi_NWifi* Ctx = nullptr; DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) { - // TODO: check the actual mailbox size (presumably 0x200) + // HACK + // the mailboxes are supposed to be 0x80 bytes + // however, as we do things instantly, emulating this is meaningless + // and only adds complication for (int i = 0; i < 8; i++) - Mailbox[i] = new FIFO(0x200); + Mailbox[i] = new FIFO(0x600);//0x80); + + // extra FIFOs acting as bigger TX/RX buffers, to work on frames + // bigger than 0x80 + //Mailbox[8] = new FIFO(0x608); + //Mailbox[9] = new FIFO(0x608); // this seems to control whether the firmware upload is done EEPROMReady = 0; @@ -151,7 +160,6 @@ void DSi_NWifi::Reset() WindowReadAddr = 0; WindowWriteAddr = 0; - // TODO: check the actual mailbox size (presumably 0x200) for (int i = 0; i < 8; i++) Mailbox[i]->Clear(); @@ -687,7 +695,6 @@ void DSi_NWifi::HandleCommand() void DSi_NWifi::BMI_Command() { - // HLE command handling stub u32 cmd = MB_Read32(0); switch (cmd) @@ -782,7 +789,6 @@ void DSi_NWifi::BMI_Command() void DSi_NWifi::HTC_Command() { - // HLE command handling stub u16 h0 = MB_Read16(0); u16 len = MB_Read16(0); u16 h2 = MB_Read16(0); @@ -847,11 +853,18 @@ void DSi_NWifi::HTC_Command() void DSi_NWifi::WMI_Command() { - // HLE command handling stub u16 h0 = MB_Read16(0); u16 len = MB_Read16(0); u16 h2 = MB_Read16(0); + u8 ep = h0 & 0xFF; + if (ep > 0x01) // data endpoints + { + WMI_SendPacket(len); + MB_Drain(0); + return; + } + u16 cmd = MB_Read16(0); switch (cmd) @@ -863,6 +876,25 @@ void DSi_NWifi::WMI_Command() } break; + case 0x0003: // disconnect + { + if (ConnectionStatus != 1) + printf("WMI: ?? trying to disconnect while not connected\n"); + + printf("WMI: disconnect\n"); + ConnectionStatus = 0; + + u8 reply[10]; + *(u16*)&reply[0] = 3; // checkme + memcpy(&reply[2], WifiAP::APMac, 6); + reply[8] = 3; // disconnect reason (via cmd) + reply[9] = 0; // assoc-response length (?????) + SendWMIEvent(1, 0x1003, reply, 10); + + SendWMIAck(); + } + break; + case 0x0004: // synchronize { Mailbox[0]->Read(); @@ -1078,6 +1110,14 @@ void DSi_NWifi::WMI_Command() } break; + case 0x0049: // 'host exit notify' + { + // + + SendWMIAck(); + } + break; + case 0xF000: // set bitrate { // TODO! @@ -1090,8 +1130,8 @@ void DSi_NWifi::WMI_Command() break; default: - printf("unknown WMI command %04X\n", cmd); - for (int i = 0; i < len; i++) + printf("unknown WMI command %04X (header: %04X:%04X:%04X)\n", cmd, h0, len, h2); + for (int i = 0; i < len-2; i++) { printf("%02X ", Mailbox[0]->Read()); if ((i&0xF)==0xF) printf("\n"); @@ -1161,6 +1201,65 @@ void DSi_NWifi::WMI_ConnectToNetwork() ConnectionStatus = 1; } +void DSi_NWifi::WMI_SendPacket(u16 len) +{ + if (ConnectionStatus != 1) + { + printf("WMI: !! trying to send shit while not connected\n"); + // TODO: report error?? + return; + } + + u16 hdr = MB_Read16(0); + if (hdr != 0x0000) + { + printf("WMI: special frame %04X\n", hdr); + return; + } + + printf("WMI: send packet, len=%d\n", len); + + u8 dstmac[6]; + u8 srcmac[6]; + u16 plen; + + *(u32*)&dstmac[0] = MB_Read32(0); + *(u16*)&dstmac[4] = MB_Read16(0); + *(u32*)&srcmac[0] = MB_Read32(0); + *(u16*)&srcmac[4] = MB_Read16(0); + plen = MB_Read16(0); + plen = ((plen & 0xFF00) >> 8) | ((plen & 0x00FF) << 8); + + if (plen > len-16) + { + printf("WMI: bad packet length %d > %d\n", plen, len-16); + return; + } + + u32 h0 = MB_Read32(0); + u16 h1 = MB_Read16(0); + + if (h0 != 0x0003AAAA || h1 != 0x0000) + { + printf("WMI: bad LLC/SLIP header\n"); + return; + } + + u16 ethertype = MB_Read16(0); + + int lan_len = (plen - 8) + 14; + + memcpy(&LANBuffer[0], dstmac, 6); // destination MAC + memcpy(&LANBuffer[6], srcmac, 6); // source MAC + *(u16*)&LANBuffer[12] = ethertype; // type + for (int i = 0; i < lan_len; i++) + { + LANBuffer[14+i] = Mailbox[0]->Read(); + } + + Platform::LAN_SendPacket(LANBuffer, lan_len); +} + //void DSi_NWifi::SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl) void DSi_NWifi::SendWMIEvent(u8 ep, u16 id, u8* data, u32 len) { @@ -1269,6 +1368,58 @@ void DSi_NWifi::SendWMIBSSInfo(u8 type, u8* data, u32 len) Mailbox[4]->Write(0); } +void DSi_NWifi::CheckRX() +{ + int rxlen = Platform::LAN_RecvPacket(LANBuffer); + if (rxlen > 0) + { + // check destination MAC + if (*(u32*)&LANBuffer[0] != 0xFFFFFFFF || *(u16*)&LANBuffer[4] != 0xFFFF) + { + if (memcmp(&LANBuffer[0], &EEPROM[0x00A], 6)) + return; + } + + // packet is good + + printf("WMI: receive packet %04X, len=%d\n", *(u16*)&LANBuffer[12], rxlen); + + int datalen = rxlen - 14; // length of packet body + + int wlen = 0; + MB_Write16(4, 0x0002); + MB_Write16(4, 16 + 8 + datalen); + MB_Write16(4, 0x0000); + wlen += 6; + + MB_Write16(4, 0x0000); + MB_Write32(4, *(u32*)&LANBuffer[0]); + MB_Write16(4, *(u16*)&LANBuffer[4]); + MB_Write32(4, *(u32*)&LANBuffer[6]); + MB_Write16(4, *(u16*)&LANBuffer[10]); + u16 plen = datalen + 8; + plen = ((plen & 0xFF00) >> 8) | ((plen & 0x00FF) << 8); + MB_Write16(4, plen); + wlen += 16; + + MB_Write16(4, 0xAAAA); + MB_Write16(4, 0x0003); + MB_Write16(4, 0x0000); + MB_Write16(4, *(u16*)&LANBuffer[12]); + wlen += 8; + + for (int i = 0; i < datalen; i++) + Mailbox[4]->Write(LANBuffer[14+i]); + + wlen += datalen; + + for (; wlen & 0x7F; wlen++) + Mailbox[4]->Write(0); + + UpdateIRQ_F1(); + } +} + u32 DSi_NWifi::WindowRead(u32 addr) { @@ -1340,6 +1491,7 @@ void DSi_NWifi::_MSTimer() }; SendWMIBSSInfo(0x01, beacon, sizeof(beacon)); + UpdateIRQ_F1(); printf("send beacon\n"); } @@ -1347,8 +1499,14 @@ void DSi_NWifi::_MSTimer() { u32 status = 0; SendWMIEvent(1, 0x100A, (u8*)&status, 4); + UpdateIRQ_F1(); } } + + if (ConnectionStatus == 1) + { + CheckRX(); + } } void DSi_NWifi::MSTimer(u32 param) diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index 46cf714..14a5d14 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -70,11 +70,14 @@ private: void WMI_Command(); void WMI_ConnectToNetwork(); + void WMI_SendPacket(u16 len); void SendWMIEvent(u8 ep, u16 id, u8* data, u32 len); void SendWMIAck(); void SendWMIBSSInfo(u8 type, u8* data, u32 len); + void CheckRX(); + u32 WindowRead(u32 addr); void WindowWrite(u32 addr, u32 val); @@ -113,7 +116,7 @@ private: while (!Mailbox[n]->IsEmpty()) Mailbox[n]->Read(); } - FIFO* Mailbox[8]; + FIFO* Mailbox[10]; u8 F0_IRQEnable; u8 F0_IRQStatus; @@ -134,7 +137,7 @@ private: u64 BeaconTimer; u32 ConnectionStatus; - u8 RXBuffer[2048]; + u8 LANBuffer[2048]; }; #endif // DSI_NWIFI_H -- cgit v1.2.3 From 91ff63a19435833034f800267fab4ea6af675414 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 16 Jun 2020 14:09:54 +0200 Subject: fix slirp crash when exiting without having inited slirp also fix misc bugs --- src/DSi_NWifi.cpp | 25 ++++++++++++++++++++++--- src/frontend/qt_sdl/LAN_Socket.cpp | 13 +++++++++++-- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 99da932..d158974 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -1211,9 +1211,16 @@ void DSi_NWifi::WMI_SendPacket(u16 len) } u16 hdr = MB_Read16(0); - if (hdr != 0x0000) + hdr = ((hdr & 0xFF00) >> 8) | ((hdr & 0x00FF) << 8); + if (hdr & 0x0003) { - printf("WMI: special frame %04X\n", hdr); + printf("WMI: special frame %04X len=%d\n", hdr, len); + for (int i = 0; i < len-2; i++) + { + printf("%02X ", Mailbox[0]->Read()); + if ((i&0xF)==0xF) printf("\n"); + } + printf("\n"); return; } @@ -1252,11 +1259,18 @@ void DSi_NWifi::WMI_SendPacket(u16 len) memcpy(&LANBuffer[0], dstmac, 6); // destination MAC memcpy(&LANBuffer[6], srcmac, 6); // source MAC *(u16*)&LANBuffer[12] = ethertype; // type - for (int i = 0; i < lan_len; i++) + for (int i = 0; i < lan_len-14; i++) { LANBuffer[14+i] = Mailbox[0]->Read(); } + for (int i = 0; i < lan_len; i++) + { + printf("%02X ", LANBuffer[i]); + if ((i&0xF)==0xF) printf("\n"); + } + printf("\n"); + Platform::LAN_SendPacket(LANBuffer, lan_len); } @@ -1373,6 +1387,7 @@ void DSi_NWifi::CheckRX() int rxlen = Platform::LAN_RecvPacket(LANBuffer); if (rxlen > 0) { + printf("WMI packet recv %04X %04X %04X\n", *(u16*)&LANBuffer[0], *(u16*)&LANBuffer[2], *(u16*)&LANBuffer[4]); // check destination MAC if (*(u32*)&LANBuffer[0] != 0xFFFFFFFF || *(u16*)&LANBuffer[4] != 0xFFFF) { @@ -1380,6 +1395,10 @@ void DSi_NWifi::CheckRX() return; } + // check source MAC, in case we get a packet we just sent out + if (!memcmp(&LANBuffer[6], &EEPROM[0x00A], 6)) + return; + // packet is good printf("WMI: receive packet %04X, len=%d\n", *(u16*)&LANBuffer[12], rxlen); diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp index 5477a7d..13a8eb1 100644 --- a/src/frontend/qt_sdl/LAN_Socket.cpp +++ b/src/frontend/qt_sdl/LAN_Socket.cpp @@ -52,7 +52,7 @@ volatile int RXNum; u32 IPv4ID; -Slirp* Ctx; +Slirp* Ctx = nullptr; const int FDListMax = 64; struct pollfd FDList[FDListMax]; @@ -164,6 +164,7 @@ void SlirpCbUnregisterPollFD(int fd, void* opaque) void SlirpCbNotify(void* opaque) { + printf("Slirp: notify???\n"); } SlirpCb cb = @@ -205,7 +206,11 @@ bool Init() void DeInit() { - slirp_cleanup(Ctx); + if (Ctx) + { + slirp_cleanup(Ctx); + Ctx = nullptr; + } } @@ -411,6 +416,8 @@ void HandleDNSFrame(u8* data, int len) int SendPacket(u8* data, int len) { + if (!Ctx) return 0; + if (len > 2048) { printf("LAN_SendPacket: error: packet too long (%d)\n", len); @@ -496,6 +503,8 @@ int SlirpCbGetREvents(int idx, void* opaque) int RecvPacket(u8* data) { + if (!Ctx) return 0; + int ret = 0; if (FDListSize > 0) -- cgit v1.2.3 From b31e049b3068683f3eac4a2deba4686aa3471a67 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 21 Jun 2020 01:43:32 +0200 Subject: wifi fixes and shit. getting there, somewhat. --- src/DSi_NWifi.cpp | 733 +++++++++++++++++++------------------ src/DSi_NWifi.h | 5 +- src/FIFO.h | 2 + src/frontend/qt_sdl/LAN_Socket.cpp | 104 +++--- 4 files changed, 440 insertions(+), 404 deletions(-) (limited to 'src') diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index d158974..84b39fa 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -125,10 +125,8 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) for (int i = 0; i < 8; i++) Mailbox[i] = new FIFO(0x600);//0x80); - // extra FIFOs acting as bigger TX/RX buffers, to work on frames - // bigger than 0x80 - //Mailbox[8] = new FIFO(0x608); - //Mailbox[9] = new FIFO(0x608); + // extra mailbox acting as a bigger RX buffer + Mailbox[8] = new FIFO(0x8000); // this seems to control whether the firmware upload is done EEPROMReady = 0; @@ -138,7 +136,7 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) DSi_NWifi::~DSi_NWifi() { - for (int i = 0; i < 8; i++) + for (int i = 0; i < 9; i++) delete Mailbox[i]; NDS::CancelEvent(NDS::Event_DSi_NWifi); @@ -160,7 +158,7 @@ void DSi_NWifi::Reset() WindowReadAddr = 0; WindowWriteAddr = 0; - for (int i = 0; i < 8; i++) + for (int i = 0; i < 9; i++) Mailbox[i]->Clear(); u8* mac = SPI_Firmware::GetWifiMAC(); @@ -183,6 +181,8 @@ void DSi_NWifi::Reset() *(u16*)&EEPROM[0x004] = chk; + // TODO: SDIO reset shouldn't reset this + // this is reset by the internal reset register, and that also resets EEPROM init BootPhase = 0; ErrorMask = 0; @@ -308,6 +308,7 @@ u8 DSi_NWifi::F1_Read(u32 addr) if (addr < 0x100) { u8 ret = Mailbox[4]->Read(); + if (addr == 0xFF) DrainRXBuffer(); UpdateIRQ_F1(); return ret; } @@ -373,6 +374,7 @@ u8 DSi_NWifi::F1_Read(u32 addr) else if (addr < 0x1000) { u8 ret = Mailbox[4]->Read(); + if (addr == 0xFFF) DrainRXBuffer(); UpdateIRQ_F1(); return ret; } @@ -397,11 +399,12 @@ u8 DSi_NWifi::F1_Read(u32 addr) else { u8 ret = Mailbox[4]->Read(); + if (addr == 0x3FFF) DrainRXBuffer(); UpdateIRQ_F1(); return ret; } - printf("NWIFI: unknown func1 read %05X\n", addr); + //printf("NWIFI: unknown func1 read %05X\n", addr); return 0; } @@ -859,287 +862,257 @@ void DSi_NWifi::WMI_Command() u8 ep = h0 & 0xFF; if (ep > 0x01) // data endpoints - { + {printf("WMI PACKET %04X:%04X:%04X\n", h0, len, h2); WMI_SendPacket(len); - MB_Drain(0); - return; } - - u16 cmd = MB_Read16(0); - - switch (cmd) + else { - case 0x0001: // connect to network - { - WMI_ConnectToNetwork(); - SendWMIAck(); - } - break; - - case 0x0003: // disconnect - { - if (ConnectionStatus != 1) - printf("WMI: ?? trying to disconnect while not connected\n"); - - printf("WMI: disconnect\n"); - ConnectionStatus = 0; - - u8 reply[10]; - *(u16*)&reply[0] = 3; // checkme - memcpy(&reply[2], WifiAP::APMac, 6); - reply[8] = 3; // disconnect reason (via cmd) - reply[9] = 0; // assoc-response length (?????) - SendWMIEvent(1, 0x1003, reply, 10); - - SendWMIAck(); - } - break; - - case 0x0004: // synchronize - { - Mailbox[0]->Read(); - // TODO?? - - SendWMIAck(); - } - break; - - case 0x0005: // create priority stream - { - // TODO??? - // there's a lot of crap in there. - - SendWMIAck(); - } - break; - - case 0x0007: // start scan + u16 cmd = MB_Read16(0); + printf("WMI CMD: %04X:%04X:%04X %04X\n", h0, len, h2, cmd); + for (int i = 0; i < len-2; i++) + { + printf("%02X ", Mailbox[0]->Peek(i)); + if ((i&0xF)==0xF) printf("\n"); + } + printf("\n"); + switch (cmd) { - u32 forcefg = MB_Read32(0); - u32 legacy = MB_Read32(0); - u32 scantime = MB_Read32(0); - u32 forceinterval = MB_Read32(0); - u8 scantype = Mailbox[0]->Read(); - u8 nchannels = Mailbox[0]->Read(); - - printf("WMI: start scan, forceFG=%d, legacy=%d, scanTime=%d, interval=%d, scanType=%d, chan=%d\n", - forcefg, legacy, scantime, forceinterval, scantype, nchannels); - - if (ScanTimer > 0) + case 0x0001: // connect to network { - printf("!! CHECKME: START SCAN BUT WAS ALREADY SCANNING (%d)\n", ScanTimer); + WMI_ConnectToNetwork(); } + break; - // checkme - ScanTimer = scantime*5; - - SendWMIAck(); - } - break; + case 0x0003: // disconnect + { + if (ConnectionStatus != 1) + printf("WMI: ?? trying to disconnect while not connected\n"); + + printf("WMI: disconnect\n"); + ConnectionStatus = 0; + + u8 reply[10]; + *(u16*)&reply[0] = 3; // checkme + memcpy(&reply[2], WifiAP::APMac, 6); + reply[8] = 3; // disconnect reason (via cmd) + reply[9] = 0; // assoc-response length (?????) + SendWMIEvent(1, 0x1003, reply, 10); + } + break; - case 0x0008: // set scan params - { - // TODO: do something with the params!! + case 0x0004: // synchronize + { + Mailbox[0]->Read(); + // TODO?? + } + break; - SendWMIAck(); - } - break; + case 0x0005: // create priority stream + { + // TODO??? + // there's a lot of crap in there. + } + break; - case 0x0009: // set BSS filter - { - // TODO: do something with the params!! - u8 bssfilter = Mailbox[0]->Read(); - Mailbox[0]->Read(); - Mailbox[0]->Read(); - Mailbox[0]->Read(); - u32 iemask = MB_Read32(0); + case 0x0007: // start scan + { + u32 forcefg = MB_Read32(0); + u32 legacy = MB_Read32(0); + u32 scantime = MB_Read32(0); + u32 forceinterval = MB_Read32(0); + u8 scantype = Mailbox[0]->Read(); + u8 nchannels = Mailbox[0]->Read(); - printf("WMI: set BSS filter, filter=%02X, iemask=%08X\n", bssfilter, iemask); + printf("WMI: start scan, forceFG=%d, legacy=%d, scanTime=%d, interval=%d, scanType=%d, chan=%d\n", + forcefg, legacy, scantime, forceinterval, scantype, nchannels); - SendWMIAck(); - } - break; + if (ScanTimer > 0) + { + printf("!! CHECKME: START SCAN BUT WAS ALREADY SCANNING (%d)\n", ScanTimer); + } - case 0x000A: // set probed BSSID - { - u8 id = Mailbox[0]->Read(); - u8 flags = Mailbox[0]->Read(); - u8 len = Mailbox[0]->Read(); + // checkme + ScanTimer = scantime*5; + } + break; - char ssid[33] = {0}; - for (int i = 0; i < len && i < 32; i++) - ssid[i] = Mailbox[0]->Read(); + case 0x0008: // set scan params + { + // TODO: do something with the params!! + } + break; - // TODO: store it somewhere - printf("WMI: set probed SSID: id=%d, flags=%02X, len=%d, SSID=%s\n", id, flags, len, ssid); + case 0x0009: // set BSS filter + { + // TODO: do something with the params!! + u8 bssfilter = Mailbox[0]->Read(); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + u32 iemask = MB_Read32(0); + + printf("WMI: set BSS filter, filter=%02X, iemask=%08X\n", bssfilter, iemask); + } + break; - SendWMIAck(); - } - break; + case 0x000A: // set probed BSSID + { + u8 id = Mailbox[0]->Read(); + u8 flags = Mailbox[0]->Read(); + u8 len = Mailbox[0]->Read(); - case 0x000D: // set disconnect timeout - { - Mailbox[0]->Read(); - // TODO?? + char ssid[33] = {0}; + for (int i = 0; i < len && i < 32; i++) + ssid[i] = Mailbox[0]->Read(); - SendWMIAck(); - } - break; + // TODO: store it somewhere + printf("WMI: set probed SSID: id=%d, flags=%02X, len=%d, SSID=%s\n", id, flags, len, ssid); + } + break; - case 0x000E: // get channel list - { - int nchan = 11; // TODO: customize?? - u8 reply[2 + (nchan*2) + 2]; + case 0x000D: // set disconnect timeout + { + Mailbox[0]->Read(); + // TODO?? + } + break; - reply[0] = 0; - reply[1] = nchan; - for (int i = 0; i < nchan; i++) - *(u16*)&reply[2 + (i*2)] = 2412 + (i*5); - *(u16*)&reply[2 + (nchan*2)] = 0; + case 0x000E: // get channel list + { + int nchan = 11; // TODO: customize?? + u8 reply[2 + (nchan*2) + 2]; - SendWMIEvent(1, 0x000E, reply, 4+(nchan*2)); + reply[0] = 0; + reply[1] = nchan; + for (int i = 0; i < nchan; i++) + *(u16*)&reply[2 + (i*2)] = 2412 + (i*5); + *(u16*)&reply[2 + (nchan*2)] = 0; - SendWMIAck(); - } - break; + SendWMIEvent(1, 0x000E, reply, 4+(nchan*2)); + } + break; - case 0x0011: // set channel params - { - Mailbox[0]->Read(); - u8 scan = Mailbox[0]->Read(); - u8 phymode = Mailbox[0]->Read(); - u8 len = Mailbox[0]->Read(); - - u16 channels[32]; - for (int i = 0; i < len && i < 32; i++) - channels[i] = MB_Read16(0); - - // TODO: store it somewhere - printf("WMI: set channel params: scan=%d, phymode=%d, len=%d, channels=", scan, phymode, len); - for (int i = 0; i < len && i < 32; i++) - printf("%d,", channels[i]); - printf("\n"); + case 0x0011: // set channel params + { + Mailbox[0]->Read(); + u8 scan = Mailbox[0]->Read(); + u8 phymode = Mailbox[0]->Read(); + u8 len = Mailbox[0]->Read(); + + u16 channels[32]; + for (int i = 0; i < len && i < 32; i++) + channels[i] = MB_Read16(0); + + // TODO: store it somewhere + printf("WMI: set channel params: scan=%d, phymode=%d, len=%d, channels=", scan, phymode, len); + for (int i = 0; i < len && i < 32; i++) + printf("%d,", channels[i]); + printf("\n"); + } + break; - SendWMIAck(); - } - break; + case 0x0012: // set power mode + { + Mailbox[0]->Read(); + // TODO?? + } + break; - case 0x0012: // set power mode - { + case 0x0017: // dummy? Mailbox[0]->Read(); - // TODO?? - - SendWMIAck(); - } - break; - - case 0x0017: // dummy? - Mailbox[0]->Read(); - SendWMIAck(); - break; - - case 0x0022: // set error bitmask - { - ErrorMask = MB_Read32(0); + break; - SendWMIAck(); - } - break; + case 0x0022: // set error bitmask + { + ErrorMask = MB_Read32(0); + } + break; - case 0x002E: // extension shit - { - u16 extcmd = MB_Read16(0); - switch (extcmd) + case 0x002E: // extension shit { - case 0x2008: // 'heartbeat'?? + u32 extcmd = MB_Read32(0); + switch (extcmd) { - u32 cookie = MB_Read32(0); - u32 source = MB_Read32(0); - - u8 reply[10]; - *(u16*)&reply[0] = 0x3007; - *(u32*)&reply[2] = cookie; - *(u32*)&reply[6] = source; - SendWMIEvent(1, 0x1010, reply, 10); + case 0x2008: // 'heartbeat'?? + { + u32 cookie = MB_Read32(0); + u32 source = MB_Read32(0); + + u8 reply[12]; + *(u32*)&reply[0] = 0x3007; + *(u32*)&reply[4] = cookie; + *(u32*)&reply[8] = source; + + if(ConnectionStatus==1)SendWMIEvent(1, 0x1010, reply, 12); + } + break; + + default: + printf("WMI: unknown ext cmd 002E:%04X\n", extcmd); + break; } - break; - - default: - printf("WMI: unknown ext cmd 002E:%04X\n", extcmd); - break; } + break; - SendWMIAck(); - } - break; - - case 0x003D: // set keepalive interval - { - Mailbox[0]->Read(); - // TODO?? - - SendWMIAck(); - } - break; - - case 0x0041: // 'WMI_SET_WSC_STATUS_CMD' - { - Mailbox[0]->Read(); - // TODO?? - - SendWMIAck(); - } - break; - - case 0x0047: // cmd47 -- timer shenanigans?? - { - // - - SendWMIAck(); - } - break; - - case 0x0048: // not supported by DSi?? - { - MB_Read32(0); - MB_Read32(0); - Mailbox[0]->Read(); - Mailbox[0]->Read(); + case 0x003D: // set keepalive interval + { + Mailbox[0]->Read(); + // TODO?? + } + break; - SendWMIAck(); - } - break; + case 0x0041: // 'WMI_SET_WSC_STATUS_CMD' + { + Mailbox[0]->Read(); + // TODO?? + } + break; - case 0x0049: // 'host exit notify' - { - // + case 0x0047: // cmd47 -- timer shenanigans?? + { + // + } + break; - SendWMIAck(); - } - break; + case 0x0048: // not supported by DSi?? + { + MB_Read32(0); + MB_Read32(0); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + } + break; - case 0xF000: // set bitrate - { - // TODO! - Mailbox[0]->Read(); - Mailbox[0]->Read(); - Mailbox[0]->Read(); + case 0x0049: // 'host exit notify' + { + // + } + break; - SendWMIAck(); - } - break; + case 0xF000: // set bitrate + { + // TODO! + Mailbox[0]->Read(); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + } + break; - default: - printf("unknown WMI command %04X (header: %04X:%04X:%04X)\n", cmd, h0, len, h2); - for (int i = 0; i < len-2; i++) - { - printf("%02X ", Mailbox[0]->Read()); - if ((i&0xF)==0xF) printf("\n"); + default: + printf("unknown WMI command %04X (header: %04X:%04X:%04X)\n", cmd, h0, len, h2); + for (int i = 0; i < len-2; i++) + { + printf("%02X ", Mailbox[0]->Read()); + if ((i&0xF)==0xF) printf("\n"); + } + printf("\n"); + break; } - printf("\n"); - break; } + if (h0 & (1<<8)) + SendWMIAck(ep); + MB_Drain(0); } @@ -1210,9 +1183,30 @@ void DSi_NWifi::WMI_SendPacket(u16 len) return; } + // header??? + // packets with bit1=1 are something special (sync??) + // otherwise, ???? + // header is 001C on ARP frames, 0000 otherwise u16 hdr = MB_Read16(0); hdr = ((hdr & 0xFF00) >> 8) | ((hdr & 0x00FF) << 8); - if (hdr & 0x0003) + u16 type = hdr & 0x0003; + + if (type == 2) // data sync + { + printf("WMI: data sync\n"); + + /*Mailbox[8]->Write(2); // eid + Mailbox[8]->Write(0x00); // flags + MB_Write16(8, 2); // data length + Mailbox[8]->Write(0); // + Mailbox[8]->Write(0); // + MB_Write16(8, 0x0200); // + + DrainRXBuffer();*/ + return; + } + + if (type) { printf("WMI: special frame %04X len=%d\n", hdr, len); for (int i = 0; i < len-2; i++) @@ -1224,7 +1218,7 @@ void DSi_NWifi::WMI_SendPacket(u16 len) return; } - printf("WMI: send packet, len=%d\n", len); + printf("WMI: send packet, hdr=%04X, len=%d\n", hdr, len); u8 dstmac[6]; u8 srcmac[6]; @@ -1264,130 +1258,125 @@ void DSi_NWifi::WMI_SendPacket(u16 len) LANBuffer[14+i] = Mailbox[0]->Read(); } - for (int i = 0; i < lan_len; i++) + /*for (int i = 0; i < lan_len; i++) { printf("%02X ", LANBuffer[i]); if ((i&0xF)==0xF) printf("\n"); } - printf("\n"); + printf("\n");*/ Platform::LAN_SendPacket(LANBuffer, lan_len); } -//void DSi_NWifi::SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl) void DSi_NWifi::SendWMIEvent(u8 ep, u16 id, u8* data, u32 len) { - u32 wlen = 0; + if (!Mailbox[8]->CanFit(6+len+2+8)) + { + printf("NWifi: !! not enough space in RX buffer for WMI event %04X\n", id); + return; + } - Mailbox[4]->Write(ep); // eid - Mailbox[4]->Write(0x02); // flags (trailer) - MB_Write16(4, len+2+8); // data length (plus event ID and trailer) - Mailbox[4]->Write(8); // trailer length - Mailbox[4]->Write(0); // - MB_Write16(4, id); // event ID - wlen += 8; + Mailbox[8]->Write(ep); // eid + Mailbox[8]->Write(0x02); // flags (trailer) + MB_Write16(8, len+2+8); // data length (plus event ID and trailer) + Mailbox[8]->Write(8); // trailer length + Mailbox[8]->Write(0); // + MB_Write16(8, id); // event ID for (int i = 0; i < len; i++) { - Mailbox[4]->Write(data[i]); - wlen++; + Mailbox[8]->Write(data[i]); } // trailer - Mailbox[4]->Write(0x02); - Mailbox[4]->Write(0x06); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - wlen += 8; - - for (; wlen & 0x7F; wlen++) - Mailbox[4]->Write(0); + Mailbox[8]->Write(0x02); + Mailbox[8]->Write(0x06); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + + DrainRXBuffer(); } -void DSi_NWifi::SendWMIAck() +void DSi_NWifi::SendWMIAck(u8 ep) { - u32 wlen = 0; - - Mailbox[4]->Write(0); // eid - Mailbox[4]->Write(0x02); // flags (trailer) - MB_Write16(4, 0xC); // data length (plus event ID and trailer) - Mailbox[4]->Write(0xC); // trailer length - Mailbox[4]->Write(0); // - wlen += 6; + if (!Mailbox[8]->CanFit(6+12)) + { + printf("NWifi: !! not enough space in RX buffer for WMI ack (ep #%d)\n", ep); + return; + } - // trailer - Mailbox[4]->Write(0x01); - Mailbox[4]->Write(0x02); - Mailbox[4]->Write(0x01); - Mailbox[4]->Write(0x01); - Mailbox[4]->Write(0x02); - Mailbox[4]->Write(0x06); - - // observed trailer data: - // 00 06 00 00 02 00 (in the first few responses) - // 00 00 00 00 00 00 - // TODO: work out what that all means? - // does software even care? - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x06); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x02); - Mailbox[4]->Write(0x00); - wlen += 0xC; - - for (; wlen & 0x7F; wlen++) - Mailbox[4]->Write(0); + Mailbox[8]->Write(0); // eid + Mailbox[8]->Write(0x02); // flags (trailer) + MB_Write16(8, 0xC); // data length (plus trailer) + Mailbox[8]->Write(0xC); // trailer length + Mailbox[8]->Write(0); // + + // credit report + Mailbox[8]->Write(0x01); + Mailbox[8]->Write(0x02); + Mailbox[8]->Write(ep); + Mailbox[8]->Write(0x01); + + // lookahead + Mailbox[8]->Write(0x02); + Mailbox[8]->Write(0x06); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + + DrainRXBuffer(); } void DSi_NWifi::SendWMIBSSInfo(u8 type, u8* data, u32 len) { - u32 wlen = 0; - - // TODO: what is the trailer about????? - // on hardware I observed one frame with trailer and another without - // plus it's different from other frames + if (!Mailbox[8]->CanFit(6+len+2+16)) + { + printf("NWifi: !! not enough space in RX buffer for WMI BSSINFO event\n"); + return; + } // TODO: check when version>=2 frame type is used? // I observed the version<2 variant on my DSi - Mailbox[4]->Write(1); // eid - Mailbox[4]->Write(0x00); // flags - MB_Write16(4, len+2+16); // data length (plus event ID and trailer) - Mailbox[4]->Write(0xFF); // trailer length - Mailbox[4]->Write(0xFF); // - MB_Write16(4, 0x1004); // event ID - wlen += 8; - - MB_Write16(4, 2437); // channel (6) (checkme!) - Mailbox[4]->Write(type); - Mailbox[4]->Write(0x1B); // 'snr' - MB_Write16(4, 0xFFBC); // RSSI - MB_Write32(4, *(u32*)&WifiAP::APMac[0]); - MB_Write16(4, *(u16*)&WifiAP::APMac[4]); - MB_Write32(4, 0); // ieMask - wlen += 16; + Mailbox[8]->Write(1); // eid + Mailbox[8]->Write(0x00); // flags + MB_Write16(8, len+2+16); // data length (plus event ID and trailer) + Mailbox[8]->Write(0xFF); // trailer length + Mailbox[8]->Write(0xFF); // + MB_Write16(8, 0x1004); // event ID + + MB_Write16(8, 2437); // channel (6) (checkme!) + Mailbox[8]->Write(type); + Mailbox[8]->Write(0x1B); // 'snr' + MB_Write16(8, 0xFFBC); // RSSI + MB_Write32(8, *(u32*)&WifiAP::APMac[0]); + MB_Write16(8, *(u16*)&WifiAP::APMac[4]); + MB_Write32(8, 0); // ieMask for (int i = 0; i < len; i++) { - Mailbox[4]->Write(data[i]); - wlen++; + Mailbox[8]->Write(data[i]); } - for (; wlen & 0x7F; wlen++) - Mailbox[4]->Write(0); + DrainRXBuffer(); } void DSi_NWifi::CheckRX() { + if (!Mailbox[8]->CanFit(2048)) + return; + int rxlen = Platform::LAN_RecvPacket(LANBuffer); if (rxlen > 0) { - printf("WMI packet recv %04X %04X %04X\n", *(u16*)&LANBuffer[0], *(u16*)&LANBuffer[2], *(u16*)&LANBuffer[4]); + //printf("WMI packet recv %04X %04X %04X\n", *(u16*)&LANBuffer[0], *(u16*)&LANBuffer[2], *(u16*)&LANBuffer[4]); // check destination MAC if (*(u32*)&LANBuffer[0] != 0xFFFFFFFF || *(u16*)&LANBuffer[4] != 0xFFFF) { @@ -1403,39 +1392,47 @@ void DSi_NWifi::CheckRX() printf("WMI: receive packet %04X, len=%d\n", *(u16*)&LANBuffer[12], rxlen); + /*for (int i = 0; i < rxlen; i++) + { + printf("%02X ", LANBuffer[i]); + if ((i&0xF)==0xF) printf("\n"); + } + printf("\n");*/ + int datalen = rxlen - 14; // length of packet body - int wlen = 0; - MB_Write16(4, 0x0002); - MB_Write16(4, 16 + 8 + datalen); - MB_Write16(4, 0x0000); - wlen += 6; - - MB_Write16(4, 0x0000); - MB_Write32(4, *(u32*)&LANBuffer[0]); - MB_Write16(4, *(u16*)&LANBuffer[4]); - MB_Write32(4, *(u32*)&LANBuffer[6]); - MB_Write16(4, *(u16*)&LANBuffer[10]); + u16 hdr = 0x0000; + //if (*(u16*)&LANBuffer[12] == 0x0608) // HAX!!! + // hdr = 0x1C00; + hdr = 0x80; + + // TODO: not hardcode the endpoint ID!! + u8 ep = 2; + + Mailbox[8]->Write(ep); + Mailbox[8]->Write(0x00); + MB_Write16(8, 16 + 8 + datalen); + Mailbox[8]->Write(0); + Mailbox[8]->Write(0); + + MB_Write16(8, hdr); + MB_Write32(8, *(u32*)&LANBuffer[0]); + MB_Write16(8, *(u16*)&LANBuffer[4]); + MB_Write32(8, *(u32*)&LANBuffer[6]); + MB_Write16(8, *(u16*)&LANBuffer[10]); u16 plen = datalen + 8; plen = ((plen & 0xFF00) >> 8) | ((plen & 0x00FF) << 8); - MB_Write16(4, plen); - wlen += 16; + MB_Write16(8, plen); - MB_Write16(4, 0xAAAA); - MB_Write16(4, 0x0003); - MB_Write16(4, 0x0000); - MB_Write16(4, *(u16*)&LANBuffer[12]); - wlen += 8; + MB_Write16(8, 0xAAAA); + MB_Write16(8, 0x0003); + MB_Write16(8, 0x0000); + MB_Write16(8, *(u16*)&LANBuffer[12]); for (int i = 0; i < datalen; i++) - Mailbox[4]->Write(LANBuffer[14+i]); + Mailbox[8]->Write(LANBuffer[14+i]); - wlen += datalen; - - for (; wlen & 0x7F; wlen++) - Mailbox[4]->Write(0); - - UpdateIRQ_F1(); + DrainRXBuffer(); } } @@ -1510,7 +1507,6 @@ void DSi_NWifi::_MSTimer() }; SendWMIBSSInfo(0x01, beacon, sizeof(beacon)); - UpdateIRQ_F1(); printf("send beacon\n"); } @@ -1518,14 +1514,33 @@ void DSi_NWifi::_MSTimer() { u32 status = 0; SendWMIEvent(1, 0x100A, (u8*)&status, 4); - UpdateIRQ_F1(); } } if (ConnectionStatus == 1) { - CheckRX(); + //if (Mailbox[4]->IsEmpty()) + CheckRX(); + } +} + +void DSi_NWifi::DrainRXBuffer() +{ + while (Mailbox[8]->Level() >= 6) + { + u16 len = Mailbox[8]->Peek(2) | (Mailbox[8]->Peek(3) << 8); + u32 totallen = len + 6; + u32 required = (totallen + 0x7F) & ~0x7F; + + if (!Mailbox[4]->CanFit(required)) + break; + + u32 i = 0; + for (; i < totallen; i++) Mailbox[4]->Write(Mailbox[8]->Read()); + for (; i < required; i++) Mailbox[4]->Write(0); } + + UpdateIRQ_F1(); } void DSi_NWifi::MSTimer(u32 param) diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index 14a5d14..a72d54d 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -73,10 +73,11 @@ private: void WMI_SendPacket(u16 len); void SendWMIEvent(u8 ep, u16 id, u8* data, u32 len); - void SendWMIAck(); + void SendWMIAck(u8 ep); void SendWMIBSSInfo(u8 type, u8* data, u32 len); void CheckRX(); + void DrainRXBuffer(); u32 WindowRead(u32 addr); void WindowWrite(u32 addr, u32 val); @@ -116,7 +117,7 @@ private: while (!Mailbox[n]->IsEmpty()) Mailbox[n]->Read(); } - FIFO* Mailbox[10]; + FIFO* Mailbox[9]; u8 F0_IRQEnable; u8 F0_IRQStatus; diff --git a/src/FIFO.h b/src/FIFO.h index fe0b2aa..2b2c102 100644 --- a/src/FIFO.h +++ b/src/FIFO.h @@ -102,6 +102,8 @@ public: bool IsEmpty() { return NumOccupied == 0; } bool IsFull() { return NumOccupied >= NumEntries; } + bool CanFit(u32 num) { return ((NumOccupied + num) <= NumEntries); } + private: u32 NumEntries; T* Entries; diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp index 13a8eb1..6232964 100644 --- a/src/frontend/qt_sdl/LAN_Socket.cpp +++ b/src/frontend/qt_sdl/LAN_Socket.cpp @@ -22,9 +22,10 @@ #include #include #include -#include "../Wifi.h" +#include "Wifi.h" #include "LAN_Socket.h" -#include "../Config.h" +#include "Config.h" +#include "FIFO.h" #include @@ -46,9 +47,7 @@ const u32 kClientIP = kSubnet | 0x10; const u8 kServerMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x44}; const u8 kDNSMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x55}; -u8 PacketBuffer[2048]; -int PacketLen; -volatile int RXNum; +FIFO* RXBuffer = nullptr; u32 IPv4ID; @@ -81,6 +80,23 @@ int clock_gettime(int, struct timespec *spec) #endif // __WIN32__ +void RXEnqueue(const void* buf, int len) +{ + int alignedlen = (len + 3) & ~3; + int totallen = alignedlen + 4; + + if (!RXBuffer->CanFit(totallen >> 2)) + { + printf("slirp: !! NOT ENOUGH SPACE IN RX BUFFER\n"); + return; + } + + u32 header = (alignedlen & 0xFFFF) | (len << 16); + RXBuffer->Write(header); + for (int i = 0; i < alignedlen; i += 4) + RXBuffer->Write(((u32*)buf)[i>>2]); +} + ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque) { if (len > 2048) @@ -91,9 +107,7 @@ ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque) printf("slirp: response packet of %d bytes, type %04X\n", len, ntohs(((u16*)buf)[6])); - PacketLen = len; - memcpy(PacketBuffer, buf, PacketLen); - RXNum = 1; + RXEnqueue(buf, len); return len; } @@ -127,7 +141,7 @@ void SlirpCbRegisterPollFD(int fd, void* opaque) { printf("Slirp: register poll FD %d\n", fd); - if (FDListSize >= FDListMax) + /*if (FDListSize >= FDListMax) { printf("!! SLIRP FD LIST FULL\n"); return; @@ -139,14 +153,14 @@ void SlirpCbRegisterPollFD(int fd, void* opaque) } FDList[FDListSize].fd = fd; - FDListSize++; + FDListSize++;*/ } void SlirpCbUnregisterPollFD(int fd, void* opaque) { printf("Slirp: unregister poll FD %d\n", fd); - if (FDListSize < 1) + /*if (FDListSize < 1) { printf("!! SLIRP FD LIST EMPTY\n"); return; @@ -159,7 +173,7 @@ void SlirpCbUnregisterPollFD(int fd, void* opaque) FDListSize--; FDList[i] = FDList[FDListSize]; } - } + }*/ } void SlirpCbNotify(void* opaque) @@ -187,6 +201,8 @@ bool Init() FDListSize = 0; memset(FDList, 0, sizeof(FDList)); + RXBuffer = new FIFO(0x8000 >> 2); + SlirpConfig cfg; memset(&cfg, 0, sizeof(cfg)); cfg.version = 1; @@ -211,6 +227,12 @@ void DeInit() slirp_cleanup(Ctx); Ctx = nullptr; } + + if (RXBuffer) + { + delete RXBuffer; + RXBuffer = nullptr; + } } @@ -379,6 +401,7 @@ void HandleDNSFrame(u8* data, int len) addr_res & 0xFF, (addr_res >> 8) & 0xFF, (addr_res >> 16) & 0xFF, addr_res >> 24); + break; p = p->ai_next; } } @@ -405,13 +428,7 @@ void HandleDNSFrame(u8* data, int len) if (framelen & 1) { *out++ = 0; framelen++; } FinishUDPFrame(resp, framelen); - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; + RXEnqueue(resp, framelen); } int SendPacket(u8* data, int len) @@ -444,24 +461,20 @@ int SendPacket(u8* data, int len) return len; } +const int PollListMax = 64; +struct pollfd PollList[PollListMax]; +int PollListSize; + int SlirpCbAddPoll(int fd, int events, void* opaque) { - int idx = -1; - for (int i = 0; i < FDListSize; i++) - { - if (FDList[i].fd == fd) - { - idx = i; - break; - } - } - - if (idx == -1) + if (PollListSize >= PollListMax) { - printf("SLIRP: ERROR! FD %d NOT REGISTERED\n", fd); + printf("slirp: POLL LIST FULL\n"); return -1; } + int idx = PollListSize++; + //printf("Slirp: add poll: fd=%d, idx=%d, events=%08X\n", fd, idx, events); u16 evt = 0; @@ -470,26 +483,26 @@ int SlirpCbAddPoll(int fd, int events, void* opaque) if (events & SLIRP_POLL_OUT) evt |= POLLWRNORM; #ifndef __WIN32__ + // CHECKME if (events & SLIRP_POLL_PRI) evt |= POLLPRI; if (events & SLIRP_POLL_ERR) evt |= POLLERR; if (events & SLIRP_POLL_HUP) evt |= POLLHUP; #endif // !__WIN32__ - FDList[idx].events = evt; + PollList[idx].fd = fd; + PollList[idx].events = evt; + return idx; } int SlirpCbGetREvents(int idx, void* opaque) { - if (idx < 0 || idx >= FDListSize) - { - printf("SLIRP: !! BAD FD INDEX %d (MAX %d)\n", idx, FDListSize); + if (idx < 0 || idx >= PollListSize) return 0; - } //printf("Slirp: get revents, idx=%d, res=%04X\n", idx, FDList[idx].revents); - u16 evt = FDList[idx].revents; + u16 evt = PollList[idx].revents; int ret = 0; if (evt & POLLIN) ret |= SLIRP_POLL_IN; @@ -507,19 +520,24 @@ int RecvPacket(u8* data) int ret = 0; - if (FDListSize > 0) + //if (PollListSize > 0) { u32 timeout = 0; + PollListSize = 0; slirp_pollfds_fill(Ctx, &timeout, SlirpCbAddPoll, nullptr); - int res = poll(FDList, FDListSize, timeout); + int res = poll(PollList, PollListSize, timeout); slirp_pollfds_poll(Ctx, res<0, SlirpCbGetREvents, nullptr); } - if (RXNum > 0) + if (!RXBuffer->IsEmpty()) { - memcpy(data, PacketBuffer, PacketLen); - ret = PacketLen; - RXNum = 0; + u32 header = RXBuffer->Read(); + u32 len = header & 0xFFFF; + + for (int i = 0; i < len; i += 4) + ((u32*)data)[i>>2] = RXBuffer->Read(); + + ret = header >> 16; } return ret; -- cgit v1.2.3 From 7132e11bd4cf9edfe5e15506e649cd655945f291 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 21 Jun 2020 10:29:08 +0200 Subject: make it work without a hack --- src/DSi_NWifi.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 84b39fa..73cf4b4 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -862,19 +862,13 @@ void DSi_NWifi::WMI_Command() u8 ep = h0 & 0xFF; if (ep > 0x01) // data endpoints - {printf("WMI PACKET %04X:%04X:%04X\n", h0, len, h2); + { WMI_SendPacket(len); } else { u16 cmd = MB_Read16(0); - printf("WMI CMD: %04X:%04X:%04X %04X\n", h0, len, h2, cmd); - for (int i = 0; i < len-2; i++) - { - printf("%02X ", Mailbox[0]->Peek(i)); - if ((i&0xF)==0xF) printf("\n"); - } - printf("\n"); + switch (cmd) { case 0x0001: // connect to network @@ -891,12 +885,13 @@ void DSi_NWifi::WMI_Command() printf("WMI: disconnect\n"); ConnectionStatus = 0; - u8 reply[10]; + u8 reply[11]; *(u16*)&reply[0] = 3; // checkme memcpy(&reply[2], WifiAP::APMac, 6); reply[8] = 3; // disconnect reason (via cmd) - reply[9] = 0; // assoc-response length (?????) - SendWMIEvent(1, 0x1003, reply, 10); + reply[9] = 0; // assoc-response length (none here) + reply[10] = 0; // we need atleast one byte here, even if there is no assoc-response + SendWMIEvent(1, 0x1003, reply, 11); } break; @@ -1043,7 +1038,7 @@ void DSi_NWifi::WMI_Command() *(u32*)&reply[4] = cookie; *(u32*)&reply[8] = source; - if(ConnectionStatus==1)SendWMIEvent(1, 0x1010, reply, 12); + SendWMIEvent(1, 0x1010, reply, 12); } break; -- cgit v1.2.3 From e43a216ab55f72a6ba1a98046abc3770a4217eb4 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 21 Jun 2020 11:02:42 +0200 Subject: take care of some minor details --- src/SPI.cpp | 34 +++++++++++++++++++--------------- src/Wifi.cpp | 2 ++ 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/SPI.cpp b/src/SPI.cpp index ac40707..eff0a05 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -162,22 +162,26 @@ void Reset() UserSettings = userdata; - // fix touchscreen coords - #if 0 - *(u16*)&Firmware[userdata+0x58] = 0; - *(u16*)&Firmware[userdata+0x5A] = 0; - Firmware[userdata+0x5C] = 0; - Firmware[userdata+0x5D] = 0; - *(u16*)&Firmware[userdata+0x5E] = 255<<4; - *(u16*)&Firmware[userdata+0x60] = 191<<4; - Firmware[userdata+0x62] = 255; - Firmware[userdata+0x63] = 191; - - // disable autoboot - //Firmware[userdata+0x64] &= 0xBF; - - *(u16*)&Firmware[userdata+0x72] = CRC16(&Firmware[userdata], 0x70, 0xFFFF); + // TODO evetually: do this in DSi mode + if (NDS::ConsoleType == 0) + { + // fix touchscreen coords + *(u16*)&Firmware[userdata+0x58] = 0; + *(u16*)&Firmware[userdata+0x5A] = 0; + Firmware[userdata+0x5C] = 0; + Firmware[userdata+0x5D] = 0; + *(u16*)&Firmware[userdata+0x5E] = 255<<4; + *(u16*)&Firmware[userdata+0x60] = 191<<4; + Firmware[userdata+0x62] = 255; + Firmware[userdata+0x63] = 191; + + // disable autoboot + //Firmware[userdata+0x64] &= 0xBF; + + *(u16*)&Firmware[userdata+0x72] = CRC16(&Firmware[userdata], 0x70, 0xFFFF); + } +#if 0 // replace MAC address with random address // TODO: make optional? Firmware[0x36] = 0x00; diff --git a/src/Wifi.cpp b/src/Wifi.cpp index ab82724..8188151 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -188,6 +188,8 @@ void Reset() IOPORT(0x000) = 0x1440; else if (console == 0x20) IOPORT(0x000) = 0xC340; + else if (NDS::ConsoleType == 1 && console == 0x57) + IOPORT(0x000) = 0xC340; // DSi has the modern DS-wifi variant else { printf("wifi: unknown console type %02X\n", console); -- cgit v1.2.3 From ff69df2a15bdb6cac618a9b19f56ea1732e0f07e Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 21 Jun 2020 12:20:02 +0200 Subject: add AES-CCM encrypt makes the eShop work --- src/DSi_AES.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/DSi_AES.cpp b/src/DSi_AES.cpp index c7c599e..dfa67bd 100644 --- a/src/DSi_AES.cpp +++ b/src/DSi_AES.cpp @@ -165,9 +165,37 @@ void ProcessBlock_CCM_Decrypt() //printf("AES-CCM: "); _printhex2(data, 16); Swap16(data_rev, data); + AES_CTR_xcrypt_buffer(&Ctx, data_rev, 16); + for (int i = 0; i < 16; i++) CurMAC[i] ^= data_rev[i]; + AES_ECB_encrypt(&Ctx, CurMAC); + + Swap16(data, data_rev); + + //printf(" -> "); _printhex2(data, 16); + + OutputFIFO->Write(*(u32*)&data[0]); + OutputFIFO->Write(*(u32*)&data[4]); + OutputFIFO->Write(*(u32*)&data[8]); + OutputFIFO->Write(*(u32*)&data[12]); +} + +void ProcessBlock_CCM_Encrypt() +{ + u8 data[16]; + u8 data_rev[16]; + + *(u32*)&data[0] = InputFIFO->Read(); + *(u32*)&data[4] = InputFIFO->Read(); + *(u32*)&data[8] = InputFIFO->Read(); + *(u32*)&data[12] = InputFIFO->Read(); + + //printf("AES-CCM: "); _printhex2(data, 16); + + Swap16(data_rev, data); for (int i = 0; i < 16; i++) CurMAC[i] ^= data_rev[i]; + AES_CTR_xcrypt_buffer(&Ctx, data_rev, 16); AES_ECB_encrypt(&Ctx, CurMAC); Swap16(data, data_rev); @@ -232,7 +260,6 @@ void WriteCnt(u32 val) OutputDMASize = dmasize_out[(val >> 14) & 0x3]; AESMode = (val >> 28) & 0x3; - if (AESMode == 1) printf("AES-CCM TODO\n"); if (val & (1<<24)) { @@ -245,6 +272,8 @@ void WriteCnt(u32 val) // transfer start (checkme) RemBlocks = BlkCnt >> 16; + if (AESMode == 0 && (!(val & (1<<20)))) printf("AES: CCM-DECRYPT MAC FROM WRFIFO, TODO\n"); + if (RemBlocks > 0) { u8 key[16]; @@ -365,14 +394,9 @@ void Update() switch (AESMode) { case 0: ProcessBlock_CCM_Decrypt(); break; + case 1: ProcessBlock_CCM_Encrypt(); break; case 2: case 3: ProcessBlock_CTR(); break; - default: - // dorp - OutputFIFO->Write(InputFIFO->Read()); - OutputFIFO->Write(InputFIFO->Read()); - OutputFIFO->Write(InputFIFO->Read()); - OutputFIFO->Write(InputFIFO->Read()); } RemBlocks--; @@ -398,6 +422,24 @@ void Update() if (CurMAC[15-i] != MAC[i]) Cnt &= ~(1<<21); } } + else if (AESMode == 1) + { + Ctx.Iv[13] = 0x00; + Ctx.Iv[14] = 0x00; + Ctx.Iv[15] = 0x00; + AES_CTR_xcrypt_buffer(&Ctx, CurMAC, 16); + + u8 finalmac[16]; + Swap16(finalmac, CurMAC); + + OutputFIFO->Write(*(u32*)&finalmac[0]); + OutputFIFO->Write(*(u32*)&finalmac[4]); + OutputFIFO->Write(*(u32*)&finalmac[8]); + OutputFIFO->Write(*(u32*)&finalmac[12]); + + // CHECKME + Cnt &= ~(1<<21); + } else { // CHECKME -- cgit v1.2.3 From c32da212f14266f77767b18cdd75286902bde926 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 21 Jun 2020 15:44:56 +0200 Subject: make it possible to static-link libslirp --- src/frontend/qt_sdl/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 75dfbe2..4f9eae0 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -95,9 +95,9 @@ if (UNIX) elseif (WIN32) target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") - target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32 slirp.dll) + target_link_libraries(melonDS slirp comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) if (BUILD_STATIC) - target_link_libraries(melonDS imm32 winmm version setupapi -static Qt5::Core Qt5::Gui Qt5::Widgets z zstd) + target_link_libraries(melonDS imm32 winmm version setupapi -static Qt5::Core Qt5::Gui Qt5::Widgets z zstd glib-2.0 intl iconv) else() target_link_libraries(melonDS Qt5::Core Qt5::Gui Qt5::Widgets) endif() -- cgit v1.2.3 From d9e1bf737c23f688871b2f422bc710777dffbd94 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 21 Jun 2020 18:34:53 +0200 Subject: blarg --- src/frontend/qt_sdl/LAN_Socket.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp index 6232964..458c931 100644 --- a/src/frontend/qt_sdl/LAN_Socket.cpp +++ b/src/frontend/qt_sdl/LAN_Socket.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include "Wifi.h" #include "LAN_Socket.h" #include "Config.h" @@ -33,6 +32,9 @@ #include #else #include + #include + #include + #include #endif @@ -45,7 +47,6 @@ const u32 kDNSIP = kSubnet | 0x02; const u32 kClientIP = kSubnet | 0x10; const u8 kServerMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x44}; -const u8 kDNSMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x55}; FIFO* RXBuffer = nullptr; @@ -53,9 +54,9 @@ u32 IPv4ID; Slirp* Ctx = nullptr; -const int FDListMax = 64; +/*const int FDListMax = 64; struct pollfd FDList[FDListMax]; -int FDListSize; +int FDListSize;*/ #ifdef __WIN32__ @@ -198,8 +199,8 @@ bool Init() { IPv4ID = 0; - FDListSize = 0; - memset(FDList, 0, sizeof(FDList)); + //FDListSize = 0; + //memset(FDList, 0, sizeof(FDList)); RXBuffer = new FIFO(0x8000 >> 2); -- cgit v1.2.3 From 173e3b037c4b23b289563491135ad07a69bd365c Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Sun, 26 Jul 2020 22:08:57 +0200 Subject: Link iconv for Windows static builds --- src/frontend/qt_sdl/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 7451307..869b905 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -79,7 +79,7 @@ elseif (WIN32) target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) if (BUILD_STATIC) - target_link_libraries(melonDS imm32 winmm version setupapi -static Qt5::Core Qt5::Gui Qt5::Widgets z zstd) + target_link_libraries(melonDS imm32 winmm version setupapi -static Qt5::Core Qt5::Gui Qt5::Widgets z zstd iconv) else() target_link_libraries(melonDS Qt5::Core Qt5::Gui Qt5::Widgets) endif() -- cgit v1.2.3 From a1f939e0cb4ca834525543e83e58587e928917a1 Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Sun, 26 Jul 2020 22:16:53 +0200 Subject: use FindIconv and link it on all platforms when not built in --- src/frontend/qt_sdl/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 869b905..f1665f5 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -46,6 +46,7 @@ set(CMAKE_AUTORCC ON) find_package(Threads REQUIRED) find_package(PkgConfig REQUIRED) +find_package(Iconv REQUIRED) pkg_check_modules(SDL2 REQUIRED sdl2) pkg_check_modules(SLIRP REQUIRED slirp) @@ -70,6 +71,10 @@ else() target_link_libraries(melonDS ${SDL2_LIBRARIES} ${SLIRP_LIBRARIES}) endif() +if (NOT Iconv_IS_BUILT_IN) + target_link_libraries(melonDS ${Iconv_LIBRARIES}) +endif() + if (UNIX) option(PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF) target_link_libraries(melonDS dl Qt5::Core Qt5::Gui Qt5::Widgets) @@ -79,7 +84,7 @@ elseif (WIN32) target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) if (BUILD_STATIC) - target_link_libraries(melonDS imm32 winmm version setupapi -static Qt5::Core Qt5::Gui Qt5::Widgets z zstd iconv) + target_link_libraries(melonDS imm32 winmm version setupapi -static Qt5::Core Qt5::Gui Qt5::Widgets z zstd) else() target_link_libraries(melonDS Qt5::Core Qt5::Gui Qt5::Widgets) endif() -- cgit v1.2.3 From 6a682a8ef0d1cc3aa35eaa70c4f7a7d106b25b06 Mon Sep 17 00:00:00 2001 From: Nadia Holmquist Pedersen Date: Sun, 26 Jul 2020 22:26:50 +0200 Subject: Link iconv instead of ${Iconv_LIBRARIES} because idk Windows --- src/frontend/qt_sdl/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index f1665f5..05c42d1 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -72,7 +72,7 @@ else() endif() if (NOT Iconv_IS_BUILT_IN) - target_link_libraries(melonDS ${Iconv_LIBRARIES}) + target_link_libraries(melonDS iconv) endif() if (UNIX) -- cgit v1.2.3