WiFi: Standardize the handling of received packets for both Ad-hoc and Infrastructure modes.

- Received packets are now queued properly and should no longer be overwritten or lost.
- Received packets under Ad-hoc mode now use the same transfer delay as Infrastructure mode. (Read one halfword every 8 microseconds.)
- Received packet transfer delay only works when the emulation level is set to WifiEmulationLevel_Compatibility. Transfer delay can be disabled by setting the emulation level to WifiEmulationLevel_Normal, which will cause the entire received packet to be transferred immediately.
This commit is contained in:
rogerman 2018-10-09 15:32:11 -07:00
parent 4e92d24b14
commit da714ea719
2 changed files with 219 additions and 250 deletions

View File

@ -736,34 +736,6 @@ RXPacketHeader WIFI_GenerateRXHeader(const u8 *packetIEEE80211HeaderPtr, const u
return rxHeader;
}
static void WIFI_RXPutWord(u16 val)
{
WifiData &wifi = wifiHandler->GetWifiData();
WIFI_IOREG_MAP &io = wifi.io;
/* abort when RX data queuing is not enabled */
if (io.RXCNT.EnableRXFIFOQueuing == 0) return;
/* abort when ringbuffer is full */
//if (wifiMac.RXReadCursor == wifiMac.RXWriteCursor) return;
/*if(wifiMac.RXWriteCursor >= wifiMac.RXReadCursor)
{
printf("WIFI: write cursor (%04X) above READCSR (%04X). Cannot write received packet.\n",
wifiMac.RXWriteCursor, wifiMac.RXReadCursor);
return;
}*/
/* write the data to cursor position */
wifi.RAM[io.RXBUF_WRCSR.HalfwordAddress] = val;
// printf("wifi: written word %04X to circbuf addr %04X\n", val, (wifiMac.RXWriteCursor << 1));
/* move cursor by one */
//printf("written one word to %04X (start %04X, end %04X), ", wifiMac.RXWriteCursor, wifiMac.RXRangeBegin, wifiMac.RXRangeEnd);
io.RXBUF_WRCSR.HalfwordAddress++;
/* wrap around */
// wifiMac.RXWriteCursor %= (wifiMac.RXRangeEnd - wifiMac.RXRangeBegin) >> 1;
// printf("new addr=%04X\n", wifiMac.RXWriteCursor);
if (io.RXBUF_WRCSR.HalfwordAddress >= ((io.RXBUF_END & 0x1FFE) >> 1))
io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_BEGIN & 0x1FFE) >> 1);
}
static void WIFI_TXStart(const WifiTXLocIndex txSlotIndex, IOREG_W_TXBUF_LOCATION &txLocation)
{
WifiData &wifi = wifiHandler->GetWifiData();
@ -1085,6 +1057,10 @@ void WIFI_write16(u32 address, u16 val)
RXCNT.value = val & 0xFF8F;
io.RXCNT.EnableRXFIFOQueuing = RXCNT.EnableRXFIFOQueuing;
if (io.RXCNT.EnableRXFIFOQueuing == 0)
{
wifiHandler->CommEmptyRXQueue();
}
if (io.RXCNT.UNKNOWN1 != RXCNT.UNKNOWN1)
{
@ -3473,6 +3449,12 @@ WifiCommInterface::WifiCommInterface()
_workingTXBuffer = NULL;
_workingRXBuffer = NULL;
_rxPacketQueue.clear();
_rxCurrentQueuedPacketPosition = 0;
_softAPStatus = APStatus_Disconnected;
_softAPSequenceNumber = 0;
}
WifiCommInterface::~WifiCommInterface()
@ -3484,6 +3466,47 @@ WifiCommInterface::~WifiCommInterface()
this->_workingRXBuffer = NULL;
}
RXQueuedPacket WifiCommInterface::_GenerateSoftAPDeauthenticationFrame()
{
RXQueuedPacket newRXPacket;
u8 *IEEE80211HeaderPtr = newRXPacket.rxData;
WifiMgmtFrameHeader &IEEE80211Header = (WifiMgmtFrameHeader &)IEEE80211HeaderPtr[0];
memcpy(IEEE80211HeaderPtr, SoftAP_DeauthFrame, sizeof(SoftAP_DeauthFrame));
IEEE80211Header.destMAC[0] = FW_Mac[0];
IEEE80211Header.destMAC[1] = FW_Mac[1];
IEEE80211Header.destMAC[2] = FW_Mac[2];
IEEE80211Header.destMAC[3] = FW_Mac[3];
IEEE80211Header.destMAC[4] = FW_Mac[4];
IEEE80211Header.destMAC[5] = FW_Mac[5];
IEEE80211Header.seqCtl.SequenceNumber = this->_softAPSequenceNumber;
newRXPacket.rxHeader = WIFI_GenerateRXHeader(newRXPacket.rxData, 1, true, sizeof(SoftAP_DeauthFrame));
return newRXPacket;
}
RXQueuedPacket WifiCommInterface::_GenerateSoftAPBeaconFrame()
{
RXQueuedPacket newRXPacket;
u8 *IEEE80211HeaderPtr = newRXPacket.rxData;
u8 *mgmtFrameBody = IEEE80211HeaderPtr + sizeof(WifiMgmtFrameHeader);
WifiMgmtFrameHeader &IEEE80211Header = (WifiMgmtFrameHeader &)IEEE80211HeaderPtr[0];
memcpy(IEEE80211HeaderPtr, SoftAP_Beacon, sizeof(SoftAP_Beacon));
IEEE80211Header.seqCtl.SequenceNumber = this->_softAPSequenceNumber;
*(u64 *)mgmtFrameBody = this->_usecCounter; // Timestamp
newRXPacket.rxHeader = WIFI_GenerateRXHeader(IEEE80211HeaderPtr, 1, true, sizeof(SoftAP_Beacon));
return newRXPacket;
}
// Create and open a PCAP file to store different Ethernet packets
// of the current connection.
void WifiCommInterface::PacketCaptureFileOpen()
@ -3579,7 +3602,7 @@ const u8* WifiCommInterface::RXPacketFilter(const u8 *rxBuffer, const size_t rxB
const u8 *packetBodyPtr = NULL;
memset(&outRXHeader, 0, sizeof(RXPacketHeader));
const DesmumeFrameHeader *desmumeFrameHeader = (DesmumeFrameHeader *)this->_workingRXBuffer;
const DesmumeFrameHeader *desmumeFrameHeader = (DesmumeFrameHeader *)rxBuffer;
size_t rxPacketSize = 0;
bool isTXRate20 = true;
@ -3589,7 +3612,7 @@ const u8* WifiCommInterface::RXPacketFilter(const u8 *rxBuffer, const size_t rxB
{
case 0x10:
{
packetIEEE80211HeaderPtr = this->_workingRXBuffer + sizeof(DesmumeFrameHeader);
packetIEEE80211HeaderPtr = rxBuffer + sizeof(DesmumeFrameHeader);
packetBodyPtr = packetIEEE80211HeaderPtr;
isTXRate20 = (desmumeFrameHeader->packetAttributes.IsTXRate20 != 0);
@ -3755,45 +3778,120 @@ const u8* WifiCommInterface::RXPacketFilter(const u8 *rxBuffer, const size_t rxB
return packetIEEE80211HeaderPtr;
}
void WifiCommInterface::RXPacketCopy(const RXPacketHeader &rxHeader, const u8 *rxBuffer)
void WifiCommInterface::RXWriteOneHalfword(u16 val)
{
WifiData &wifi = wifiHandler->GetWifiData();
WIFI_IOREG_MAP &io = wifi.io;
if (io.RXCNT.EnableRXFIFOQueuing != 0)
wifi.RAM[io.RXBUF_WRCSR.HalfwordAddress] = val;
io.RXBUF_WRCSR.HalfwordAddress++;
// wrap around
if (io.RXBUF_WRCSR.HalfwordAddress >= ((io.RXBUF_END & 0x1FFE) >> 1))
{
io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_BEGIN & 0x1FFE) >> 1);
}
io.RXTX_ADDR.HalfwordAddress = io.RXBUF_WRCSR.HalfwordAddress;
}
void WifiCommInterface::EmptyRXQueue()
{
this->_rxPacketQueue.clear();
this->_rxCurrentQueuedPacketPosition = 0;
}
void WifiCommInterface::Trigger()
{
WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io;
this->_usecCounter++;
if ( ((this->_usecCounter & 131071) == 0) && (io.RXCNT.EnableRXFIFOQueuing != 0) )
{
//zero sez: every 1/10 second? does it have to be precise? this is so costly..
// Okay for 128 ms then
RXQueuedPacket newRXPacket = this->_GenerateSoftAPBeaconFrame();
this->_rxPacketQueue.push_back(newRXPacket);
this->_softAPSequenceNumber++;
}
if (!this->_rxPacketQueue.empty() && (io.RXCNT.EnableRXFIFOQueuing != 0))
{
const RXQueuedPacket &rxPacket = this->_rxPacketQueue.front();
const size_t totalPacketLength = (sizeof(RXPacketHeader) + rxPacket.rxHeader.length > sizeof(RXQueuedPacket)) ? sizeof(RXQueuedPacket) : sizeof(RXPacketHeader) + rxPacket.rxHeader.length;
if (this->_rxCurrentQueuedPacketPosition == 0)
{
// Finally, we can copy the packet into WiFi RAM.
WIFI_triggerIRQ(WifiIRQ06_RXStart);
}
for (int i = 0; i < sizeof(RXPacketHeader); i+=2)
// If the user selects compatibility mode, then we will emulate the transfer delays
// involved with copying RX packet data into WiFi RAM. Otherwise, just copy all of
// the RX packet data into WiFi RAM immediately.
if (this->_emulationLevel == WifiEmulationLevel_Compatibility)
{
wifi.RAM[io.RXBUF_WRCSR.HalfwordAddress] = *(u16 *)&((u8 *)&rxHeader)[i];
io.RXBUF_WRCSR.HalfwordAddress++;
if (io.RXBUF_WRCSR.HalfwordAddress >= ((io.RXBUF_END & 0x1FFE) >> 1))
// Copy the RX packet data into WiFi RAM over time.
//
// Given a connection of 2 megabits per second, we take ~4 microseconds to transfer a byte.
// This works out to needing ~8 microseconds to transfer a halfword.
if ( (this->_rxCurrentQueuedPacketPosition == 0) || ((this->_usecCounter & 7) == 0) )
{
io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_BEGIN & 0x1FFE) >> 1);
this->RXWriteOneHalfword(*(u16 *)&rxPacket.rawFrameData[this->_rxCurrentQueuedPacketPosition]);
this->_rxCurrentQueuedPacketPosition += 2;
}
}
else
{
// Copy the entire RX packet data into WiFi RAM immediately.
while (this->_rxCurrentQueuedPacketPosition < totalPacketLength)
{
this->RXWriteOneHalfword(*(u16 *)&rxPacket.rawFrameData[this->_rxCurrentQueuedPacketPosition]);
this->_rxCurrentQueuedPacketPosition += 2;
}
}
for (int i = 0; i < rxHeader.length; i+=2)
if (this->_rxCurrentQueuedPacketPosition >= totalPacketLength)
{
wifi.RAM[io.RXBUF_WRCSR.HalfwordAddress] = *(u16 *)&rxBuffer[i];
io.RXBUF_WRCSR.HalfwordAddress++;
if (io.RXBUF_WRCSR.HalfwordAddress >= ((io.RXBUF_END & 0x1FFE) >> 1))
{
io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_BEGIN & 0x1FFE) >> 1);
}
}
this->_rxPacketQueue.pop_front();
this->_rxCurrentQueuedPacketPosition = 0;
// Adjust the RX cursor address so that it is 4-byte aligned.
io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_WRCSR.HalfwordAddress + 1) & 0x0FFE);
if (io.RXBUF_WRCSR.HalfwordAddress >= ((io.RXBUF_END & 0x1FFE) >> 1))
{
io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_BEGIN & 0x1FFE) >> 1);
}
io.RX_COUNT.OkayCount++;
WIFI_triggerIRQ(WifiIRQ00_RXComplete);
}
}
// 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->_usecCounter & 1023) == 0)
{
const size_t rxBytes = this->RXPacketGet(this->_workingRXBuffer);
if (rxBytes > 0)
{
RXQueuedPacket newRXPacket;
const u8 *packetIEEE80211HeaderPtr = this->RXPacketFilter(this->_workingRXBuffer, rxBytes, newRXPacket.rxHeader);
if (packetIEEE80211HeaderPtr == NULL)
{
return;
}
memcpy(newRXPacket.rxData, packetIEEE80211HeaderPtr, newRXPacket.rxHeader.length);
this->_rxPacketQueue.push_back(newRXPacket);
this->_softAPSequenceNumber++;
}
}
}
AdhocCommInterface::AdhocCommInterface()
{
_commInterfaceID = WifiCommInterfaceID_AdHoc;
@ -3819,6 +3917,8 @@ bool AdhocCommInterface::Start(WifiEmulationLevel emulationLevel)
this->_usecCounter = 0;
this->EmptyRXQueue();
// 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)
@ -3891,6 +3991,7 @@ bool AdhocCommInterface::Start(WifiEmulationLevel emulationLevel)
// Allocate 16KB worth of memory per buffer for sending packets. Hopefully, this should be plenty.
this->_workingTXBuffer = (u8 *)malloc(WIFI_WORKING_PACKET_BUFFER_SIZE);
this->_workingRXBuffer = (u8 *)malloc(WIFI_WORKING_PACKET_BUFFER_SIZE);
this->_softAPSequenceNumber = 0;
this->_emulationLevel = emulationLevel;
WIFI_LOG(1, "Ad-hoc: Initialization successful.\n");
@ -3987,41 +4088,12 @@ size_t AdhocCommInterface::RXPacketGet(u8 *rxTargetBuffer)
return rxPacketSize;
}
void AdhocCommInterface::Trigger()
{
this->_usecCounter++;
// Check every millisecond if we received a packet
if (!(this->_usecCounter & 1023))
{
const size_t rxBytes = this->RXPacketGet(this->_workingRXBuffer);
if (rxBytes > 0)
{
RXPacketHeader rxHeader;
const u8 *packetIEEE80211HeaderPtr = this->RXPacketFilter(this->_workingRXBuffer, rxBytes, rxHeader);
if (packetIEEE80211HeaderPtr == NULL)
{
return;
}
this->RXPacketCopy(rxHeader, packetIEEE80211HeaderPtr);
}
}
}
SoftAPCommInterface::SoftAPCommInterface()
{
_commInterfaceID = WifiCommInterfaceID_Infrastructure;
_pcap = &dummyPCapInterface;
_bridgeDeviceIndex = 0;
_bridgeDevice = NULL;
memset(_curPacket, 0, sizeof(_curPacket));
_curPacketSize = 0;
_curPacketPos = 0;
_curPacketSending = false;
_status = APStatus_Disconnected;
_seqNum = 0;
}
SoftAPCommInterface::~SoftAPCommInterface()
@ -4110,56 +4182,6 @@ bool SoftAPCommInterface::_IsDNSRequestToWFC(u16 ethertype, const u8 *body)
return false;
}
void SoftAPCommInterface::_Deauthenticate()
{
u8 *IEEE80211HeaderPtr = this->_curPacket + sizeof(RXPacketHeader);
WifiMgmtFrameHeader &IEEE80211Header = (WifiMgmtFrameHeader &)IEEE80211HeaderPtr[0];
memcpy(IEEE80211HeaderPtr, SoftAP_DeauthFrame, sizeof(SoftAP_DeauthFrame));
IEEE80211Header.destMAC[0] = FW_Mac[0];
IEEE80211Header.destMAC[1] = FW_Mac[1];
IEEE80211Header.destMAC[2] = FW_Mac[2];
IEEE80211Header.destMAC[3] = FW_Mac[3];
IEEE80211Header.destMAC[4] = FW_Mac[4];
IEEE80211Header.destMAC[5] = FW_Mac[5];
IEEE80211Header.seqCtl.SequenceNumber = this->_seqNum;
this->_seqNum++;
RXPacketHeader &rxHeader = (RXPacketHeader &)this->_curPacket[0];
rxHeader = WIFI_GenerateRXHeader(IEEE80211HeaderPtr, 1, true, sizeof(SoftAP_DeauthFrame));
// Let's prepare to send
this->_curPacketSize = sizeof(RXPacketHeader) + sizeof(SoftAP_DeauthFrame);
this->_curPacketPos = 0;
this->_curPacketSending = true;
this->_status = APStatus_Disconnected;
}
void SoftAPCommInterface::_SendBeacon()
{
u8 *IEEE80211HeaderPtr = this->_curPacket + sizeof(RXPacketHeader);
u8 *mgmtFrameBody = IEEE80211HeaderPtr + sizeof(WifiMgmtFrameHeader);
WifiMgmtFrameHeader &IEEE80211Header = (WifiMgmtFrameHeader &)IEEE80211HeaderPtr[0];
memcpy(IEEE80211HeaderPtr, SoftAP_Beacon, sizeof(SoftAP_Beacon));
IEEE80211Header.seqCtl.SequenceNumber = this->_seqNum;
this->_seqNum++;
*(u64 *)mgmtFrameBody = this->_usecCounter; // Timestamp
RXPacketHeader &rxHeader = (RXPacketHeader &)this->_curPacket[0];
rxHeader = WIFI_GenerateRXHeader(IEEE80211HeaderPtr, 1, true, sizeof(SoftAP_Beacon));
// Let's prepare to send
this->_curPacketSize = sizeof(RXPacketHeader) + sizeof(SoftAP_Beacon);
this->_curPacketPos = 0;
this->_curPacketSending = true;
}
void SoftAPCommInterface::SetPCapInterface(ClientPCapInterface *pcapInterface)
{
this->_pcap = (pcapInterface == NULL) ? &dummyPCapInterface : pcapInterface;
@ -4188,17 +4210,14 @@ bool SoftAPCommInterface::Start(WifiEmulationLevel emulationLevel)
this->_usecCounter = 0;
memset(this->_curPacket, 0, sizeof(this->_curPacket));
this->_curPacketSize = 0;
this->_curPacketPos = 0;
this->_curPacketSending = false;
this->EmptyRXQueue();
// Allocate 16KB worth of memory per buffer for sending packets. Hopefully, this should be plenty.
this->_workingTXBuffer = (u8 *)malloc(WIFI_WORKING_PACKET_BUFFER_SIZE);
this->_workingRXBuffer = (u8 *)malloc(WIFI_WORKING_PACKET_BUFFER_SIZE);
this->_status = APStatus_Disconnected;
this->_seqNum = 0;
this->_softAPStatus = APStatus_Disconnected;
this->_softAPSequenceNumber = 0;
if (isPCapSupported && (emulationLevel != WifiEmulationLevel_Off))
{
@ -4252,6 +4271,8 @@ void SoftAPCommInterface::Stop()
this->_bridgeDevice = NULL;
}
this->EmptyRXQueue();
free(this->_workingTXBuffer);
this->_workingTXBuffer = NULL;
@ -4279,8 +4300,10 @@ void SoftAPCommInterface::SendPacket(const TXPacketHeader &txHeader, const u8 *p
{
case WifiFrameType_Management:
{
RXQueuedPacket newRXPacket;
size_t packetLen = 0;
u8 *IEEE80211FrameHeaderPtr = this->_curPacket + sizeof(RXPacketHeader);
u8 *IEEE80211FrameHeaderPtr = newRXPacket.rxData;
u8 *mgmtFrameBody = IEEE80211FrameHeaderPtr + sizeof(WifiMgmtFrameHeader);
WifiMgmtFrameHeader &mgmtFrameHeader = (WifiMgmtFrameHeader &)IEEE80211FrameHeaderPtr[0];
@ -4303,14 +4326,14 @@ void SoftAPCommInterface::SendPacket(const TXPacketHeader &txHeader, const u8 *p
{
packetLen = sizeof(SoftAP_AuthFrame);
memcpy(IEEE80211FrameHeaderPtr, SoftAP_AuthFrame, packetLen);
this->_status = APStatus_Authenticated;
this->_softAPStatus = APStatus_Authenticated;
break;
}
case WifiFrameManagementSubtype_AssociationRequest:
{
if (this->_status != APStatus_Authenticated)
if (this->_softAPStatus != APStatus_Authenticated)
{
return;
}
@ -4318,7 +4341,7 @@ void SoftAPCommInterface::SendPacket(const TXPacketHeader &txHeader, const u8 *p
packetLen = sizeof(SoftAP_AssocResponse);
memcpy(IEEE80211FrameHeaderPtr, SoftAP_AssocResponse, packetLen);
this->_status = APStatus_Associated;
this->_softAPStatus = APStatus_Associated;
WIFI_LOG(1, "SoftAP connected!\n");
#if WIFI_SAVE_PCAP_TO_FILE
this->PacketCaptureFileOpen();
@ -4328,7 +4351,7 @@ void SoftAPCommInterface::SendPacket(const TXPacketHeader &txHeader, const u8 *p
case WifiFrameManagementSubtype_Disassociation:
{
this->_status = APStatus_Authenticated;
this->_softAPStatus = APStatus_Authenticated;
const u16 reasonCode = *(u16 *)mgmtFrameBody;
if (reasonCode != 0)
@ -4342,7 +4365,7 @@ void SoftAPCommInterface::SendPacket(const TXPacketHeader &txHeader, const u8 *p
{
const u16 reasonCode = *(u16 *)mgmtFrameBody;
this->_status = APStatus_Disconnected;
this->_softAPStatus = APStatus_Disconnected;
WIFI_LOG(1, "SoftAP disconnected. ReasonCode=%d\n", (int)reasonCode);
this->PacketCaptureFileClose();
return;
@ -4360,17 +4383,12 @@ void SoftAPCommInterface::SendPacket(const TXPacketHeader &txHeader, const u8 *p
mgmtFrameHeader.destMAC[4] = FW_Mac[4];
mgmtFrameHeader.destMAC[5] = FW_Mac[5];
mgmtFrameHeader.seqCtl.SequenceNumber = this->_seqNum;
this->_seqNum++;
mgmtFrameHeader.seqCtl.SequenceNumber = this->_softAPSequenceNumber;
RXPacketHeader &rxHeader = (RXPacketHeader &)this->_curPacket[0];
rxHeader = WIFI_GenerateRXHeader(this->_curPacket + sizeof(RXPacketHeader), 1, true, packetLen);
// Let's prepare to send
this->_curPacketSize = sizeof(RXPacketHeader) + packetLen;
this->_curPacketPos = 0;
this->_curPacketSending = true;
newRXPacket.rxHeader = WIFI_GenerateRXHeader(IEEE80211FrameHeaderPtr, 1, true, packetLen);
this->_rxPacketQueue.push_back(newRXPacket);
this->_softAPSequenceNumber++;
break;
}
@ -4381,13 +4399,13 @@ void SoftAPCommInterface::SendPacket(const TXPacketHeader &txHeader, const u8 *p
{
const WifiDataFrameHeaderSTA2DS &IEEE80211FrameHeader = (WifiDataFrameHeaderSTA2DS &)packetData[0];
// If it has an LLC/SNAP header, send it over the Ethernet.
// If it has an LLC/SNAP header, then send it over Ethernet.
if ( WIFI_IsLLCSNAPHeader(packetData + sizeof(WifiDataFrameHeaderSTA2DS)) )
{
const WifiLLCSNAPHeader &snapHeader = (WifiLLCSNAPHeader &)packetData[sizeof(WifiDataFrameHeaderSTA2DS)];
const u8 *inFrameBody = packetData + sizeof(WifiDataFrameHeaderSTA2DS) + sizeof(WifiLLCSNAPHeader);
if (this->_status != APStatus_Associated)
if (this->_softAPStatus != APStatus_Associated)
{
return;
}
@ -4395,7 +4413,10 @@ void SoftAPCommInterface::SendPacket(const TXPacketHeader &txHeader, const u8 *p
if (this->_IsDNSRequestToWFC(snapHeader.ethertype, inFrameBody))
{
// Removed to allow WFC communication.
//SoftAP_Deauthenticate();
//RXQueuedPacket rxPacket = this->_GenerateSoftAPDeauthenticationFrame();
//this->_rxPacketQueue.push_back(rxPacket);
//this->_softAPSequenceNumber++;
//this->_softAPStatus = APStatus_Disconnected;
//return;
}
@ -4443,7 +4464,7 @@ void SoftAPCommInterface::SendPacket(const TXPacketHeader &txHeader, const u8 *p
size_t SoftAPCommInterface::RXPacketGet(u8 *rxTargetBuffer)
{
size_t rxPacketSize = 0;
if (rxTargetBuffer == NULL)
if ( (this->_bridgeDevice == NULL) || (rxTargetBuffer == NULL) )
{
return rxPacketSize;
}
@ -4463,7 +4484,7 @@ size_t SoftAPCommInterface::RXPacketGet(u8 *rxTargetBuffer)
// Update the sequence number.
WifiDataFrameHeaderDS2STA &IEEE80211Header = (WifiDataFrameHeaderDS2STA &)rxTargetBuffer[sizeof(DesmumeFrameHeader)];
IEEE80211Header.seqCtl.SequenceNumber = this->_seqNum;
IEEE80211Header.seqCtl.SequenceNumber = this->_softAPSequenceNumber;
// Write the FCS at the end of the frame.
u32 &fcs = (u32 &)rxTargetBuffer[sizeof(DesmumeFrameHeader) + emulatorHeader.emuPacketSize];
@ -4473,85 +4494,6 @@ size_t SoftAPCommInterface::RXPacketGet(u8 *rxTargetBuffer)
return rxPacketSize + sizeof(DesmumeFrameHeader);
}
void SoftAPCommInterface::Trigger()
{
WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io;
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(WifiIRQ06_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;
// Adjust the RX cursor address so that it is 4-byte aligned.
io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_WRCSR.HalfwordAddress + 1) & 0x0FFE);
WIFI_triggerIRQ(WifiIRQ00_RXComplete);
}
}
// 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)
{
const size_t rxBytes = this->RXPacketGet(this->_workingRXBuffer);
if (rxBytes > 0)
{
RXPacketHeader rxHeader;
const u8 *packetIEEE80211HeaderPtr = this->RXPacketFilter(this->_workingRXBuffer, rxBytes, rxHeader);
if (packetIEEE80211HeaderPtr == NULL)
{
return;
}
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], io.RXBUF_WRCSR.HalfwordAddress<<1);
}
this->RXPacketCopy(rxHeader, packetIEEE80211HeaderPtr);
this->_seqNum++;
}
}
}
}
WifiHandler::WifiHandler()
{
_selectedEmulationLevel = WifiEmulationLevel_Off;
@ -4856,6 +4798,14 @@ void WifiHandler::CommTrigger()
}
}
void WifiHandler::CommEmptyRXQueue()
{
if (this->_currentCommInterface != NULL)
{
this->_currentCommInterface->EmptyRXQueue();
}
}
bool WifiHandler::IsPCapSupported()
{
return ((this->_pcap != NULL) && (this->_pcap != &dummyPCapInterface));

View File

@ -26,6 +26,7 @@
#include <stdio.h>
#include "types.h"
#include <deque>
#include <string>
#include <vector>
@ -3139,6 +3140,24 @@ typedef struct
u8 rssiMin;
} RXPacketHeader;
// The maximum possible size of any 802.11 frame is 2346 bytes:
// - Max MTU is 2304 bytes
// - Max 802.11 header size is 30 bytes
// - WEP Encryption Header size is 8 bytes
// - FCS size is 4 bytes
#define MAX_PACKET_SIZE_80211 2346
typedef union
{
u8 rawFrameData[sizeof(RXPacketHeader) + MAX_PACKET_SIZE_80211];
struct
{
RXPacketHeader rxHeader;
u8 rxData[MAX_PACKET_SIZE_80211];
};
} RXQueuedPacket;
extern LegacyWifiSFormat legacyWifiSF;
/* wifimac io */
@ -3229,8 +3248,17 @@ protected:
u8 *_workingTXBuffer;
u8 *_workingRXBuffer;
std::deque<RXQueuedPacket> _rxPacketQueue;
size_t _rxCurrentQueuedPacketPosition;
EAPStatus _softAPStatus;
u16 _softAPSequenceNumber;
FILE *_packetCaptureFile; // PCAP file to store the Ethernet packets.
RXQueuedPacket _GenerateSoftAPDeauthenticationFrame();
RXQueuedPacket _GenerateSoftAPBeaconFrame();
public:
WifiCommInterface();
virtual ~WifiCommInterface();
@ -3240,13 +3268,15 @@ public:
void PacketCaptureFileWrite(const u8 *packet, u32 len, bool isReceived);
const u8* RXPacketFilter(const u8 *rxBuffer, const size_t rxBytes, RXPacketHeader &outRXHeader);
void RXPacketCopy(const RXPacketHeader &rxHeader, const u8 *rxBuffer);
void RXWriteOneHalfword(u16 val);
void EmptyRXQueue();
virtual bool Start(WifiEmulationLevel emulationLevel) = 0;
virtual void Stop() = 0;
virtual void SendPacket(const TXPacketHeader &txHeader, const u8 *packetData) = 0;
virtual size_t RXPacketGet(u8 *rxTargetBuffer) = 0;
virtual void Trigger() = 0;
void Trigger();
};
class AdhocCommInterface : public WifiCommInterface
@ -3263,7 +3293,6 @@ public:
virtual void Stop();
virtual void SendPacket(const TXPacketHeader &txHeader, const u8 *packetData);
virtual size_t RXPacketGet(u8 *rxTargetBuffer);
virtual void Trigger();
};
class SoftAPCommInterface : public WifiCommInterface
@ -3273,18 +3302,8 @@ protected:
int _bridgeDeviceIndex;
void *_bridgeDevice;
u8 _curPacket[4096];
s32 _curPacketSize;
s32 _curPacketPos;
bool _curPacketSending;
EAPStatus _status;
u16 _seqNum;
void* _GetBridgeDeviceAtIndex(int deviceIndex, char *outErrorBuf);
bool _IsDNSRequestToWFC(u16 ethertype, const u8 *body);
void _Deauthenticate();
void _SendBeacon();
public:
SoftAPCommInterface();
@ -3300,7 +3319,6 @@ public:
virtual void Stop();
virtual void SendPacket(const TXPacketHeader &txHeader, const u8 *packetData);
virtual size_t RXPacketGet(u8 *rxTargetBuffer);
virtual void Trigger();
};
class WifiHandler
@ -3358,6 +3376,7 @@ public:
void CommStop();
void CommSendPacket(const TXPacketHeader &txHeader, const u8 *packetData);
void CommTrigger();
void CommEmptyRXQueue();
bool IsSocketsSupported();
void SetSocketsSupported(bool isSupported);