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
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue