Added BBA TAP backend for OS X.
TUN/TAP OS X needs to be installed, and /dev/tap0 chown’d to the user. The tap0 network interface doesn’t appear until /dev/tap0 is opened by the program, so all bridging must be done once the game is already running. Unfortunately, bridging seems to be broken on OS X, so this does not actually work over LAN (yet!).
This commit is contained in:
parent
b106dbc96e
commit
891fb056a3
|
@ -2,38 +2,110 @@
|
||||||
// Licensed under GPLv2
|
// Licensed under GPLv2
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "Common/StringUtil.h"
|
||||||
#include "Core/HW/EXI_Device.h"
|
#include "Core/HW/EXI_Device.h"
|
||||||
#include "Core/HW/EXI_DeviceEthernet.h"
|
#include "Core/HW/EXI_DeviceEthernet.h"
|
||||||
|
|
||||||
bool CEXIETHERNET::Activate()
|
bool CEXIETHERNET::Activate()
|
||||||
{
|
{
|
||||||
return false;
|
if (IsActivated())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Assumes TunTap OS X is installed, and /dev/tun0 is not in use
|
||||||
|
// and readable / writable by the logged-in user
|
||||||
|
|
||||||
|
if ((fd = open("/dev/tap0", O_RDWR)) < 0)
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "Couldn't open /dev/tap0, unable to init BBA");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
readEnabled = false;
|
||||||
|
|
||||||
|
INFO_LOG(SP1, "BBA initialized.");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIETHERNET::Deactivate()
|
void CEXIETHERNET::Deactivate()
|
||||||
{
|
{
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
|
||||||
|
readEnabled = false;
|
||||||
|
if (readThread.joinable())
|
||||||
|
readThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEXIETHERNET::IsActivated()
|
bool CEXIETHERNET::IsActivated()
|
||||||
{
|
{
|
||||||
return false;
|
return fd != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEXIETHERNET::SendFrame(u8 *, u32)
|
bool CEXIETHERNET::SendFrame(u8* frame, u32 size)
|
||||||
{
|
{
|
||||||
return false;
|
INFO_LOG(SP1, "SendFrame %x\n%s", size, ArrayToString(frame, size, 0x10).c_str());
|
||||||
|
|
||||||
|
int writtenBytes = write(fd, frame, size);
|
||||||
|
if ((u32)writtenBytes != size)
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "SendFrame(): expected to write %d bytes, instead wrote %d",
|
||||||
|
size, writtenBytes);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendComplete();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadThreadHandler(CEXIETHERNET* self)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (self->fd < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fd_set rfds;
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(self->fd, &rfds);
|
||||||
|
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 50000;
|
||||||
|
if (select(self->fd + 1, &rfds, nullptr, nullptr, &timeout) <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int readBytes = read(self->fd, self->mRecvBuffer, BBA_RECV_SIZE);
|
||||||
|
if (readBytes < 0)
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "Failed to read from BBA, err=%d", readBytes);
|
||||||
|
}
|
||||||
|
else if (self->readEnabled)
|
||||||
|
{
|
||||||
|
INFO_LOG(SP1, "Read data: %s", ArrayToString(self->mRecvBuffer, readBytes, 0x10).c_str());
|
||||||
|
self->mRecvBufferLength = readBytes;
|
||||||
|
self->RecvHandlePacket();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEXIETHERNET::RecvInit()
|
bool CEXIETHERNET::RecvInit()
|
||||||
{
|
{
|
||||||
return false;
|
readThread = std::thread(ReadThreadHandler, this);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CEXIETHERNET::RecvStart()
|
bool CEXIETHERNET::RecvStart()
|
||||||
{
|
{
|
||||||
return false;
|
if (!readThread.joinable())
|
||||||
|
RecvInit();
|
||||||
|
|
||||||
|
readEnabled = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIETHERNET::RecvStop()
|
void CEXIETHERNET::RecvStop()
|
||||||
{
|
{
|
||||||
|
readEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ CEXIETHERNET::CEXIETHERNET()
|
||||||
mHAdapter = INVALID_HANDLE_VALUE;
|
mHAdapter = INVALID_HANDLE_VALUE;
|
||||||
mHRecvEvent = INVALID_HANDLE_VALUE;
|
mHRecvEvent = INVALID_HANDLE_VALUE;
|
||||||
mHReadWait = INVALID_HANDLE_VALUE;
|
mHReadWait = INVALID_HANDLE_VALUE;
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__) || defined(__APPLE__)
|
||||||
fd = -1;
|
fd = -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,7 +319,7 @@ public:
|
||||||
DWORD mMtu;
|
DWORD mMtu;
|
||||||
OVERLAPPED mReadOverlapped;
|
OVERLAPPED mReadOverlapped;
|
||||||
static VOID CALLBACK ReadWaitCallback(PVOID lpParameter, BOOLEAN TimerFired);
|
static VOID CALLBACK ReadWaitCallback(PVOID lpParameter, BOOLEAN TimerFired);
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__) || defined(__APPLE__)
|
||||||
int fd;
|
int fd;
|
||||||
std::thread readThread;
|
std::thread readThread;
|
||||||
volatile bool readEnabled;
|
volatile bool readEnabled;
|
||||||
|
|
Loading…
Reference in New Issue