From 2bd09eafebbc98e2e2b9fbb023b31551ccd8cf12 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 4 Nov 2023 17:00:12 +0100 Subject: [PATCH] convert Wifi and WifiAP --- src/ARMJIT_Memory.cpp | 9 +- src/NDS.cpp | 29 ++-- src/NDS.h | 2 + src/Wifi.cpp | 197 +++++++-------------- src/Wifi.h | 396 ++++++++++++++++++++++++++---------------- src/WifiAP.cpp | 66 ++----- src/WifiAP.h | 44 +++-- 7 files changed, 376 insertions(+), 367 deletions(-) diff --git a/src/ARMJIT_Memory.cpp b/src/ARMJIT_Memory.cpp index 7a1781ec..b1673abc 100644 --- a/src/ARMJIT_Memory.cpp +++ b/src/ARMJIT_Memory.cpp @@ -1212,7 +1212,7 @@ int ClassifyAddress7(u32 addr) } } -void WifiWrite32(u32 addr, u32 val) +/*void WifiWrite32(u32 addr, u32 val) { Wifi::Write(addr, val & 0xFFFF); Wifi::Write(addr + 2, val >> 16); @@ -1221,7 +1221,7 @@ void WifiWrite32(u32 addr, u32 val) u32 WifiRead32(u32 addr) { return (u32)Wifi::Read(addr) | ((u32)Wifi::Read(addr + 2) << 16); -} +}*/ template void VRAMWrite(u32 addr, T val) @@ -1358,7 +1358,8 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size) } } break; - case 0x04800000: + // TODO: the wifi funcs also ought to check POWCNT + /*case 0x04800000: if (addr < 0x04810000 && size >= 16) { switch (size | store) @@ -1369,7 +1370,7 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size) case 33: return (void*)WifiWrite32; } } - break; + break;*/ case 0x06000000: case 0x06800000: switch (size | store) diff --git a/src/NDS.cpp b/src/NDS.cpp index 3fd8f4cc..2fdbf63b 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -181,6 +181,7 @@ u16 RCnt; class SPU* SPU; class SPIHost* SPI; class RTC* RTC; +class Wifi* Wifi; bool Running; @@ -222,11 +223,11 @@ bool Init() SPU = new class SPU; SPI = new class SPIHost(); RTC = new class RTC(); + Wifi = new class Wifi(); if (!NDSCart::Init()) return false; if (!GBACart::Init()) return false; if (!GPU::Init()) return false; - if (!Wifi::Init()) return false; if (!DSi::Init()) return false; @@ -253,11 +254,11 @@ void DeInit() delete SPU; SPU = nullptr; delete SPI; SPI = nullptr; delete RTC; RTC = nullptr; + delete Wifi; Wifi = nullptr; NDSCart::DeInit(); GBACart::DeInit(); GPU::DeInit(); - Wifi::DeInit(); DSi::DeInit(); @@ -646,7 +647,7 @@ void Reset() SPU->Reset(); SPI->Reset(); RTC->Reset(); - Wifi::Reset(); + Wifi->Reset(); // TODO: move the SOUNDBIAS/degrade logic to SPU? @@ -848,7 +849,7 @@ bool DoSavestate(Savestate* file) SPU->DoSavestate(file); SPI->DoSavestate(file); RTC->DoSavestate(file); - Wifi::DoSavestate(file); + Wifi->DoSavestate(file); if (ConsoleType == 1) DSi::DoSavestate(file); @@ -858,7 +859,7 @@ bool DoSavestate(Savestate* file) GPU::SetPowerCnt(PowerControl9); SPU->SetPowerCnt(PowerControl7 & 0x0001); - Wifi::SetPowerCnt(PowerControl7 & 0x0002); + Wifi->SetPowerCnt(PowerControl7 & 0x0002); } #ifdef JIT_ENABLED @@ -2542,8 +2543,8 @@ u8 ARM7Read8(u32 addr) if (addr < 0x04810000) { if (!(PowerControl7 & (1<<1))) return 0; - if (addr & 0x1) return Wifi::Read(addr-1) >> 8; - return Wifi::Read(addr) & 0xFF; + if (addr & 0x1) return Wifi->Read(addr-1) >> 8; + return Wifi->Read(addr) & 0xFF; } break; @@ -2609,7 +2610,7 @@ u16 ARM7Read16(u32 addr) if (addr < 0x04810000) { if (!(PowerControl7 & (1<<1))) return 0; - return Wifi::Read(addr); + return Wifi->Read(addr); } break; @@ -2675,7 +2676,7 @@ u32 ARM7Read32(u32 addr) if (addr < 0x04810000) { if (!(PowerControl7 & (1<<1))) return 0; - return Wifi::Read(addr) | (Wifi::Read(addr+2) << 16); + return Wifi->Read(addr) | (Wifi->Read(addr+2) << 16); } break; @@ -2818,7 +2819,7 @@ void ARM7Write16(u32 addr, u16 val) if (addr < 0x04810000) { if (!(PowerControl7 & (1<<1))) return; - Wifi::Write(addr, val); + Wifi->Write(addr, val); return; } break; @@ -2898,8 +2899,8 @@ void ARM7Write32(u32 addr, u32 val) if (addr < 0x04810000) { if (!(PowerControl7 & (1<<1))) return; - Wifi::Write(addr, val & 0xFFFF); - Wifi::Write(addr+2, val >> 16); + Wifi->Write(addr, val & 0xFFFF); + Wifi->Write(addr+2, val >> 16); return; } break; @@ -4332,7 +4333,7 @@ void ARM7IOWrite16(u32 addr, u16 val) u16 change = PowerControl7 ^ val; PowerControl7 = val & 0x0003; SPU->SetPowerCnt(val & 0x0001); - Wifi::SetPowerCnt(val & 0x0002); + Wifi->SetPowerCnt(val & 0x0002); if (change & 0x0002) UpdateWifiTimings(); } return; @@ -4462,7 +4463,7 @@ void ARM7IOWrite32(u32 addr, u32 val) u16 change = PowerControl7 ^ val; PowerControl7 = val & 0x0003; SPU->SetPowerCnt(val & 0x0001); - Wifi::SetPowerCnt(val & 0x0002); + Wifi->SetPowerCnt(val & 0x0002); if (change & 0x0002) UpdateWifiTimings(); } return; diff --git a/src/NDS.h b/src/NDS.h index cffcd5dc..4b556c64 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -33,6 +33,7 @@ class SPU; class SPIHost; class RTC; +class Wifi; namespace NDS { @@ -253,6 +254,7 @@ extern u16 RCnt; extern class SPU* SPU; extern class SPIHost* SPI; extern class RTC* RTC; +extern class Wifi* Wifi; const u32 ARM7WRAMSize = 0x10000; extern u8* ARM7WRAM; diff --git a/src/Wifi.cpp b/src/Wifi.cpp index 3716b4c5..1486b409 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -27,91 +27,19 @@ using Platform::Log; using Platform::LogLevel; -namespace Wifi -{ //#define WIFI_LOG printf #define WIFI_LOG(...) {} #define PRINT_MAC(pf, mac) Log(LogLevel::Debug, "%s: %02X:%02X:%02X:%02X:%02X:%02X\n", pf, (mac)[0], (mac)[1], (mac)[2], (mac)[3], (mac)[4], (mac)[5]); -u8 RAM[0x2000]; -u16 IO[0x1000>>1]; - #define IOPORT(x) IO[(x)>>1] #define IOPORT8(x) ((u8*)IO)[x] // destination MACs for MP frames -const u8 MPCmdMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x00}; -const u8 MPReplyMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x10}; -const u8 MPAckMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x03}; - -const int kTimerInterval = 8; -const u32 kTimeCheckMask = ~(kTimerInterval - 1); - -bool Enabled; -bool PowerOn; - -s32 TimerError; - -u16 Random; - -// general, always-on microsecond counter -u64 USTimestamp; - -u64 USCounter; -u64 USCompare; -bool BlockBeaconIRQ14; - -u32 CmdCounter; - -u8 BBRegs[0x100]; -u8 BBRegsRO[0x100]; - -u8 RFVersion; -u32 RFRegs[0x40]; - -struct TXSlot -{ - bool Valid; - u16 Addr; - u16 Length; - u8 Rate; - u8 CurPhase; - int CurPhaseTime; - u32 HalfwordTimeMask; -}; - -TXSlot TXSlots[6]; -u8 TXBuffer[0x2000]; - -u8 RXBuffer[2048]; -u32 RXBufferPtr; -int RXTime; -u32 RXHalfwordTimeMask; - -u32 ComStatus; // 0=waiting for packets 1=receiving 2=sending -u32 TXCurSlot; -u32 RXCounter; - -int MPReplyTimer; -u16 MPClientMask, MPClientFail; - -u8 MPClientReplies[15*1024]; - -u16 MPLastSeqno; - -bool MPInited; -bool LANInited; - -int USUntilPowerOn; -bool ForcePowerOn; - -// MULTIPLAYER SYNC APPARATUS -bool IsMP; -bool IsMPClient; -u64 NextSync; // for clients: timestamp for next sync point -u64 RXTimestamp; +const u8 Wifi::MPCmdMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x00}; +const u8 Wifi::MPReplyMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x10}; +const u8 Wifi::MPAckMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x03}; // multiplayer host TX sequence: // 1. preamble @@ -148,9 +76,20 @@ u64 RXTimestamp; // * TX errors (if applicable) -bool Init() +bool MACEqual(u8* a, const u8* b) { - NDS::RegisterEventFunc(NDS::Event_Wifi, 0, USTimer); + return (*(u32*)&a[0] == *(u32*)&b[0]) && (*(u16*)&a[4] == *(u16*)&b[4]); +} + +bool MACIsBroadcast(u8* a) +{ + return (*(u32*)&a[0] == 0xFFFFFFFF) && (*(u16*)&a[4] == 0xFFFF); +} + + +Wifi::Wifi() +{ + NDS::RegisterEventFunc(NDS::Event_Wifi, 0, MemberEventFunc(Wifi, USTimer)); //MPInited = false; //LANInited = false; @@ -161,24 +100,22 @@ bool Init() Platform::LAN_Init(); LANInited = true; - WifiAP::Init(); - - return true; + WifiAP = new class WifiAP(this); } -void DeInit() +Wifi::~Wifi() { if (MPInited) Platform::MP_DeInit(); if (LANInited) Platform::LAN_DeInit(); - WifiAP::DeInit(); + delete WifiAP; WifiAP = nullptr; NDS::UnregisterEventFunc(NDS::Event_Wifi, 0); } -void Reset() +void Wifi::Reset() { memset(RAM, 0, 0x2000); memset(IO, 0, 0x1000); @@ -277,10 +214,10 @@ void Reset() NextSync = 0; RXTimestamp = 0; - WifiAP::Reset(); + WifiAP->Reset(); } -void DoSavestate(Savestate* file) +void Wifi::DoSavestate(Savestate* file) { file->Section("WIFI"); @@ -355,7 +292,7 @@ void DoSavestate(Savestate* file) } -void ScheduleTimer(bool first) +void Wifi::ScheduleTimer(bool first) { if (first) TimerError = 0; @@ -367,7 +304,7 @@ void ScheduleTimer(bool first) NDS::ScheduleEvent(NDS::Event_Wifi, !first, delay, 0, 0); } -void UpdatePowerOn() +void Wifi::UpdatePowerOn() { bool on = Enabled; @@ -405,17 +342,14 @@ void UpdatePowerOn() } } -void SetPowerCnt(u32 val) +void Wifi::SetPowerCnt(u32 val) { Enabled = val & (1<<1); UpdatePowerOn(); } -void PowerDown(); -void StartTX_Beacon(); - -void SetIRQ(u32 irq) +void Wifi::SetIRQ(u32 irq) { u32 oldflags = IOPORT(W_IF) & IOPORT(W_IE); @@ -426,7 +360,7 @@ void SetIRQ(u32 irq) NDS::SetIRQ(1, NDS::IRQ_Wifi); } -void SetIRQ13() +void Wifi::SetIRQ13() { SetIRQ(13); @@ -440,7 +374,7 @@ void SetIRQ13() } } -void SetIRQ14(int source) // 0=USCOMPARE 1=BEACONCOUNT 2=forced +void Wifi::SetIRQ14(int source) // 0=USCOMPARE 1=BEACONCOUNT 2=forced { if (source != 2) IOPORT(W_BeaconCount1) = IOPORT(W_BeaconInterval); @@ -469,7 +403,7 @@ void SetIRQ14(int source) // 0=USCOMPARE 1=BEACONCOUNT 2=forced IOPORT(W_ListenCount)--; } -void SetIRQ15() +void Wifi::SetIRQ15() { SetIRQ(15); @@ -481,7 +415,7 @@ void SetIRQ15() } -void SetStatus(u32 status) +void Wifi::SetStatus(u32 status) { // TODO, eventually: states 2/4/7 u16 rfpins[10] = {0x04, 0x84, 0, 0x46, 0, 0x84, 0x87, 0, 0x46, 0x04}; @@ -490,7 +424,7 @@ void SetStatus(u32 status) } -void PowerDown() +void Wifi::PowerDown() { IOPORT(W_TXReqRead) &= ~0x000F; IOPORT(W_PowerState) |= 0x0200; @@ -504,20 +438,14 @@ void PowerDown() } -bool MACEqual(const u8* a, const u8* b) -{ - return (*(u32*)&a[0] == *(u32*)&b[0]) && (*(u16*)&a[4] == *(u16*)&b[4]); -} - - -int PreambleLen(int rate) +int Wifi::PreambleLen(int rate) { if (rate == 1) return 192; if (IOPORT(W_Preamble) & 0x0004) return 96; return 192; } -u32 NumClients(u16 bitmask) +u32 Wifi::NumClients(u16 bitmask) { u32 ret = 0; for (int i = 1; i < 16; i++) @@ -527,14 +455,14 @@ u32 NumClients(u16 bitmask) return ret; } -void IncrementTXCount(TXSlot* slot) +void Wifi::IncrementTXCount(TXSlot* slot) { u8 cnt = RAM[slot->Addr + 0x4]; if (cnt < 0xFF) cnt++; *(u16*)&RAM[slot->Addr + 0x4] = cnt; } -void ReportMPReplyErrors(u16 clientfail) +void Wifi::ReportMPReplyErrors(u16 clientfail) { // TODO: do these trigger any IRQ? @@ -547,7 +475,7 @@ void ReportMPReplyErrors(u16 clientfail) } } -void TXSendFrame(TXSlot* slot, int num) +void Wifi::TXSendFrame(TXSlot* slot, int num) { u32 noseqno = 0; @@ -597,7 +525,7 @@ void TXSendFrame(TXSlot* slot, int num) case 2: case 3: Platform::MP_SendPacket(TXBuffer, 12+len, USTimestamp); - if (!IsMP) WifiAP::SendPacket(TXBuffer, 12+len); + if (!IsMP) WifiAP->SendPacket(TXBuffer, 12+len); break; case 1: @@ -617,7 +545,7 @@ void TXSendFrame(TXSlot* slot, int num) } } -void StartTX_LocN(int nslot, int loc) +void Wifi::StartTX_LocN(int nslot, int loc) { TXSlot* slot = &TXSlots[nslot]; @@ -637,7 +565,7 @@ void StartTX_LocN(int nslot, int loc) slot->CurPhaseTime = PreambleLen(slot->Rate); } -void StartTX_Cmd() +void Wifi::StartTX_Cmd() { TXSlot* slot = &TXSlots[1]; @@ -672,7 +600,7 @@ void StartTX_Cmd() } } -void StartTX_Beacon() +void Wifi::StartTX_Beacon() { TXSlot* slot = &TXSlots[4]; @@ -691,7 +619,7 @@ void StartTX_Beacon() IOPORT(W_TXBusy) |= 0x0010; } -void FireTX() +void Wifi::FireTX() { if (!(IOPORT(W_RXCnt) & 0x8000)) return; @@ -736,7 +664,7 @@ void FireTX() } } -void SendMPDefaultReply() +void Wifi::SendMPDefaultReply() { u8 reply[12 + 28]; @@ -766,7 +694,7 @@ void SendMPDefaultReply() WIFI_LOG("wifi: sent %d/40 bytes of MP default reply\n", txlen); } -void SendMPReply(u16 clienttime, u16 clientmask) +void Wifi::SendMPReply(u16 clienttime, u16 clientmask) { TXSlot* slot = &TXSlots[5]; @@ -827,7 +755,7 @@ void SendMPReply(u16 clienttime, u16 clientmask) IOPORT(W_TXBusy) |= 0x0080; } -void SendMPAck(u16 cmdcount, u16 clientfail) +void Wifi::SendMPAck(u16 cmdcount, u16 clientfail) { u8 ack[12 + 32]; @@ -873,10 +801,7 @@ void SendMPAck(u16 cmdcount, u16 clientfail) WIFI_LOG("wifi: sent %d/44 bytes of MP ack, %d %d\n", txlen, ComStatus, RXTime); } -bool CheckRX(int type); -void MPClientReplyRX(int client); - -bool ProcessTX(TXSlot* slot, int num) +bool Wifi::ProcessTX(TXSlot* slot, int num) { slot->CurPhaseTime -= kTimerInterval; if (slot->CurPhaseTime > 0) @@ -1137,7 +1062,7 @@ bool ProcessTX(TXSlot* slot, int num) } -inline void IncrementRXAddr(u16& addr, u16 inc = 2) +inline void Wifi::IncrementRXAddr(u16& addr, u16 inc) { for (u32 i = 0; i < inc; i += 2) { @@ -1148,7 +1073,7 @@ inline void IncrementRXAddr(u16& addr, u16 inc = 2) } } -void StartRX() +void Wifi::StartRX() { u16 framelen = *(u16*)&RXBuffer[8]; RXTime = framelen; @@ -1176,7 +1101,7 @@ void StartRX() ComStatus |= 1; } -void FinishRX() +void Wifi::FinishRX() { ComStatus &= ~0x1; RXCounter = 0; @@ -1451,7 +1376,7 @@ void FinishRX() } } -void MPClientReplyRX(int client) +void Wifi::MPClientReplyRX(int client) { if (IOPORT(W_PowerState) & 0x0300) return; @@ -1492,7 +1417,7 @@ void MPClientReplyRX(int client) StartRX(); } -bool CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames +bool Wifi::CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames { if (IOPORT(W_PowerState) & 0x0300) return false; @@ -1517,7 +1442,7 @@ bool CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames { rxlen = Platform::MP_RecvPacket(RXBuffer, ×tamp); if ((rxlen <= 0) && (!IsMP)) - rxlen = WifiAP::RecvPacket(RXBuffer); + rxlen = WifiAP->RecvPacket(RXBuffer); } else { @@ -1632,7 +1557,7 @@ bool CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames } -void MSTimer() +void Wifi::MSTimer() { if (IOPORT(W_USCompareCnt)) { @@ -1656,7 +1581,7 @@ void MSTimer() } } -void USTimer(u32 param) +void Wifi::USTimer(u32 param) { USTimestamp += kTimerInterval; @@ -1676,7 +1601,7 @@ void USTimer(u32 param) } if (!(USTimestamp & 0x3FF & kTimeCheckMask)) - WifiAP::MSTimer(); + WifiAP->MSTimer(); bool switchOffPowerSaving = false; if (USUntilPowerOn < 0) @@ -1839,7 +1764,7 @@ void USTimer(u32 param) } -void RFTransfer_Type2() +void Wifi::RFTransfer_Type2() { u32 id = (IOPORT(W_RFData2) >> 2) & 0x1F; @@ -1856,7 +1781,7 @@ void RFTransfer_Type2() } } -void RFTransfer_Type3() +void Wifi::RFTransfer_Type3() { u32 id = (IOPORT(W_RFData1) >> 8) & 0x3F; @@ -1873,7 +1798,7 @@ void RFTransfer_Type3() } -u16 Read(u32 addr) +u16 Wifi::Read(u32 addr) { if (addr >= 0x04810000) return 0; @@ -1976,7 +1901,7 @@ u16 Read(u32 addr) return IOPORT(addr&0xFFF); } -void Write(u32 addr, u16 val) +void Wifi::Write(u32 addr, u16 val) { if (addr >= 0x04810000) return; @@ -2331,14 +2256,12 @@ void Write(u32 addr, u16 val) } -u8* GetMAC() +u8* Wifi::GetMAC() { return (u8*)&IOPORT(W_MACAddr0); } -u8* GetBSSID() +u8* Wifi::GetBSSID() { return (u8*)&IOPORT(W_BSSID0); } - -} diff --git a/src/Wifi.h b/src/Wifi.h index e3570390..5a4f839e 100644 --- a/src/Wifi.h +++ b/src/Wifi.h @@ -21,178 +21,268 @@ #include "Savestate.h" -namespace Wifi +class WifiAP; + +class Wifi { +public: -enum -{ - W_ID = 0x000, + enum + { + W_ID = 0x000, - W_ModeReset = 0x004, - W_ModeWEP = 0x006, - W_TXStatCnt = 0x008, - W_IF = 0x010, - W_IE = 0x012, + W_ModeReset = 0x004, + W_ModeWEP = 0x006, + W_TXStatCnt = 0x008, + W_IF = 0x010, + W_IE = 0x012, - W_MACAddr0 = 0x018, - W_MACAddr1 = 0x01A, - W_MACAddr2 = 0x01C, - W_BSSID0 = 0x020, - W_BSSID1 = 0x022, - W_BSSID2 = 0x024, - W_AIDLow = 0x028, - W_AIDFull = 0x02A, + W_MACAddr0 = 0x018, + W_MACAddr1 = 0x01A, + W_MACAddr2 = 0x01C, + W_BSSID0 = 0x020, + W_BSSID1 = 0x022, + W_BSSID2 = 0x024, + W_AIDLow = 0x028, + W_AIDFull = 0x02A, - W_TXRetryLimit = 0x02C, - W_RXCnt = 0x030, - W_WEPCnt = 0x032, + W_TXRetryLimit = 0x02C, + W_RXCnt = 0x030, + W_WEPCnt = 0x032, - W_PowerUS = 0x036, - W_PowerTX = 0x038, - W_PowerState = 0x03C, - W_PowerForce = 0x040, - W_PowerUnk = 0x48, + W_PowerUS = 0x036, + W_PowerTX = 0x038, + W_PowerState = 0x03C, + W_PowerForce = 0x040, + W_PowerUnk = 0x48, - W_Random = 0x044, + W_Random = 0x044, - W_RXBufBegin = 0x050, - W_RXBufEnd = 0x052, - W_RXBufWriteCursor = 0x054, - W_RXBufWriteAddr = 0x056, - W_RXBufReadAddr = 0x058, - W_RXBufReadCursor = 0x05A, - W_RXBufCount = 0x05C, - W_RXBufDataRead = 0x060, - W_RXBufGapAddr = 0x062, - W_RXBufGapSize = 0x064, + W_RXBufBegin = 0x050, + W_RXBufEnd = 0x052, + W_RXBufWriteCursor = 0x054, + W_RXBufWriteAddr = 0x056, + W_RXBufReadAddr = 0x058, + W_RXBufReadCursor = 0x05A, + W_RXBufCount = 0x05C, + W_RXBufDataRead = 0x060, + W_RXBufGapAddr = 0x062, + W_RXBufGapSize = 0x064, - W_TXBufWriteAddr = 0x068, - W_TXBufCount = 0x06C, - W_TXBufDataWrite = 0x070, - W_TXBufGapAddr = 0x074, - W_TXBufGapSize = 0x076, + W_TXBufWriteAddr = 0x068, + W_TXBufCount = 0x06C, + W_TXBufDataWrite = 0x070, + W_TXBufGapAddr = 0x074, + W_TXBufGapSize = 0x076, - W_TXSlotBeacon = 0x080, - W_TXBeaconTIM = 0x084, - W_ListenCount = 0x088, - W_BeaconInterval = 0x08C, - W_ListenInterval = 0x08E, - W_TXSlotCmd = 0x090, - W_TXSlotReply1 = 0x094, - W_TXSlotReply2 = 0x098, - W_TXSlotLoc1 = 0x0A0, - W_TXSlotLoc2 = 0x0A4, - W_TXSlotLoc3 = 0x0A8, - W_TXReqReset = 0x0AC, - W_TXReqSet = 0x0AE, - W_TXReqRead = 0x0B0, - W_TXSlotReset = 0x0B4, - W_TXBusy = 0x0B6, - W_TXStat = 0x0B8, - W_Preamble = 0x0BC, - W_CmdTotalTime = 0x0C0, - W_CmdReplyTime = 0x0C4, - W_RXFilter = 0x0D0, - W_RXLenCrop = 0x0DA, - W_RXFilter2 = 0x0E0, + W_TXSlotBeacon = 0x080, + W_TXBeaconTIM = 0x084, + W_ListenCount = 0x088, + W_BeaconInterval = 0x08C, + W_ListenInterval = 0x08E, + W_TXSlotCmd = 0x090, + W_TXSlotReply1 = 0x094, + W_TXSlotReply2 = 0x098, + W_TXSlotLoc1 = 0x0A0, + W_TXSlotLoc2 = 0x0A4, + W_TXSlotLoc3 = 0x0A8, + W_TXReqReset = 0x0AC, + W_TXReqSet = 0x0AE, + W_TXReqRead = 0x0B0, + W_TXSlotReset = 0x0B4, + W_TXBusy = 0x0B6, + W_TXStat = 0x0B8, + W_Preamble = 0x0BC, + W_CmdTotalTime = 0x0C0, + W_CmdReplyTime = 0x0C4, + W_RXFilter = 0x0D0, + W_RXLenCrop = 0x0DA, + W_RXFilter2 = 0x0E0, - W_USCountCnt = 0x0E8, - W_USCompareCnt = 0x0EA, - W_CmdCountCnt = 0x0EE, + W_USCountCnt = 0x0E8, + W_USCompareCnt = 0x0EA, + W_CmdCountCnt = 0x0EE, - W_USCount0 = 0x0F8, - W_USCount1 = 0x0FA, - W_USCount2 = 0x0FC, - W_USCount3 = 0x0FE, - W_USCompare0 = 0x0F0, - W_USCompare1 = 0x0F2, - W_USCompare2 = 0x0F4, - W_USCompare3 = 0x0F6, + W_USCount0 = 0x0F8, + W_USCount1 = 0x0FA, + W_USCount2 = 0x0FC, + W_USCount3 = 0x0FE, + W_USCompare0 = 0x0F0, + W_USCompare1 = 0x0F2, + W_USCompare2 = 0x0F4, + W_USCompare3 = 0x0F6, - W_ContentFree = 0x10C, - W_PreBeacon = 0x110, - W_CmdCount = 0x118, - W_BeaconCount1 = 0x11C, - W_BeaconCount2 = 0x134, + W_ContentFree = 0x10C, + W_PreBeacon = 0x110, + W_CmdCount = 0x118, + W_BeaconCount1 = 0x11C, + W_BeaconCount2 = 0x134, - W_BBCnt = 0x158, - W_BBWrite = 0x15A, - W_BBRead = 0x15C, - W_BBBusy = 0x15E, - W_BBMode = 0x160, - W_BBPower = 0x168, + W_BBCnt = 0x158, + W_BBWrite = 0x15A, + W_BBRead = 0x15C, + W_BBBusy = 0x15E, + W_BBMode = 0x160, + W_BBPower = 0x168, - W_RFData2 = 0x17C, - W_RFData1 = 0x17E, - W_RFBusy = 0x180, - W_RFCnt = 0x184, + W_RFData2 = 0x17C, + W_RFData1 = 0x17E, + W_RFBusy = 0x180, + W_RFCnt = 0x184, - W_TXHeaderCnt = 0x194, - W_RFPins = 0x19C, + W_TXHeaderCnt = 0x194, + W_RFPins = 0x19C, - W_RXStatIncIF = 0x1A8, - W_RXStatIncIE = 0x1AA, - W_RXStatHalfIF = 0x1AC, - W_RXStatHalfIE = 0x1AE, - W_TXErrorCount = 0x1C0, - W_RXCount = 0x1C4, + W_RXStatIncIF = 0x1A8, + W_RXStatIncIE = 0x1AA, + W_RXStatHalfIF = 0x1AC, + W_RXStatHalfIE = 0x1AE, + W_TXErrorCount = 0x1C0, + W_RXCount = 0x1C4, - W_CMDStat0 = 0x1D0, - W_CMDStat1 = 0x1D2, - W_CMDStat2 = 0x1D4, - W_CMDStat3 = 0x1D6, - W_CMDStat4 = 0x1D8, - W_CMDStat5 = 0x1DA, - W_CMDStat6 = 0x1DC, - W_CMDStat7 = 0x1DE, + W_CMDStat0 = 0x1D0, + W_CMDStat1 = 0x1D2, + W_CMDStat2 = 0x1D4, + W_CMDStat3 = 0x1D6, + W_CMDStat4 = 0x1D8, + W_CMDStat5 = 0x1DA, + W_CMDStat6 = 0x1DC, + W_CMDStat7 = 0x1DE, - W_TXSeqNo = 0x210, - W_RFStatus = 0x214, - W_IFSet = 0x21C, - W_RXTXAddr = 0x268, + W_TXSeqNo = 0x210, + W_RFStatus = 0x214, + W_IFSet = 0x21C, + W_RXTXAddr = 0x268, + }; + + Wifi(); + ~Wifi(); + void Reset(); + void DoSavestate(Savestate* file); + + void SetPowerCnt(u32 val); + + void USTimer(u32 param); + + u16 Read(u32 addr); + void Write(u32 addr, u16 val); + + u8* GetMAC(); + u8* GetBSSID(); + +private: + u8 RAM[0x2000]; + u16 IO[0x1000>>1]; + + static const u8 MPCmdMAC[6]; + static const u8 MPReplyMAC[6]; + static const u8 MPAckMAC[6]; + + static const int kTimerInterval = 8; + static const u32 kTimeCheckMask = ~(kTimerInterval - 1); + + bool Enabled; + bool PowerOn; + + s32 TimerError; + + u16 Random; + + // general, always-on microsecond counter + u64 USTimestamp; + + u64 USCounter; + u64 USCompare; + bool BlockBeaconIRQ14; + + u32 CmdCounter; + + u8 BBRegs[0x100]; + u8 BBRegsRO[0x100]; + + u8 RFVersion; + u32 RFRegs[0x40]; + + struct TXSlot + { + bool Valid; + u16 Addr; + u16 Length; + u8 Rate; + u8 CurPhase; + int CurPhaseTime; + u32 HalfwordTimeMask; + }; + + TXSlot TXSlots[6]; + u8 TXBuffer[0x2000]; + + u8 RXBuffer[2048]; + u32 RXBufferPtr; + int RXTime; + u32 RXHalfwordTimeMask; + + u32 ComStatus; // 0=waiting for packets 1=receiving 2=sending + u32 TXCurSlot; + u32 RXCounter; + + int MPReplyTimer; + u16 MPClientMask, MPClientFail; + + u8 MPClientReplies[15*1024]; + + u16 MPLastSeqno; + + bool MPInited; + bool LANInited; + + int USUntilPowerOn; + bool ForcePowerOn; + + // MULTIPLAYER SYNC APPARATUS + bool IsMP; + bool IsMPClient; + u64 NextSync; // for clients: timestamp for next sync point + u64 RXTimestamp; + + class WifiAP* WifiAP; + + void ScheduleTimer(bool first); + void UpdatePowerOn(); + + void SetIRQ(u32 irq); + void SetIRQ13(); + void SetIRQ14(int source); + void SetIRQ15(); + + void SetStatus(u32 status); + void PowerDown(); + + int PreambleLen(int rate); + u32 NumClients(u16 bitmask); + void IncrementTXCount(TXSlot* slot); + void ReportMPReplyErrors(u16 clientfail); + + void TXSendFrame(TXSlot* slot, int num); + void StartTX_LocN(int nslot, int loc); + void StartTX_Cmd(); + void StartTX_Beacon(); + void FireTX(); + void SendMPDefaultReply(); + void SendMPReply(u16 clienttime, u16 clientmask); + void SendMPAck(u16 cmdcount, u16 clientfail); + bool ProcessTX(TXSlot* slot, int num); + + void IncrementRXAddr(u16& addr, u16 inc = 2); + void StartRX(); + void FinishRX(); + void MPClientReplyRX(int client); + bool CheckRX(int type); + + void MSTimer(); + + void RFTransfer_Type2(); + void RFTransfer_Type3(); }; -enum -{ - Event_RXCheck = 0, - Event_IRQ15, - Event_MSTimer, - Event_RFWakeup, - Event_RX, - Event_TX, - Event_MPClientSync, - Event_RF, - Event_BB, - - Event_MAX -}; - -struct SchedEvent -{ - void (*Func)(u32 param); - u64 Timestamp; - u32 Param; -}; - - -extern bool MPInited; - - -bool Init(); -void DeInit(); -void Reset(); -void DoSavestate(Savestate* file); - -void SetPowerCnt(u32 val); - -void USTimer(u32 param); - -u16 Read(u32 addr); -void Write(u32 addr, u16 val); - -u8* GetMAC(); -u8* GetBSSID(); - -} - #endif diff --git a/src/WifiAP.cpp b/src/WifiAP.cpp index c9cccea0..9107a812 100644 --- a/src/WifiAP.cpp +++ b/src/WifiAP.cpp @@ -30,10 +30,9 @@ using Platform::Log; using Platform::LogLevel; -namespace WifiAP -{ -const u8 APMac[6] = {AP_MAC}; +const char* WifiAP::APName = "melonAP"; +const u8 WifiAP::APMac[6] = {0x00, 0xF0, 0x77, 0x77, 0x77, 0x77}; #define PWRITE_8(p, v) *p++ = v; #define PWRITE_16(p, v) *(u16*)p = v; p += 2; @@ -65,33 +64,19 @@ const u8 APMac[6] = {AP_MAC}; #define PALIGN_4(p, base) while (PLEN(p,base) & 0x3) *p++ = 0xFF; -u64 USCounter; - -u16 SeqNo; - -bool BeaconDue; - -u8 PacketBuffer[2048]; -int PacketLen; -int RXNum; - -u8 LANBuffer[2048]; - -// this is a lazy AP, we only keep track of one client -// 0=disconnected 1=authenticated 2=associated -int ClientStatus; +bool MACEqual(u8* a, const u8* b); +bool MACIsBroadcast(u8* a); -bool Init() -{ - return true; -} - -void DeInit() +WifiAP::WifiAP(class Wifi* wifi) : Wifi(wifi) { } -void Reset() +WifiAP::~WifiAP() +{ +} + +void WifiAP::Reset() { // random starting point for the counter USCounter = 0x428888000ULL; @@ -107,18 +92,7 @@ void Reset() } -bool MACEqual(u8* a, u8* b) -{ - return (*(u32*)&a[0] == *(u32*)&b[0]) && (*(u16*)&a[4] == *(u16*)&b[4]); -} - -bool MACIsBroadcast(u8* a) -{ - return (*(u32*)&a[0] == 0xFFFFFFFF) && (*(u16*)&a[4] == 0xFFFF); -} - - -void MSTimer() +void WifiAP::MSTimer() { USCounter += 0x400; @@ -131,7 +105,7 @@ void MSTimer() } -int HandleManagementFrame(u8* data, int len) +int WifiAP::HandleManagementFrame(u8* data, int len) { // TODO: perfect this // noting that frames sent pre-auth/assoc don't have a proper BSSID @@ -199,8 +173,8 @@ int HandleManagementFrame(u8* data, int len) PWRITE_16(p, 0x0021); // capability PWRITE_8(p, 0x01); PWRITE_8(p, 0x02); PWRITE_8(p, 0x82); PWRITE_8(p, 0x84); // rates PWRITE_8(p, 0x03); PWRITE_8(p, 0x01); PWRITE_8(p, 0x06); // current channel - PWRITE_8(p, 0x00); PWRITE_8(p, strlen(AP_NAME)); - memcpy(p, AP_NAME, strlen(AP_NAME)); p += strlen(AP_NAME); + PWRITE_8(p, 0x00); PWRITE_8(p, strlen(APName)); + memcpy(p, APName, strlen(APName)); p += strlen(APName); PacketLen = PLEN(p, base); RXNum = 1; @@ -282,7 +256,7 @@ int HandleManagementFrame(u8* data, int len) } -int SendPacket(u8* data, int len) +int WifiAP::SendPacket(u8* data, int len) { data += 12; @@ -330,7 +304,7 @@ int SendPacket(u8* data, int len) return 0; } -int RecvPacket(u8* data) +int WifiAP::RecvPacket(u8* data) { if (BeaconDue) { @@ -353,8 +327,8 @@ int RecvPacket(u8* data) PWRITE_8(p, 0x01); PWRITE_8(p, 0x02); PWRITE_8(p, 0x82); PWRITE_8(p, 0x84); // rates PWRITE_8(p, 0x03); PWRITE_8(p, 0x01); PWRITE_8(p, 0x06); // current channel PWRITE_8(p, 0x05); PWRITE_8(p, 0x04); PWRITE_8(p, 0); PWRITE_8(p, 0); PWRITE_8(p, 0); PWRITE_8(p, 0); // TIM - PWRITE_8(p, 0x00); PWRITE_8(p, strlen(AP_NAME)); - memcpy(p, AP_NAME, strlen(AP_NAME)); p += strlen(AP_NAME); + PWRITE_8(p, 0x00); PWRITE_8(p, strlen(APName)); + memcpy(p, APName, strlen(APName)); p += strlen(APName); PALIGN_4(p, base); PWRITE_32(p, 0xDEADBEEF); // checksum. doesn't matter for now @@ -394,7 +368,7 @@ int RecvPacket(u8* data) // check destination MAC if (!MACIsBroadcast(&LANBuffer[0])) { - if (!MACEqual(&LANBuffer[0], Wifi::GetMAC())) + if (!MACEqual(&LANBuffer[0], Wifi->GetMAC())) return 0; } @@ -427,5 +401,3 @@ int RecvPacket(u8* data) return 0; } - -} diff --git a/src/WifiAP.h b/src/WifiAP.h index 04dbfa82..717e1c6c 100644 --- a/src/WifiAP.h +++ b/src/WifiAP.h @@ -21,24 +21,44 @@ #include "types.h" -namespace WifiAP +class Wifi; + +class WifiAP { +public: + WifiAP(Wifi* wifi); + ~WifiAP(); + void Reset(); -#define AP_MAC 0x00, 0xF0, 0x77, 0x77, 0x77, 0x77 -#define AP_NAME "melonAP" + static const char* APName; + static const u8 APMac[6]; -extern const u8 APMac[6]; + void MSTimer(); -bool Init(); -void DeInit(); -void Reset(); + // packet format: 12-byte TX header + original 802.11 frame + int SendPacket(u8* data, int len); + int RecvPacket(u8* data); -void MSTimer(); +private: + class Wifi* Wifi; -// packet format: 12-byte TX header + original 802.11 frame -int SendPacket(u8* data, int len); -int RecvPacket(u8* data); + u64 USCounter; -} + u16 SeqNo; + + bool BeaconDue; + + u8 PacketBuffer[2048]; + int PacketLen; + int RXNum; + + u8 LANBuffer[2048]; + + // this is a lazy AP, we only keep track of one client + // 0=disconnected 1=authenticated 2=associated + int ClientStatus; + + int HandleManagementFrame(u8* data, int len); +}; #endif