From 5e67e9ca7c2f23cfaac997a89d0c3f6e56039085 Mon Sep 17 00:00:00 2001 From: rogerman Date: Fri, 10 Aug 2018 18:36:33 -0700 Subject: [PATCH] WiFi: Do a big refactor of the client interface code for better code cleanliness, organization, and stability. There are also some minor behavior changes. - EXPERIMENTAL_WIFI_COMM no longer disables all of the WiFi-related code. Instead, the WiFi code is always enabled and actually running the code is now controlled using WifiHandler::SetEmulationLevel(). - On the Windows port, EXPERIMENTAL_WIFI_COMM no longer hides all of the WiFi options. Instead, it only affects the user's ability to control the WiFi emulation. (Forces the WiFi emulation level to WifiEmulationLevel_Off if EXPERIMENTAL_WIFI_COMM is undefined.) - The Cocoa port (and probably other POSIX-based ports) should now work better with the WiFi code. - WiFi comm interfaces no longer initialize only once upon app startup. Instead, they initialize each time the emulator resets, and then uninitialize each time a ROM is unloaded. Now, users no longer have to restart the app in order to apply any changed WiFi settings. Instead, users only need to reset the emulator or load a new ROM. - Previously, the SoftAP comm interface wouldn't run if libpcap was unavailable or if a network device wasn't found. Now, the SoftAP comm interface will now run without libpcap or a network device, albeit with significantly reduced functionality. - Previously, saving pcap files required WIFI_LOGGING_LEVEL >= 3. Now, saving pcap files no longer relies on WIFI_LOGGING_LEVEL, instead relying on WIFI_SAVE_PCAP_TO_FILE to enable the functionality. --- desmume/src/NDSSystem.cpp | 41 +- desmume/src/NDSSystem.h | 13 +- desmume/src/driver.h | 53 +- .../frontend/cocoa/ClientExecutionControl.cpp | 69 +- .../frontend/cocoa/ClientExecutionControl.h | 13 + .../project.pbxproj | 36 +- .../project.pbxproj | 12 + desmume/src/frontend/cocoa/cocoa_core.mm | 4 + desmume/src/frontend/cocoa/cocoa_util.h | 1 + desmume/src/frontend/cocoa/cocoa_util.mm | 54 + .../userinterface/EmuControllerDelegate.mm | 2 + desmume/src/frontend/windows/main.cpp | 340 ++- desmume/src/frontend/windows/winpcap.h | 24 +- desmume/src/wifi.cpp | 2047 +++++++++++------ desmume/src/wifi.h | 286 ++- 15 files changed, 1891 insertions(+), 1104 deletions(-) mode change 100644 => 100755 desmume/src/NDSSystem.cpp mode change 100644 => 100755 desmume/src/NDSSystem.h mode change 100644 => 100755 desmume/src/driver.h mode change 100644 => 100755 desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj mode change 100644 => 100755 desmume/src/frontend/windows/winpcap.h mode change 100644 => 100755 desmume/src/wifi.cpp mode change 100644 => 100755 desmume/src/wifi.h diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp old mode 100644 new mode 100755 index d06e3ccf1..f3dc0254b --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -102,8 +102,6 @@ int TotalLagFrames; TSCalInfo TSCal; -WifiEmulationLevel wifiEmulationLevel = WifiEmulationLevel_Off; - namespace DLDI { bool tryPatch(void* data, size_t size, unsigned int device); @@ -181,8 +179,9 @@ int NDS_Init() if (SPU_Init(SNDCORE_DUMMY, 740) != 0) return -1; - - WIFI_Init() ; + + delete wifiHandler; + wifiHandler = new WifiHandler; cheats = new CHEATS(); cheatSearch = new CHEATSEARCH(); @@ -199,7 +198,9 @@ void NDS_DeInit(void) GPU = NULL; MMU_DeInit(); - WIFI_DeInit(); + + delete wifiHandler; + wifiHandler = NULL; delete cheats; cheats = NULL; @@ -572,6 +573,9 @@ bool GameInfo::loadROM(std::string fname, u32 type) void GameInfo::closeROM() { + if (wifiHandler != NULL) + wifiHandler->CommStop(); + if (GPU != NULL) GPU->ForceFrameStop(); @@ -1333,19 +1337,16 @@ void Sequencer::init() dma_1_1.controller = &MMU_new.dma[1][1]; dma_1_2.controller = &MMU_new.dma[1][2]; dma_1_3.controller = &MMU_new.dma[1][3]; - - - #ifdef EXPERIMENTAL_WIFI_COMM - if(wifiEmulationLevel > WifiEmulationLevel_Off) + + if (wifiHandler->GetCurrentEmulationLevel() != WifiEmulationLevel_Off) { wifi.enabled = true; wifi.timestamp = kWifiCycles; } else + { wifi.enabled = false; - #else - wifi.enabled = false; - #endif + } } static void execHardware_hblank() @@ -1670,10 +1671,7 @@ u64 Sequencer::findNext() if(sqrtunit.isEnabled()) next = _fast_min(next,sqrtunit.next()); if(gxfifo.enabled) next = _fast_min(next,gxfifo.next()); if(readslot1.isEnabled()) next = _fast_min(next,readslot1.next()); - -#ifdef EXPERIMENTAL_WIFI_COMM - if (wifiEmulationLevel > WifiEmulationLevel_Off) next = _fast_min(next,wifi.next()); -#endif + if (wifi.enabled) next = _fast_min(next,wifi.next()); #define test(X,Y) if(dma_##X##_##Y .isEnabled()) next = _fast_min(next,dma_##X##_##Y .next()); test(0,0); test(0,1); test(0,2); test(0,3); @@ -1729,16 +1727,14 @@ void Sequencer::execHardware() } } -#ifdef EXPERIMENTAL_WIFI_COMM - if(wifiEmulationLevel > WifiEmulationLevel_Off) + if (wifiHandler->GetCurrentEmulationLevel() != WifiEmulationLevel_Off) { - if(wifi.isTriggered()) + if (wifi.isTriggered()) { WIFI_usTrigger(); wifi.timestamp += kWifiCycles; } } -#endif if(divider.isTriggered()) divider.exec(); if(sqrtunit.isTriggered()) sqrtunit.exec(); @@ -2671,8 +2667,8 @@ void NDS_Reset() GPU->Reset(); - WIFI_Reset(); - memcpy(FW_Mac, (MMU.fw.data + 0x36), 6); + wifiHandler->Reset(); + wifiHandler->CommStart(); SPU_DeInit(); SPU_ReInit(!canBootFromFirmware && bootResult); @@ -3088,6 +3084,7 @@ void emu_halt(EmuHaltReasonCode reasonCode, NDSErrorTag errorTag) NDS_CurrentCPUInfoToNDSError(_lastNDSError); + wifiHandler->CommStop(); GPU->ForceFrameStop(); execute = false; diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h old mode 100644 new mode 100755 index 2aadc24aa..452794f17 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -217,14 +217,6 @@ enum NDS_CONSOLE_TYPE NDS_CONSOLE_TYPE_DSI = 0xFE }; -enum WifiEmulationLevel -{ - WifiEmulationLevel_Off = 0, - WifiEmulationLevel_Normal = 10000, - WifiEmulationLevel_Compatibility = 65535, -}; -extern WifiEmulationLevel wifiEmulationLevel; - struct NDSSystem { s32 wifiCycle; @@ -573,8 +565,7 @@ extern struct TCommonSettings strcpy(ARM7BIOS, "biosnds7.bin"); strcpy(Firmware, "firmware.bin"); - /* WIFI mode: adhoc = 0, infrastructure = 1 */ - wifi.mode = 1; + wifi.mode = WifiCommInterfaceID_Infrastructure; wifi.infraBridgeAdapter = 0; for(int i=0;i<16;i++) @@ -656,7 +647,7 @@ extern struct TCommonSettings u32 jit_max_block_size; struct _Wifi { - int mode; + WifiCommInterfaceID mode; int infraBridgeAdapter; } wifi; diff --git a/desmume/src/driver.h b/desmume/src/driver.h old mode 100644 new mode 100755 index 7573a140b..a0b3a7031 --- a/desmume/src/driver.h +++ b/desmume/src/driver.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009-2015 DeSmuME team + Copyright (C) 2009-2018 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,9 +22,6 @@ #include "types.h" #include "debug.h" -#ifdef EXPERIMENTAL_WIFI_COMM -#include -#endif class VIEW3D_Driver { @@ -39,53 +36,7 @@ class BaseDriver { public: BaseDriver(); ~BaseDriver(); - -#ifdef EXPERIMENTAL_WIFI_COMM -#ifdef HOST_WINDOWS - virtual bool WIFI_SocketsAvailable() { return true; } - virtual bool WIFI_PCapAvailable() { return false; } - - virtual void WIFI_GetUniqueMAC(u8* mac) {} - - virtual bool WIFI_WFCWarning() { return false; } - - virtual int PCAP_findalldevs(pcap_if_t** alldevs, char* errbuf) { return -1; } - virtual void PCAP_freealldevs(pcap_if_t* alldevs) {} - virtual pcap_t* PCAP_open(const char* source, int snaplen, int flags, int readtimeout, char* errbuf) { return NULL; } - virtual void PCAP_close(pcap_t* dev) {} - virtual int PCAP_setnonblock(pcap_t* dev, int nonblock, char* errbuf) { return -1; } - virtual int PCAP_sendpacket(pcap_t* dev, const u_char* data, int len) { return -1; } - virtual int PCAP_dispatch(pcap_t* dev, int num, pcap_handler callback, u_char* userdata) { return -1; } -#else - virtual bool WIFI_SocketsAvailable() { return true; } - virtual bool WIFI_PCapAvailable() { return true; } - - virtual void WIFI_GetUniqueMAC(u8* mac) {} - - virtual bool WIFI_WFCWarning() { return false; } - - virtual int PCAP_findalldevs(pcap_if_t** alldevs, char* errbuf) { - return pcap_findalldevs(alldevs, errbuf); } - - virtual void PCAP_freealldevs(pcap_if_t* alldevs) { - pcap_freealldevs(alldevs); } - - virtual pcap_t* PCAP_open(const char* source, int snaplen, int flags, int readtimeout, char* errbuf) { - return pcap_open_live(source, snaplen, flags, readtimeout, errbuf); } - - virtual void PCAP_close(pcap_t* dev) { - pcap_close(dev); } - - virtual int PCAP_setnonblock(pcap_t* dev, int nonblock, char* errbuf) { - return pcap_setnonblock(dev, nonblock, errbuf); } - - virtual int PCAP_sendpacket(pcap_t* dev, const u_char* data, int len) { - return pcap_sendpacket(dev, data, len); } - - virtual int PCAP_dispatch(pcap_t* dev, int num, pcap_handler callback, u_char* userdata) { - return pcap_dispatch(dev, num, callback, userdata); } -#endif -#endif + virtual void AVI_SoundUpdate(void* soundData, int soundLen) {} virtual bool AVI_IsRecording() { return FALSE; } virtual bool WAV_IsRecording() { return FALSE; } diff --git a/desmume/src/frontend/cocoa/ClientExecutionControl.cpp b/desmume/src/frontend/cocoa/ClientExecutionControl.cpp index 2f80bcbc8..6ca884195 100644 --- a/desmume/src/frontend/cocoa/ClientExecutionControl.cpp +++ b/desmume/src/frontend/cocoa/ClientExecutionControl.cpp @@ -86,6 +86,8 @@ ClientExecutionControl::ClientExecutionControl() _settingsPending.enableFirmwareBoot = false; _settingsPending.enableDebugConsole = false; _settingsPending.enableEnsataEmulation = false; + _settingsPending.wifiMode = WifiCommInterfaceID_AdHoc; + _settingsPending.wifiBridgeDeviceIndex = 0; _settingsPending.enableExecutionSpeedLimiter = true; _settingsPending.executionSpeed = SPEED_SCALAR_NORMAL; @@ -560,6 +562,60 @@ void ClientExecutionControl::SetEnableEnsataEmulation(bool enable) pthread_mutex_unlock(&this->_mutexSettingsPendingOnNDSExec); } +int ClientExecutionControl::GetWifiMode() +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + const int wifiMode = this->_settingsPending.wifiMode; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); + + return wifiMode; +} + +void ClientExecutionControl::SetWifiMode(int wifiMode) +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + this->_settingsPending.wifiMode = wifiMode; + + this->_newSettingsPendingOnReset = true; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); +} + +int ClientExecutionControl::GetWifiBridgeDeviceIndex() +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + const int wifiBridgeDeviceIndex = this->_settingsPending.wifiBridgeDeviceIndex; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); + + return wifiBridgeDeviceIndex; +} + +void ClientExecutionControl::SetWifiBridgeDeviceIndex(int wifiBridgeDeviceIndex) +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + this->_settingsPending.wifiBridgeDeviceIndex = wifiBridgeDeviceIndex; + + this->_newSettingsPendingOnReset = true; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); +} + +uint32_t ClientExecutionControl::GetWifiIP4Address() +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + const uint32_t ip4Address = this->_settingsPending.wifiIP4Address; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); + + return ip4Address; +} + +void ClientExecutionControl::SetWifiIP4Address(uint32_t ip4Address) +{ + pthread_mutex_lock(&this->_mutexSettingsPendingOnReset); + this->_settingsPending.wifiIP4Address = ip4Address; + + this->_newSettingsPendingOnReset = true; + pthread_mutex_unlock(&this->_mutexSettingsPendingOnReset); +} + bool ClientExecutionControl::GetEnableCheats() { pthread_mutex_lock(&this->_mutexSettingsPendingOnNDSExec); @@ -903,6 +959,10 @@ void ClientExecutionControl::ApplySettingsOnReset() this->_settingsApplied.enableExternalFirmware = this->_settingsPending.enableExternalFirmware; this->_settingsApplied.enableFirmwareBoot = this->_settingsPending.enableFirmwareBoot; + this->_settingsApplied.wifiMode = this->_settingsPending.wifiMode; + this->_settingsApplied.wifiBridgeDeviceIndex = this->_settingsPending.wifiBridgeDeviceIndex; + this->_settingsApplied.wifiIP4Address = this->_settingsPending.wifiIP4Address; + this->_settingsApplied.cpuEmulationEngineName = this->_settingsPending.cpuEmulationEngineName; this->_settingsApplied.slot1DeviceName = this->_settingsPending.slot1DeviceName; this->_ndsFrameInfo.cpuEmulationEngineName = this->_settingsApplied.cpuEmulationEngineName; @@ -921,8 +981,15 @@ void ClientExecutionControl::ApplySettingsOnReset() CommonSettings.jit_max_block_size = this->_settingsApplied.JITMaxBlockSize; CommonSettings.UseExtBIOS = this->_settingsApplied.enableExternalBIOS; CommonSettings.UseExtFirmware = this->_settingsApplied.enableExternalFirmware; - CommonSettings.UseExtFirmwareSettings = this->_settingsApplied.enableExternalFirmware; + //CommonSettings.UseExtFirmwareSettings = this->_settingsApplied.enableExternalFirmware; + CommonSettings.UseExtFirmwareSettings = false; CommonSettings.BootFromFirmware = this->_settingsApplied.enableFirmwareBoot; + CommonSettings.wifi.mode = (WifiCommInterfaceID)this->_settingsApplied.wifiMode; + CommonSettings.wifi.infraBridgeAdapter = this->_settingsApplied.wifiBridgeDeviceIndex; + + wifiHandler->SetIP4Address(this->_settingsApplied.wifiIP4Address); + wifiHandler->SetCommInterfaceID((WifiCommInterfaceID)this->_settingsApplied.wifiMode); + wifiHandler->SetBridgeDeviceIndex(this->_settingsApplied.wifiBridgeDeviceIndex); if (this->_settingsApplied.filePathARM9BIOS.length() == 0) { diff --git a/desmume/src/frontend/cocoa/ClientExecutionControl.h b/desmume/src/frontend/cocoa/ClientExecutionControl.h index cc3cd1340..2d7fac2a6 100644 --- a/desmume/src/frontend/cocoa/ClientExecutionControl.h +++ b/desmume/src/frontend/cocoa/ClientExecutionControl.h @@ -92,6 +92,10 @@ struct ClientExecutionControlSettings bool enableDebugConsole; bool enableEnsataEmulation; + int wifiMode; + int wifiBridgeDeviceIndex; + uint32_t wifiIP4Address; + bool enableCheats; bool enableExecutionSpeedLimiter; @@ -295,6 +299,15 @@ public: bool GetEnableEnsataEmulation(); void SetEnableEnsataEmulation(bool enable); + int GetWifiMode(); + void SetWifiMode(int wifiMode); + + int GetWifiBridgeDeviceIndex(); + void SetWifiBridgeDeviceIndex(int wifiBridgeDeviceIndex); + + uint32_t GetWifiIP4Address(); + void SetWifiIP4Address(uint32_t ip4Address); + bool GetEnableCheats(); void SetEnableCheats(bool enable); diff --git a/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj b/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj index 9afe3303d..cc6461a93 100644 --- a/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj +++ b/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj @@ -253,7 +253,6 @@ AB405694169F5DCC0016AC3E /* x86util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB405676169F5DCC0016AC3E /* x86util.cpp */; }; AB405695169F5DCC0016AC3E /* x86util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB405676169F5DCC0016AC3E /* x86util.cpp */; }; AB407F371A6206FB00313213 /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB47B52C18A3F722009A42AF /* xbrz.cpp */; }; - AB4676F314AB12D60002FF94 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AB0A0D1914AACA9600E83E91 /* libz.dylib */; }; AB47B52E18A3F722009A42AF /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB47B52C18A3F722009A42AF /* xbrz.cpp */; }; AB47B52F18A45C35009A42AF /* xbrz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB47B52C18A3F722009A42AF /* xbrz.cpp */; }; AB4C81E41B21676C00ACECD5 /* hq3x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB4C81E31B21676C00ACECD5 /* hq3x.cpp */; }; @@ -263,6 +262,16 @@ AB4FCEBD1692AB82000F498F /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB4FCEBC1692AB82000F498F /* Accelerate.framework */; }; AB4FCEBE1692AB82000F498F /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB4FCEBC1692AB82000F498F /* Accelerate.framework */; }; AB4FCEBF1692AB82000F498F /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB4FCEBC1692AB82000F498F /* Accelerate.framework */; }; + AB53B0BE211E63FE003D0ED9 /* libpcap.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AB53B0BC211E63E4003D0ED9 /* libpcap.tbd */; }; + AB53B0BF211E63FF003D0ED9 /* libpcap.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AB53B0BC211E63E4003D0ED9 /* libpcap.tbd */; }; + AB53B0C0211E6400003D0ED9 /* libpcap.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AB53B0BC211E63E4003D0ED9 /* libpcap.tbd */; }; + AB53B0C1211E6400003D0ED9 /* libpcap.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AB53B0BC211E63E4003D0ED9 /* libpcap.tbd */; }; + AB53B0C2211E6401003D0ED9 /* libpcap.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AB53B0BC211E63E4003D0ED9 /* libpcap.tbd */; }; + AB53B0C3211E6405003D0ED9 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AB53B0BD211E63E8003D0ED9 /* libz.tbd */; }; + AB53B0C4211E6405003D0ED9 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AB53B0BD211E63E8003D0ED9 /* libz.tbd */; }; + AB53B0C5211E6406003D0ED9 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AB53B0BD211E63E8003D0ED9 /* libz.tbd */; }; + AB53B0C6211E6407003D0ED9 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AB53B0BD211E63E8003D0ED9 /* libz.tbd */; }; + AB53B0C7211E6407003D0ED9 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = AB53B0BD211E63E8003D0ED9 /* libz.tbd */; }; AB54718B1E27610500508C5C /* MacMetalDisplayViewShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = AB54718A1E27610500508C5C /* MacMetalDisplayViewShaders.metal */; }; AB54718C1E27610500508C5C /* MacMetalDisplayViewShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = AB54718A1E27610500508C5C /* MacMetalDisplayViewShaders.metal */; }; AB54718D1E27610500508C5C /* MacMetalDisplayViewShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = AB54718A1E27610500508C5C /* MacMetalDisplayViewShaders.metal */; }; @@ -489,7 +498,6 @@ AB796D6915CDCBA200C59155 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29B97325FDCFA39411CA2CEA /* Foundation.framework */; }; AB796D6A15CDCBA200C59155 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB350BA41478AC96007165AC /* IOKit.framework */; }; AB796D6B15CDCBA200C59155 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC570D4134431DA00E7B0B1 /* OpenGL.framework */; }; - AB796D6C15CDCBA200C59155 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AB0A0D1914AACA9600E83E91 /* libz.dylib */; }; AB7EC7F4189B2B92009D198A /* Icon_AutoholdClear_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = AB7EC7F2189B2B92009D198A /* Icon_AutoholdClear_420x420.png */; }; AB7EC7F5189B2B92009D198A /* Icon_AutoholdClear_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = AB7EC7F2189B2B92009D198A /* Icon_AutoholdClear_420x420.png */; }; AB7EC7F6189B2B92009D198A /* Icon_AutoholdSet_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = AB7EC7F3189B2B92009D198A /* Icon_AutoholdSet_420x420.png */; }; @@ -789,7 +797,6 @@ AB8F3D261A53AC2600A80BF6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29B97325FDCFA39411CA2CEA /* Foundation.framework */; }; AB8F3D271A53AC2600A80BF6 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB350BA41478AC96007165AC /* IOKit.framework */; }; AB8F3D281A53AC2600A80BF6 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC570D4134431DA00E7B0B1 /* OpenGL.framework */; }; - AB8F3D291A53AC2600A80BF6 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AB0A0D1914AACA9600E83E91 /* libz.dylib */; }; AB901BDE1420706100348EEC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = AB901BDD1420706100348EEC /* Localizable.strings */; }; AB9038A617C5ECFD00F410BD /* advanscene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB9038A517C5ECFD00F410BD /* advanscene.cpp */; }; AB9038A717C5ECFD00F410BD /* advanscene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB9038A517C5ECFD00F410BD /* advanscene.cpp */; }; @@ -895,7 +902,6 @@ ABB3C6661501BF8A00E0C22E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; ABB3C6671501BF8A00E0C22E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29B97325FDCFA39411CA2CEA /* Foundation.framework */; }; ABB3C6691501BF8A00E0C22E /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC570D4134431DA00E7B0B1 /* OpenGL.framework */; }; - ABB3C66A1501BF8A00E0C22E /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AB0A0D1914AACA9600E83E91 /* libz.dylib */; }; ABB3C66C1501C04F00E0C22E /* NDSGameCore.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABB3C63E1501BB8300E0C22E /* NDSGameCore.mm */; }; ABB3C6701501C04F00E0C22E /* videofilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB817A35143EE2DB00A7DFE9 /* videofilter.cpp */; }; ABB3C6721501C04F00E0C22E /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB58F32C1364F44B0074C376 /* cocoa_file.mm */; }; @@ -1428,7 +1434,6 @@ ABE145AF1FBBA71A0097A4A8 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB350BA41478AC96007165AC /* IOKit.framework */; }; ABE145B11FBBA71A0097A4A8 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC570D4134431DA00E7B0B1 /* OpenGL.framework */; }; ABE145B21FBBA71A0097A4A8 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3BF4321E2562F2003E2B24 /* QuartzCore.framework */; }; - ABE145B31FBBA71A0097A4A8 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AB0A0D1914AACA9600E83E91 /* libz.dylib */; }; ABE145B41FBBA71A0097A4A8 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABAE1F6E1F6873E70080EFE3 /* CoreVideo.framework */; }; ABE5DE95143F781900835AD8 /* videofilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB817A35143EE2DB00A7DFE9 /* videofilter.cpp */; }; ABE5DFE5143FB1DA00835AD8 /* cocoa_videofilter.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE5DFE4143FB1DA00835AD8 /* cocoa_videofilter.mm */; }; @@ -1542,7 +1547,6 @@ AB01005D170D07B000D70FBE /* InputProfileController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InputProfileController.mm; sourceTree = ""; }; AB02475B13886BF300E9F9AB /* KeyNames.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = KeyNames.plist; sourceTree = ""; }; AB02791814415E4C0075E58C /* Info (Debug).plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info (Debug).plist"; sourceTree = ""; }; - AB0A0D1914AACA9600E83E91 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; AB0F28FE14BE6E68009ABC6F /* Icon_Execute_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Execute_420x420.png; path = images/Icon_Execute_420x420.png; sourceTree = ""; }; AB0F28FF14BE6E68009ABC6F /* Icon_Pause_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Pause_420x420.png; path = images/Icon_Pause_420x420.png; sourceTree = ""; }; AB0F290014BE6E68009ABC6F /* Icon_Speed1x_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Speed1x_420x420.png; path = images/Icon_Speed1x_420x420.png; sourceTree = ""; }; @@ -1785,6 +1789,8 @@ AB47B52C18A3F722009A42AF /* xbrz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xbrz.cpp; sourceTree = ""; }; AB4C81E31B21676C00ACECD5 /* hq3x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hq3x.cpp; sourceTree = ""; }; AB4FCEBC1692AB82000F498F /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; + AB53B0BC211E63E4003D0ED9 /* libpcap.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libpcap.tbd; path = usr/lib/libpcap.tbd; sourceTree = SDKROOT; }; + AB53B0BD211E63E8003D0ED9 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; AB54718A1E27610500508C5C /* MacMetalDisplayViewShaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = MacMetalDisplayViewShaders.metal; sourceTree = ""; }; AB5648FD186E6EA8002740F4 /* cocoa_slot2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_slot2.h; sourceTree = ""; }; AB5648FE186E6EA8002740F4 /* cocoa_slot2.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_slot2.mm; sourceTree = ""; }; @@ -2301,6 +2307,8 @@ buildActionMask = 2147483647; files = ( AB4FCEBE1692AB82000F498F /* Accelerate.framework in Frameworks */, + AB53B0C5211E6406003D0ED9 /* libz.tbd in Frameworks */, + AB53B0BE211E63FE003D0ED9 /* libpcap.tbd in Frameworks */, ABC5720D1344346600E7B0B1 /* AppKit.framework in Frameworks */, ABACB8DD1710B656003B845D /* AudioToolbox.framework in Frameworks */, ABC570D1134431CE00E7B0B1 /* AudioUnit.framework in Frameworks */, @@ -2313,7 +2321,6 @@ AB3BF4421E262959003E2B24 /* Metal.framework in Frameworks */, ABC570D5134431DA00E7B0B1 /* OpenGL.framework in Frameworks */, AB3BF4341E256309003E2B24 /* QuartzCore.framework in Frameworks */, - AB4676F314AB12D60002FF94 /* libz.dylib in Frameworks */, ABAE1F711F6874090080EFE3 /* CoreVideo.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2323,6 +2330,8 @@ buildActionMask = 2147483647; files = ( AB4FCEBD1692AB82000F498F /* Accelerate.framework in Frameworks */, + AB53B0C7211E6407003D0ED9 /* libz.tbd in Frameworks */, + AB53B0C1211E6400003D0ED9 /* libpcap.tbd in Frameworks */, AB796D6615CDCBA200C59155 /* AppKit.framework in Frameworks */, ABACB8DC1710B621003B845D /* AudioToolbox.framework in Frameworks */, AB796D6715CDCBA200C59155 /* AudioUnit.framework in Frameworks */, @@ -2336,7 +2345,6 @@ AB78B5C21E384F2200297FED /* Metal.framework in Frameworks */, AB796D6B15CDCBA200C59155 /* OpenGL.framework in Frameworks */, AB3BF4331E2562F2003E2B24 /* QuartzCore.framework in Frameworks */, - AB796D6C15CDCBA200C59155 /* libz.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2345,6 +2353,8 @@ buildActionMask = 2147483647; files = ( AB8F3D1F1A53AC2600A80BF6 /* Accelerate.framework in Frameworks */, + AB53B0C6211E6407003D0ED9 /* libz.tbd in Frameworks */, + AB53B0C0211E6400003D0ED9 /* libpcap.tbd in Frameworks */, AB8F3D201A53AC2600A80BF6 /* AppKit.framework in Frameworks */, AB8F3D211A53AC2600A80BF6 /* AudioToolbox.framework in Frameworks */, AB8F3D221A53AC2600A80BF6 /* AudioUnit.framework in Frameworks */, @@ -2357,7 +2367,6 @@ AB78B5C11E384F2100297FED /* Metal.framework in Frameworks */, AB8F3D281A53AC2600A80BF6 /* OpenGL.framework in Frameworks */, AB3BF4351E256309003E2B24 /* QuartzCore.framework in Frameworks */, - AB8F3D291A53AC2600A80BF6 /* libz.dylib in Frameworks */, ABAE1F701F6874090080EFE3 /* CoreVideo.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2367,13 +2376,14 @@ buildActionMask = 2147483647; files = ( AB4FCEBF1692AB82000F498F /* Accelerate.framework in Frameworks */, + AB53B0C3211E6405003D0ED9 /* libz.tbd in Frameworks */, ABB3C6641501BF8A00E0C22E /* AppKit.framework in Frameworks */, ABACB8DE1710B65F003B845D /* AudioToolbox.framework in Frameworks */, ABB3C6651501BF8A00E0C22E /* AudioUnit.framework in Frameworks */, ABB3C6661501BF8A00E0C22E /* Cocoa.framework in Frameworks */, ABB3C6671501BF8A00E0C22E /* Foundation.framework in Frameworks */, + AB53B0C2211E6401003D0ED9 /* libpcap.tbd in Frameworks */, ABB3C6691501BF8A00E0C22E /* OpenGL.framework in Frameworks */, - ABB3C66A1501BF8A00E0C22E /* libz.dylib in Frameworks */, ABC503B11AAC4355002FCD43 /* CoreAudio.framework in Frameworks */, AB5785FD17176AFC002C5FC7 /* OpenEmuBase.framework in Frameworks */, ); @@ -2387,15 +2397,16 @@ ABE145A71FBBA71A0097A4A8 /* AppKit.framework in Frameworks */, ABE145A81FBBA71A0097A4A8 /* AudioToolbox.framework in Frameworks */, ABE145A91FBBA71A0097A4A8 /* AudioUnit.framework in Frameworks */, + AB53B0C4211E6405003D0ED9 /* libz.tbd in Frameworks */, ABE145AA1FBBA71A0097A4A8 /* Carbon.framework in Frameworks */, ABE145AB1FBBA71A0097A4A8 /* Cocoa.framework in Frameworks */, ABE145AC1FBBA71A0097A4A8 /* CoreAudio.framework in Frameworks */, ABE145AD1FBBA71A0097A4A8 /* ForceFeedback.framework in Frameworks */, + AB53B0BF211E63FF003D0ED9 /* libpcap.tbd in Frameworks */, ABE145AE1FBBA71A0097A4A8 /* Foundation.framework in Frameworks */, ABE145AF1FBBA71A0097A4A8 /* IOKit.framework in Frameworks */, ABE145B11FBBA71A0097A4A8 /* OpenGL.framework in Frameworks */, ABE145B21FBBA71A0097A4A8 /* QuartzCore.framework in Frameworks */, - ABE145B31FBBA71A0097A4A8 /* libz.dylib in Frameworks */, ABE145B41FBBA71A0097A4A8 /* CoreVideo.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2479,7 +2490,8 @@ AB3BF4401E262943003E2B24 /* Metal.framework */, ABC570D4134431DA00E7B0B1 /* OpenGL.framework */, AB3BF4321E2562F2003E2B24 /* QuartzCore.framework */, - AB0A0D1914AACA9600E83E91 /* libz.dylib */, + AB53B0BC211E63E4003D0ED9 /* libpcap.tbd */, + AB53B0BD211E63E8003D0ED9 /* libz.tbd */, ); name = "Linked Frameworks"; sourceTree = ""; diff --git a/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj b/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj old mode 100644 new mode 100755 index 8bdb13dcc..3821caecd --- a/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj +++ b/desmume/src/frontend/cocoa/DeSmuME (XCode 3).xcodeproj/project.pbxproj @@ -693,6 +693,11 @@ AB37E3781D6188BC004A2C0D /* colorspacehandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB37E36C1D6188BC004A2C0D /* colorspacehandler.cpp */; }; AB37E37C1D6188BC004A2C0D /* colorspacehandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB37E36C1D6188BC004A2C0D /* colorspacehandler.cpp */; }; AB37E3801D6188BC004A2C0D /* colorspacehandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB37E36C1D6188BC004A2C0D /* colorspacehandler.cpp */; }; + AB3932C4211E610200DA9D80 /* libpcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3932C3211E610200DA9D80 /* libpcap.dylib */; }; + AB3932C5211E611F00DA9D80 /* libpcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3932C3211E610200DA9D80 /* libpcap.dylib */; }; + AB3932C6211E612400DA9D80 /* libpcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3932C3211E610200DA9D80 /* libpcap.dylib */; }; + AB3932C7211E612A00DA9D80 /* libpcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3932C3211E610200DA9D80 /* libpcap.dylib */; }; + AB3932C8211E612E00DA9D80 /* libpcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AB3932C3211E610200DA9D80 /* libpcap.dylib */; }; AB3ACB7814C2361100D7D192 /* appDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB3ACB6714C2361100D7D192 /* appDelegate.mm */; }; AB3ACB7914C2361100D7D192 /* cheatWindowDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB3ACB6914C2361100D7D192 /* cheatWindowDelegate.mm */; }; AB3ACB7C14C2361100D7D192 /* inputPrefsView.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB3ACB6F14C2361100D7D192 /* inputPrefsView.mm */; }; @@ -1921,6 +1926,7 @@ AB37E36F1D6188BC004A2C0D /* colorspacehandler_AltiVec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colorspacehandler_AltiVec.h; sourceTree = ""; }; AB37E3721D6188BC004A2C0D /* colorspacehandler_SSE2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = colorspacehandler_SSE2.cpp; sourceTree = ""; }; AB37E3731D6188BC004A2C0D /* colorspacehandler_SSE2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colorspacehandler_SSE2.h; sourceTree = ""; }; + AB3932C3211E610200DA9D80 /* libpcap.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpcap.dylib; path = usr/lib/libpcap.dylib; sourceTree = SDKROOT; }; AB3ACB6614C2361100D7D192 /* appDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = appDelegate.h; sourceTree = ""; }; AB3ACB6714C2361100D7D192 /* appDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = appDelegate.mm; sourceTree = ""; }; AB3ACB6814C2361100D7D192 /* cheatWindowDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cheatWindowDelegate.h; sourceTree = ""; }; @@ -2349,6 +2355,7 @@ AB1CC8001AA509C2008B0A16 /* CoreAudio.framework in Frameworks */, AB3E69801E25FB9800D4CC75 /* QuartzCore.framework in Frameworks */, AB446DB61F69DB69002F32B6 /* CoreVideo.framework in Frameworks */, + AB3932C8211E612E00DA9D80 /* libpcap.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2370,6 +2377,7 @@ AB1CC80A1AA509DF008B0A16 /* CoreAudio.framework in Frameworks */, AB3E697F1E25FB9700D4CC75 /* QuartzCore.framework in Frameworks */, AB446DB51F69DB69002F32B6 /* CoreVideo.framework in Frameworks */, + AB3932C7211E612A00DA9D80 /* libpcap.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2391,6 +2399,7 @@ AB1CC80D1AA509E1008B0A16 /* CoreAudio.framework in Frameworks */, AB3E69451E25FB8400D4CC75 /* QuartzCore.framework in Frameworks */, AB446DA11F69DB56002F32B6 /* CoreVideo.framework in Frameworks */, + AB3932C4211E610200DA9D80 /* libpcap.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2412,6 +2421,7 @@ AB1CC80C1AA509E0008B0A16 /* CoreAudio.framework in Frameworks */, AB3E697D1E25FB9600D4CC75 /* QuartzCore.framework in Frameworks */, AB446DB31F69DB68002F32B6 /* CoreVideo.framework in Frameworks */, + AB3932C5211E611F00DA9D80 /* libpcap.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2433,6 +2443,7 @@ AB1CC80B1AA509E0008B0A16 /* CoreAudio.framework in Frameworks */, AB3E697E1E25FB9700D4CC75 /* QuartzCore.framework in Frameworks */, AB446DB41F69DB68002F32B6 /* CoreVideo.framework in Frameworks */, + AB3932C6211E612400DA9D80 /* libpcap.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2511,6 +2522,7 @@ AB350BA41478AC96007165AC /* IOKit.framework */, ABC570D4134431DA00E7B0B1 /* OpenGL.framework */, AB3E69441E25FB8400D4CC75 /* QuartzCore.framework */, + AB3932C3211E610200DA9D80 /* libpcap.dylib */, AB0A0D1914AACA9600E83E91 /* libz.dylib */, ); name = "Linked Frameworks"; diff --git a/desmume/src/frontend/cocoa/cocoa_core.mm b/desmume/src/frontend/cocoa/cocoa_core.mm index 05530def3..5560e5e8b 100644 --- a/desmume/src/frontend/cocoa/cocoa_core.mm +++ b/desmume/src/frontend/cocoa/cocoa_core.mm @@ -129,6 +129,9 @@ volatile bool execute = true; threadParam.cdsCore = self; + wifiHandler->SetUniqueMACValue((uint32_t)[[NSProcessInfo processInfo] processIdentifier]); + wifiHandler->SetEmulationLevel(WifiEmulationLevel_Off); + pthread_rwlock_init(&threadParam.rwlockOutputList, NULL); pthread_mutex_init(&threadParam.mutexThreadExecute, NULL); pthread_cond_init(&threadParam.condThreadExecute, NULL); @@ -794,6 +797,7 @@ volatile bool execute = true; [self setCoreState:ExecutionBehavior_Pause]; pthread_mutex_lock(&threadParam.mutexThreadExecute); + execControl->SetWifiIP4Address([CocoaDSUtil hostIP4AddressAsUInt32]); execControl->ApplySettingsOnReset(); NDS_Reset(); pthread_mutex_unlock(&threadParam.mutexThreadExecute); diff --git a/desmume/src/frontend/cocoa/cocoa_util.h b/desmume/src/frontend/cocoa/cocoa_util.h index bf7e130af..3dc60b342 100644 --- a/desmume/src/frontend/cocoa/cocoa_util.h +++ b/desmume/src/frontend/cocoa/cocoa_util.h @@ -44,6 +44,7 @@ + (NSString *) operatingSystemString; + (NSString *) modelIdentifierString; ++ (uint32_t) hostIP4AddressAsUInt32; @end diff --git a/desmume/src/frontend/cocoa/cocoa_util.mm b/desmume/src/frontend/cocoa/cocoa_util.mm index 9fed13e4b..549215dcf 100644 --- a/desmume/src/frontend/cocoa/cocoa_util.mm +++ b/desmume/src/frontend/cocoa/cocoa_util.mm @@ -163,6 +163,60 @@ return modelIdentifierStr; } ++ (uint32_t) hostIP4AddressAsUInt32 +{ + uint32_t ip4Address_u32 = 0; + + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + [numberFormatter setAllowsFloats:NO]; + + NSArray *ipAddresses = [[NSHost hostWithName:[[NSHost currentHost] name]] addresses]; + for (NSString *ipAddress in ipAddresses) + { + if ([ipAddress isEqualToString:@"127.0.0.1"]) + { + continue; + } + else + { + NSArray *ipParts = [ipAddress componentsSeparatedByString:@"."]; + + if ([ipParts count] != 4) + { + continue; + } + else + { + NSNumber *ipPartNumber[4] = { + [numberFormatter numberFromString:(NSString *)[ipParts objectAtIndex:0]], + [numberFormatter numberFromString:(NSString *)[ipParts objectAtIndex:1]], + [numberFormatter numberFromString:(NSString *)[ipParts objectAtIndex:2]], + [numberFormatter numberFromString:(NSString *)[ipParts objectAtIndex:3]] + }; + + if ( (ipPartNumber[0] == nil) || (ipPartNumber[1] == nil) || (ipPartNumber[2] == nil) || (ipPartNumber[3] == nil) ) + { + continue; + } + else + { + const uint8_t ipPart_u8[4] = { + [ipPartNumber[0] unsignedCharValue], + [ipPartNumber[1] unsignedCharValue], + [ipPartNumber[2] unsignedCharValue], + [ipPartNumber[3] unsignedCharValue] + }; + + ip4Address_u32 = (ipPart_u8[0]) | (ipPart_u8[1] << 8) | (ipPart_u8[2] << 16) | (ipPart_u8[3] << 24); + break; + } + } + } + } + + return ip4Address_u32; +} + @end @implementation DirectoryURLDragDestTextField diff --git a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm index 738607d76..d4539b12f 100644 --- a/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm +++ b/desmume/src/frontend/cocoa/userinterface/EmuControllerDelegate.mm @@ -1630,6 +1630,7 @@ [self pauseCore]; CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content]; + [cdsCore execControl]->SetWifiIP4Address([CocoaDSUtil hostIP4AddressAsUInt32]); [cdsCore execControl]->ApplySettingsOnReset(); [cdsCore updateSlot1DeviceStatus]; [self writeDefaultsSlot1Settings:nil]; @@ -1781,6 +1782,7 @@ [[windowController window] displayIfNeeded]; } + [cdsCore execControl]->SetWifiIP4Address([CocoaDSUtil hostIP4AddressAsUInt32]); [cdsCore execControl]->ApplySettingsOnReset(); [cdsCore setMasterExecute:YES]; diff --git a/desmume/src/frontend/windows/main.cpp b/desmume/src/frontend/windows/main.cpp index efcad8a1b..2be481052 100755 --- a/desmume/src/frontend/windows/main.cpp +++ b/desmume/src/frontend/windows/main.cpp @@ -294,11 +294,7 @@ msgBoxInterface msgBoxWnd = { }; //====================== Dialogs end - -#ifdef EXPERIMENTAL_WIFI_COMM -bool bSocketsAvailable = false; #include "winpcap.h" -#endif VideoInfo video; @@ -555,6 +551,50 @@ public: } }; +class WinPCapInterface : public ClientPCapInterface +{ +public: + virtual int findalldevs(void **alldevs, char *errbuf) + { + return _pcap_findalldevs((pcap_if_t **)alldevs, errbuf); + } + + virtual void freealldevs(void *alldevs) + { + _pcap_freealldevs((pcap_if_t *)alldevs); + } + + virtual void* open(const char *source, int snaplen, int flags, int readtimeout, char *errbuf) + { + return _pcap_open_live(source, snaplen, flags, readtimeout, errbuf); + } + + virtual void close(void *dev) + { + _pcap_close((pcap_t *)dev); + } + + virtual int setnonblock(void *dev, int nonblock, char *errbuf) + { + return _pcap_setnonblock((pcap_t *)dev, nonblock, errbuf); + } + + virtual int sendpacket(void *dev, const void *data, int len) + { + return _pcap_sendpacket((pcap_t *)dev, (u_char *)data, len); + } + + virtual int dispatch(void *dev, int num, void *callback, void *userdata) + { + if (callback == NULL) + { + return -1; + } + + return _pcap_dispatch((pcap_t *)dev, num, (pcap_handler)callback, (u_char *)userdata); + } +}; + GPUEventHandlerWindows *WinGPUEvent = NULL; LRESULT CALLBACK HUDFontSettingsDlgProc(HWND hw, UINT msg, WPARAM wp, LPARAM lp); @@ -562,9 +602,7 @@ LRESULT CALLBACK GFX3DSettingsDlgProc(HWND hw, UINT msg, WPARAM wp, LPARAM lp); LRESULT CALLBACK SoundSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK EmulationSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK MicrophoneSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); -#ifdef EXPERIMENTAL_WIFI_COMM LRESULT CALLBACK WifiSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); -#endif //struct configured_features { // u16 arm9_gdb_port; @@ -2712,97 +2750,6 @@ static void ExitRunLoop() class WinDriver : public BaseDriver { -#ifdef EXPERIMENTAL_WIFI_COMM - virtual bool WIFI_SocketsAvailable() { return bSocketsAvailable; } - virtual bool WIFI_PCapAvailable() { return bWinPCapAvailable; } - - virtual void WIFI_GetUniqueMAC(u8* mac) - { - if (mac == NULL) return; - - char hostname[256]; - if (gethostname(hostname, 256) != 0) - strncpy(hostname, "127.0.0.1", 256); - - hostent* he = gethostbyname(hostname); - unsigned long ipaddr; - if (he == NULL || he->h_addr_list[0] == NULL) - ipaddr = 0x0100007F; // 127.0.0.1 - else - ipaddr = *(unsigned long*)he->h_addr_list[0]; - - unsigned long pid = GetCurrentProcessId(); - - unsigned long hash = pid; - while ((hash & 0xFF000000) == 0) - hash <<= 1; - hash >>= 1; - hash += ipaddr >> 8; - hash &= 0x00FFFFFF; - - mac[3] = hash >> 16; - mac[4] = (hash >> 8) & 0xFF; - mac[5] = hash & 0xFF; - } - - virtual bool WIFI_WFCWarning() - { - return MessageBox(NULL, "You are trying to connect to the Nintendo WFC servers.\n" - "\n" - "Please don't do this." - "\n" - "DeSmuME is not perfect yet, and connecting to WFC will cause unexpected problems\n" - "for Nintendo, and for DeSmuME, which neither of us want.\n" - "\n" - "And you don't want that either, right?\n" - "\n" - "You may get your IP blocked and then you won't even be able to use your real DS.\n" - "You may cause DeSmuME to get blocked, which would be a shame since we wouldn't even\n" - "be able to work on it any more.\n" - "\n" - "By the time you read this, it may have already happened due to irresponsible individuals\n" - "ignoring this message.\n" - "\n" - "So please don't do it.\n" - "\n" - "We aren't going to try to stop you, since someone will just make a hacked build and you\n" - "won't get a chance to read this. So please, stop yourself.\n" - "\n" - "Do you still want to connect?", - "DeSmuME - WFC warning", - MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING - ) == IDYES; - } - - virtual int PCAP_findalldevs(pcap_if_t** alldevs, char* errbuf) { - return _pcap_findalldevs(alldevs, errbuf); - } - - virtual void PCAP_freealldevs(pcap_if_t* alldevs) { - _pcap_freealldevs(alldevs); - } - - virtual pcap_t* PCAP_open(const char* source, int snaplen, int flags, int readtimeout, char* errbuf) { - return _pcap_open_live(source, snaplen, flags, readtimeout, errbuf); - } - - virtual void PCAP_close(pcap_t* dev) { - _pcap_close(dev); - } - - virtual int PCAP_setnonblock(pcap_t* dev, int nonblock, char* errbuf) { - return _pcap_setnonblock(dev, nonblock, errbuf); - } - - virtual int PCAP_sendpacket(pcap_t* dev, const u_char* data, int len) { - return _pcap_sendpacket(dev, data, len); - } - - virtual int PCAP_dispatch(pcap_t* dev, int num, pcap_handler callback, u_char* userdata) { - return _pcap_dispatch(dev, num, callback, userdata); - } -#endif - virtual bool AVI_IsRecording() { return ::AVI_IsRecording(); @@ -2984,16 +2931,27 @@ int _main() OGLLoadEntryPoints_3_2_Func = OGLLoadEntryPoints_3_2; OGLCreateRenderer_3_2_Func = OGLCreateRenderer_3_2; + bool isSocketsSupported = false; + bool isPCapSupported = false; -#ifdef EXPERIMENTAL_WIFI_COMM WSADATA wsaData; - WORD version = MAKEWORD(1,1); + WORD version = MAKEWORD(2,2); - if (WSAStartup(version, &wsaData) == 0) - bSocketsAvailable = true; + // Start up Windows Sockets. + if (WSAStartup(version, &wsaData) == 0) + { + // Check for a matching DLL version. If the version doesn't match, then bail. + if ( (LOBYTE(wsaData.wVersion) == 2) && (HIBYTE(wsaData.wVersion) == 2) ) + { + isSocketsSupported = true; + } + else + { + WSACleanup(); + } + } - LoadWinPCap(); -#endif + LoadWinPCap(isPCapSupported); driver = new WinDriver(); WinGPUEvent = new GPUEventHandlerWindows; @@ -3211,11 +3169,7 @@ int _main() SetStyle(style); DragAcceptFiles(MainWindow->getHWnd(), TRUE); - -#ifdef EXPERIMENTAL_WIFI_COMM EnableMenuItem(mainMenu, IDM_WIFISETTINGS, MF_ENABLED); -#endif - InitCustomKeys(&CustomKeys); Hud.reset(); @@ -3328,17 +3282,7 @@ int _main() Piano.Enabled = (slot2_device_type == NDS_SLOT2_EASYPIANO)?true:false; Paddle.Enabled = (slot2_device_type == NDS_SLOT2_PADDLE)?true:false; - if (GetPrivateProfileBool("Wifi", "Enabled", false, IniName)) - { - if (GetPrivateProfileBool("Wifi", "Compatibility Mode", false, IniName)) - wifiEmulationLevel = WifiEmulationLevel_Compatibility; - else - wifiEmulationLevel = WifiEmulationLevel_Normal; - } - else - wifiEmulationLevel = WifiEmulationLevel_Off; - - CommonSettings.wifi.mode = GetPrivateProfileInt("Wifi", "Mode", 0, IniName); + CommonSettings.wifi.mode = (WifiCommInterfaceID)GetPrivateProfileInt("Wifi", "Mode", WifiCommInterfaceID_AdHoc, IniName); CommonSettings.wifi.infraBridgeAdapter = GetPrivateProfileInt("Wifi", "BridgeAdapter", 0, IniName); osd = new OSDCLASS(-1); @@ -3347,6 +3291,37 @@ int _main() GPU->SetEventHandler(WinGPUEvent); + WinPCapInterface *winpcapInterface = (isPCapSupported) ? new WinPCapInterface : NULL; + wifiHandler->SetPCapInterface(winpcapInterface); + wifiHandler->SetSocketsSupported(isSocketsSupported); + + // Get the host's IP4 address. + char hostname[256]; + if (gethostname(hostname, 256) != 0) + strncpy(hostname, "127.0.0.1", 256); + + hostent *he = gethostbyname(hostname); + unsigned long ipaddr; + if (he == NULL || he->h_addr_list[0] == NULL) + ipaddr = 0x0100007F; // 127.0.0.1 + else + ipaddr = *(unsigned long*)he->h_addr_list[0]; + + wifiHandler->SetIP4Address(ipaddr); + wifiHandler->SetUniqueMACValue((u32)GetCurrentProcessId()); + wifiHandler->SetCommInterfaceID(CommonSettings.wifi.mode); + wifiHandler->SetBridgeDeviceIndex(CommonSettings.wifi.infraBridgeAdapter); + + if (GetPrivateProfileBool("Wifi", "Enabled", false, IniName)) + { + if (GetPrivateProfileBool("Wifi", "Compatibility Mode", false, IniName)) + wifiHandler->SetEmulationLevel(WifiEmulationLevel_Compatibility); + else + wifiHandler->SetEmulationLevel(WifiEmulationLevel_Normal); + } + else + wifiHandler->SetEmulationLevel(WifiEmulationLevel_Off); + CommonSettings.GFX3D_Renderer_TextureScalingFactor = (cmdline.texture_upscale != -1) ? cmdline.texture_upscale : GetPrivateProfileInt("3D", "TextureScalingFactor ", 1, IniName); int newPrescaleHD = (cmdline.gpu_resolution_multiplier != -1) ? cmdline.gpu_resolution_multiplier : GetPrivateProfileInt("3D", "PrescaleHD", 1, IniName); @@ -3616,9 +3591,10 @@ int _main() UnregWndClass("DeSmuME"); -#ifdef EXPERIMENTAL_WIFI_COMM - WSACleanup(); -#endif + if (wifiHandler->IsSocketsSupported()) + { + WSACleanup(); + } return 0; } @@ -4496,11 +4472,9 @@ void RunConfig(CONFIGSCREEN which) case CONFIGSCREEN_PATHSETTINGS: DialogBoxW(hAppInst, MAKEINTRESOURCEW(IDD_PATHSETTINGS), hwnd, (DLGPROC)PathSettingsDlgProc); break; -#ifdef EXPERIMENTAL_WIFI_COMM case CONFIGSCREEN_WIFI: DialogBoxW(hAppInst,MAKEINTRESOURCEW(IDD_WIFISETTINGS), hwnd, (DLGPROC) WifiSettingsDlgProc); break; -#endif } if (tpaused) @@ -4556,15 +4530,10 @@ static void TwiddleLayer(UINT ctlid, int core, int layer) LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int tmp_execute; + switch (message) // handle the messages { case WM_INITMENU: - { -#ifdef EXPERIMENTAL_WIFI_COMM - if (!(bSocketsAvailable || bWinPCapAvailable)) -#endif - DeleteMenu(GetMenu(hwnd), IDM_WIFISETTINGS, MF_BYCOMMAND); - } return 0; case WM_EXITMENULOOP: @@ -7063,67 +7032,83 @@ LRESULT CALLBACK MicrophoneSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, return FALSE; } -#ifdef EXPERIMENTAL_WIFI_COMM LRESULT CALLBACK WifiSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + const bool isSocketsSupported = wifiHandler->IsSocketsSupported(); + const bool isPCapSupported = wifiHandler->IsPCapSupported(); + const WifiEmulationLevel emulationLevel = wifiHandler->GetSelectedEmulationLevel(); + switch(uMsg) { case WM_INITDIALOG: { - char errbuf[PCAP_ERRBUF_SIZE]; - pcap_if_t *alldevs; - pcap_if_t *d; - int i; - HWND cur; - - if (wifiEmulationLevel > WifiEmulationLevel_Off) +#ifdef EXPERIMENTAL_WIFI_COMM + if (emulationLevel != WifiEmulationLevel_Off) { - CheckDlgItem(hDlg, IDC_WIFI_ENABLED, true); - CheckDlgItem(hDlg, IDC_WIFI_COMPAT, wifiEmulationLevel == WifiEmulationLevel_Compatibility); + CheckDlgItem(hDlg, IDC_WIFI_ENABLED, TRUE); + CheckDlgItem(hDlg, IDC_WIFI_COMPAT, (emulationLevel == WifiEmulationLevel_Compatibility)); } else { - CheckDlgItem(hDlg, IDC_WIFI_ENABLED, false); - CheckDlgItem(hDlg, IDC_WIFI_COMPAT, GetPrivateProfileBool("Wifi", "Compatibility Mode", false, IniName)); + CheckDlgItem(hDlg, IDC_WIFI_ENABLED, FALSE); + CheckDlgItem(hDlg, IDC_WIFI_COMPAT, GetPrivateProfileBool("Wifi", "Compatibility Mode", FALSE, IniName)); } - - if (bSocketsAvailable && bWinPCapAvailable) +#else + CheckDlgItem(hDlg, IDC_WIFI_ENABLED, FALSE); + CheckDlgItem(hDlg, IDC_WIFI_COMPAT, FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_WIFI_ENABLED), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_WIFI_COMPAT), FALSE); +#endif + if (isSocketsSupported && isPCapSupported) CheckRadioButton(hDlg, IDC_WIFIMODE0, IDC_WIFIMODE1, IDC_WIFIMODE0 + CommonSettings.wifi.mode); - else if(bSocketsAvailable) + else if(isSocketsSupported) CheckRadioButton(hDlg, IDC_WIFIMODE0, IDC_WIFIMODE1, IDC_WIFIMODE0); - else if(bWinPCapAvailable) + else CheckRadioButton(hDlg, IDC_WIFIMODE0, IDC_WIFIMODE1, IDC_WIFIMODE1); - if (bWinPCapAvailable) + HWND deviceMenu = GetDlgItem(hDlg, IDC_BRIDGEADAPTER); + int menuItemCount = ComboBox_GetCount(deviceMenu); + int deviceCount = -1; + std::vector deviceStringList; + + for (int i = 0; i < menuItemCount; i++) { - if(driver->PCAP_findalldevs(&alldevs, errbuf) == -1) - { - // TODO: fail more gracefully! - EndDialog(hDlg, TRUE); - return TRUE; - } + ComboBox_DeleteString(deviceMenu, 0); + } - cur = GetDlgItem(hDlg, IDC_BRIDGEADAPTER); - for(i = 0, d = alldevs; d != NULL; i++, d = d->next) - { - char buf[256] = {0}; - // on x64 description is empty - if (d->description[0] == 0) - strcpy(buf, d->name); - else - strcpy(buf, d->description); - - ComboBox_AddString(cur, buf); - } - ComboBox_SetCurSel(cur, CommonSettings.wifi.infraBridgeAdapter); + if (isPCapSupported) + { + deviceCount = wifiHandler->GetBridgeDeviceList(&deviceStringList); } else { - EnableWindow(GetDlgItem(hDlg, IDC_WIFIMODE1), FALSE); - EnableWindow(GetDlgItem(hDlg, IDC_BRIDGEADAPTER), FALSE); + SetDlgItemText(hDlg, IDC_WIFIMODE1, "Infrastructure (winpcap not loaded)"); + } + + if (deviceCount < 0) + { + ComboBox_AddString(deviceMenu, "Error: Cannot find any devices."); + ComboBox_SetCurSel(deviceMenu, 0); + EnableWindow(deviceMenu, FALSE); + } + else if (deviceCount == 0) + { + ComboBox_AddString(deviceMenu, "No devices found."); + ComboBox_SetCurSel(deviceMenu, 0); + EnableWindow(deviceMenu, FALSE); + } + else + { + for (size_t i = 0; i < deviceCount; i++) + { + ComboBox_AddString(deviceMenu, deviceStringList[i].c_str()); + } + + ComboBox_SetCurSel(deviceMenu, CommonSettings.wifi.infraBridgeAdapter); + EnableWindow(deviceMenu, TRUE); } - if (!bSocketsAvailable) + if (!isSocketsSupported) EnableWindow(GetDlgItem(hDlg, IDC_WIFIMODE0), FALSE); } return TRUE; @@ -7140,27 +7125,33 @@ LRESULT CALLBACK WifiSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM if(romloaded) val = MessageBox(hDlg, "The current ROM needs to be reset to apply changes.\nReset now ?", "DeSmuME", (MB_YESNO | MB_ICONQUESTION)); - if (IsDlgCheckboxChecked(hDlg, IDC_WIFI_ENABLED)) +#ifdef EXPERIMENTAL_WIFI_COMM + if (IsDlgCheckboxChecked(hDlg, IDC_WIFI_ENABLED)) { if (IsDlgCheckboxChecked(hDlg, IDC_WIFI_COMPAT)) - wifiEmulationLevel = WifiEmulationLevel_Compatibility; + wifiHandler->SetEmulationLevel(WifiEmulationLevel_Compatibility); else - wifiEmulationLevel = WifiEmulationLevel_Normal; + wifiHandler->SetEmulationLevel(WifiEmulationLevel_Normal); } else - wifiEmulationLevel = WifiEmulationLevel_Off; + wifiHandler->SetEmulationLevel(WifiEmulationLevel_Off); WritePrivateProfileBool("Wifi", "Enabled", IsDlgCheckboxChecked(hDlg, IDC_WIFI_ENABLED), IniName); WritePrivateProfileBool("Wifi", "Compatibility Mode", IsDlgCheckboxChecked(hDlg, IDC_WIFI_COMPAT), IniName); +#else + wifiHandler->SetEmulationLevel(WifiEmulationLevel_Off); +#endif if (IsDlgButtonChecked(hDlg, IDC_WIFIMODE0)) - CommonSettings.wifi.mode = 0; + CommonSettings.wifi.mode = WifiCommInterfaceID_AdHoc; else - CommonSettings.wifi.mode = 1; + CommonSettings.wifi.mode = WifiCommInterfaceID_Infrastructure; WritePrivateProfileInt("Wifi", "Mode", CommonSettings.wifi.mode, IniName); + wifiHandler->SetCommInterfaceID(CommonSettings.wifi.mode); cur = GetDlgItem(hDlg, IDC_BRIDGEADAPTER); CommonSettings.wifi.infraBridgeAdapter = ComboBox_GetCurSel(cur); + wifiHandler->SetBridgeDeviceIndex(CommonSettings.wifi.infraBridgeAdapter); WritePrivateProfileInt("Wifi", "BridgeAdapter", CommonSettings.wifi.infraBridgeAdapter, IniName); if(val == IDYES) @@ -7180,7 +7171,6 @@ LRESULT CALLBACK WifiSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM return FALSE; } -#endif static void SoundSettings_updateVolumeReadout(HWND hDlg) { diff --git a/desmume/src/frontend/windows/winpcap.h b/desmume/src/frontend/windows/winpcap.h old mode 100644 new mode 100755 index cd3b62384..49183a8fa --- a/desmume/src/frontend/windows/winpcap.h +++ b/desmume/src/frontend/windows/winpcap.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2010 DeSmuME team + Copyright (C) 2010-2018 DeSmuME team This file is part of DeSmuME @@ -21,14 +21,16 @@ #ifndef WINPCAP_H #define WINPCAP_H -#define HAVE_REMOTE -#define WPCAP -#define PACKET_SIZE 65535 +#ifndef HAVE_REMOTE + #define HAVE_REMOTE +#endif + +#ifndef WPCAP + #define WPCAP +#endif #include -static bool bWinPCapAvailable = false; - typedef int (__cdecl *T_pcap_findalldevs)(pcap_if_t** alldevs, char* errbuf); typedef void (__cdecl *T_pcap_freealldevs)(pcap_if_t* alldevs); typedef pcap_t* (__cdecl *T_pcap_open_live)(const char* source, int snaplen, int flags, int readtimeout, char* errbuf); @@ -51,11 +53,16 @@ T_pcap_dispatch _pcap_dispatch = NULL; if (_##name == NULL) return; -static void LoadWinPCap() +static void LoadWinPCap(bool &outResult) { + bool result = false; + HMODULE wpcap = LoadLibrary("wpcap.dll"); if (wpcap == NULL) + { + outResult = result; return; + } LOADSYMBOL(pcap_findalldevs); LOADSYMBOL(pcap_freealldevs); @@ -65,7 +72,8 @@ static void LoadWinPCap() LOADSYMBOL(pcap_sendpacket); LOADSYMBOL(pcap_dispatch); - bWinPCapAvailable = true; + result = true; + outResult = result; } #endif diff --git a/desmume/src/wifi.cpp b/desmume/src/wifi.cpp old mode 100644 new mode 100755 index 7db09dc29..86410897a --- a/desmume/src/wifi.cpp +++ b/desmume/src/wifi.cpp @@ -26,56 +26,58 @@ #include #ifdef HOST_WINDOWS - #include + #include #include - #define socket_t SOCKET + #define socket_t SOCKET #define sockaddr_t SOCKADDR #ifndef WXPORT #include "windriver.h" #endif #define PCAP_DEVICE_NAME description #else - #include - #include - #include - #include - #include - #define socket_t int + #include + #include + #include + #include + #include + #define socket_t int #define sockaddr_t struct sockaddr #define closesocket close #define PCAP_DEVICE_NAME name #endif -#ifndef INVALID_SOCKET - #define INVALID_SOCKET (socket_t)-1 -#endif +#ifndef INVALID_SOCKET + #define INVALID_SOCKET (socket_t)-1 +#endif #define BASEPORT 7000 +#define PACKET_SIZE 65535 -// PCAP file to store the Ethernet packets. -FILE* captured_packets; - -const u8 BroadcastMAC[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - -bool bWFCUserWarned = false; - -#ifdef EXPERIMENTAL_WIFI_COMM -socket_t wifi_socket = INVALID_SOCKET; -sockaddr_t sendAddr; -#ifndef WIN32 -#include "pcap/pcap.h" +// Some platforms need HAVE_REMOTE to work with libpcap, but +// Apple platforms are not among them. +#ifndef __APPLE__ + #define HAVE_REMOTE #endif -pcap_t *wifi_bridge = NULL; + +#ifdef HOST_WINDOWS + #define WPCAP #endif +#include +typedef struct pcap pcap_t; + //sometimes this isnt defined #ifndef PCAP_OPENFLAG_PROMISCUOUS -#define PCAP_OPENFLAG_PROMISCUOUS 1 + #define PCAP_OPENFLAG_PROMISCUOUS 1 +#endif + +// PCAP_ERRBUF_SIZE should 256 bytes according to POSIX libpcap and winpcap. +// Define it if it isn't available. +#ifndef PCAP_ERRBUF_SIZE + #define PCAP_ERRBUF_SIZE 256 #endif wifimac_t wifiMac; -Adhoc_t Adhoc; -SoftAP_t SoftAP; /******************************************************************************* @@ -241,59 +243,8 @@ FW_WFCProfile FW_WFCProfile3 = {"", {0, 0} }; -/******************************************************************************* - - Communication interface - - *******************************************************************************/ - -struct WifiComInterface -{ - bool (*Init)(); - void (*DeInit)(); - void (*Reset)(); - void (*SendPacket)(u8* packet, u32 len); - void (*usTrigger)(); -}; - -#ifdef EXPERIMENTAL_WIFI_COMM -bool SoftAP_Init(); -void SoftAP_DeInit(); -void SoftAP_Reset(); -void SoftAP_SendPacket(u8 *packet, u32 len); -void SoftAP_usTrigger(); - -WifiComInterface CI_SoftAP = { - SoftAP_Init, - SoftAP_DeInit, - SoftAP_Reset, - SoftAP_SendPacket, - SoftAP_usTrigger -}; - -bool Adhoc_Init(); -void Adhoc_DeInit(); -void Adhoc_Reset(); -void Adhoc_SendPacket(u8* packet, u32 len); -void Adhoc_usTrigger(); - -WifiComInterface CI_Adhoc = { - Adhoc_Init, - Adhoc_DeInit, - Adhoc_Reset, - Adhoc_SendPacket, - Adhoc_usTrigger -}; -#endif - -WifiComInterface* wifiComs[] = { -#ifdef EXPERIMENTAL_WIFI_COMM - &CI_Adhoc, - &CI_SoftAP, -#endif - NULL -}; -WifiComInterface* wifiCom; +DummyPCapInterface dummyPCapInterface; +WifiHandler *wifiHandler = NULL; /******************************************************************************* @@ -318,9 +269,13 @@ WifiComInterface* wifiCom; #define WIFI_LOG(level, ...) if(level <= WIFI_LOGGING_LEVEL) printf("WIFI: " __VA_ARGS__); #endif #else -#define WIFI_LOG(level, ...) {} + #define WIFI_LOG(level, ...) {} #endif +// For debugging purposes, the results of libpcap can be written to a file. +// Note that enabling this setting can negatively affect emulation performance. +#define WIFI_SAVE_PCAP_TO_FILE 0 + /******************************************************************************* Helpers @@ -333,13 +288,12 @@ INLINE u32 WIFI_alignedLen(u32 len) } // Fast MAC compares - -INLINE bool WIFI_compareMAC(u8* a, u8* b) +INLINE bool WIFI_compareMAC(const u8 *a, const u8 *b) { return ((*(u32*)&a[0]) == (*(u32*)&b[0])) && ((*(u16*)&a[4]) == (*(u16*)&b[4])); } -INLINE bool WIFI_isBroadcastMAC(u8* a) +INLINE bool WIFI_isBroadcastMAC(const u8 *a) { return ((*(u32*)&a[0]) == 0xFFFFFFFF) && ((*(u16*)&a[4]) == 0xFFFF); } @@ -370,7 +324,7 @@ static u32 WIFI_calcCRC32(u8 *data, int len) { u32 crc = 0xFFFFFFFF; - while(len--) + while (len--) crc = (crc >> 8) ^ WIFI_CRC32Table[(crc & 0xFF) ^ *data++]; return (crc ^ 0xFFFFFFFF); @@ -379,15 +333,15 @@ static u32 WIFI_calcCRC32(u8 *data, int len) static void WIFI_initCRC32Table() { static bool initialized = false; - if(initialized) return; + if (initialized) return; initialized = true; u32 polynomial = 0x04C11DB7; - for(int i = 0; i < 0x100; i++) + for (int i = 0; i < 0x100; i++) { WIFI_CRC32Table[i] = reflect(i, 8) << 24; - for(int j = 0; j < 8; j++) + for (int j = 0; j < 8; j++) WIFI_CRC32Table[i] = (WIFI_CRC32Table[i] << 1) ^ (WIFI_CRC32Table[i] & (1 << 31) ? polynomial : 0); WIFI_CRC32Table[i] = reflect(WIFI_CRC32Table[i], 32); } @@ -638,60 +592,6 @@ static void WIFI_triggerIRQ(u8 irq) WIFI_triggerIRQMask(1<= ARRAY_SIZE(wifiComs)) - CommonSettings.wifi.mode = 0; - wifiCom = wifiComs[CommonSettings.wifi.mode]; - if(wifiCom) - wifiCom->Init(); - - bWFCUserWarned = false; - - return true; -} - -void WIFI_DeInit() -{ - if(wifiCom) - wifiCom->DeInit(); -} - -void WIFI_Reset() -{ - memset(&wifiMac, 0, sizeof(wifimac_t)); - - WIFI_resetRF(&wifiMac.RF); - - wifiMac.powerOn = FALSE; - wifiMac.powerOnPending = FALSE; - - wifiMac.rfStatus = 0x0000; - wifiMac.rfPins = 0x0004; - - if((u32)CommonSettings.wifi.mode >= ARRAY_SIZE(wifiComs)) - CommonSettings.wifi.mode = 0; - wifiCom = wifiComs[CommonSettings.wifi.mode]; - if(wifiCom) - wifiCom->Reset(); - - bWFCUserWarned = false; -} - - INLINE u16 WIFI_GetRXFlags(u8* packet) { u16 ret = 0x0010; @@ -747,7 +647,6 @@ INLINE void WIFI_MakeRXHeader(u8* buf, u16 flags, u16 xferRate, u16 len, u8 maxR buf[11] = 255;//minRSSI; } -#ifdef EXPERIMENTAL_WIFI_COMM static void WIFI_RXPutWord(u16 val) { /* abort when RX data queuing is not enabled */ @@ -769,10 +668,9 @@ static void WIFI_RXPutWord(u16 val) /* wrap around */ // wifiMac.RXWriteCursor %= (wifiMac.RXRangeEnd - wifiMac.RXRangeBegin) >> 1; // printf("new addr=%04X\n", wifiMac.RXWriteCursor); - if(wifiMac.RXWriteCursor >= ((wifiMac.RXRangeEnd & 0x1FFE) >> 1)) + if (wifiMac.RXWriteCursor >= ((wifiMac.RXRangeEnd & 0x1FFE) >> 1)) wifiMac.RXWriteCursor = ((wifiMac.RXRangeBegin & 0x1FFE) >> 1); } -#endif static void WIFI_TXStart(u8 slot) { @@ -908,8 +806,7 @@ static void WIFI_ExtraTXStart() // Note: Extra transfers trigger two TX start interrupts according to GBATek WIFI_triggerIRQ(WIFI_IRQ_TXSTART); - if(wifiCom) - wifiCom->SendPacket((u8*)&wifiMac.RAM[address+6], txLen); + wifiHandler->CommSendPacket((u8 *)&wifiMac.RAM[address+6], txLen); WIFI_triggerIRQ(WIFI_IRQ_UNK); if (BIT13(wifiMac.TXStatCnt)) @@ -976,9 +873,8 @@ static void WIFI_BeaconTXStart() *(u32*)&wifiMac.RAM[address + 6 + ((txLen-4) >> 1)] = crc32; WIFI_triggerIRQ(WIFI_IRQ_TXSTART); - if(wifiCom) - wifiCom->SendPacket((u8*)&wifiMac.RAM[address+6], txLen); - + wifiHandler->CommSendPacket((u8 *)&wifiMac.RAM[address+6], txLen); + if (BIT15(wifiMac.TXStatCnt)) { WIFI_triggerIRQ(WIFI_IRQ_TXEND); @@ -992,7 +888,7 @@ static void WIFI_BeaconTXStart() void WIFI_write16(u32 address, u16 val) { - BOOL action = FALSE; + bool action = false; if (!nds.power2.wifi) return; u32 page = address & 0x7000; @@ -1015,7 +911,7 @@ void WIFI_write16(u32 address, u16 val) // anything else: I/O ports // only the first mirror (0x0000 - 0x0FFF) causes a special action - if (page == 0x0000) action = TRUE; + if (page == 0x0000) action = true; address &= 0x0FFF; switch (address) @@ -1112,28 +1008,28 @@ void WIFI_write16(u32 address, u16 val) wifiMac.WEP_enable = (val & 0x8000) != 0; break; case REG_WIFI_POWERSTATE: - wifiMac.powerOn = ((val & 0x0002)?TRUE:FALSE); - if(wifiMac.powerOn) WIFI_triggerIRQ(WIFI_IRQ_RFWAKEUP); + wifiMac.powerOn = ((val & 0x0002) ? true : false); + if (wifiMac.powerOn) WIFI_triggerIRQ(WIFI_IRQ_RFWAKEUP); break; case REG_WIFI_POWERFORCE: - if((val & 0x8000) && (!wifiMac.powerOnPending)) + if ((val & 0x8000) && (!wifiMac.powerOnPending)) { - /* BOOL newPower = ((val & 0x0001)?FALSE:TRUE); - if(newPower != wifiMac.powerOn) + /* bool newPower = ((val & 0x0001) ? false : true); + if (newPower != wifiMac.powerOn) { - if(!newPower) - wifiMac.powerOn = FALSE; + if (!newPower) + wifiMac.powerOn = false; else - wifiMac.powerOnPending = TRUE; + wifiMac.powerOnPending = true; }*/ - wifiMac.powerOn = ((val & 0x0001) ? FALSE : TRUE); + wifiMac.powerOn = ((val & 0x0001) ? false : true); } break; case REG_WIFI_POWERACK: - if((val == 0x0000) && wifiMac.powerOnPending) + if ((val == 0x0000) && wifiMac.powerOnPending) { - wifiMac.powerOn = TRUE; - wifiMac.powerOnPending = FALSE; + wifiMac.powerOn = true; + wifiMac.powerOnPending = false; } break; case REG_WIFI_POWER_TX: @@ -1141,7 +1037,7 @@ void WIFI_write16(u32 address, u16 val) break; case REG_WIFI_RXCNT: wifiMac.RXCnt = val & 0xFF0E; - if(BIT0(val)) + if (BIT0(val)) { wifiMac.RXWriteCursor = WIFI_IOREG(REG_WIFI_WRITECSRLATCH); WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; @@ -1149,12 +1045,12 @@ void WIFI_write16(u32 address, u16 val) break; case REG_WIFI_RXRANGEBEGIN: wifiMac.RXRangeBegin = val; - if(wifiMac.RXWriteCursor < ((val & 0x1FFE) >> 1)) + if (wifiMac.RXWriteCursor < ((val & 0x1FFE) >> 1)) wifiMac.RXWriteCursor = ((val & 0x1FFE) >> 1); break; case REG_WIFI_RXRANGEEND: wifiMac.RXRangeEnd = val; - if(wifiMac.RXWriteCursor >= ((val & 0x1FFE) >> 1)) + if (wifiMac.RXWriteCursor >= ((val & 0x1FFE) >> 1)) wifiMac.RXWriteCursor = ((wifiMac.RXRangeBegin & 0x1FFE) >> 1); break; @@ -1341,7 +1237,7 @@ void WIFI_write16(u32 address, u16 val) u16 WIFI_read16(u32 address) { - BOOL action = FALSE; + bool action = false; if (!nds.power2.wifi) return 0; u32 page = address & 0x7000; @@ -1360,7 +1256,7 @@ u16 WIFI_read16(u32 address) // anything else: I/O ports // only the first mirror causes a special action - if (page == 0x0000) action = TRUE; + if (page == 0x0000) action = true; address &= 0x0FFF; switch (address) @@ -1571,23 +1467,22 @@ void WIFI_usTrigger() WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); } - if((wifiMac.usec & 3) == 0) + if ((wifiMac.usec & 3) == 0) { int slot = wifiMac.txCurSlot; - if(wifiMac.txSlotBusy[slot]) + if (wifiMac.txSlotBusy[slot]) { wifiMac.txSlotRemainingBytes[slot]--; wifiMac.RXTXAddr++; - if(wifiMac.txSlotRemainingBytes[slot] == 0) + if (wifiMac.txSlotRemainingBytes[slot] == 0) { wifiMac.txSlotBusy[slot] = 0; wifiMac.TXSlot[slot] &= 0x7FFF; + + wifiHandler->CommSendPacket((u8 *)&wifiMac.RAM[wifiMac.txSlotAddr[slot]+6], wifiMac.txSlotLen[slot]); - if(wifiCom) - wifiCom->SendPacket((u8*)&wifiMac.RAM[wifiMac.txSlotAddr[slot]+6], wifiMac.txSlotLen[slot]); - - while((wifiMac.txSlotBusy[wifiMac.txCurSlot] == 0) && (wifiMac.txCurSlot > 0)) + while ((wifiMac.txSlotBusy[wifiMac.txCurSlot] == 0) && (wifiMac.txCurSlot > 0)) wifiMac.txCurSlot--; wifiMac.RAM[wifiMac.txSlotAddr[slot]] = 0x0001; @@ -1608,8 +1503,7 @@ void WIFI_usTrigger() } } - if(wifiCom) - wifiCom->usTrigger(); + wifiHandler->CommTrigger(); } /******************************************************************************* @@ -1617,8 +1511,6 @@ void WIFI_usTrigger() Ad-hoc communication interface *******************************************************************************/ - -#ifdef EXPERIMENTAL_WIFI_COMM #define ADHOC_MAGIC "NDSWIFI\0" #define ADHOC_PROTOCOL_VERSION 0x0100 // v1.0 @@ -1630,208 +1522,6 @@ typedef struct _Adhoc_FrameHeader } Adhoc_FrameHeader; - -bool Adhoc_Init() -{ - BOOL opt_true = TRUE; - int res; - - if (!driver->WIFI_SocketsAvailable()) - { - WIFI_LOG(1, "Ad-hoc: failed to initialize sockets.\n"); - wifi_socket = INVALID_SOCKET; - return false; - } - - // Create an UDP socket - wifi_socket = socket(AF_INET, SOCK_DGRAM, 0); - if (wifi_socket < 0) - { - WIFI_LOG(1, "Ad-hoc: Failed to create socket.\n"); - return false; - } - - // Enable the socket to be bound to an address/port that is already in use - // This enables us to communicate with another DeSmuME instance running on the same computer. - res = setsockopt(wifi_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(BOOL)); - - // Bind the socket to any address on port 7000 - sockaddr_t saddr; - saddr.sa_family = AF_INET; - *(u32*)&saddr.sa_data[2] = htonl(INADDR_ANY); - *(u16*)&saddr.sa_data[0] = htons(BASEPORT); - res = bind(wifi_socket, &saddr, sizeof(sockaddr_t)); - if (res < 0) - { - WIFI_LOG(1, "Ad-hoc: failed to bind the socket.\n"); - closesocket(wifi_socket); wifi_socket = INVALID_SOCKET; - return false; - } - - // Enable broadcast mode - // Not doing so results in failure when sendto'ing to broadcast address - res = setsockopt(wifi_socket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(BOOL)); - if (res < 0) - { - WIFI_LOG(1, "Ad-hoc: failed to enable broadcast mode.\n"); - closesocket(wifi_socket); wifi_socket = INVALID_SOCKET; - return false; - } - - // Prepare an address structure for sending packets - sendAddr.sa_family = AF_INET; - *(u32*)&sendAddr.sa_data[2] = htonl(INADDR_BROADCAST); - *(u16*)&sendAddr.sa_data[0] = htons(BASEPORT); - - Adhoc_Reset(); - - WIFI_LOG(1, "Ad-hoc: initialization successful.\n"); - - return true; -} - -void Adhoc_DeInit() -{ - if (wifi_socket >= 0) - closesocket(wifi_socket); -} - -void Adhoc_Reset() -{ - Adhoc.usecCounter = 0; - - driver->WIFI_GetUniqueMAC(FW_Mac); - NDS_PatchFirmwareMAC(); - - printf("WIFI: ADHOC: MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", - FW_Mac[0], FW_Mac[1], FW_Mac[2], FW_Mac[3], FW_Mac[4], FW_Mac[5]); -} - -void Adhoc_SendPacket(u8* packet, u32 len) -{ - if (wifi_socket < 0) - return; - - WIFI_LOG(2, "Ad-hoc: sending a packet of %i bytes, frame control: %04X\n", len, *(u16*)&packet[0]); - - u32 frameLen = sizeof(Adhoc_FrameHeader) + len; - - u8* frame = new u8[frameLen]; - u8* ptr = frame; - - Adhoc_FrameHeader header; - strncpy(header.magic, ADHOC_MAGIC, 8); - header.version = ADHOC_PROTOCOL_VERSION; - header.packetLen = len; - memcpy(ptr, &header, sizeof(Adhoc_FrameHeader)); - ptr += sizeof(Adhoc_FrameHeader); - - memcpy(ptr, packet, len); - - int nbytes = sendto(wifi_socket, (const char*)frame, frameLen, 0, &sendAddr, sizeof(sockaddr_t)); - - WIFI_LOG(4, "Ad-hoc: sent %i/%i bytes of packet.\n", nbytes, frameLen); - - delete[] frame; -} - -void Adhoc_usTrigger() -{ - Adhoc.usecCounter++; - - if (wifi_socket < 0) - return; - - // Check every millisecond if we received a packet - if (!(Adhoc.usecCounter & 1023)) - { - fd_set fd; - struct timeval tv; - - FD_ZERO(&fd); - FD_SET(wifi_socket, &fd); - tv.tv_sec = 0; - tv.tv_usec = 0; - - if (select(1, &fd, 0, 0, &tv)) - { - sockaddr_t fromAddr; - socklen_t fromLen = sizeof(sockaddr_t); - u8 buf[1536]; - u8* ptr; - u16 packetLen; - - int nbytes = recvfrom(wifi_socket, (char*)buf, 1536, 0, &fromAddr, &fromLen); - - // No packet arrived (or there was an error) - if (nbytes <= 0) - return; - - ptr = buf; - Adhoc_FrameHeader header = *(Adhoc_FrameHeader*)ptr; - - // Check the magic string in header - if (strncmp(header.magic, ADHOC_MAGIC, 8)) - return; - - // Check the ad-hoc protocol version - if (header.version != ADHOC_PROTOCOL_VERSION) - return; - - packetLen = header.packetLen; - ptr += sizeof(Adhoc_FrameHeader); - - // If the packet is for us, send it to the wifi core - if (!WIFI_compareMAC(&ptr[10], &wifiMac.mac.bytes[0])) - { - if (WIFI_isBroadcastMAC(&ptr[16]) || - WIFI_compareMAC(&ptr[16], &wifiMac.bss.bytes[0]) || - WIFI_isBroadcastMAC(&wifiMac.bss.bytes[0])) - { - /* printf("packet was for us: mac=%02X:%02X.%02X.%02X.%02X.%02X, bssid=%02X:%02X.%02X.%02X.%02X.%02X\n", - wifiMac.mac.bytes[0], wifiMac.mac.bytes[1], wifiMac.mac.bytes[2], wifiMac.mac.bytes[3], wifiMac.mac.bytes[4], wifiMac.mac.bytes[5], - wifiMac.bss.bytes[0], wifiMac.bss.bytes[1], wifiMac.bss.bytes[2], wifiMac.bss.bytes[3], wifiMac.bss.bytes[4], wifiMac.bss.bytes[5]); - printf("da=%02X:%02X.%02X.%02X.%02X.%02X, sa=%02X:%02X.%02X.%02X.%02X.%02X, bssid=%02X:%02X.%02X.%02X.%02X.%02X\n", - ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], - ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], - ptr[16], ptr[17], ptr[18], ptr[19], ptr[20], ptr[21]);*/ - /* WIFI_LOG(3, "Ad-hoc: received a packet of %i bytes from %i.%i.%i.%i (port %i).\n", - nbytes, - (u8)fromAddr.sa_data[2], (u8)fromAddr.sa_data[3], - (u8)fromAddr.sa_data[4], (u8)fromAddr.sa_data[5], - ntohs(*(u16*)&fromAddr.sa_data[0]));*/ - WIFI_LOG(2, "Ad-hoc: received a packet of %i bytes, frame control: %04X\n", packetLen, *(u16*)&ptr[0]); - //WIFI_LOG(2, "Storing packet at %08X.\n", 0x04804000 + (wifiMac.RXWriteCursor<<1)); - - //if (((*(u16*)&ptr[0]) != 0x0080) && ((*(u16*)&ptr[0]) != 0x0228)) - // printf("received packet, framectl=%04X\n", (*(u16*)&ptr[0])); - - //if ((*(u16*)&ptr[0]) == 0x0228) - // printf("wifi: received fucking packet!\n"); - - WIFI_triggerIRQ(WIFI_IRQ_RXSTART); - - u8* packet = new u8[12 + packetLen]; - - WIFI_MakeRXHeader(packet, WIFI_GetRXFlags(ptr), 20, packetLen, 0, 0); - memcpy(&packet[12], ptr, packetLen); - - for (int i = 0; i < (12 + packetLen); i += 2) - { - u16 word = *(u16*)&packet[i]; - WIFI_RXPutWord(word); - } - - wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1)); - WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; - wifiMac.RXNum++; - WIFI_triggerIRQ(WIFI_IRQ_RXEND); - } - } - } - } -} - /******************************************************************************* SoftAP (fake wifi access point) @@ -1932,106 +1622,419 @@ const u8 SoftAP_DeauthFrame[] = { 0x01, 0x00, // Reason code (is "unspecified" ok?) }; -//todo - make a class to wrap this -//todo - zeromus - inspect memory leak safety of all this -static pcap_if_t * WIFI_index_device(pcap_if_t *alldevs, int index) +static void SoftAP_PacketRX_Callback(u_char *userData, const pcap_pkthdr *pktHeader, const u_char *pktData) { - pcap_if_t *curr = alldevs; - - for(int i = 0; i < index; i++) - curr = curr->next; - - WIFI_LOG(2, "SoftAP: using %s as device.\n", curr->PCAP_DEVICE_NAME); - - return curr; + if (userData == NULL) + { + return; + } + + SoftAPCommInterface *softAP = (SoftAPCommInterface *)userData; + softAP->PacketRX(pktHeader, (u8 *)pktData); } -bool SoftAP_Init() +void DummyPCapInterface::__CopyErrorString(char *errbuf) { - SoftAP.usecCounter = 0; + const char *errString = "libpcap is not available"; + strncpy(errbuf, errString, PCAP_ERRBUF_SIZE); +} - SoftAP.curPacketSize = 0; - SoftAP.curPacketPos = 0; - SoftAP.curPacketSending = FALSE; +int DummyPCapInterface::findalldevs(void **alldevs, char *errbuf) +{ + this->__CopyErrorString(errbuf); + return -1; +} - SoftAP.status = APStatus_Disconnected; - SoftAP.seqNum = 0; +void DummyPCapInterface::freealldevs(void *alldevs) +{ + // Do nothing. +} - if (!driver->WIFI_PCapAvailable()) - { - WIFI_LOG(1, "SoftAP: PCap library not available on your system.\n"); - wifi_bridge = NULL; - return false; - } - else - { - WIFI_LOG(1, "SoftAP: PCap library available on your system.\n"); - } +void* DummyPCapInterface::open(const char *source, int snaplen, int flags, int readtimeout, char *errbuf) +{ + this->__CopyErrorString(errbuf); + return NULL; +} + +void DummyPCapInterface::close(void *dev) +{ + // Do nothing. +} + +int DummyPCapInterface::setnonblock(void *dev, int nonblock, char *errbuf) +{ + this->__CopyErrorString(errbuf); + return -1; +} + +int DummyPCapInterface::sendpacket(void *dev, const void *data, int len) +{ + return -1; +} + +int DummyPCapInterface::dispatch(void *dev, int num, void *callback, void *userdata) +{ + return -1; +} + +#ifndef HOST_WINDOWS + +int POSIXPCapInterface::findalldevs(void **alldevs, char *errbuf) +{ + return pcap_findalldevs((pcap_if_t **)alldevs, errbuf); +} + +void POSIXPCapInterface::freealldevs(void *alldevs) +{ + pcap_freealldevs((pcap_if_t *)alldevs); +} + +void* POSIXPCapInterface::open(const char *source, int snaplen, int flags, int readtimeout, char *errbuf) +{ + return pcap_open_live(source, snaplen, flags, readtimeout, errbuf); +} + +void POSIXPCapInterface::close(void *dev) +{ + pcap_close((pcap_t *)dev); +} + +int POSIXPCapInterface::setnonblock(void *dev, int nonblock, char *errbuf) +{ + return pcap_setnonblock((pcap_t *)dev, nonblock, errbuf); +} + +int POSIXPCapInterface::sendpacket(void *dev, const void *data, int len) +{ + return pcap_sendpacket((pcap_t *)dev, (u_char *)data, len); +} + +int POSIXPCapInterface::dispatch(void *dev, int num, void *callback, void *userdata) +{ + if (callback == NULL) + { + return -1; + } - char errbuf[PCAP_ERRBUF_SIZE]; - pcap_if_t *alldevs; - int ret; + return pcap_dispatch((pcap_t *)dev, num, (pcap_handler)callback, (u_char *)userdata); +} - ret = driver->PCAP_findalldevs(&alldevs, errbuf); - if (ret == -1 || alldevs == NULL) +#endif + +WifiCommInterface::WifiCommInterface() +{ + _usecCounter = 0; + _emulationLevel = WifiEmulationLevel_Off; +} + +WifiCommInterface::~WifiCommInterface() +{ + // Do nothing... for now. +} + +AdhocCommInterface::AdhocCommInterface() +{ + _commInterfaceID = WifiCommInterfaceID_AdHoc; + + _wifiSocket = (socket_t *)malloc(sizeof(socket_t)); + *((socket_t *)_wifiSocket) = INVALID_SOCKET; + + _sendAddr = (sockaddr_t *)malloc(sizeof(sockaddr_t)); + + _packetBuffer = NULL; +} + +AdhocCommInterface::~AdhocCommInterface() +{ + this->Stop(); + + free(this->_wifiSocket); + free(this->_sendAddr); +} + +bool AdhocCommInterface::Start(WifiEmulationLevel emulationLevel) +{ + int socketOptValueTrue = 1; + int result = -1; + + this->_usecCounter = 0; + + // Ad-hoc mode won't have a partial-functioning variant, and so just return + // if the WiFi emulation level is Off. + if (emulationLevel == WifiEmulationLevel_Off) { - WIFI_LOG(1, "SoftAP: PCap: failed to find any network adapter: %s\n", errbuf); + this->_emulationLevel = WifiEmulationLevel_Off; return false; } - else - { - WIFI_LOG(1, "SoftAP: PCap: Find a network adapter.\n"); - } - pcap_if_t* dev = WIFI_index_device(alldevs,CommonSettings.wifi.infraBridgeAdapter); - wifi_bridge = driver->PCAP_open(dev->name, PACKET_SIZE, PCAP_OPENFLAG_PROMISCUOUS, 1, errbuf); - if(wifi_bridge == NULL) + socket_t &thisSocket = *((socket_t *)this->_wifiSocket); + + // Create an UDP socket. + thisSocket = socket(AF_INET, SOCK_DGRAM, 0); + if (thisSocket < 0) { - WIFI_LOG(1, "SoftAP: PCap: failed to open %s: %s\n", dev->PCAP_DEVICE_NAME, errbuf); - driver->PCAP_freealldevs(alldevs); + thisSocket = INVALID_SOCKET; + this->_emulationLevel = WifiEmulationLevel_Off; + + // Ad-hoc mode really needs a socket to work at all, so don't even bother + // running this comm interface if we didn't get a working socket. + WIFI_LOG(1, "Ad-hoc: Failed to create socket.\n"); return false; } - else - { - WIFI_LOG(1, "SoftAP: PCap: Device %s successfully opened.\n", dev->PCAP_DEVICE_NAME); - } - - driver->PCAP_freealldevs(alldevs); - - // Set non-blocking mode - if (driver->PCAP_setnonblock(wifi_bridge, 1, errbuf) == -1) + + // Enable the socket to be bound to an address/port that is already in use + // This enables us to communicate with another DeSmuME instance running on the same computer. + result = setsockopt(thisSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&socketOptValueTrue, sizeof(int)); + +#ifdef SO_REUSEPORT + // Some platforms also need to enable SO_REUSEPORT, so do so if its necessary. + result = setsockopt(thisSocket, SOL_SOCKET, SO_REUSEPORT, (const char *)&socketOptValueTrue, sizeof(int)); +#endif + + // Bind the socket to any address on port 7000. + sockaddr_t saddr; + saddr.sa_family = AF_INET; + *(u32 *)&saddr.sa_data[2] = htonl(INADDR_ANY); + *(u16 *)&saddr.sa_data[0] = htons(BASEPORT); + + result = bind(thisSocket, &saddr, sizeof(sockaddr_t)); + if (result < 0) { - WIFI_LOG(1, "SoftAP: PCap: failed to set non-blocking mode: %s\n", errbuf); - driver->PCAP_close(wifi_bridge); wifi_bridge = NULL; + closesocket(thisSocket); + thisSocket = INVALID_SOCKET; + this->_emulationLevel = WifiEmulationLevel_Off; + + WIFI_LOG(1, "Ad-hoc: Failed to bind the socket.\n"); return false; } - else - { - WIFI_LOG(1, "SoftAP: PCap: Non-blocking mode successfully activated.\n"); - } + + // Enable broadcast mode + // Not doing so results in failure when sendto'ing to broadcast address + result = setsockopt(thisSocket, SOL_SOCKET, SO_BROADCAST, (const char *)&socketOptValueTrue, sizeof(int)); + if (result < 0) + { + closesocket(thisSocket); + thisSocket = INVALID_SOCKET; + this->_emulationLevel = WifiEmulationLevel_Off; + + WIFI_LOG(1, "Ad-hoc: Failed to enable broadcast mode.\n"); + return false; + } + + // Prepare an address structure for sending packets. + sockaddr_t &thisSendAddr = *((sockaddr_t *)this->_sendAddr); + thisSendAddr.sa_family = AF_INET; + *(u32 *)&thisSendAddr.sa_data[2] = htonl(INADDR_BROADCAST); + *(u16 *)&thisSendAddr.sa_data[0] = htons(BASEPORT); + + // Allocate 16KB worth of memory for sending packets. Hopefully, this should be plenty. + this->_packetBuffer = (u8 *)malloc(16 * 1024); + + this->_emulationLevel = emulationLevel; + WIFI_LOG(1, "Ad-hoc: Initialization successful.\n"); return true; } -void SoftAP_DeInit() +void AdhocCommInterface::Stop() { - if(wifi_bridge != NULL) - driver->PCAP_close(wifi_bridge); + socket_t &thisSocket = *((socket_t *)this->_wifiSocket); + + if (thisSocket >= 0) + { + closesocket(thisSocket); + } + + free(this->_packetBuffer); + this->_packetBuffer = NULL; } -void SoftAP_Reset() +void AdhocCommInterface::SendPacket(void *data, size_t len) { - SoftAP.usecCounter = 0; + socket_t &thisSocket = *((socket_t *)this->_wifiSocket); + sockaddr_t &thisSendAddr = *((sockaddr_t *)this->_sendAddr); - SoftAP.curPacketSize = 0; - SoftAP.curPacketPos = 0; - SoftAP.curPacketSending = FALSE; - - SoftAP.status = APStatus_Disconnected; - SoftAP.seqNum = 0; + if (thisSocket < 0) + { + return; + } + + WIFI_LOG(2, "Ad-hoc: sending a packet of %i bytes, frame control: %04X\n", (int)len, *(u16 *)data); + + size_t frameLen = sizeof(Adhoc_FrameHeader) + len; + u8 *ptr = this->_packetBuffer; + + Adhoc_FrameHeader header; + strncpy(header.magic, ADHOC_MAGIC, 8); + header.version = ADHOC_PROTOCOL_VERSION; + header.packetLen = len; + memcpy(ptr, &header, sizeof(Adhoc_FrameHeader)); + ptr += sizeof(Adhoc_FrameHeader); + + memcpy(ptr, data, len); + + size_t nbytes = sendto(thisSocket, (const char *)this->_packetBuffer, frameLen, 0, &thisSendAddr, sizeof(sockaddr_t)); + + WIFI_LOG(4, "Ad-hoc: sent %i/%i bytes of packet.\n", (int)nbytes, (int)frameLen); } -static bool SoftAP_IsDNSRequestToWFC(u16 ethertype, u8* body) +void AdhocCommInterface::Trigger() +{ + socket_t &thisSocket = *((socket_t *)this->_wifiSocket); + + this->_usecCounter++; + + if (thisSocket < 0) + { + return; + } + + // Check every millisecond if we received a packet + if (!(this->_usecCounter & 1023)) + { + fd_set fd; + struct timeval tv; + + FD_ZERO(&fd); + FD_SET(thisSocket, &fd); + tv.tv_sec = 0; + tv.tv_usec = 0; + + if (select(1, &fd, 0, 0, &tv)) + { + sockaddr_t fromAddr; + socklen_t fromLen = sizeof(sockaddr_t); + u8 buf[1536]; + u8 *ptr; + u16 packetLen; + + int nbytes = recvfrom(thisSocket, (char *)buf, 1536, 0, &fromAddr, &fromLen); + + // No packet arrived (or there was an error) + if (nbytes <= 0) + return; + + ptr = buf; + Adhoc_FrameHeader header = *(Adhoc_FrameHeader *)ptr; + + // Check the magic string in header + if (strncmp(header.magic, ADHOC_MAGIC, 8)) + return; + + // Check the ad-hoc protocol version + if (header.version != ADHOC_PROTOCOL_VERSION) + return; + + packetLen = header.packetLen; + ptr += sizeof(Adhoc_FrameHeader); + + // If the packet is for us, send it to the wifi core + if (!WIFI_compareMAC(&ptr[10], &wifiMac.mac.bytes[0])) + { + if (WIFI_isBroadcastMAC(&ptr[16]) || + WIFI_compareMAC(&ptr[16], &wifiMac.bss.bytes[0]) || + WIFI_isBroadcastMAC(&wifiMac.bss.bytes[0])) + { + /* printf("packet was for us: mac=%02X:%02X.%02X.%02X.%02X.%02X, bssid=%02X:%02X.%02X.%02X.%02X.%02X\n", + wifiMac.mac.bytes[0], wifiMac.mac.bytes[1], wifiMac.mac.bytes[2], wifiMac.mac.bytes[3], wifiMac.mac.bytes[4], wifiMac.mac.bytes[5], + wifiMac.bss.bytes[0], wifiMac.bss.bytes[1], wifiMac.bss.bytes[2], wifiMac.bss.bytes[3], wifiMac.bss.bytes[4], wifiMac.bss.bytes[5]); + printf("da=%02X:%02X.%02X.%02X.%02X.%02X, sa=%02X:%02X.%02X.%02X.%02X.%02X, bssid=%02X:%02X.%02X.%02X.%02X.%02X\n", + ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], + ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], + ptr[16], ptr[17], ptr[18], ptr[19], ptr[20], ptr[21]);*/ + /* WIFI_LOG(3, "Ad-hoc: received a packet of %i bytes from %i.%i.%i.%i (port %i).\n", + nbytes, + (u8)fromAddr.sa_data[2], (u8)fromAddr.sa_data[3], + (u8)fromAddr.sa_data[4], (u8)fromAddr.sa_data[5], + ntohs(*(u16*)&fromAddr.sa_data[0]));*/ + WIFI_LOG(2, "Ad-hoc: received a packet of %i bytes, frame control: %04X\n", packetLen, *(u16*)&ptr[0]); + //WIFI_LOG(2, "Storing packet at %08X.\n", 0x04804000 + (wifiMac.RXWriteCursor<<1)); + + //if (((*(u16*)&ptr[0]) != 0x0080) && ((*(u16*)&ptr[0]) != 0x0228)) + // printf("received packet, framectl=%04X\n", (*(u16*)&ptr[0])); + + //if ((*(u16*)&ptr[0]) == 0x0228) + // printf("wifi: received fucking packet!\n"); + + WIFI_triggerIRQ(WIFI_IRQ_RXSTART); + + u8 *packet = new u8[12 + packetLen]; + + WIFI_MakeRXHeader(packet, WIFI_GetRXFlags(ptr), 20, packetLen, 0, 0); + memcpy(&packet[12], ptr, packetLen); + + for (int i = 0; i < (12 + packetLen); i += 2) + { + u16 word = *(u16 *)&packet[i]; + WIFI_RXPutWord(word); + } + + wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1)); + WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; + wifiMac.RXNum++; + WIFI_triggerIRQ(WIFI_IRQ_RXEND); + } + } + } + } +} + +SoftAPCommInterface::SoftAPCommInterface() +{ + _commInterfaceID = WifiCommInterfaceID_Infrastructure; + _pcap = &dummyPCapInterface; + _bridgeDeviceIndex = 0; + _bridgeDevice = NULL; + _packetCaptureFile = NULL; + + memset(_curPacket, 0, sizeof(_curPacket)); + _curPacketSize = 0; + _curPacketPos = 0; + _curPacketSending = false; + _status = APStatus_Disconnected; + _seqNum = 0; +} + +SoftAPCommInterface::~SoftAPCommInterface() +{ + this->Stop(); +} + +void* SoftAPCommInterface::_GetBridgeDeviceAtIndex(int deviceIndex, char *outErrorBuf) +{ + void *deviceList = NULL; + void *theDevice = NULL; + int result = this->_pcap->findalldevs((void **)&deviceList, outErrorBuf); + + if ( (result == -1) || (deviceList == NULL) ) + { + WIFI_LOG(1, "SoftAP: Failed to find any network adapter: %s\n", outErrorBuf); + return theDevice; + } + + pcap_if_t *currentDevice = (pcap_if_t *)deviceList; + + for (int i = 0; i < deviceIndex; i++) + { + currentDevice = currentDevice->next; + } + + theDevice = this->_pcap->open(currentDevice->name, PACKET_SIZE, PCAP_OPENFLAG_PROMISCUOUS, 1, outErrorBuf); + if (theDevice == NULL) + { + WIFI_LOG(1, "SoftAP: Failed to open device %s: %s\n", currentDevice->PCAP_DEVICE_NAME, outErrorBuf); + } + else + { + WIFI_LOG(1, "SoftAP: Device %s successfully opened.\n", currentDevice->PCAP_DEVICE_NAME); + } + + this->_pcap->freealldevs(deviceList); + + return theDevice; +} + +bool SoftAPCommInterface::_IsDNSRequestToWFC(u16 ethertype, u8 *body) { // Check the various headers... if (ntohs(ethertype) != 0x0800) return false; // EtherType: IP @@ -2049,352 +2052,169 @@ static bool SoftAP_IsDNSRequestToWFC(u16 ethertype, u8* body) u8 bitlength = 0; char domainname[256] = ""; while ((bitlength = body[curoffset++]) != 0) { - strncat(domainname, (const char*)&body[curoffset], bitlength); + strncat(domainname, (const char *)&body[curoffset], bitlength); curoffset += bitlength; if (body[curoffset] != 0) + { strcat(domainname, "."); + } } - + // if the domain name contains nintendowifi.net // it is most likely a WFC server // (note, conntest.nintendowifi.net just contains a dummy HTML page and // is used for connection tests, I think we can let this one slide) - if ((strstr(domainname, "nintendowifi.net") != NULL) && + if ((strstr(domainname, "nintendowifi.net") != NULL) && (strcmp(domainname, "conntest.nintendowifi.net") != 0)) + { return true; - + } + // Skip the type and class - we don't care about that curoffset += 4; } - + return false; } -static void SoftAP_Deauthenticate() +void SoftAPCommInterface::_Deauthenticate() { u32 packetLen = sizeof(SoftAP_DeauthFrame); - - memcpy(&SoftAP.curPacket[12], SoftAP_DeauthFrame, packetLen); - - memcpy(&SoftAP.curPacket[12 + 4], FW_Mac, 6); // Receiver MAC - - *(u16*)&SoftAP.curPacket[12 + 22] = SoftAP.seqNum << 4; // Sequence number - SoftAP.seqNum++; - + + memcpy(&this->_curPacket[12], SoftAP_DeauthFrame, packetLen); + + memcpy(&this->_curPacket[12 + 4], FW_Mac, 6); // Receiver MAC + + *(u16 *)&this->_curPacket[12 + 22] = this->_seqNum << 4; // Sequence number + this->_seqNum++; + u16 rxflags = 0x0010; - if (WIFI_compareMAC(wifiMac.bss.bytes, &SoftAP.curPacket[12 + 16])) - rxflags |= 0x8000; - - WIFI_MakeRXHeader(SoftAP.curPacket, rxflags, 20, packetLen, 0, 0); - - // Let's prepare to send - SoftAP.curPacketSize = packetLen + 12; - SoftAP.curPacketPos = 0; - SoftAP.curPacketSending = TRUE; - - SoftAP.status = APStatus_Disconnected; -} - -void SoftAP_SendPacket(u8 *packet, u32 len) -{ - u16 frameCtl = *(u16*)&packet[0]; - - WIFI_LOG(3, "SoftAP: Received a packet of length %i bytes. Frame control = %04X\n", - len, frameCtl); - - //use this to log wifi messages easily - /*static int ctr=0; - char buf[100]; - sprintf(buf,"wifi%04d.txt",ctr); - FILE* outf = fopen(buf,"wb"); - fwrite(packet,1,len,outf); - fclose(outf); - ctr++;*/ - - switch((frameCtl >> 2) & 0x3) + if (WIFI_compareMAC(wifiMac.bss.bytes, &this->_curPacket[12 + 16])) { - case 0x0: // Management frame - { - u32 packetLen; - - switch((frameCtl >> 4) & 0xF) - { - case 0x4: // Probe request (WFC) - { - packetLen = sizeof(SoftAP_ProbeResponse); - memcpy(&SoftAP.curPacket[12], SoftAP_ProbeResponse, packetLen); - - // Add the timestamp - u64 timestamp = SoftAP.usecCounter; - *(u64*)&SoftAP.curPacket[12 + 24] = timestamp; - } - break; - - case 0xB: // Authentication - { - packetLen = sizeof(SoftAP_AuthFrame); - memcpy(&SoftAP.curPacket[12], SoftAP_AuthFrame, packetLen); - - SoftAP.status = APStatus_Authenticated; - } - break; - - case 0x0: // Association request - { - if (SoftAP.status != APStatus_Authenticated) - return; - - packetLen = sizeof(SoftAP_AssocResponse); - memcpy(&SoftAP.curPacket[12], SoftAP_AssocResponse, packetLen); - - SoftAP.status = APStatus_Associated; - WIFI_LOG(1, "SoftAP connected!\n"); -#if (WIFI_LOGGING_LEVEL >= 3) - create_packet(); -#endif - } - break; - - case 0xA: // Disassociation - SoftAP.status = APStatus_Authenticated; - return; - - case 0xC: // Deauthentication - SoftAP.status = APStatus_Disconnected; - WIFI_LOG(1, "SoftAP disconnected\n"); - - if (captured_packets != NULL) - { - fclose(captured_packets); - captured_packets = NULL; - } - - return; - - default: - WIFI_LOG(2, "SoftAP: unknown management frame type %04X\n", (frameCtl >> 4) & 0xF); - return; - } - - memcpy(&SoftAP.curPacket[12 + 4], FW_Mac, 6); // Receiver MAC - - *(u16*)&SoftAP.curPacket[12 + 22] = SoftAP.seqNum << 4; // Sequence number - SoftAP.seqNum++; - - u16 rxflags = 0x0010; - if (WIFI_compareMAC(wifiMac.bss.bytes, &SoftAP.curPacket[12 + 16])) - rxflags |= 0x8000; - - WIFI_MakeRXHeader(SoftAP.curPacket, rxflags, 20, packetLen, 0, 0); // make the RX header - - // Let's prepare to send - SoftAP.curPacketSize = packetLen + 12; - SoftAP.curPacketPos = 0; - SoftAP.curPacketSending = TRUE; - } - break; - - case 0x2: // Data frame - { - // If it has a LLC/SLIP header, send it over the Ethernet - if (((*(u16*)&packet[24]) == 0xAAAA) && ((*(u16*)&packet[26]) == 0x0003) && ((*(u16*)&packet[28]) == 0x0000)) - { - if (SoftAP.status != APStatus_Associated) - return; - - if (SoftAP_IsDNSRequestToWFC(*(u16*)&packet[30], &packet[32])) - { - // Removed to allow WFC communication. - //SoftAP_Deauthenticate(); - //return; - } - - u32 epacketLen = ((len - 30 - 4) + 14); - u8 epacket[2048]; - - //printf("----- SENDING ETHERNET PACKET: len=%i, ethertype=%04X -----\n", - // len, *(u16*)&packet[30]); - - memcpy(&epacket[0], &packet[16], 6); - memcpy(&epacket[6], &packet[10], 6); - *(u16*)&epacket[12] = *(u16*)&packet[30]; - memcpy(&epacket[14], &packet[32], epacketLen - 14); - - if(wifi_bridge != NULL) { - // Store the packet in the PCAP file. -#if (WIFI_LOGGING_LEVEL >= 3) - save_packet(epacket, epacketLen, SoftAP.usecCounter / 1000000, SoftAP.usecCounter % 1000000, false); -#endif - // Send it - driver->PCAP_sendpacket(wifi_bridge, epacket, epacketLen); - } - } - else - { - WIFI_LOG(1, "SoftAP: received non-Ethernet data frame. wtf?\n"); - } - } - break; + rxflags |= 0x8000; } + + WIFI_MakeRXHeader(this->_curPacket, rxflags, 20, packetLen, 0, 0); + + // Let's prepare to send + this->_curPacketSize = packetLen + 12; + this->_curPacketPos = 0; + this->_curPacketSending = true; + + this->_status = APStatus_Disconnected; } -INLINE void SoftAP_SendBeacon() +void SoftAPCommInterface::_SendBeacon() { u32 packetLen = sizeof(SoftAP_Beacon); - - memcpy(&SoftAP.curPacket[12], SoftAP_Beacon, packetLen); // Copy the beacon template - - *(u16*)&SoftAP.curPacket[12 + 22] = SoftAP.seqNum << 4; // Sequence number - SoftAP.seqNum++; - - u64 timestamp = SoftAP.usecCounter; - *(u64*)&SoftAP.curPacket[12 + 24] = timestamp; // Timestamp - + + memcpy(&this->_curPacket[12], SoftAP_Beacon, packetLen); // Copy the beacon template + + *(u16 *)&this->_curPacket[12 + 22] = this->_seqNum << 4; // Sequence number + this->_seqNum++; + + u64 timestamp = this->_usecCounter; + *(u64 *)&this->_curPacket[12 + 24] = timestamp; // Timestamp + u16 rxflags = 0x0011; - if (WIFI_compareMAC(wifiMac.bss.bytes, &SoftAP.curPacket[12 + 16])) + if (WIFI_compareMAC(wifiMac.bss.bytes, &this->_curPacket[12 + 16])) rxflags |= 0x8000; - - WIFI_MakeRXHeader(SoftAP.curPacket, rxflags, 20, packetLen, 0, 0); - + + WIFI_MakeRXHeader(this->_curPacket, rxflags, 20, packetLen, 0, 0); + // Let's prepare to send - SoftAP.curPacketSize = packetLen + 12; - SoftAP.curPacketPos = 0; - SoftAP.curPacketSending = TRUE; + this->_curPacketSize = packetLen + 12; + this->_curPacketPos = 0; + this->_curPacketSending = true; } -static void SoftAP_RXHandler(u_char* user, const struct pcap_pkthdr* h, const u_char* _data) +void SoftAPCommInterface::PacketRX(const void *pktHeader, const u8 *pktData) { // safety checks - if ((_data == NULL) || (h == NULL)) - return; - - u8* data = (u8*)_data; - - // reject the packet if it wasn't for us - if (!(WIFI_isBroadcastMAC(&data[0]) || WIFI_compareMAC(&data[0], wifiMac.mac.bytes))) - return; - - // reject the packet if we just sent it - if (WIFI_compareMAC(&data[6], wifiMac.mac.bytes)) - return; - - if (SoftAP.curPacketSending) + if ( (pktData == NULL) || (pktHeader == NULL) ) { - printf("crap we're gonna nuke a packet at %i/%i (%04X) (%04X)\n", SoftAP.curPacketPos, SoftAP.curPacketSize, *(u16*)&SoftAP.curPacket[12], wifiMac.RXWriteCursor<<1); + return; } - + + // reject the packet if it wasn't for us + if (!(WIFI_isBroadcastMAC(&pktData[0]) || WIFI_compareMAC(&pktData[0], wifiMac.mac.bytes))) + { + return; + } + + // reject the packet if we just sent it + if (WIFI_compareMAC(&pktData[6], wifiMac.mac.bytes)) + { + return; + } + + pcap_pkthdr *header = (pcap_pkthdr *)pktHeader; + u32 headerLength = header->len; + + if (this->_curPacketSending) + { + printf("crap we're gonna nuke a packet at %i/%i (%04X) (%04X)\n", this->_curPacketPos, this->_curPacketSize, *(u16 *)&this->_curPacket[12], wifiMac.RXWriteCursor<<1); + } + // The packet was for us. Let's process it then. WIFI_triggerIRQ(WIFI_IRQ_RXSTART); - - int wpacketLen = WIFI_alignedLen(26 + 6 + (h->len-14)); + + int wpacketLen = WIFI_alignedLen(26 + 6 + (headerLength-14)); u8 wpacket[2048]; - + // Save ethernet packet into the PCAP file. // Filter broadcast because of privacy. They aren't needed to study the protocol with the nintendo server // and can include PC Discovery protocols -#if (WIFI_LOGGING_LEVEL >= 3) - if (!WIFI_isBroadcastMAC(&data[0])) - save_packet(data, h->len, SoftAP.usecCounter / 1000000, SoftAP.usecCounter % 1000000, true); +#if WIFI_SAVE_PCAP_TO_FILE + if (!WIFI_isBroadcastMAC(&pktData[0])) + { + this->PacketCaptureFileWrite(pktData, headerLength, true); + } #endif //printf("RECEIVED DATA FRAME: len=%i/%i, src=%02X:%02X:%02X:%02X:%02X:%02X, dst=%02X:%02X:%02X:%02X:%02X:%02X, ethertype=%04X\n", // 24+ (h->caplen-12), 24 + (h->len-12), data[6], data[7], data[8], data[9], data[10], data[11], // data[0], data[1], data[2], data[3], data[4], data[5], *(u16*)&data[12]); - + u16 rxflags = 0x0018; - if (WIFI_compareMAC(wifiMac.bss.bytes, (u8*)SoftAP_MACAddr)) + if (WIFI_compareMAC(wifiMac.bss.bytes, (u8 *)SoftAP_MACAddr)) + { rxflags |= 0x8000; - + } + // Make a valid 802.11 frame WIFI_MakeRXHeader(wpacket, rxflags, 20, wpacketLen, 0, 0); *(u16*)&wpacket[12+0] = 0x0208; *(u16*)&wpacket[12+2] = 0x0000; - memcpy(&wpacket[12+4], &data[0], 6); + memcpy(&wpacket[12+4], &pktData[0], 6); memcpy(&wpacket[12+10], SoftAP_MACAddr, 6); - memcpy(&wpacket[12+16], &data[6], 6); - *(u16*)&wpacket[12+22] = SoftAP.seqNum << 4; + memcpy(&wpacket[12+16], &pktData[6], 6); + *(u16*)&wpacket[12+22] = this->_seqNum << 4; *(u16*)&wpacket[12+24] = 0xAAAA; *(u16*)&wpacket[12+26] = 0x0003; *(u16*)&wpacket[12+28] = 0x0000; - *(u16*)&wpacket[12+30] = *(u16*)&data[12]; - memcpy(&wpacket[12+32], &data[14], h->len-14); - - SoftAP.seqNum++; - + *(u16*)&wpacket[12+30] = *(u16 *)&pktData[12]; + memcpy(&wpacket[12+32], &pktData[14], headerLength-14); + + this->_seqNum++; + // put it in the RX buffer for (int i = 0; i < (12 + wpacketLen); i += 2) { - u16 word = *(u16*)&wpacket[i]; + u16 word = *(u16 *)&wpacket[i]; WIFI_RXPutWord(word); } - + // Done! wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1)); WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; - + WIFI_triggerIRQ(WIFI_IRQ_RXEND); } -void SoftAP_usTrigger() -{ - SoftAP.usecCounter++; - - // other packets will have priority over beacons - // 'cause they might be only once of them - // whereas there will be sooo much beacons - if(!SoftAP.curPacketSending) // && SoftAP.status != APStatus_Associated) - { - //if(wifiMac.ioMem[0xD0 >> 1] & 0x0400) - { - //zero sez: every 1/10 second? does it have to be precise? this is so costly.. - // Okay for 128 ms then - if((SoftAP.usecCounter & 131071) == 0) - { - SoftAP_SendBeacon(); - } - } - } - - /* Given a connection of 2 megabits per second, */ - /* we take ~4 microseconds to transfer a byte, */ - /* ie ~8 microseconds to transfer a word. */ - if((SoftAP.curPacketSending) && !(SoftAP.usecCounter & 7)) - { - if(SoftAP.curPacketPos == 0) - WIFI_triggerIRQ(WIFI_IRQ_RXSTART); - - u16 word = *(u16*)&SoftAP.curPacket[SoftAP.curPacketPos]; - WIFI_RXPutWord(word); - - SoftAP.curPacketPos += 2; - if(SoftAP.curPacketPos >= SoftAP.curPacketSize) - { - SoftAP.curPacketSize = 0; - SoftAP.curPacketPos = 0; - SoftAP.curPacketSending = FALSE; - - wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1)); - WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; - - WIFI_triggerIRQ(WIFI_IRQ_RXEND); - } - } - - // EXTREMELY EXPERIMENTAL packet receiving code - // Can now receive 64 packets per millisecond. Completely arbitrary limit. Todo: tweak if needed. - // But due to using non-blocking mode, this shouldn't be as slow as it used to be. - if ((SoftAP.usecCounter & 1023) == 0) - if(wifi_bridge != NULL) - driver->PCAP_dispatch(wifi_bridge, 64, SoftAP_RXHandler, NULL); -} - -#endif - -/* - Create and open a PCAP file to store different Ethernet packets - of the current connection. -*/ -static void create_packet() +// Create and open a PCAP file to store different Ethernet packets +// of the current connection. +void SoftAPCommInterface::PacketCaptureFileOpen() { // Create file using as name the current time and game code time_t ti; @@ -2404,15 +2224,15 @@ static void create_packet() char* gamecd = gameInfo.header.gameCode; char file_name[50]; sprintf( - file_name, - "%c%c%c%c [%02d-%02d-%02d-%02d].pcap", - gamecd[0], gamecd[1], gamecd[2], gamecd[3], - t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec - ); - + file_name, + "%c%c%c%c [%02d-%02d-%02d-%02d].pcap", + gamecd[0], gamecd[1], gamecd[2], gamecd[3], + t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec + ); + // Open as binary write - captured_packets = fopen(file_name, "wb"); - if (captured_packets == NULL) + this->_packetCaptureFile = fopen(file_name, "wb"); + if (this->_packetCaptureFile == NULL) { printf("Can't create capture log file: %s\n", file_name); } @@ -2427,43 +2247,740 @@ static void create_packet() const u32 pre_time = 0x00000000; // usually not used const u32 snapshot_len = 0x0000ffff; // Maximum length of each packet const u32 ll_header_typ = 0x00000001; // For Ethernet - - fwrite(&magic_header, sizeof(char), 4, captured_packets); - fwrite(&major_version, sizeof(char), 2, captured_packets); - fwrite(&minor_version, sizeof(char), 2, captured_packets); - fwrite(&gmt_time, sizeof(char), 4, captured_packets); - fwrite(&pre_time, sizeof(char), 4, captured_packets); - fwrite(&snapshot_len, sizeof(char), 4, captured_packets); - fwrite(&ll_header_typ, sizeof(char), 4, captured_packets); - - fflush(captured_packets); + + fwrite(&magic_header, sizeof(char), 4, this->_packetCaptureFile); + fwrite(&major_version, sizeof(char), 2, this->_packetCaptureFile); + fwrite(&minor_version, sizeof(char), 2, this->_packetCaptureFile); + fwrite(&gmt_time, sizeof(char), 4, this->_packetCaptureFile); + fwrite(&pre_time, sizeof(char), 4, this->_packetCaptureFile); + fwrite(&snapshot_len, sizeof(char), 4, this->_packetCaptureFile); + fwrite(&ll_header_typ, sizeof(char), 4, this->_packetCaptureFile); + + fflush(this->_packetCaptureFile); } } -/* - Save an Ethernet packet into the PCAP file of the current connection. -*/ -static void save_packet(u8* packet, u32 len, u32 seconds, u32 millis, bool isReceived) +void SoftAPCommInterface::PacketCaptureFileClose() { - if (captured_packets == NULL) + if (this->_packetCaptureFile != NULL) + { + fclose(this->_packetCaptureFile); + this->_packetCaptureFile = NULL; + } +} + +// Save an Ethernet packet into the PCAP file of the current connection. +void SoftAPCommInterface::PacketCaptureFileWrite(const u8 *packet, u32 len, bool isReceived) +{ + if (this->_packetCaptureFile == NULL) { printf("Can't save packet... %d\n", isReceived); return; } - + + const u32 seconds = this->_usecCounter / 1000000; + const u32 millis = this->_usecCounter % 1000000; + // Add the packet // more info: http://www.kroosec.com/2012/10/a-look-at-pcap-file-format.html printf("WIFI: Saving packet of %04x bytes | %d\n", len, isReceived); - + // First create the header - fwrite(&seconds, sizeof(char), 4, captured_packets); // This should be seconds since Unix Epoch, but it works :D - fwrite(&millis, sizeof(char), 4, captured_packets); - fwrite(&len, sizeof(char), 4, captured_packets); - fwrite(&len, sizeof(char), 4, captured_packets); - + fwrite(&seconds, sizeof(char), 4, this->_packetCaptureFile); // This should be seconds since Unix Epoch, but it works :D + fwrite(&millis, sizeof(char), 4, this->_packetCaptureFile); + fwrite(&len, sizeof(char), 4, this->_packetCaptureFile); + fwrite(&len, sizeof(char), 4, this->_packetCaptureFile); + // Then write the packet - fwrite(packet, sizeof(char), len, captured_packets); - + fwrite(packet, sizeof(char), len, this->_packetCaptureFile); + // Flush the file - fflush(captured_packets); + fflush(this->_packetCaptureFile); +} + +void SoftAPCommInterface::SetPCapInterface(ClientPCapInterface *pcapInterface) +{ + this->_pcap = (pcapInterface == NULL) ? &dummyPCapInterface : pcapInterface; +} + +ClientPCapInterface* SoftAPCommInterface::GetPCapInterface() +{ + return this->_pcap; +} + +int SoftAPCommInterface::GetBridgeDeviceIndex() +{ + return this->_bridgeDeviceIndex; +} + +void SoftAPCommInterface::SetBridgeDeviceIndex(int deviceIndex) +{ + this->_bridgeDeviceIndex = deviceIndex; +} + +bool SoftAPCommInterface::Start(WifiEmulationLevel emulationLevel) +{ + const bool isPCapSupported = (this->_pcap != &dummyPCapInterface); + WifiEmulationLevel pendingEmulationLevel = emulationLevel; + char errbuf[PCAP_ERRBUF_SIZE]; + + this->_usecCounter = 0; + + memset(this->_curPacket, 0, sizeof(this->_curPacket)); + this->_curPacketSize = 0; + this->_curPacketPos = 0; + this->_curPacketSending = false; + + this->_status = APStatus_Disconnected; + this->_seqNum = 0; + + if (isPCapSupported && (emulationLevel != WifiEmulationLevel_Off)) + { + this->_bridgeDevice = this->_GetBridgeDeviceAtIndex(this->_bridgeDeviceIndex, errbuf); + } + else + { + this->_bridgeDevice = NULL; + pendingEmulationLevel = WifiEmulationLevel_Off; + + if (!isPCapSupported) + { + WIFI_LOG(1, "SoftAP: No libpcap interface has been set.\n"); + } + + if (emulationLevel == WifiEmulationLevel_Off) + { + WIFI_LOG(1, "SoftAP: Emulation level is OFF.\n"); + } + } + + // Set non-blocking mode + if (this->_bridgeDevice != NULL) + { + int result = this->_pcap->setnonblock(this->_bridgeDevice, 1, errbuf); + if (result == -1) + { + this->_pcap->close(this->_bridgeDevice); + this->_bridgeDevice = NULL; + pendingEmulationLevel = WifiEmulationLevel_Off; + + WIFI_LOG(1, "SoftAP: libpcap failed to set non-blocking mode: %s\n", errbuf); + } + else + { + WIFI_LOG(1, "SoftAP: libpcap has set non-blocking mode.\n"); + } + } + + this->_emulationLevel = pendingEmulationLevel; + return true; +} + +void SoftAPCommInterface::Stop() +{ + this->PacketCaptureFileClose(); + + if (this->_bridgeDevice != NULL) + { + this->_pcap->close(this->_bridgeDevice); + } +} + +void SoftAPCommInterface::SendPacket(void *data, size_t len) +{ + u8 *packet = (u8 *)data; + u16 frameCtl = *(u16 *)&packet[0]; + + WIFI_LOG(3, "SoftAP: Received a packet of length %i bytes. Frame control = %04X\n", + (int)len, frameCtl); + + //use this to log wifi messages easily + /*static int ctr=0; + char buf[100]; + sprintf(buf,"wifi%04d.txt",ctr); + FILE* outf = fopen(buf,"wb"); + fwrite(packet,1,len,outf); + fclose(outf); + ctr++;*/ + + switch((frameCtl >> 2) & 0x3) + { + case 0x0: // Management frame + { + u32 packetLen; + + switch ((frameCtl >> 4) & 0xF) + { + case 0x4: // Probe request (WFC) + { + packetLen = sizeof(SoftAP_ProbeResponse); + memcpy(&this->_curPacket[12], SoftAP_ProbeResponse, packetLen); + + // Add the timestamp + u64 timestamp = this->_usecCounter; + *(u64 *)&this->_curPacket[12 + 24] = timestamp; + + break; + } + + case 0xB: // Authentication + { + packetLen = sizeof(SoftAP_AuthFrame); + memcpy(&this->_curPacket[12], SoftAP_AuthFrame, packetLen); + this->_status = APStatus_Authenticated; + + break; + } + + case 0x0: // Association request + { + if (this->_status != APStatus_Authenticated) + { + return; + } + + packetLen = sizeof(SoftAP_AssocResponse); + memcpy(&this->_curPacket[12], SoftAP_AssocResponse, packetLen); + + this->_status = APStatus_Associated; + WIFI_LOG(1, "SoftAP connected!\n"); +#if WIFI_SAVE_PCAP_TO_FILE + this->PacketCaptureFileOpen(); +#endif + break; + } + + case 0xA: // Disassociation + this->_status = APStatus_Authenticated; + return; + + case 0xC: // Deauthentication + { + this->_status = APStatus_Disconnected; + WIFI_LOG(1, "SoftAP disconnected.\n"); + this->PacketCaptureFileClose(); + return; + } + + default: + WIFI_LOG(2, "SoftAP: unknown management frame type %04X\n", (frameCtl >> 4) & 0xF); + return; + } + + memcpy(&this->_curPacket[12 + 4], FW_Mac, 6); // Receiver MAC + + *(u16 *)&this->_curPacket[12 + 22] = this->_seqNum << 4; // Sequence number + this->_seqNum++; + + u16 rxflags = 0x0010; + if (WIFI_compareMAC(wifiMac.bss.bytes, &this->_curPacket[12 + 16])) + { + rxflags |= 0x8000; + } + + WIFI_MakeRXHeader(this->_curPacket, rxflags, 20, packetLen, 0, 0); // make the RX header + + // Let's prepare to send + this->_curPacketSize = packetLen + 12; + this->_curPacketPos = 0; + this->_curPacketSending = true; + } + break; + + case 0x2: // Data frame + { + // If it has a LLC/SLIP header, send it over the Ethernet + if ((*(u16 *)&packet[24] == 0xAAAA) && (*(u16 *)&packet[26] == 0x0003) && (*(u16 *)&packet[28] == 0x0000)) + { + if (this->_status != APStatus_Associated) + return; + + if (this->_IsDNSRequestToWFC(*(u16 *)&packet[30], &packet[32])) + { + // Removed to allow WFC communication. + //SoftAP_Deauthenticate(); + //return; + } + + u32 epacketLen = ((len - 30 - 4) + 14); + u8 epacket[2048]; + + //printf("----- SENDING ETHERNET PACKET: len=%i, ethertype=%04X -----\n", + // len, *(u16*)&packet[30]); + + memcpy(&epacket[0], &packet[16], 6); + memcpy(&epacket[6], &packet[10], 6); + *(u16 *)&epacket[12] = *(u16 *)&packet[30]; + memcpy(&epacket[14], &packet[32], epacketLen - 14); + + if (this->_bridgeDevice != NULL) + { +#if WIFI_SAVE_PCAP_TO_FILE + // Store the packet in the PCAP file. + this->PacketCaptureFileWrite(epacket, epacketLen, false); +#endif + // Send it + this->_pcap->sendpacket(this->_bridgeDevice, epacket, epacketLen); + } + } + else + { + WIFI_LOG(1, "SoftAP: received non-Ethernet data frame. wtf?\n"); + } + } + break; + } +} + +void SoftAPCommInterface::Trigger() +{ + this->_usecCounter++; + + // other packets will have priority over beacons + // 'cause they might be only once of them + // whereas there will be sooo much beacons + if (!this->_curPacketSending) // && SoftAP.status != APStatus_Associated) + { + // if(wifiMac.ioMem[0xD0 >> 1] & 0x0400) + { + //zero sez: every 1/10 second? does it have to be precise? this is so costly.. + // Okay for 128 ms then + if ((this->_usecCounter & 131071) == 0) + { + this->_SendBeacon(); + } + } + } + + /* Given a connection of 2 megabits per second, */ + /* we take ~4 microseconds to transfer a byte, */ + /* ie ~8 microseconds to transfer a word. */ + if ((this->_curPacketSending) && !(this->_usecCounter & 7)) + { + if (this->_curPacketPos == 0) + { + WIFI_triggerIRQ(WIFI_IRQ_RXSTART); + } + + u16 word = *(u16 *)&this->_curPacket[this->_curPacketPos]; + WIFI_RXPutWord(word); + + this->_curPacketPos += 2; + if (this->_curPacketPos >= this->_curPacketSize) + { + this->_curPacketSize = 0; + this->_curPacketPos = 0; + this->_curPacketSending = false; + + wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1)); + WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; + + WIFI_triggerIRQ(WIFI_IRQ_RXEND); + } + } + + // EXTREMELY EXPERIMENTAL packet receiving code + // Can now receive 64 packets per millisecond. Completely arbitrary limit. Todo: tweak if needed. + // But due to using non-blocking mode, this shouldn't be as slow as it used to be. + if (this->_bridgeDevice != NULL) + { + if ((this->_usecCounter & 1023) == 0) + { + this->_pcap->dispatch(this->_bridgeDevice, 64, (void *)&SoftAP_PacketRX_Callback, this); + } + } +} + +WifiHandler::WifiHandler() +{ + _selectedEmulationLevel = WifiEmulationLevel_Off; + _currentEmulationLevel = _selectedEmulationLevel; + + _adhocCommInterface = new AdhocCommInterface; + _softAPCommInterface = new SoftAPCommInterface; + + _selectedCommID = WifiCommInterfaceID_AdHoc; + _currentCommID = _selectedCommID; + _currentCommInterface = NULL; + + _selectedBridgeDeviceIndex = 0; + + _adhocMACMode = WifiMACMode_Automatic; + _infrastructureMACMode = WifiMACMode_ReadFromFirmware; + _ip4Address = 0; + _uniqueMACValue = 0; + +#ifndef HOST_WINDOWS + _pcap = new POSIXPCapInterface; + _isSocketsSupported = true; +#else + _pcap = &dummyPCapInterface; + _isSocketsSupported = false; +#endif + + WIFI_initCRC32Table(); + Reset(); +} + +WifiHandler::~WifiHandler() +{ + delete this->_currentCommInterface; +} + +void WifiHandler::Reset() +{ + memset(&wifiMac, 0, sizeof(wifimac_t)); + + WIFI_resetRF(&wifiMac.RF); + + wifiMac.powerOn = false; + wifiMac.powerOnPending = false; + wifiMac.rfStatus = 0x0000; + wifiMac.rfPins = 0x0004; + + this->_didWarnWFCUser = false; +} + +WifiEmulationLevel WifiHandler::GetSelectedEmulationLevel() +{ + return this->_selectedEmulationLevel; +} + +WifiEmulationLevel WifiHandler::GetCurrentEmulationLevel() +{ + return this->_currentEmulationLevel; +} + +void WifiHandler::SetEmulationLevel(WifiEmulationLevel emulationLevel) +{ +#ifdef EXPERIMENTAL_WIFI_COMM + this->_selectedEmulationLevel = emulationLevel; +#else + this->_selectedEmulationLevel = WifiEmulationLevel_Off; +#endif +} + +WifiCommInterfaceID WifiHandler::GetSelectedCommInterfaceID() +{ + return this->_selectedCommID; +} + +WifiCommInterfaceID WifiHandler::GetCurrentCommInterfaceID() +{ + return this->_currentCommID; +} + +void WifiHandler::SetCommInterfaceID(WifiCommInterfaceID commID) +{ + this->_selectedCommID = commID; +} + +int WifiHandler::GetBridgeDeviceList(std::vector *deviceStringList) +{ + int result = -1; + + if (deviceStringList == NULL) + { + return result; + } + + char errbuf[PCAP_ERRBUF_SIZE]; + pcap_if_t *deviceList; + + result = this->GetPCapInterface()->findalldevs((void **)&deviceList, errbuf); + if ( (result == -1) || (deviceList == NULL) ) + { + return result; + } + + pcap_if_t *currentDevice = deviceList; + for (size_t i = 0; currentDevice != NULL; i++, currentDevice = currentDevice->next) + { + // on x64 description is empty + if (currentDevice->description[0] == 0) + { + deviceStringList->push_back(currentDevice->name); + } + else + { + deviceStringList->push_back(currentDevice->description); + } + } + + return deviceStringList->size(); +} + +int WifiHandler::GetSelectedBridgeDeviceIndex() +{ + return this->_selectedBridgeDeviceIndex; +} + +int WifiHandler::GetCurrentBridgeDeviceIndex() +{ + return this->_softAPCommInterface->GetBridgeDeviceIndex(); +} + +void WifiHandler::SetBridgeDeviceIndex(int deviceIndex) +{ + this->_selectedBridgeDeviceIndex = deviceIndex; +} + +bool WifiHandler::CommStart() +{ + bool result = false; + + WifiEmulationLevel pendingEmulationLevel = this->_selectedEmulationLevel; + WifiCommInterface *selectedCommInterface = NULL; + WifiMACMode selectedMACMode = WifiMACMode_Manual; + + switch (this->_selectedCommID) + { + case WifiCommInterfaceID_AdHoc: + { + if (this->_isSocketsSupported) + { + selectedCommInterface = this->_adhocCommInterface; + selectedMACMode = this->_adhocMACMode; + } + else + { + WIFI_LOG(1, "Ad-hoc mode requires sockets, but sockets are not supported on this system.\n"); + pendingEmulationLevel = WifiEmulationLevel_Off; + } + break; + } + + case WifiCommInterfaceID_Infrastructure: + { + selectedCommInterface = this->_softAPCommInterface; + selectedMACMode = this->_infrastructureMACMode; + + if (!this->IsPCapSupported()) + { + WIFI_LOG(1, "Infrastructure mode requires libpcap for full functionality,\n but libpcap is not available on this system. Network functions\n will be disabled for this session.\n"); + } + break; + } + + default: + break; + } + + // Stop the current comm interface. + if (this->_currentCommInterface != NULL) + { + this->_currentCommInterface->Stop(); + } + + // Assign the pcap interface to SoftAP if pcap is available. + if (this->_selectedCommID == WifiCommInterfaceID_Infrastructure) + { + this->_softAPCommInterface->SetPCapInterface(this->_pcap); + this->_softAPCommInterface->SetBridgeDeviceIndex(this->_selectedBridgeDeviceIndex); + } + + // Start the new comm interface. + this->_currentCommInterface = selectedCommInterface; + + if (this->_currentCommInterface == NULL) + { + pendingEmulationLevel = WifiEmulationLevel_Off; + } + else + { + result = this->_currentCommInterface->Start(pendingEmulationLevel); + if (!result) + { + this->_currentCommInterface->Stop(); + this->_currentCommInterface = NULL; + pendingEmulationLevel = WifiEmulationLevel_Off; + } + else + { + // Set the current MAC address based on the selected MAC mode. + switch (selectedMACMode) + { + case WifiMACMode_Automatic: + this->GenerateMACFromValues(FW_Mac); + NDS_PatchFirmwareMAC(); + break; + + case WifiMACMode_Manual: + this->CopyMACFromUserValues(FW_Mac); + NDS_PatchFirmwareMAC(); + break; + + case WifiMACMode_ReadFromFirmware: + memcpy(FW_Mac, (MMU.fw.data + 0x36), 6); + break; + } + + // Starting the comm interface was successful. + // Report the MAC address to the user as confirmation. + printf("WIFI: MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", + FW_Mac[0], FW_Mac[1], FW_Mac[2], FW_Mac[3], FW_Mac[4], FW_Mac[5]); + } + } + + this->_currentEmulationLevel = pendingEmulationLevel; + + return result; +} + +void WifiHandler::CommStop() +{ + if (this->_currentCommInterface != NULL) + { + this->_currentCommInterface->Stop(); + this->_currentCommInterface = NULL; + } +} + +void WifiHandler::CommSendPacket(void *data, size_t len) +{ + if (this->_currentCommInterface != NULL) + { + this->_currentCommInterface->SendPacket(data, len); + } +} + +void WifiHandler::CommTrigger() +{ + if (this->_currentCommInterface != NULL) + { + this->_currentCommInterface->Trigger(); + } +} + +bool WifiHandler::IsPCapSupported() +{ + return ((this->_pcap != NULL) && (this->_pcap != &dummyPCapInterface)); +} + +bool WifiHandler::IsSocketsSupported() +{ + return this->_isSocketsSupported; +} + +void WifiHandler::SetSocketsSupported(bool isSupported) +{ + this->_isSocketsSupported = isSupported; +} + +ClientPCapInterface* WifiHandler::GetPCapInterface() +{ + return this->_pcap; +} + +void WifiHandler::SetPCapInterface(ClientPCapInterface *pcapInterface) +{ + this->_pcap = (pcapInterface == NULL) ? &dummyPCapInterface : pcapInterface; +} + +WifiMACMode WifiHandler::GetMACModeForComm(WifiCommInterfaceID commID) +{ + if (commID == WifiCommInterfaceID_Infrastructure) + { + return this->_infrastructureMACMode; + } + + return this->_adhocMACMode; +} + +void WifiHandler::SetMACModeForComm(WifiCommInterfaceID commID, WifiMACMode macMode) +{ + switch (commID) + { + case WifiCommInterfaceID_AdHoc: + this->_adhocMACMode = macMode; + break; + + case WifiCommInterfaceID_Infrastructure: + this->_infrastructureMACMode = macMode; + break; + + default: + break; + } +} + +uint32_t WifiHandler::GetIP4Address() +{ + return this->_ip4Address; +} + +void WifiHandler::SetIP4Address(u32 ip4Address) +{ + this->_ip4Address = ip4Address; +} + +uint32_t WifiHandler::GetUniqueMACValue() +{ + return this->_uniqueMACValue; +} + +void WifiHandler::SetUniqueMACValue(u32 uniqueValue) +{ + this->_uniqueMACValue = uniqueValue; +} + +void WifiHandler::GetUserMACValues(u8 *outValue3, u8 *outValue4, u8 *outValue5) +{ + *outValue3 = this->_userMAC[0]; + *outValue4 = this->_userMAC[1]; + *outValue5 = this->_userMAC[2]; +} + +void WifiHandler::SetUserMACValues(u8 inValue3, u8 inValue4, u8 inValue5) +{ + this->_userMAC[0] = inValue3; + this->_userMAC[1] = inValue4; + this->_userMAC[2] = inValue5; +} + +void WifiHandler::GenerateMACFromValues(u8 outMAC[6]) +{ + if (outMAC == NULL) + { + return; + } + + // If the user passes in 0.0.0.0 for ip4Address, then use the default IP + // address of 127.0.0.1. Otherwise, just use whatever the user gave us. + const u32 ipAddr = (this->_ip4Address == 0) ? 0x0100007F : this->_ip4Address; + + // If the user passes in 0 for uniqueID, then simply generate a random + // number for hash. Yes, we are using rand() here, which is not a very + // good RNG, but at least it's better than nothing. + u32 hash = (this->_uniqueMACValue == 0) ? (u32)rand() : this->_uniqueMACValue; + + while ((hash & 0xFF000000) == 0) + { + hash <<= 1; + } + + hash >>= 1; + hash += ipAddr >> 8; + hash &= 0x00FFFFFF; + + outMAC[3] = hash >> 16; + outMAC[4] = (hash >> 8) & 0xFF; + outMAC[5] = hash & 0xFF; +} + +void WifiHandler::CopyMACFromUserValues(u8 outMAC[6]) +{ + if (outMAC == NULL) + { + return; + } + + // The first three MAC values are Nintendo's signature MAC values. + // The last three MAC values are user-defined. + outMAC[0] = 0x00; + outMAC[1] = 0x09; + outMAC[2] = 0xBF; + outMAC[3] = this->_userMAC[0]; + outMAC[4] = this->_userMAC[1]; + outMAC[5] = this->_userMAC[2]; } diff --git a/desmume/src/wifi.h b/desmume/src/wifi.h old mode 100644 new mode 100755 index d8a4c3913..c5387bd98 --- a/desmume/src/wifi.h +++ b/desmume/src/wifi.h @@ -19,24 +19,15 @@ along with DeSmuME; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef WIFI_H #define WIFI_H #include #include "types.h" -#ifdef EXPERIMENTAL_WIFI_COMM - -#ifndef __APPLE__ -#define HAVE_REMOTE -#endif - -#define WPCAP -#define PACKET_SIZE 65535 -#define _INC_STDIO - -#endif - +#include +#include #define REG_WIFI_ID 0x000 #define REG_WIFI_MODE 0x004 @@ -178,11 +169,6 @@ /* WIFI misc constants */ #define WIFI_CHIPID 0x1440 /* emulates "old" wifi chip, new is 0xC340 */ -// SAVE PACKETS HACK FUNCTIONS -static void create_packet(); -static void save_packet(u8* packet, u32 len, u32 seconds, u32 millis, bool isReceived); -u32 timeval2millis(struct timeval tv); - /* Referenced as RF_ in dswifi: rffilter_t */ /* based on the documentation for the RF2958 chip of RF Micro Devices */ /* using the register names as in docs ( http://www.rfmd.com/pdfs/2958.pdf )*/ @@ -434,14 +420,34 @@ enum EAPStatus APStatus_Associated }; +enum WifiEmulationLevel +{ + WifiEmulationLevel_Off = 0, + WifiEmulationLevel_Normal = 10000, + WifiEmulationLevel_Compatibility = 65535, +}; + +enum WifiCommInterfaceID +{ + WifiCommInterfaceID_AdHoc = 0, + WifiCommInterfaceID_Infrastructure = 1 +}; + +enum WifiMACMode +{ + WifiMACMode_Automatic = 0, + WifiMACMode_Manual = 1, + WifiMACMode_ReadFromFirmware = 2 +}; + /* wifimac_t: the buildin mac (arm7 addressrange: 0x04800000-0x04FFFFFF )*/ /* http://www.akkit.org/info/dswifi.htm#WifiIOMap */ typedef struct { /* power */ - BOOL powerOn; - BOOL powerOnPending; + bool powerOn; + bool powerOnPending; /* status */ u16 rfStatus; @@ -454,7 +460,7 @@ typedef struct /* modes */ u16 macMode; u16 wepMode; - BOOL WEP_enable; + bool WEP_enable; /* sending */ u16 TXStatCnt; @@ -464,7 +470,7 @@ typedef struct u16 TXOpt; u16 TXStat; u16 BeaconAddr; - BOOL BeaconEnable; + bool BeaconEnable; u16 TXSlotExtra; u16 TXSeqNo; u8 txCurSlot; @@ -501,13 +507,13 @@ typedef struct u16 retryLimit; /* timing */ - BOOL crystalEnabled; + bool crystalEnabled; u64 usec; - BOOL usecEnable; + bool usecEnable; u64 ucmp; - BOOL ucmpEnable; + bool ucmpEnable; u32 eCount; - BOOL eCountEnable; + bool eCountEnable; u16 BeaconInterval; u16 BeaconCount1; u16 BeaconCount2; @@ -542,7 +548,7 @@ typedef struct /* tx packets */ s32 curPacketSize[3]; s32 curPacketPos[3]; - BOOL curPacketSending[3]; + bool curPacketSending[3]; /* I/O ports */ u16 IOPorts[0x800]; @@ -552,40 +558,7 @@ typedef struct } wifimac_t; - -typedef struct -{ - u64 usecCounter; - -} Adhoc_t; - -typedef struct -{ - u64 usecCounter; - - u8 curPacket[4096]; - s32 curPacketSize; - s32 curPacketPos; - BOOL curPacketSending; - - EAPStatus status; - u16 seqNum; - -} SoftAP_t; - -// desmume host communication -#ifdef EXPERIMENTAL_WIFI_COMM -typedef struct pcap pcap_t; -extern pcap_t *wifi_bridge; -#endif - extern wifimac_t wifiMac; -extern Adhoc_t Adhoc; -extern SoftAP_t SoftAP; - -bool WIFI_Init(); -void WIFI_DeInit(); -void WIFI_Reset(); /* subchip communication IO functions */ void WIFI_setRF_CNT(u16 val); @@ -632,6 +605,199 @@ typedef struct _FW_WFCProfile } FW_WFCProfile; +class ClientPCapInterface +{ +public: + virtual int findalldevs(void **alldevs, char *errbuf) = 0; + virtual void freealldevs(void *alldevs) = 0; + virtual void* open(const char *source, int snaplen, int flags, int readtimeout, char *errbuf) = 0; + virtual void close(void *dev) = 0; + virtual int setnonblock(void *dev, int nonblock, char *errbuf) = 0; + virtual int sendpacket(void *dev, const void *data, int len) = 0; + virtual int dispatch(void *dev, int num, void *callback, void *userdata) = 0; +}; + +class DummyPCapInterface : public ClientPCapInterface +{ +private: + void __CopyErrorString(char *errbuf); + +public: + virtual int findalldevs(void **alldevs, char *errbuf); + virtual void freealldevs(void *alldevs); + virtual void* open(const char *source, int snaplen, int flags, int readtimeout, char *errbuf); + virtual void close(void *dev); + virtual int setnonblock(void *dev, int nonblock, char *errbuf); + virtual int sendpacket(void *dev, const void *data, int len); + virtual int dispatch(void *dev, int num, void *callback, void *userdata); +}; + +#ifndef HOST_WINDOWS + +class POSIXPCapInterface : public ClientPCapInterface +{ +public: + virtual int findalldevs(void **alldevs, char *errbuf); + virtual void freealldevs(void *alldevs); + virtual void* open(const char *source, int snaplen, int flags, int readtimeout, char *errbuf); + virtual void close(void *dev); + virtual int setnonblock(void *dev, int nonblock, char *errbuf); + virtual int sendpacket(void *dev, const void *data, int len); + virtual int dispatch(void *dev, int num, void *callback, void *userdata); +}; + +#endif + +class WifiCommInterface +{ +protected: + WifiCommInterfaceID _commInterfaceID; + WifiEmulationLevel _emulationLevel; + u64 _usecCounter; + +public: + WifiCommInterface(); + virtual ~WifiCommInterface(); + + virtual bool Start(WifiEmulationLevel emulationLevel) = 0; + virtual void Stop() = 0; + virtual void SendPacket(void *data, size_t len) = 0; + virtual void Trigger() = 0; +}; + +class AdhocCommInterface : public WifiCommInterface +{ +protected: + void *_wifiSocket; + void *_sendAddr; + u8 *_packetBuffer; + +public: + AdhocCommInterface(); + ~AdhocCommInterface(); + + virtual bool Start(WifiEmulationLevel emulationLevel); + virtual void Stop(); + virtual void SendPacket(void *data, size_t len); + virtual void Trigger(); +}; + +class SoftAPCommInterface : public WifiCommInterface +{ +protected: + ClientPCapInterface *_pcap; + int _bridgeDeviceIndex; + void *_bridgeDevice; + FILE *_packetCaptureFile; // PCAP file to store the Ethernet packets. + + u8 _curPacket[4096]; + s32 _curPacketSize; + s32 _curPacketPos; + bool _curPacketSending; + + EAPStatus _status; + u16 _seqNum; + + void* _GetBridgeDeviceAtIndex(int deviceIndex, char *outErrorBuf); + bool _IsDNSRequestToWFC(u16 ethertype, u8 *body); + void _Deauthenticate(); + void _SendBeacon(); + +public: + SoftAPCommInterface(); + virtual ~SoftAPCommInterface(); + + void SetPCapInterface(ClientPCapInterface *pcapInterface); + ClientPCapInterface* GetPCapInterface(); + + int GetBridgeDeviceIndex(); + void SetBridgeDeviceIndex(int deviceIndex); + + void PacketRX(const void *pktHeader, const u8 *pktData); + + void PacketCaptureFileOpen(); + void PacketCaptureFileClose(); + void PacketCaptureFileWrite(const u8 *packet, u32 len, bool isReceived); + + virtual bool Start(WifiEmulationLevel emulationLevel); + virtual void Stop(); + virtual void SendPacket(void *data, size_t len); + virtual void Trigger(); +}; + +class WifiHandler +{ +protected: + AdhocCommInterface *_adhocCommInterface; + SoftAPCommInterface *_softAPCommInterface; + + WifiEmulationLevel _selectedEmulationLevel; + WifiEmulationLevel _currentEmulationLevel; + + WifiCommInterfaceID _selectedCommID; + WifiCommInterfaceID _currentCommID; + WifiCommInterface *_currentCommInterface; + + int _selectedBridgeDeviceIndex; + + ClientPCapInterface *_pcap; + bool _isSocketsSupported; + bool _didWarnWFCUser; + + WifiMACMode _adhocMACMode; + WifiMACMode _infrastructureMACMode; + u32 _ip4Address; + u32 _uniqueMACValue; + u8 _userMAC[3]; + +public: + WifiHandler(); + ~WifiHandler(); + + void Reset(); + + WifiEmulationLevel GetSelectedEmulationLevel(); + WifiEmulationLevel GetCurrentEmulationLevel(); + void SetEmulationLevel(WifiEmulationLevel emulationLevel); + + WifiCommInterfaceID GetSelectedCommInterfaceID(); + WifiCommInterfaceID GetCurrentCommInterfaceID(); + void SetCommInterfaceID(WifiCommInterfaceID commID); + + int GetBridgeDeviceList(std::vector *deviceStringList); + + int GetSelectedBridgeDeviceIndex(); + int GetCurrentBridgeDeviceIndex(); + void SetBridgeDeviceIndex(int deviceIndex); + + bool CommStart(); + void CommStop(); + void CommSendPacket(void *data, size_t len); + void CommTrigger(); + + bool IsSocketsSupported(); + void SetSocketsSupported(bool isSupported); + + bool IsPCapSupported(); + ClientPCapInterface* GetPCapInterface(); + void SetPCapInterface(ClientPCapInterface *pcapInterface); + + WifiMACMode GetMACModeForComm(WifiCommInterfaceID commID); + void SetMACModeForComm(WifiCommInterfaceID commID, WifiMACMode macMode); + + uint32_t GetIP4Address(); + void SetIP4Address(u32 ip4Address); + + uint32_t GetUniqueMACValue(); + void SetUniqueMACValue(u32 uniqueValue); + + void GetUserMACValues(u8 *outValue3, u8 *outValue4, u8 *outValue5); + void SetUserMACValues(u8 inValue3, u8 inValue4, u8 inValue5); + + void GenerateMACFromValues(u8 outMAC[6]); + void CopyMACFromUserValues(u8 outMAC[6]); +}; + /* wifi data to be stored in firmware, when no firmware image was loaded */ extern u8 FW_Mac[6]; extern const u8 FW_WIFIInit[32]; @@ -642,5 +808,7 @@ extern const u8 FW_BBChannel[14]; extern FW_WFCProfile FW_WFCProfile1; extern FW_WFCProfile FW_WFCProfile2; extern FW_WFCProfile FW_WFCProfile3; +extern DummyPCapInterface dummyPCapInterface; +extern WifiHandler *wifiHandler; #endif