mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-26 07:45:33 +01:00
Merge pull request #9117 from fuzziqersoftware/add-tapserver-bba
Add tapserver network interface for macOS since TunTap is now unmaintained
This commit is contained in:
commit
2feb5f204a
@ -623,6 +623,7 @@ if(WIN32)
|
|||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
target_sources(core PRIVATE
|
target_sources(core PRIVATE
|
||||||
HW/EXI/BBA/TAP_Apple.cpp
|
HW/EXI/BBA/TAP_Apple.cpp
|
||||||
|
HW/EXI/BBA/TAPServer_Apple.cpp
|
||||||
HW/EXI/BBA/XLINK_KAI_BBA.cpp
|
HW/EXI/BBA/XLINK_KAI_BBA.cpp
|
||||||
HW/WiimoteReal/IOdarwin.h
|
HW/WiimoteReal/IOdarwin.h
|
||||||
HW/WiimoteReal/IOdarwin_private.h
|
HW/WiimoteReal/IOdarwin_private.h
|
||||||
|
127
Source/Core/Core/HW/EXI/BBA/TAPServer_Apple.cpp
Normal file
127
Source/Core/Core/HW/EXI/BBA/TAPServer_Apple.cpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// Copyright 2020 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
|
#include "Common/StringUtil.h"
|
||||||
|
#include "Core/HW/EXI/EXI_Device.h"
|
||||||
|
#include "Core/HW/EXI/EXI_DeviceEthernet.h"
|
||||||
|
|
||||||
|
namespace ExpansionInterface
|
||||||
|
{
|
||||||
|
// This interface is only implemented on macOS, since macOS needs a replacement
|
||||||
|
// for TunTap when the kernel extension is no longer supported. This interface
|
||||||
|
// only appears in the menu on macOS, so on other platforms, it does nothing and
|
||||||
|
// refuses to activate.
|
||||||
|
|
||||||
|
constexpr char socket_path[] = "/tmp/dolphin-tap";
|
||||||
|
|
||||||
|
bool CEXIETHERNET::TAPServerNetworkInterface::Activate()
|
||||||
|
{
|
||||||
|
if (IsActivated())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
sockaddr_un sun = {};
|
||||||
|
if (sizeof(socket_path) > sizeof(sun.sun_path))
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "Socket path is too long, unable to init BBA");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sun.sun_family = AF_UNIX;
|
||||||
|
strcpy(sun.sun_path, socket_path);
|
||||||
|
|
||||||
|
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "Couldn't create socket, unable to init BBA");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connect(fd, reinterpret_cast<sockaddr*>(&sun), sizeof(sun)) == -1)
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "Couldn't connect socket (%d), unable to init BBA", errno);
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
INFO_LOG(SP1, "BBA initialized.\n");
|
||||||
|
return RecvInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CEXIETHERNET::TAPServerNetworkInterface::SendFrame(const u8* frame, u32 size)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const std::string s = ArrayToString(frame, size, 0x10);
|
||||||
|
INFO_LOG(SP1, "SendFrame %x\n%s\n", size, s.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto size16 = u16(size);
|
||||||
|
if (write(fd, &size16, 2) != 2)
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "SendFrame(): could not write size field\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int written_bytes = write(fd, frame, size);
|
||||||
|
if (u32(written_bytes) != size)
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "SendFrame(): expected to write %d bytes, instead wrote %d", size,
|
||||||
|
written_bytes);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_eth_ref->SendComplete();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEXIETHERNET::TAPServerNetworkInterface::ReadThreadHandler()
|
||||||
|
{
|
||||||
|
while (!readThreadShutdown.IsSet())
|
||||||
|
{
|
||||||
|
fd_set rfds;
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(fd, &rfds);
|
||||||
|
|
||||||
|
timeval timeout;
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 50000;
|
||||||
|
if (select(fd + 1, &rfds, nullptr, nullptr, &timeout) <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
u16 size;
|
||||||
|
if (read(fd, &size, 2) != 2)
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "Failed to read size field from BBA, err=%d", errno);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int read_bytes = read(fd, m_eth_ref->mRecvBuffer.get(), size);
|
||||||
|
if (read_bytes < 0)
|
||||||
|
{
|
||||||
|
ERROR_LOG(SP1, "Failed to read packet data from BBA, err=%d", errno);
|
||||||
|
}
|
||||||
|
else if (readEnabled.IsSet())
|
||||||
|
{
|
||||||
|
std::string data_string = ArrayToString(m_eth_ref->mRecvBuffer.get(), read_bytes, 0x10);
|
||||||
|
INFO_LOG(SP1, "Read data: %s", data_string.c_str());
|
||||||
|
m_eth_ref->mRecvBufferLength = read_bytes;
|
||||||
|
m_eth_ref->RecvHandlePacket();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CEXIETHERNET::TAPServerNetworkInterface::RecvInit()
|
||||||
|
{
|
||||||
|
readThread = std::thread(&CEXIETHERNET::TAPServerNetworkInterface::ReadThreadHandler, this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ExpansionInterface
|
@ -136,6 +136,12 @@ std::unique_ptr<IEXIDevice> EXIDevice_Create(const TEXIDevices device_type, cons
|
|||||||
result = std::make_unique<CEXIETHERNET>(BBADeviceType::TAP);
|
result = std::make_unique<CEXIETHERNET>(BBADeviceType::TAP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
case EXIDEVICE_ETHTAPSERVER:
|
||||||
|
result = std::make_unique<CEXIETHERNET>(BBADeviceType::TAPSERVER);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case EXIDEVICE_ETHXLINK:
|
case EXIDEVICE_ETHXLINK:
|
||||||
result = std::make_unique<CEXIETHERNET>(BBADeviceType::XLINK);
|
result = std::make_unique<CEXIETHERNET>(BBADeviceType::XLINK);
|
||||||
break;
|
break;
|
||||||
|
@ -33,6 +33,9 @@ enum TEXIDevices : int
|
|||||||
EXIDEVICE_MEMORYCARDFOLDER,
|
EXIDEVICE_MEMORYCARDFOLDER,
|
||||||
EXIDEVICE_AGP,
|
EXIDEVICE_AGP,
|
||||||
EXIDEVICE_ETHXLINK,
|
EXIDEVICE_ETHXLINK,
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
EXIDEVICE_ETHTAPSERVER,
|
||||||
|
#endif
|
||||||
EXIDEVICE_NONE = 0xFF
|
EXIDEVICE_NONE = 0xFF
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,6 +48,12 @@ CEXIETHERNET::CEXIETHERNET(BBADeviceType type)
|
|||||||
m_network_interface = std::make_unique<TAPNetworkInterface>(this);
|
m_network_interface = std::make_unique<TAPNetworkInterface>(this);
|
||||||
INFO_LOG_FMT(SP1, "Created TAP physical network interface.");
|
INFO_LOG_FMT(SP1, "Created TAP physical network interface.");
|
||||||
break;
|
break;
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
case BBADeviceType::TAPSERVER:
|
||||||
|
m_network_interface = std::make_unique<TAPServerNetworkInterface>(this);
|
||||||
|
INFO_LOG(SP1, "Created tapserver physical network interface.");
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case BBADeviceType::XLINK:
|
case BBADeviceType::XLINK:
|
||||||
// TODO start BBA with network link down, bring it up after "connected" response from XLink
|
// TODO start BBA with network link down, bring it up after "connected" response from XLink
|
||||||
|
|
||||||
|
@ -202,6 +202,9 @@ enum class BBADeviceType
|
|||||||
{
|
{
|
||||||
TAP,
|
TAP,
|
||||||
XLINK,
|
XLINK,
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
TAPSERVER,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class CEXIETHERNET : public IEXIDevice
|
class CEXIETHERNET : public IEXIDevice
|
||||||
@ -337,7 +340,7 @@ private:
|
|||||||
void RecvStart() override;
|
void RecvStart() override;
|
||||||
void RecvStop() override;
|
void RecvStop() override;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
#if defined(WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
#if defined(WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
|
||||||
defined(__OpenBSD__)
|
defined(__OpenBSD__)
|
||||||
std::thread readThread;
|
std::thread readThread;
|
||||||
@ -356,6 +359,22 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
class TAPServerNetworkInterface : public TAPNetworkInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TAPServerNetworkInterface(CEXIETHERNET* eth_ref) : TAPNetworkInterface(eth_ref) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool Activate() override;
|
||||||
|
bool SendFrame(const u8* frame, u32 size) override;
|
||||||
|
bool RecvInit() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ReadThreadHandler();
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class XLinkNetworkInterface : public NetworkInterface
|
class XLinkNetworkInterface : public NetworkInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -100,12 +100,16 @@ void GameCubePane::CreateWidgets()
|
|||||||
|
|
||||||
// Add SP1 devices
|
// Add SP1 devices
|
||||||
|
|
||||||
for (const auto& entry :
|
std::vector<std::pair<QString, ExpansionInterface::TEXIDevices>> sp1Entries{
|
||||||
{std::make_pair(tr("<Nothing>"), ExpansionInterface::EXIDEVICE_NONE),
|
std::make_pair(tr("<Nothing>"), ExpansionInterface::EXIDEVICE_NONE),
|
||||||
std::make_pair(tr("Dummy"), ExpansionInterface::EXIDEVICE_DUMMY),
|
std::make_pair(tr("Dummy"), ExpansionInterface::EXIDEVICE_DUMMY),
|
||||||
std::make_pair(tr("Broadband Adapter (TAP)"), ExpansionInterface::EXIDEVICE_ETH),
|
std::make_pair(tr("Broadband Adapter (TAP)"), ExpansionInterface::EXIDEVICE_ETH),
|
||||||
std::make_pair(tr("Broadband Adapter (XLink Kai)"),
|
std::make_pair(tr("Broadband Adapter (XLink Kai)"), ExpansionInterface::EXIDEVICE_ETHXLINK)};
|
||||||
ExpansionInterface::EXIDEVICE_ETHXLINK)})
|
#if defined(__APPLE__)
|
||||||
|
sp1Entries.emplace_back(std::make_pair(tr("Broadband Adapter (tapserver)"),
|
||||||
|
ExpansionInterface::EXIDEVICE_ETHTAPSERVER));
|
||||||
|
#endif
|
||||||
|
for (const auto& entry : sp1Entries)
|
||||||
{
|
{
|
||||||
m_slot_combos[2]->addItem(entry.first, entry.second);
|
m_slot_combos[2]->addItem(entry.first, entry.second);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user