Wifi: warning, possible awesomeness inside

DeSmuME can now connect to the WFC servers.
Connections may be unstable though. (hint, MKDS suffers from a timing problem when the race starts)
Also it seems safe to use the same fixed MAC. The only packets that contain the MAC address of the DS are DHCP and ARP packets sent at the beginning.
This commit is contained in:
luigi__ 2010-04-18 10:59:04 +00:00
parent 31f60d908a
commit 5cd32213da
1 changed files with 88 additions and 120 deletions

View File

@ -71,6 +71,17 @@ wifimac_t wifiMac;
Adhoc_t Adhoc;
SoftAP_t SoftAP;
/*******************************************************************************
WIFI TODO
- emulate transmission delays for Beacon and Extra transfers
- emulate delays when receiving as well (may need some queuing system)
- take transfer rate and preamble into account
- figure out RFSTATUS and RFPINS
*******************************************************************************/
/*******************************************************************************
Firmware info needed for if no firmware image is available
@ -1482,31 +1493,15 @@ u16 WIFI_read16(u32 address)
return wifiMac.pid;
case REG_WIFI_AID_HIGH:
return wifiMac.aid;
// RFSTATUS, RFPINS
// TODO: figure out how to emulate those correctly
// without breaking Nintendo's games
case REG_WIFI_RFSTATUS:
//WIFI_LOG(3, "Read RF_STATUS: %04X\n", wifiMac.rfStatus);
//printf("-------------------- read RFSTATUS at %08X -----------------------------\n", NDS_ARM7.instruct_adr);
return 0x0009;
//return wifiMac.rfStatus;
case REG_WIFI_RFPINS:
//WIFI_LOG(3, "Read RF_PINS: %04X\n", wifiMac.rfPins);
//emu_halt();
// printf("-------------------- read RFPINS at %08X -----------------------------\n", NDS_ARM7.instruct_adr);
//return wifiMac.rfPins;
return 0x0004;
case 0x210:
//printf("read TX reg %04X\n", address);
break;
/*case 0x1B6:
{
u16 val = wifiMac.RXNum << 8;
wifiMac.RXNum = 0;
return val;
}*/
/* case 0x94:
case 0x98:
case 0x1B6:
case 0x1C4:*/
// printf("wifi: Read from port %03X\n", address);
return 0x00C6;
case 0x268:
return wifiMac.RXTXAddr;
@ -1828,24 +1823,28 @@ void Adhoc_usTrigger()
// so the RX header length field is indeed header+body
// Hence the CRC32 has been removed from those templates.
const u8 SoftAP_MACAddr[6] = {0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D};
// If you wanna change SoftAP's MAC address, change this
// Warning, don't mistake this for an array, it isn't
#define SOFTAP_MACADDR 0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D
const u8 SoftAP_MACAddr[6] = {SOFTAP_MACADDR};
const u8 SoftAP_Beacon[] = {
/* 802.11 header */
0x80, 0x00, // Frame control
0x00, 0x00, // Duration ID
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Receiver
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // Sender
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // BSSID
SOFTAP_MACADDR, // Sender
SOFTAP_MACADDR, // BSSID
0x00, 0x00, // Sequence control
/* Frame body */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp (modified later)
0x80, 0x00, // Beacon interval
0x0F, 0x00, // Capablilty information
0x21, 0x00, // Capablilty information
0x01, 0x02, 0x82, 0x84, // Supported rates
0x03, 0x01, 0x06, // Current channel
0x05, 0x04, 0x00, 0x00, 0x00, 0x00, // TIM
0x05, 0x04, 0x02, 0x01, 0x00, 0x00, // TIM (no idea what the hell it is)
0x00, 0x06, 'S', 'o', 'f', 't', 'A', 'P', // SSID
};
@ -1854,14 +1853,14 @@ const u8 SoftAP_ProbeResponse[] = {
0x50, 0x00, // Frame control
0x00, 0x00, // Duration ID
0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // Sender
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // BSSID
SOFTAP_MACADDR, // Sender
SOFTAP_MACADDR, // BSSID
0x00, 0x00, // Sequence control
/* Frame body */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp (modified later)
0x80, 0x00, // Beacon interval
0x0F, 0x00, // Capablilty information
0x21, 0x00, // Capablilty information
0x01, 0x02, 0x82, 0x84, // Supported rates
0x03, 0x01, 0x06, // Current channel
0x00, 0x06, 'S', 'o', 'f', 't', 'A', 'P', // SSID
@ -1873,8 +1872,8 @@ const u8 SoftAP_AuthFrame[] = {
0xB0, 0x00, // Frame control
0x00, 0x00, // Duration ID
0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // Sender
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // BSSID
SOFTAP_MACADDR, // Sender
SOFTAP_MACADDR, // BSSID
0x00, 0x00, // Sequence control
/* Frame body */
@ -1888,12 +1887,12 @@ const u8 SoftAP_AssocResponse[] = {
0x10, 0x00, // Frame control
0x00, 0x00, // Duration ID
0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // Sender
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // BSSID
SOFTAP_MACADDR, // Sender
SOFTAP_MACADDR, // BSSID
0x00, 0x00, // Sequence control
/* Frame body */
0x0F, 0x00, // Capability information
0x21, 0x00, // Capability information
0x00, 0x00, // Status
0x01, 0xC0, // Assocation ID
0x01, 0x02, 0x82, 0x84, // Supported rates
@ -1981,59 +1980,33 @@ void SoftAP_SendPacket(u8 *packet, u32 len)
{
u16 frameCtl = *(u16*)&packet[0];
/*WIFI_LOG(3, */printf("SoftAP: Received a packet of length %i bytes. Frame control = %04X\n",
WIFI_LOG(3, "SoftAP: Received a packet of length %i bytes. Frame control = %04X\n",
len, frameCtl);
switch((frameCtl >> 2) & 0x3)
{
case 0x0: // Management frame
{
u32 packetLen;
switch((frameCtl >> 4) & 0xF)
{
case 0x4: // Probe request (WFC)
{
u32 packetLen = sizeof(SoftAP_ProbeResponse);
u32 totalLen = (packetLen + 12);
// Make the RX header
WIFI_MakeRXHeader(SoftAP.curPacket, 0x0010, 20, packetLen, 0, 0);
// Copy the probe response template
packetLen = sizeof(SoftAP_ProbeResponse);
memcpy(&SoftAP.curPacket[12], SoftAP_ProbeResponse, packetLen);
// Add the MAC address
memcpy(&SoftAP.curPacket[12 + 4], FW_Mac, 6);
// Add the timestamp
u64 timestamp = SoftAP.usecCounter;
*(u64*)&SoftAP.curPacket[12 + 24] = timestamp;
// Let's prepare to send
SoftAP.curPacketSize = totalLen;
SoftAP.curPacketPos = 0;
SoftAP.curPacketSending = TRUE;
}
break;
case 0xB: // Authentication
{
u32 packetLen = sizeof(SoftAP_AuthFrame);
u32 totalLen = (packetLen + 12);
// Make the RX header
WIFI_MakeRXHeader(SoftAP.curPacket, 0x0010, 20, packetLen, 0, 0);
// Copy the authentication frame template
packetLen = sizeof(SoftAP_AuthFrame);
memcpy(&SoftAP.curPacket[12], SoftAP_AuthFrame, packetLen);
// Add the MAC address
memcpy(&SoftAP.curPacket[12 + 4], FW_Mac, 6);
// Let's prepare to send
SoftAP.curPacketSize = totalLen;
SoftAP.curPacketPos = 0;
SoftAP.curPacketSending = TRUE;
SoftAP.status = APStatus_Authenticated;
}
break;
@ -2043,23 +2016,9 @@ void SoftAP_SendPacket(u8 *packet, u32 len)
if (SoftAP.status != APStatus_Authenticated)
return;
u32 packetLen = sizeof(SoftAP_AssocResponse);
u32 totalLen = (packetLen + 12);
// Make the RX header
WIFI_MakeRXHeader(SoftAP.curPacket, 0x0010, 20, packetLen, 0, 0);
// Copy the association response template
packetLen = sizeof(SoftAP_AssocResponse);
memcpy(&SoftAP.curPacket[12], SoftAP_AssocResponse, packetLen);
// Add the MAC address
memcpy(&SoftAP.curPacket[12 + 4], FW_Mac, 6);
// Let's prepare to send
SoftAP.curPacketSize = totalLen;
SoftAP.curPacketPos = 0;
SoftAP.curPacketSending = TRUE;
SoftAP.status = APStatus_Associated;
WIFI_LOG(1, "SoftAP connected!\n");
}
@ -2067,17 +2026,33 @@ void SoftAP_SendPacket(u8 *packet, u32 len)
case 0xA: // Disassociation
SoftAP.status = APStatus_Authenticated;
break;
return;
case 0xC: // Deauthentication
SoftAP.status = APStatus_Disconnected;
WIFI_LOG(1, "SoftAP disconnected\n");
break;
return;
default:
WIFI_LOG(2, "SoftAP: unknown management frame type %04X\n", (frameCtl >> 4) & 0xF);
break;
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;
@ -2092,8 +2067,8 @@ void SoftAP_SendPacket(u8 *packet, u32 len)
u32 epacketLen = ((len - 30 - 4) + 14);
u8 epacket[2048];
printf("----- SENDING ETHERNET PACKET: len=%i, ethertype=%04X -----\n",
len, *(u16*)&packet[30]);
//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);
@ -2115,20 +2090,23 @@ void SoftAP_SendPacket(u8 *packet, u32 len)
INLINE void SoftAP_SendBeacon()
{
u32 packetLen = sizeof(SoftAP_Beacon);
u32 totalLen = (packetLen + 12);
// Make the RX header
WIFI_MakeRXHeader(SoftAP.curPacket, 0x0011, 20, packetLen, 0, 0);
memcpy(&SoftAP.curPacket[12], SoftAP_Beacon, packetLen); // Copy the beacon template
// Copy the beacon template
memcpy(&SoftAP.curPacket[12], SoftAP_Beacon, packetLen);
*(u16*)&SoftAP.curPacket[12 + 22] = SoftAP.seqNum << 4; // Sequence number
SoftAP.seqNum++;
// Add the timestamp
u64 timestamp = SoftAP.usecCounter;
*(u64*)&SoftAP.curPacket[12 + 24] = timestamp;
*(u64*)&SoftAP.curPacket[12 + 24] = timestamp; // Timestamp
u16 rxflags = 0x0010;
if (WIFI_compareMAC(wifiMac.bss.bytes, &SoftAP.curPacket[12 + 16]))
rxflags |= 0x8000;
WIFI_MakeRXHeader(SoftAP.curPacket, 0x8011, 20, packetLen, 0, 0);
// Let's prepare to send
SoftAP.curPacketSize = totalLen;
SoftAP.curPacketSize = packetLen + 12;
SoftAP.curPacketPos = 0;
SoftAP.curPacketSending = TRUE;
}
@ -2159,20 +2137,26 @@ static void SoftAP_RXHandler(u_char* user, const struct pcap_pkthdr* h, const u_
// 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))
rxflags |= 0x8000;
// Make a valid 802.11 frame
WIFI_MakeRXHeader(wpacket, 0x0018, 20, wpacketLen, 0, 0);
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+10], SoftAP_MACAddr, 6);
memcpy(&wpacket[12+16], &data[6], 6);
*(u16*)&wpacket[12+22] = 0x0000; // Sequence control. Todo?
*(u16*)&wpacket[12+22] = SoftAP.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], wpacketLen);
SoftAP.seqNum++;
// put it in the RX buffer
for (int i = 0; i < (12 + wpacketLen); i += 2)
{
@ -2183,7 +2167,7 @@ static void SoftAP_RXHandler(u_char* user, const struct pcap_pkthdr* h, const u_
// Done!
wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1));
WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor;
wifiMac.RXNum++;
WIFI_triggerIRQ(WIFI_IRQ_RXEND);
}
@ -2191,6 +2175,9 @@ 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)
{
//if(wifiMac.ioMem[0xD0 >> 1] & 0x0400)
@ -2199,8 +2186,6 @@ void SoftAP_usTrigger()
// Okay for 128 ms then
if((SoftAP.usecCounter & 131071) == 0)
{
//printf("send beacon, store to %04X (readcsr=%04X), size=%x\n",
// wifiMac.RXHWWriteCursor<<1, wifiMac.RXReadCursor<<1, sizeof(SoftAP_Beacon)+12);
SoftAP_SendBeacon();
}
}
@ -2211,40 +2196,23 @@ void SoftAP_usTrigger()
/* ie ~8 microseconds to transfer a word. */
if((SoftAP.curPacketSending) && !(SoftAP.usecCounter & 7))
{
if(SoftAP.curPacketPos >= 0)
{
if(SoftAP.curPacketPos == 0)
{
WIFI_triggerIRQ(WIFI_IRQ_RXSTART);
if(SoftAP.curPacketPos == 0)
WIFI_triggerIRQ(WIFI_IRQ_RXSTART);
wifiMac.rfStatus = 0x0009;
wifiMac.rfPins = 0x0004;
}
else
{
wifiMac.rfStatus = 0x0001;
wifiMac.rfPins = 0x0084;
}
u16 word = *(u16*)&SoftAP.curPacket[SoftAP.curPacketPos];
WIFI_RXPutWord(word);
}
u16 word = *(u16*)&SoftAP.curPacket[SoftAP.curPacketPos];
WIFI_RXPutWord(word);
SoftAP.curPacketPos += 2;
if(SoftAP.curPacketPos >= SoftAP.curPacketSize)
{
//printf("SoftAP: packet finished sending, size=%i, startaddr=%04X", SoftAP.curPacketSize, WIFI_IOREG(REG_WIFI_RXHWWRITECSR));
SoftAP.curPacketSize = 0;
SoftAP.curPacketPos = 0;
SoftAP.curPacketSending = FALSE;
wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1));
WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor;
//printf(", end=%04X\n", wifiMac.RXWriteCursor);
WIFI_triggerIRQ(WIFI_IRQ_RXEND);
SoftAP.seqNum += 0x10;
}
}