diff options
-rw-r--r-- | src/DSi_NWifi.cpp | 733 | ||||
-rw-r--r-- | src/DSi_NWifi.h | 5 | ||||
-rw-r--r-- | src/FIFO.h | 2 | ||||
-rw-r--r-- | src/frontend/qt_sdl/LAN_Socket.cpp | 104 |
4 files changed, 440 insertions, 404 deletions
diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index d158974..84b39fa 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -125,10 +125,8 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) for (int i = 0; i < 8; i++) Mailbox[i] = new FIFO<u8>(0x600);//0x80); - // extra FIFOs acting as bigger TX/RX buffers, to work on frames - // bigger than 0x80 - //Mailbox[8] = new FIFO<u8>(0x608); - //Mailbox[9] = new FIFO<u8>(0x608); + // extra mailbox acting as a bigger RX buffer + Mailbox[8] = new FIFO<u8>(0x8000); // this seems to control whether the firmware upload is done EEPROMReady = 0; @@ -138,7 +136,7 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) DSi_NWifi::~DSi_NWifi() { - for (int i = 0; i < 8; i++) + for (int i = 0; i < 9; i++) delete Mailbox[i]; NDS::CancelEvent(NDS::Event_DSi_NWifi); @@ -160,7 +158,7 @@ void DSi_NWifi::Reset() WindowReadAddr = 0; WindowWriteAddr = 0; - for (int i = 0; i < 8; i++) + for (int i = 0; i < 9; i++) Mailbox[i]->Clear(); u8* mac = SPI_Firmware::GetWifiMAC(); @@ -183,6 +181,8 @@ void DSi_NWifi::Reset() *(u16*)&EEPROM[0x004] = chk; + // TODO: SDIO reset shouldn't reset this + // this is reset by the internal reset register, and that also resets EEPROM init BootPhase = 0; ErrorMask = 0; @@ -308,6 +308,7 @@ u8 DSi_NWifi::F1_Read(u32 addr) if (addr < 0x100) { u8 ret = Mailbox[4]->Read(); + if (addr == 0xFF) DrainRXBuffer(); UpdateIRQ_F1(); return ret; } @@ -373,6 +374,7 @@ u8 DSi_NWifi::F1_Read(u32 addr) else if (addr < 0x1000) { u8 ret = Mailbox[4]->Read(); + if (addr == 0xFFF) DrainRXBuffer(); UpdateIRQ_F1(); return ret; } @@ -397,11 +399,12 @@ u8 DSi_NWifi::F1_Read(u32 addr) else { u8 ret = Mailbox[4]->Read(); + if (addr == 0x3FFF) DrainRXBuffer(); UpdateIRQ_F1(); return ret; } - printf("NWIFI: unknown func1 read %05X\n", addr); + //printf("NWIFI: unknown func1 read %05X\n", addr); return 0; } @@ -859,287 +862,257 @@ void DSi_NWifi::WMI_Command() u8 ep = h0 & 0xFF; if (ep > 0x01) // data endpoints - { + {printf("WMI PACKET %04X:%04X:%04X\n", h0, len, h2); WMI_SendPacket(len); - MB_Drain(0); - return; } - - u16 cmd = MB_Read16(0); - - switch (cmd) + else { - case 0x0001: // connect to network - { - WMI_ConnectToNetwork(); - SendWMIAck(); - } - break; - - case 0x0003: // disconnect - { - if (ConnectionStatus != 1) - printf("WMI: ?? trying to disconnect while not connected\n"); - - printf("WMI: disconnect\n"); - ConnectionStatus = 0; - - u8 reply[10]; - *(u16*)&reply[0] = 3; // checkme - memcpy(&reply[2], WifiAP::APMac, 6); - reply[8] = 3; // disconnect reason (via cmd) - reply[9] = 0; // assoc-response length (?????) - SendWMIEvent(1, 0x1003, reply, 10); - - SendWMIAck(); - } - break; - - case 0x0004: // synchronize - { - Mailbox[0]->Read(); - // TODO?? - - SendWMIAck(); - } - break; - - case 0x0005: // create priority stream - { - // TODO??? - // there's a lot of crap in there. - - SendWMIAck(); - } - break; - - case 0x0007: // start scan + u16 cmd = MB_Read16(0); + printf("WMI CMD: %04X:%04X:%04X %04X\n", h0, len, h2, cmd); + for (int i = 0; i < len-2; i++) + { + printf("%02X ", Mailbox[0]->Peek(i)); + if ((i&0xF)==0xF) printf("\n"); + } + printf("\n"); + switch (cmd) { - u32 forcefg = MB_Read32(0); - u32 legacy = MB_Read32(0); - u32 scantime = MB_Read32(0); - u32 forceinterval = MB_Read32(0); - u8 scantype = Mailbox[0]->Read(); - u8 nchannels = Mailbox[0]->Read(); - - printf("WMI: start scan, forceFG=%d, legacy=%d, scanTime=%d, interval=%d, scanType=%d, chan=%d\n", - forcefg, legacy, scantime, forceinterval, scantype, nchannels); - - if (ScanTimer > 0) + case 0x0001: // connect to network { - printf("!! CHECKME: START SCAN BUT WAS ALREADY SCANNING (%d)\n", ScanTimer); + WMI_ConnectToNetwork(); } + break; - // checkme - ScanTimer = scantime*5; - - SendWMIAck(); - } - break; + case 0x0003: // disconnect + { + if (ConnectionStatus != 1) + printf("WMI: ?? trying to disconnect while not connected\n"); + + printf("WMI: disconnect\n"); + ConnectionStatus = 0; + + u8 reply[10]; + *(u16*)&reply[0] = 3; // checkme + memcpy(&reply[2], WifiAP::APMac, 6); + reply[8] = 3; // disconnect reason (via cmd) + reply[9] = 0; // assoc-response length (?????) + SendWMIEvent(1, 0x1003, reply, 10); + } + break; - case 0x0008: // set scan params - { - // TODO: do something with the params!! + case 0x0004: // synchronize + { + Mailbox[0]->Read(); + // TODO?? + } + break; - SendWMIAck(); - } - break; + case 0x0005: // create priority stream + { + // TODO??? + // there's a lot of crap in there. + } + break; - case 0x0009: // set BSS filter - { - // TODO: do something with the params!! - u8 bssfilter = Mailbox[0]->Read(); - Mailbox[0]->Read(); - Mailbox[0]->Read(); - Mailbox[0]->Read(); - u32 iemask = MB_Read32(0); + case 0x0007: // start scan + { + u32 forcefg = MB_Read32(0); + u32 legacy = MB_Read32(0); + u32 scantime = MB_Read32(0); + u32 forceinterval = MB_Read32(0); + u8 scantype = Mailbox[0]->Read(); + u8 nchannels = Mailbox[0]->Read(); - printf("WMI: set BSS filter, filter=%02X, iemask=%08X\n", bssfilter, iemask); + printf("WMI: start scan, forceFG=%d, legacy=%d, scanTime=%d, interval=%d, scanType=%d, chan=%d\n", + forcefg, legacy, scantime, forceinterval, scantype, nchannels); - SendWMIAck(); - } - break; + if (ScanTimer > 0) + { + printf("!! CHECKME: START SCAN BUT WAS ALREADY SCANNING (%d)\n", ScanTimer); + } - case 0x000A: // set probed BSSID - { - u8 id = Mailbox[0]->Read(); - u8 flags = Mailbox[0]->Read(); - u8 len = Mailbox[0]->Read(); + // checkme + ScanTimer = scantime*5; + } + break; - char ssid[33] = {0}; - for (int i = 0; i < len && i < 32; i++) - ssid[i] = Mailbox[0]->Read(); + case 0x0008: // set scan params + { + // TODO: do something with the params!! + } + break; - // TODO: store it somewhere - printf("WMI: set probed SSID: id=%d, flags=%02X, len=%d, SSID=%s\n", id, flags, len, ssid); + case 0x0009: // set BSS filter + { + // TODO: do something with the params!! + u8 bssfilter = Mailbox[0]->Read(); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + u32 iemask = MB_Read32(0); + + printf("WMI: set BSS filter, filter=%02X, iemask=%08X\n", bssfilter, iemask); + } + break; - SendWMIAck(); - } - break; + case 0x000A: // set probed BSSID + { + u8 id = Mailbox[0]->Read(); + u8 flags = Mailbox[0]->Read(); + u8 len = Mailbox[0]->Read(); - case 0x000D: // set disconnect timeout - { - Mailbox[0]->Read(); - // TODO?? + char ssid[33] = {0}; + for (int i = 0; i < len && i < 32; i++) + ssid[i] = Mailbox[0]->Read(); - SendWMIAck(); - } - break; + // TODO: store it somewhere + printf("WMI: set probed SSID: id=%d, flags=%02X, len=%d, SSID=%s\n", id, flags, len, ssid); + } + break; - case 0x000E: // get channel list - { - int nchan = 11; // TODO: customize?? - u8 reply[2 + (nchan*2) + 2]; + case 0x000D: // set disconnect timeout + { + Mailbox[0]->Read(); + // TODO?? + } + break; - reply[0] = 0; - reply[1] = nchan; - for (int i = 0; i < nchan; i++) - *(u16*)&reply[2 + (i*2)] = 2412 + (i*5); - *(u16*)&reply[2 + (nchan*2)] = 0; + case 0x000E: // get channel list + { + int nchan = 11; // TODO: customize?? + u8 reply[2 + (nchan*2) + 2]; - SendWMIEvent(1, 0x000E, reply, 4+(nchan*2)); + reply[0] = 0; + reply[1] = nchan; + for (int i = 0; i < nchan; i++) + *(u16*)&reply[2 + (i*2)] = 2412 + (i*5); + *(u16*)&reply[2 + (nchan*2)] = 0; - SendWMIAck(); - } - break; + SendWMIEvent(1, 0x000E, reply, 4+(nchan*2)); + } + break; - case 0x0011: // set channel params - { - Mailbox[0]->Read(); - u8 scan = Mailbox[0]->Read(); - u8 phymode = Mailbox[0]->Read(); - u8 len = Mailbox[0]->Read(); - - u16 channels[32]; - for (int i = 0; i < len && i < 32; i++) - channels[i] = MB_Read16(0); - - // TODO: store it somewhere - printf("WMI: set channel params: scan=%d, phymode=%d, len=%d, channels=", scan, phymode, len); - for (int i = 0; i < len && i < 32; i++) - printf("%d,", channels[i]); - printf("\n"); + case 0x0011: // set channel params + { + Mailbox[0]->Read(); + u8 scan = Mailbox[0]->Read(); + u8 phymode = Mailbox[0]->Read(); + u8 len = Mailbox[0]->Read(); + + u16 channels[32]; + for (int i = 0; i < len && i < 32; i++) + channels[i] = MB_Read16(0); + + // TODO: store it somewhere + printf("WMI: set channel params: scan=%d, phymode=%d, len=%d, channels=", scan, phymode, len); + for (int i = 0; i < len && i < 32; i++) + printf("%d,", channels[i]); + printf("\n"); + } + break; - SendWMIAck(); - } - break; + case 0x0012: // set power mode + { + Mailbox[0]->Read(); + // TODO?? + } + break; - case 0x0012: // set power mode - { + case 0x0017: // dummy? Mailbox[0]->Read(); - // TODO?? - - SendWMIAck(); - } - break; - - case 0x0017: // dummy? - Mailbox[0]->Read(); - SendWMIAck(); - break; - - case 0x0022: // set error bitmask - { - ErrorMask = MB_Read32(0); + break; - SendWMIAck(); - } - break; + case 0x0022: // set error bitmask + { + ErrorMask = MB_Read32(0); + } + break; - case 0x002E: // extension shit - { - u16 extcmd = MB_Read16(0); - switch (extcmd) + case 0x002E: // extension shit { - case 0x2008: // 'heartbeat'?? + u32 extcmd = MB_Read32(0); + switch (extcmd) { - u32 cookie = MB_Read32(0); - u32 source = MB_Read32(0); - - u8 reply[10]; - *(u16*)&reply[0] = 0x3007; - *(u32*)&reply[2] = cookie; - *(u32*)&reply[6] = source; - SendWMIEvent(1, 0x1010, reply, 10); + case 0x2008: // 'heartbeat'?? + { + u32 cookie = MB_Read32(0); + u32 source = MB_Read32(0); + + u8 reply[12]; + *(u32*)&reply[0] = 0x3007; + *(u32*)&reply[4] = cookie; + *(u32*)&reply[8] = source; + + if(ConnectionStatus==1)SendWMIEvent(1, 0x1010, reply, 12); + } + break; + + default: + printf("WMI: unknown ext cmd 002E:%04X\n", extcmd); + break; } - break; - - default: - printf("WMI: unknown ext cmd 002E:%04X\n", extcmd); - break; } + break; - SendWMIAck(); - } - break; - - case 0x003D: // set keepalive interval - { - Mailbox[0]->Read(); - // TODO?? - - SendWMIAck(); - } - break; - - case 0x0041: // 'WMI_SET_WSC_STATUS_CMD' - { - Mailbox[0]->Read(); - // TODO?? - - SendWMIAck(); - } - break; - - case 0x0047: // cmd47 -- timer shenanigans?? - { - // - - SendWMIAck(); - } - break; - - case 0x0048: // not supported by DSi?? - { - MB_Read32(0); - MB_Read32(0); - Mailbox[0]->Read(); - Mailbox[0]->Read(); + case 0x003D: // set keepalive interval + { + Mailbox[0]->Read(); + // TODO?? + } + break; - SendWMIAck(); - } - break; + case 0x0041: // 'WMI_SET_WSC_STATUS_CMD' + { + Mailbox[0]->Read(); + // TODO?? + } + break; - case 0x0049: // 'host exit notify' - { - // + case 0x0047: // cmd47 -- timer shenanigans?? + { + // + } + break; - SendWMIAck(); - } - break; + case 0x0048: // not supported by DSi?? + { + MB_Read32(0); + MB_Read32(0); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + } + break; - case 0xF000: // set bitrate - { - // TODO! - Mailbox[0]->Read(); - Mailbox[0]->Read(); - Mailbox[0]->Read(); + case 0x0049: // 'host exit notify' + { + // + } + break; - SendWMIAck(); - } - break; + case 0xF000: // set bitrate + { + // TODO! + Mailbox[0]->Read(); + Mailbox[0]->Read(); + Mailbox[0]->Read(); + } + break; - default: - printf("unknown WMI command %04X (header: %04X:%04X:%04X)\n", cmd, h0, len, h2); - for (int i = 0; i < len-2; i++) - { - printf("%02X ", Mailbox[0]->Read()); - if ((i&0xF)==0xF) printf("\n"); + default: + printf("unknown WMI command %04X (header: %04X:%04X:%04X)\n", cmd, h0, len, h2); + for (int i = 0; i < len-2; i++) + { + printf("%02X ", Mailbox[0]->Read()); + if ((i&0xF)==0xF) printf("\n"); + } + printf("\n"); + break; } - printf("\n"); - break; } + if (h0 & (1<<8)) + SendWMIAck(ep); + MB_Drain(0); } @@ -1210,9 +1183,30 @@ void DSi_NWifi::WMI_SendPacket(u16 len) return; } + // header??? + // packets with bit1=1 are something special (sync??) + // otherwise, ???? + // header is 001C on ARP frames, 0000 otherwise u16 hdr = MB_Read16(0); hdr = ((hdr & 0xFF00) >> 8) | ((hdr & 0x00FF) << 8); - if (hdr & 0x0003) + u16 type = hdr & 0x0003; + + if (type == 2) // data sync + { + printf("WMI: data sync\n"); + + /*Mailbox[8]->Write(2); // eid + Mailbox[8]->Write(0x00); // flags + MB_Write16(8, 2); // data length + Mailbox[8]->Write(0); // + Mailbox[8]->Write(0); // + MB_Write16(8, 0x0200); // + + DrainRXBuffer();*/ + return; + } + + if (type) { printf("WMI: special frame %04X len=%d\n", hdr, len); for (int i = 0; i < len-2; i++) @@ -1224,7 +1218,7 @@ void DSi_NWifi::WMI_SendPacket(u16 len) return; } - printf("WMI: send packet, len=%d\n", len); + printf("WMI: send packet, hdr=%04X, len=%d\n", hdr, len); u8 dstmac[6]; u8 srcmac[6]; @@ -1264,130 +1258,125 @@ void DSi_NWifi::WMI_SendPacket(u16 len) LANBuffer[14+i] = Mailbox[0]->Read(); } - for (int i = 0; i < lan_len; i++) + /*for (int i = 0; i < lan_len; i++) { printf("%02X ", LANBuffer[i]); if ((i&0xF)==0xF) printf("\n"); } - printf("\n"); + printf("\n");*/ Platform::LAN_SendPacket(LANBuffer, lan_len); } -//void DSi_NWifi::SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl) void DSi_NWifi::SendWMIEvent(u8 ep, u16 id, u8* data, u32 len) { - u32 wlen = 0; + if (!Mailbox[8]->CanFit(6+len+2+8)) + { + printf("NWifi: !! not enough space in RX buffer for WMI event %04X\n", id); + return; + } - Mailbox[4]->Write(ep); // eid - Mailbox[4]->Write(0x02); // flags (trailer) - MB_Write16(4, len+2+8); // data length (plus event ID and trailer) - Mailbox[4]->Write(8); // trailer length - Mailbox[4]->Write(0); // - MB_Write16(4, id); // event ID - wlen += 8; + Mailbox[8]->Write(ep); // eid + Mailbox[8]->Write(0x02); // flags (trailer) + MB_Write16(8, len+2+8); // data length (plus event ID and trailer) + Mailbox[8]->Write(8); // trailer length + Mailbox[8]->Write(0); // + MB_Write16(8, id); // event ID for (int i = 0; i < len; i++) { - Mailbox[4]->Write(data[i]); - wlen++; + Mailbox[8]->Write(data[i]); } // trailer - Mailbox[4]->Write(0x02); - Mailbox[4]->Write(0x06); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - wlen += 8; - - for (; wlen & 0x7F; wlen++) - Mailbox[4]->Write(0); + Mailbox[8]->Write(0x02); + Mailbox[8]->Write(0x06); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + + DrainRXBuffer(); } -void DSi_NWifi::SendWMIAck() +void DSi_NWifi::SendWMIAck(u8 ep) { - u32 wlen = 0; - - Mailbox[4]->Write(0); // eid - Mailbox[4]->Write(0x02); // flags (trailer) - MB_Write16(4, 0xC); // data length (plus event ID and trailer) - Mailbox[4]->Write(0xC); // trailer length - Mailbox[4]->Write(0); // - wlen += 6; + if (!Mailbox[8]->CanFit(6+12)) + { + printf("NWifi: !! not enough space in RX buffer for WMI ack (ep #%d)\n", ep); + return; + } - // trailer - Mailbox[4]->Write(0x01); - Mailbox[4]->Write(0x02); - Mailbox[4]->Write(0x01); - Mailbox[4]->Write(0x01); - Mailbox[4]->Write(0x02); - Mailbox[4]->Write(0x06); - - // observed trailer data: - // 00 06 00 00 02 00 (in the first few responses) - // 00 00 00 00 00 00 - // TODO: work out what that all means? - // does software even care? - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x06); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x00); - Mailbox[4]->Write(0x02); - Mailbox[4]->Write(0x00); - wlen += 0xC; - - for (; wlen & 0x7F; wlen++) - Mailbox[4]->Write(0); + Mailbox[8]->Write(0); // eid + Mailbox[8]->Write(0x02); // flags (trailer) + MB_Write16(8, 0xC); // data length (plus trailer) + Mailbox[8]->Write(0xC); // trailer length + Mailbox[8]->Write(0); // + + // credit report + Mailbox[8]->Write(0x01); + Mailbox[8]->Write(0x02); + Mailbox[8]->Write(ep); + Mailbox[8]->Write(0x01); + + // lookahead + Mailbox[8]->Write(0x02); + Mailbox[8]->Write(0x06); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + Mailbox[8]->Write(0x00); + + DrainRXBuffer(); } void DSi_NWifi::SendWMIBSSInfo(u8 type, u8* data, u32 len) { - u32 wlen = 0; - - // TODO: what is the trailer about????? - // on hardware I observed one frame with trailer and another without - // plus it's different from other frames + if (!Mailbox[8]->CanFit(6+len+2+16)) + { + printf("NWifi: !! not enough space in RX buffer for WMI BSSINFO event\n"); + return; + } // TODO: check when version>=2 frame type is used? // I observed the version<2 variant on my DSi - Mailbox[4]->Write(1); // eid - Mailbox[4]->Write(0x00); // flags - MB_Write16(4, len+2+16); // data length (plus event ID and trailer) - Mailbox[4]->Write(0xFF); // trailer length - Mailbox[4]->Write(0xFF); // - MB_Write16(4, 0x1004); // event ID - wlen += 8; - - MB_Write16(4, 2437); // channel (6) (checkme!) - Mailbox[4]->Write(type); - Mailbox[4]->Write(0x1B); // 'snr' - MB_Write16(4, 0xFFBC); // RSSI - MB_Write32(4, *(u32*)&WifiAP::APMac[0]); - MB_Write16(4, *(u16*)&WifiAP::APMac[4]); - MB_Write32(4, 0); // ieMask - wlen += 16; + Mailbox[8]->Write(1); // eid + Mailbox[8]->Write(0x00); // flags + MB_Write16(8, len+2+16); // data length (plus event ID and trailer) + Mailbox[8]->Write(0xFF); // trailer length + Mailbox[8]->Write(0xFF); // + MB_Write16(8, 0x1004); // event ID + + MB_Write16(8, 2437); // channel (6) (checkme!) + Mailbox[8]->Write(type); + Mailbox[8]->Write(0x1B); // 'snr' + MB_Write16(8, 0xFFBC); // RSSI + MB_Write32(8, *(u32*)&WifiAP::APMac[0]); + MB_Write16(8, *(u16*)&WifiAP::APMac[4]); + MB_Write32(8, 0); // ieMask for (int i = 0; i < len; i++) { - Mailbox[4]->Write(data[i]); - wlen++; + Mailbox[8]->Write(data[i]); } - for (; wlen & 0x7F; wlen++) - Mailbox[4]->Write(0); + DrainRXBuffer(); } void DSi_NWifi::CheckRX() { + if (!Mailbox[8]->CanFit(2048)) + return; + int rxlen = Platform::LAN_RecvPacket(LANBuffer); if (rxlen > 0) { - printf("WMI packet recv %04X %04X %04X\n", *(u16*)&LANBuffer[0], *(u16*)&LANBuffer[2], *(u16*)&LANBuffer[4]); + //printf("WMI packet recv %04X %04X %04X\n", *(u16*)&LANBuffer[0], *(u16*)&LANBuffer[2], *(u16*)&LANBuffer[4]); // check destination MAC if (*(u32*)&LANBuffer[0] != 0xFFFFFFFF || *(u16*)&LANBuffer[4] != 0xFFFF) { @@ -1403,39 +1392,47 @@ void DSi_NWifi::CheckRX() printf("WMI: receive packet %04X, len=%d\n", *(u16*)&LANBuffer[12], rxlen); + /*for (int i = 0; i < rxlen; i++) + { + printf("%02X ", LANBuffer[i]); + if ((i&0xF)==0xF) printf("\n"); + } + printf("\n");*/ + int datalen = rxlen - 14; // length of packet body - int wlen = 0; - MB_Write16(4, 0x0002); - MB_Write16(4, 16 + 8 + datalen); - MB_Write16(4, 0x0000); - wlen += 6; - - MB_Write16(4, 0x0000); - MB_Write32(4, *(u32*)&LANBuffer[0]); - MB_Write16(4, *(u16*)&LANBuffer[4]); - MB_Write32(4, *(u32*)&LANBuffer[6]); - MB_Write16(4, *(u16*)&LANBuffer[10]); + u16 hdr = 0x0000; + //if (*(u16*)&LANBuffer[12] == 0x0608) // HAX!!! + // hdr = 0x1C00; + hdr = 0x80; + + // TODO: not hardcode the endpoint ID!! + u8 ep = 2; + + Mailbox[8]->Write(ep); + Mailbox[8]->Write(0x00); + MB_Write16(8, 16 + 8 + datalen); + Mailbox[8]->Write(0); + Mailbox[8]->Write(0); + + MB_Write16(8, hdr); + MB_Write32(8, *(u32*)&LANBuffer[0]); + MB_Write16(8, *(u16*)&LANBuffer[4]); + MB_Write32(8, *(u32*)&LANBuffer[6]); + MB_Write16(8, *(u16*)&LANBuffer[10]); u16 plen = datalen + 8; plen = ((plen & 0xFF00) >> 8) | ((plen & 0x00FF) << 8); - MB_Write16(4, plen); - wlen += 16; + MB_Write16(8, plen); - MB_Write16(4, 0xAAAA); - MB_Write16(4, 0x0003); - MB_Write16(4, 0x0000); - MB_Write16(4, *(u16*)&LANBuffer[12]); - wlen += 8; + MB_Write16(8, 0xAAAA); + MB_Write16(8, 0x0003); + MB_Write16(8, 0x0000); + MB_Write16(8, *(u16*)&LANBuffer[12]); for (int i = 0; i < datalen; i++) - Mailbox[4]->Write(LANBuffer[14+i]); + Mailbox[8]->Write(LANBuffer[14+i]); - wlen += datalen; - - for (; wlen & 0x7F; wlen++) - Mailbox[4]->Write(0); - - UpdateIRQ_F1(); + DrainRXBuffer(); } } @@ -1510,7 +1507,6 @@ void DSi_NWifi::_MSTimer() }; SendWMIBSSInfo(0x01, beacon, sizeof(beacon)); - UpdateIRQ_F1(); printf("send beacon\n"); } @@ -1518,14 +1514,33 @@ void DSi_NWifi::_MSTimer() { u32 status = 0; SendWMIEvent(1, 0x100A, (u8*)&status, 4); - UpdateIRQ_F1(); } } if (ConnectionStatus == 1) { - CheckRX(); + //if (Mailbox[4]->IsEmpty()) + CheckRX(); + } +} + +void DSi_NWifi::DrainRXBuffer() +{ + while (Mailbox[8]->Level() >= 6) + { + u16 len = Mailbox[8]->Peek(2) | (Mailbox[8]->Peek(3) << 8); + u32 totallen = len + 6; + u32 required = (totallen + 0x7F) & ~0x7F; + + if (!Mailbox[4]->CanFit(required)) + break; + + u32 i = 0; + for (; i < totallen; i++) Mailbox[4]->Write(Mailbox[8]->Read()); + for (; i < required; i++) Mailbox[4]->Write(0); } + + UpdateIRQ_F1(); } void DSi_NWifi::MSTimer(u32 param) diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h index 14a5d14..a72d54d 100644 --- a/src/DSi_NWifi.h +++ b/src/DSi_NWifi.h @@ -73,10 +73,11 @@ private: void WMI_SendPacket(u16 len); void SendWMIEvent(u8 ep, u16 id, u8* data, u32 len); - void SendWMIAck(); + void SendWMIAck(u8 ep); void SendWMIBSSInfo(u8 type, u8* data, u32 len); void CheckRX(); + void DrainRXBuffer(); u32 WindowRead(u32 addr); void WindowWrite(u32 addr, u32 val); @@ -116,7 +117,7 @@ private: while (!Mailbox[n]->IsEmpty()) Mailbox[n]->Read(); } - FIFO<u8>* Mailbox[10]; + FIFO<u8>* Mailbox[9]; u8 F0_IRQEnable; u8 F0_IRQStatus; @@ -102,6 +102,8 @@ public: bool IsEmpty() { return NumOccupied == 0; } bool IsFull() { return NumOccupied >= NumEntries; } + bool CanFit(u32 num) { return ((NumOccupied + num) <= NumEntries); } + private: u32 NumEntries; T* Entries; diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp index 13a8eb1..6232964 100644 --- a/src/frontend/qt_sdl/LAN_Socket.cpp +++ b/src/frontend/qt_sdl/LAN_Socket.cpp @@ -22,9 +22,10 @@ #include <stdlib.h> #include <string.h> #include <list> -#include "../Wifi.h" +#include "Wifi.h" #include "LAN_Socket.h" -#include "../Config.h" +#include "Config.h" +#include "FIFO.h" #include <slirp/libslirp.h> @@ -46,9 +47,7 @@ const u32 kClientIP = kSubnet | 0x10; const u8 kServerMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x44}; const u8 kDNSMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x55}; -u8 PacketBuffer[2048]; -int PacketLen; -volatile int RXNum; +FIFO<u32>* RXBuffer = nullptr; u32 IPv4ID; @@ -81,6 +80,23 @@ int clock_gettime(int, struct timespec *spec) #endif // __WIN32__ +void RXEnqueue(const void* buf, int len) +{ + int alignedlen = (len + 3) & ~3; + int totallen = alignedlen + 4; + + if (!RXBuffer->CanFit(totallen >> 2)) + { + printf("slirp: !! NOT ENOUGH SPACE IN RX BUFFER\n"); + return; + } + + u32 header = (alignedlen & 0xFFFF) | (len << 16); + RXBuffer->Write(header); + for (int i = 0; i < alignedlen; i += 4) + RXBuffer->Write(((u32*)buf)[i>>2]); +} + ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque) { if (len > 2048) @@ -91,9 +107,7 @@ ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque) printf("slirp: response packet of %d bytes, type %04X\n", len, ntohs(((u16*)buf)[6])); - PacketLen = len; - memcpy(PacketBuffer, buf, PacketLen); - RXNum = 1; + RXEnqueue(buf, len); return len; } @@ -127,7 +141,7 @@ void SlirpCbRegisterPollFD(int fd, void* opaque) { printf("Slirp: register poll FD %d\n", fd); - if (FDListSize >= FDListMax) + /*if (FDListSize >= FDListMax) { printf("!! SLIRP FD LIST FULL\n"); return; @@ -139,14 +153,14 @@ void SlirpCbRegisterPollFD(int fd, void* opaque) } FDList[FDListSize].fd = fd; - FDListSize++; + FDListSize++;*/ } void SlirpCbUnregisterPollFD(int fd, void* opaque) { printf("Slirp: unregister poll FD %d\n", fd); - if (FDListSize < 1) + /*if (FDListSize < 1) { printf("!! SLIRP FD LIST EMPTY\n"); return; @@ -159,7 +173,7 @@ void SlirpCbUnregisterPollFD(int fd, void* opaque) FDListSize--; FDList[i] = FDList[FDListSize]; } - } + }*/ } void SlirpCbNotify(void* opaque) @@ -187,6 +201,8 @@ bool Init() FDListSize = 0; memset(FDList, 0, sizeof(FDList)); + RXBuffer = new FIFO<u32>(0x8000 >> 2); + SlirpConfig cfg; memset(&cfg, 0, sizeof(cfg)); cfg.version = 1; @@ -211,6 +227,12 @@ void DeInit() slirp_cleanup(Ctx); Ctx = nullptr; } + + if (RXBuffer) + { + delete RXBuffer; + RXBuffer = nullptr; + } } @@ -379,6 +401,7 @@ void HandleDNSFrame(u8* data, int len) addr_res & 0xFF, (addr_res >> 8) & 0xFF, (addr_res >> 16) & 0xFF, addr_res >> 24); + break; p = p->ai_next; } } @@ -405,13 +428,7 @@ void HandleDNSFrame(u8* data, int len) if (framelen & 1) { *out++ = 0; framelen++; } FinishUDPFrame(resp, framelen); - // TODO: if there is already a packet queued, this will overwrite it - // that being said, this will only happen during DHCP setup, so probably - // not a big deal - - PacketLen = framelen; - memcpy(PacketBuffer, resp, PacketLen); - RXNum = 1; + RXEnqueue(resp, framelen); } int SendPacket(u8* data, int len) @@ -444,24 +461,20 @@ int SendPacket(u8* data, int len) return len; } +const int PollListMax = 64; +struct pollfd PollList[PollListMax]; +int PollListSize; + int SlirpCbAddPoll(int fd, int events, void* opaque) { - int idx = -1; - for (int i = 0; i < FDListSize; i++) - { - if (FDList[i].fd == fd) - { - idx = i; - break; - } - } - - if (idx == -1) + if (PollListSize >= PollListMax) { - printf("SLIRP: ERROR! FD %d NOT REGISTERED\n", fd); + printf("slirp: POLL LIST FULL\n"); return -1; } + int idx = PollListSize++; + //printf("Slirp: add poll: fd=%d, idx=%d, events=%08X\n", fd, idx, events); u16 evt = 0; @@ -470,26 +483,26 @@ int SlirpCbAddPoll(int fd, int events, void* opaque) if (events & SLIRP_POLL_OUT) evt |= POLLWRNORM; #ifndef __WIN32__ + // CHECKME if (events & SLIRP_POLL_PRI) evt |= POLLPRI; if (events & SLIRP_POLL_ERR) evt |= POLLERR; if (events & SLIRP_POLL_HUP) evt |= POLLHUP; #endif // !__WIN32__ - FDList[idx].events = evt; + PollList[idx].fd = fd; + PollList[idx].events = evt; + return idx; } int SlirpCbGetREvents(int idx, void* opaque) { - if (idx < 0 || idx >= FDListSize) - { - printf("SLIRP: !! BAD FD INDEX %d (MAX %d)\n", idx, FDListSize); + if (idx < 0 || idx >= PollListSize) return 0; - } //printf("Slirp: get revents, idx=%d, res=%04X\n", idx, FDList[idx].revents); - u16 evt = FDList[idx].revents; + u16 evt = PollList[idx].revents; int ret = 0; if (evt & POLLIN) ret |= SLIRP_POLL_IN; @@ -507,19 +520,24 @@ int RecvPacket(u8* data) int ret = 0; - if (FDListSize > 0) + //if (PollListSize > 0) { u32 timeout = 0; + PollListSize = 0; slirp_pollfds_fill(Ctx, &timeout, SlirpCbAddPoll, nullptr); - int res = poll(FDList, FDListSize, timeout); + int res = poll(PollList, PollListSize, timeout); slirp_pollfds_poll(Ctx, res<0, SlirpCbGetREvents, nullptr); } - if (RXNum > 0) + if (!RXBuffer->IsEmpty()) { - memcpy(data, PacketBuffer, PacketLen); - ret = PacketLen; - RXNum = 0; + u32 header = RXBuffer->Read(); + u32 len = header & 0xFFFF; + + for (int i = 0; i < len; i += 4) + ((u32*)data)[i>>2] = RXBuffer->Read(); + + ret = header >> 16; } return ret; |