mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-28 16:49:58 -06:00
Slight cleanup in the main file. Win32 tries sending the packet, but fails with error 0x57 or 0x6 in WriteFile function, depending on how I have it set up. Linux sends out the packet, or at least it says it sends it out. Requires root priv in Linux and openVPN installed to use the /dev/net/tun device.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3217 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -20,23 +20,81 @@
|
|||||||
#include "../EXI_DeviceEthernet.h"
|
#include "../EXI_DeviceEthernet.h"
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <stropts.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <linux/if_tun.h>
|
||||||
|
int fd = -1;
|
||||||
bool CEXIETHERNET::deactivate()
|
bool CEXIETHERNET::deactivate()
|
||||||
{
|
{
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
return true;
|
return true;
|
||||||
// TODO: Actually deactivate
|
|
||||||
}
|
}
|
||||||
bool CEXIETHERNET::isActivated()
|
bool CEXIETHERNET::isActivated()
|
||||||
{
|
{
|
||||||
return false;
|
return fd != -1 ? true : false;
|
||||||
//TODO: Never Activated Yet!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEXIETHERNET::activate() {
|
bool CEXIETHERNET::activate() {
|
||||||
if(isActivated())
|
if(isActivated())
|
||||||
return true;
|
return true;
|
||||||
else
|
if( (fd = open("/dev/net/tun", O_RDWR)) < 0)
|
||||||
|
{
|
||||||
|
DEBUGPRINT("Couldn't Open device\n");
|
||||||
return false;
|
return false;
|
||||||
//TODO: Activate Device!
|
}
|
||||||
|
struct ifreq ifr;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
ifr.ifr_flags = IFF_TAP;
|
||||||
|
|
||||||
|
strncpy(ifr.ifr_name, "Dolphin", IFNAMSIZ);
|
||||||
|
|
||||||
|
if( (err = ioctl(fd, TUNSETIFF, (void*) &ifr)) < 0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
DEBUGPRINT(" Error with IOCTL: 0x%X\n", err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DEBUGPRINT("Returned Socket name is: %s\n", ifr.ifr_name);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
bool CEXIETHERNET::startRecv() {
|
||||||
|
DEBUGPRINT("Start Receive!\n");
|
||||||
|
exit(0);
|
||||||
|
/*if(!isActivated())
|
||||||
|
return false;// Should actually be an assert
|
||||||
|
DEBUGPRINT("startRecv... ");
|
||||||
|
if(mWaiting) {
|
||||||
|
DEBUGPRINT("already waiting\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
DWORD BytesRead = 0;
|
||||||
|
DWORD *Buffer = (DWORD *)malloc(2048); // Should be enough
|
||||||
|
DWORD res = ReadFile(mHAdapter, Buffer, BytesRead,
|
||||||
|
&mRecvBufferLength, &mReadOverlapped);
|
||||||
|
mRecvBuffer.write(BytesRead, Buffer);
|
||||||
|
free(Buffer);
|
||||||
|
if(res) { //Operation completed immediately
|
||||||
|
DEBUGPRINT("completed, res %i\n", res);
|
||||||
|
mWaiting = true;
|
||||||
|
} else {
|
||||||
|
res = GetLastError();
|
||||||
|
if (res == ERROR_IO_PENDING) { //'s ok :)
|
||||||
|
DEBUGPRINT("pending\n");
|
||||||
|
//WaitCallback will be called
|
||||||
|
mWaiting = true;
|
||||||
|
} else { //error occurred
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;*/
|
||||||
}
|
}
|
||||||
bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size)
|
bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size)
|
||||||
{
|
{
|
||||||
@ -46,18 +104,14 @@ bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size)
|
|||||||
DEBUGPRINT( "%02X", etherpckt[a]);
|
DEBUGPRINT( "%02X", etherpckt[a]);
|
||||||
}
|
}
|
||||||
DEBUGPRINT( " : Size: %d\n", size);
|
DEBUGPRINT( " : Size: %d\n", size);
|
||||||
int raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
|
int numBytesWrit = write(fd, etherpckt, size);
|
||||||
DEBUGPRINT("Raw socket is : %d\n", raw_socket);
|
|
||||||
int sm=1;
|
|
||||||
const int *val=&sm;
|
|
||||||
int result = setsockopt(raw_socket, IPPROTO_IP, IP_HDRINCL, val, sizeof(sm));
|
|
||||||
DEBUGPRINT("Result is : %d\n", result);
|
|
||||||
int numBytesWrit = write(raw_socket, etherpckt, size);
|
|
||||||
if(numBytesWrit != size)
|
if(numBytesWrit != size)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("BBA sendPacket %i only got %i bytes sent!\n", size, numBytesWrit);
|
DEBUGPRINT("BBA sendPacket %i only got %i bytes sent!\n", size, numBytesWrit);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
DEBUGPRINT("Sent out the correct number of bytes: %d\n", size);
|
||||||
//fwrite(etherpckt, size, size, raw_socket);
|
//fwrite(etherpckt, size, size, raw_socket);
|
||||||
/*DWORD numBytesWrit;
|
/*DWORD numBytesWrit;
|
||||||
OVERLAPPED overlap;
|
OVERLAPPED overlap;
|
||||||
|
@ -137,8 +137,12 @@ bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size)
|
|||||||
DWORD numBytesWrit;
|
DWORD numBytesWrit;
|
||||||
OVERLAPPED overlap;
|
OVERLAPPED overlap;
|
||||||
//ZERO_OBJECT(overlap);
|
//ZERO_OBJECT(overlap);
|
||||||
//overlap.hEvent = mHRecvEvent;
|
overlap.hEvent = mHRecvEvent;
|
||||||
WriteFile(mHAdapter, etherpckt, size, &numBytesWrit, &overlap);
|
if(!WriteFile(mHAdapter, etherpckt, size, &numBytesWrit, &overlap))
|
||||||
|
{ // Fail Boat
|
||||||
|
DWORD res = GetLastError();
|
||||||
|
DEBUGPRINT("Failed to send packet with error 0x%X\n", res);
|
||||||
|
}
|
||||||
if(numBytesWrit != size)
|
if(numBytesWrit != size)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("BBA sendPacket %i only got %i bytes sent!\n", size, numBytesWrit);
|
DEBUGPRINT("BBA sendPacket %i only got %i bytes sent!\n", size, numBytesWrit);
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include "EXI_Device.h"
|
#include "EXI_Device.h"
|
||||||
#include "EXI_DeviceEthernet.h"
|
#include "EXI_DeviceEthernet.h"
|
||||||
|
|
||||||
//#define SONICDEBUG
|
#define SONICDEBUG
|
||||||
|
|
||||||
void DEBUGPRINT (const char * format, ...)
|
void DEBUGPRINT (const char * format, ...)
|
||||||
{
|
{
|
||||||
@ -95,7 +95,6 @@ CEXIETHERNET::CEXIETHERNET() :
|
|||||||
|
|
||||||
Expecting = EXPECT_NONE;
|
Expecting = EXPECT_NONE;
|
||||||
mExpectVariableLengthImmWrite = false;
|
mExpectVariableLengthImmWrite = false;
|
||||||
mBbaMem[BBA_NWAYS] = (BBA_NWAYS_LS10 | BBA_NWAYS_LPNWAY | BBA_NWAYS_ANCLPT | BBA_NWAYS_10TXF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIETHERNET::SetCS(int cs)
|
void CEXIETHERNET::SetCS(int cs)
|
||||||
@ -130,10 +129,10 @@ bool CEXIETHERNET::IsInterruptSet()
|
|||||||
|
|
||||||
void CEXIETHERNET::recordSendComplete()
|
void CEXIETHERNET::recordSendComplete()
|
||||||
{
|
{
|
||||||
mBbaMem[0x00] &= ~0x06;
|
mBbaMem[BBA_NCRA] &= ~0x06;
|
||||||
if(mBbaMem[0x08] & BBA_INTERRUPT_SENT)
|
if(mBbaMem[0x08] & BBA_INTERRUPT_SENT)
|
||||||
{
|
{
|
||||||
mBbaMem[0x09] |= BBA_INTERRUPT_SENT;
|
mBbaMem[BBA_IR] |= BBA_INTERRUPT_SENT;
|
||||||
DEBUGPRINT( "\t\tBBA Send interrupt raised\n");
|
DEBUGPRINT( "\t\tBBA Send interrupt raised\n");
|
||||||
//exit(0);
|
//exit(0);
|
||||||
m_bInterruptSet = true;
|
m_bInterruptSet = true;
|
||||||
@ -155,6 +154,8 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
|
|||||||
DEBUGPRINT( "IMM Write, size 0x%x, data 0x%x mWriteP 0x%x\n", _uSize, _uData, mWriteP);
|
DEBUGPRINT( "IMM Write, size 0x%x, data 0x%x mWriteP 0x%x\n", _uSize, _uData, mWriteP);
|
||||||
if (mExpectVariableLengthImmWrite)
|
if (mExpectVariableLengthImmWrite)
|
||||||
{
|
{
|
||||||
|
DEBUGPRINT("Variable Length IMM Write: Size: %d _uData: 0x%08X swapped: 0x%08X\n", _uSize, _uData, Common::swap32(_uData));
|
||||||
|
// TODO: Use Swapped or unswapped?
|
||||||
if(_uSize == 4)
|
if(_uSize == 4)
|
||||||
{
|
{
|
||||||
_uData = Common::swap32(_uData);
|
_uData = Common::swap32(_uData);
|
||||||
@ -218,16 +219,15 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
|
|||||||
exit(0);
|
exit(0);
|
||||||
//throw hardware_fatal_exception("BBA Transmit without a packet!");
|
//throw hardware_fatal_exception("BBA Transmit without a packet!");
|
||||||
}
|
}
|
||||||
// TODO: Actually Make it send a packet
|
|
||||||
sendPacket(mWriteBuffer.p(), mWriteBuffer.size());
|
sendPacket(mWriteBuffer.p(), mWriteBuffer.size());
|
||||||
mReadyToSend = false;
|
mReadyToSend = false;
|
||||||
//exit(0);
|
//exit(0);
|
||||||
}
|
}
|
||||||
mBbaMem[0x00] = MAKE(u8, SwappedData);
|
mBbaMem[BBA_NCRA] = MAKE(u8, SwappedData);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BBA_NWAYC:
|
case BBA_NWAYC:
|
||||||
DEBUGPRINT( "\t[INFO]BBA_NWAYCn");
|
DEBUGPRINT( "\t[INFO]BBA_NWAYC\n");
|
||||||
if(Common::swap32(_uData) & (BBA_NWAYC_ANE | BBA_NWAYC_ANS_RA))
|
if(Common::swap32(_uData) & (BBA_NWAYC_ANE | BBA_NWAYC_ANS_RA))
|
||||||
{
|
{
|
||||||
DEBUGPRINT("ACTIVATING!\n");
|
DEBUGPRINT("ACTIVATING!\n");
|
||||||
@ -242,7 +242,7 @@ void CEXIETHERNET::ImmWrite(u32 _uData, u32 _uSize)
|
|||||||
//exit(0);
|
//exit(0);
|
||||||
assert(_uSize == 2 || _uSize == 1);
|
assert(_uSize == 2 || _uSize == 1);
|
||||||
mRBRPP = (u8)_uData << 8; //Whinecube: I hope this works with both write sizes.
|
mRBRPP = (u8)_uData << 8; //Whinecube: I hope this works with both write sizes.
|
||||||
mRBEmpty = mRBRPP == ((u32)mCbw.p_write() + CB_OFFSET);
|
mRBEmpty = (mRBRPP == ((u32)mCbw.p_write() + CB_OFFSET));
|
||||||
checkRecvBuffer();
|
checkRecvBuffer();
|
||||||
break;
|
break;
|
||||||
case BBA_RWP: //RWP - Receive Buffer Write Page Pointer
|
case BBA_RWP: //RWP - Receive Buffer Write Page Pointer
|
||||||
@ -388,8 +388,6 @@ u32 CEXIETHERNET::ImmRead(u32 _uSize)
|
|||||||
}
|
}
|
||||||
u32 uResult = 0;
|
u32 uResult = 0;
|
||||||
memcpy(&uResult, mBbaMem + mReadP, _uSize);
|
memcpy(&uResult, mBbaMem + mReadP, _uSize);
|
||||||
if(mReadP == 0x31)
|
|
||||||
uResult = (BBA_NWAYS_LS10 | BBA_NWAYS_LPNWAY |BBA_NWAYS_ANCLPT | BBA_NWAYS_10TXF);
|
|
||||||
// TODO: We do as well?
|
// TODO: We do as well?
|
||||||
uResult = Common::swap32(uResult); //Whinecube : we have a byteswap problem...
|
uResult = Common::swap32(uResult); //Whinecube : we have a byteswap problem...
|
||||||
|
|
||||||
@ -410,7 +408,7 @@ void CEXIETHERNET::DMAWrite(u32 _uAddr, u32 _uSize)
|
|||||||
{
|
{
|
||||||
if(mExpectVariableLengthImmWrite)
|
if(mExpectVariableLengthImmWrite)
|
||||||
{
|
{
|
||||||
DEBUGPRINT("Address is 0x%x and size is 0x%x\n", _uAddr, _uSize);
|
DEBUGPRINT("DMA Write: Address is 0x%x and size is 0x%x\n", _uAddr, _uSize);
|
||||||
mWriteBuffer.write(_uSize, Memory::GetPointer(_uAddr));
|
mWriteBuffer.write(_uSize, Memory::GetPointer(_uAddr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -123,13 +123,14 @@ private:
|
|||||||
bool isActivated();
|
bool isActivated();
|
||||||
bool resume();
|
bool resume();
|
||||||
bool startRecv();
|
bool startRecv();
|
||||||
|
|
||||||
|
volatile bool mWaiting;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HANDLE mHAdapter, mHRecvEvent, mHReadWait;
|
HANDLE mHAdapter, mHRecvEvent, mHReadWait;
|
||||||
DWORD mMtu;
|
DWORD mMtu;
|
||||||
OVERLAPPED mReadOverlapped;
|
OVERLAPPED mReadOverlapped;
|
||||||
WriteBuffer mRecvBuffer;
|
WriteBuffer mRecvBuffer;
|
||||||
DWORD mRecvBufferLength;
|
DWORD mRecvBufferLength;
|
||||||
volatile bool mWaiting;
|
|
||||||
static VOID CALLBACK ReadWaitCallback(PVOID lpParameter, BOOLEAN TimerFired);
|
static VOID CALLBACK ReadWaitCallback(PVOID lpParameter, BOOLEAN TimerFired);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user