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:
SlEePlEs5 2014-04-12 01:38:22 +02:00
parent b106dbc96e
commit 891fb056a3
3 changed files with 80 additions and 8 deletions

View file

@ -2,38 +2,110 @@
// Licensed under GPLv2
// Refer to the license.txt file included.
#include "Common/StringUtil.h"
#include "Core/HW/EXI_Device.h"
#include "Core/HW/EXI_DeviceEthernet.h"
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()
{
close(fd);
fd = -1;
readEnabled = false;
if (readThread.joinable())
readThread.join();
}
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()
{
return false;
readThread = std::thread(ReadThreadHandler, this);
return true;
}
bool CEXIETHERNET::RecvStart()
{
return false;
if (!readThread.joinable())
RecvInit();
readEnabled = true;
return true;
}
void CEXIETHERNET::RecvStop()
{
readEnabled = false;
}

View file

@ -44,7 +44,7 @@ CEXIETHERNET::CEXIETHERNET()
mHAdapter = INVALID_HANDLE_VALUE;
mHRecvEvent = INVALID_HANDLE_VALUE;
mHReadWait = INVALID_HANDLE_VALUE;
#elif defined(__linux__)
#elif defined(__linux__) || defined(__APPLE__)
fd = -1;
#endif
}

View file

@ -319,7 +319,7 @@ public:
DWORD mMtu;
OVERLAPPED mReadOverlapped;
static VOID CALLBACK ReadWaitCallback(PVOID lpParameter, BOOLEAN TimerFired);
#elif defined(__linux__)
#elif defined(__linux__) || defined(__APPLE__)
int fd;
std::thread readThread;
volatile bool readEnabled;