mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Merge pull request #13957 from jordan-woyak/wmreal-iolinux-fixes
WiimoteReal/IOLinux: Improvements, fixes, and code cleanups.
This commit is contained in:
@@ -97,6 +97,7 @@ add_library(common
|
||||
JsonUtil.cpp
|
||||
Lazy.h
|
||||
LinearDiskCache.h
|
||||
UnixUtil.h
|
||||
Logging/ConsoleListener.h
|
||||
Logging/Log.h
|
||||
Logging/LogManager.cpp
|
||||
|
||||
@@ -43,13 +43,18 @@ const char* StrErrorWrapper(int error, char* buffer, std::size_t length)
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string StrerrorString(int error)
|
||||
{
|
||||
char error_message[BUFFER_SIZE];
|
||||
|
||||
return StrErrorWrapper(error, error_message, BUFFER_SIZE);
|
||||
}
|
||||
|
||||
// Wrapper function to get last strerror(errno) string.
|
||||
// This function might change the error code.
|
||||
std::string LastStrerrorString()
|
||||
{
|
||||
char error_message[BUFFER_SIZE];
|
||||
|
||||
return StrErrorWrapper(errno, error_message, BUFFER_SIZE);
|
||||
return StrerrorString(errno);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -45,8 +45,9 @@ namespace Common
|
||||
// strerror_r wrapper to handle XSI and GNU versions.
|
||||
const char* StrErrorWrapper(int error, char* buffer, std::size_t length);
|
||||
|
||||
// Wrapper function to get last strerror(errno) string.
|
||||
// This function might change the error code.
|
||||
// Wrapper functions to get strerror(errno) string, which itself is not threadsafe.
|
||||
// These functions might change the error code.
|
||||
std::string StrerrorString(int error);
|
||||
std::string LastStrerrorString();
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -86,6 +86,21 @@ std::optional<MACAddress> StringToMacAddress(std::string_view mac_string)
|
||||
return std::make_optional(mac);
|
||||
}
|
||||
|
||||
std::string BluetoothAddressToString(BluetoothAddress bdaddr)
|
||||
{
|
||||
std::ranges::reverse(bdaddr);
|
||||
return MacAddressToString(std::bit_cast<MACAddress>(bdaddr));
|
||||
}
|
||||
|
||||
std::optional<BluetoothAddress> StringToBluetoothAddress(std::string_view str)
|
||||
{
|
||||
auto result = StringToMacAddress(str);
|
||||
if (!result)
|
||||
return std::nullopt;
|
||||
std::ranges::reverse(*result);
|
||||
return std::bit_cast<BluetoothAddress>(*result);
|
||||
}
|
||||
|
||||
EthernetHeader::EthernetHeader() = default;
|
||||
|
||||
EthernetHeader::EthernetHeader(u16 ether_type) : ethertype(htons(ether_type))
|
||||
|
||||
@@ -36,6 +36,12 @@ enum DHCPConst
|
||||
};
|
||||
|
||||
using MACAddress = std::array<u8, MAC_ADDRESS_SIZE>;
|
||||
|
||||
// Note: Bluetooth address display order is reverse of the storage order.
|
||||
struct BluetoothAddress : std::array<u8, MAC_ADDRESS_SIZE>
|
||||
{
|
||||
};
|
||||
|
||||
constexpr std::size_t IPV4_ADDR_LEN = 4;
|
||||
using IPAddress = std::array<u8, IPV4_ADDR_LEN>;
|
||||
constexpr IPAddress IP_ADDR_ANY = {0, 0, 0, 0};
|
||||
@@ -259,8 +265,13 @@ struct NetworkErrorState
|
||||
};
|
||||
|
||||
MACAddress GenerateMacAddress(MACConsumer type);
|
||||
|
||||
std::string MacAddressToString(const MACAddress& mac);
|
||||
std::optional<MACAddress> StringToMacAddress(std::string_view mac_string);
|
||||
|
||||
std::string BluetoothAddressToString(BluetoothAddress bdaddr);
|
||||
std::optional<BluetoothAddress> StringToBluetoothAddress(std::string_view str);
|
||||
|
||||
u16 ComputeNetworkChecksum(const void* data, u16 length, u32 initial_value = 0);
|
||||
u16 ComputeTCPNetworkChecksum(const IPAddress& from, const IPAddress& to, const void* data,
|
||||
u16 length, u8 protocol);
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2025 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
||||
namespace UnixUtil
|
||||
{
|
||||
inline int CreateEventFD(unsigned int count, int flags)
|
||||
{
|
||||
const int result = eventfd(count, flags);
|
||||
if (result == -1)
|
||||
{
|
||||
ERROR_LOG_FMT(COMMON, "eventfd failed: {}", Common::LastStrerrorString());
|
||||
std::abort();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Repeatedly call a function that can erroneously produce EINTR.
|
||||
auto RetryOnEINTR(auto func, auto... args)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
const int result = func(args...);
|
||||
if (result >= 0 || errno != EINTR)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a very low-effort wrapper for pthread.
|
||||
// It allows creating a pthread from any callable (e.g. a lambda).
|
||||
// The wrapper object must exist for the lifetime of the thread.
|
||||
template <typename Func>
|
||||
struct PThreadWrapper
|
||||
{
|
||||
Func func;
|
||||
pthread_t handle{};
|
||||
|
||||
explicit PThreadWrapper(Func&& f) : func(std::move(f))
|
||||
{
|
||||
if (int result = pthread_create(
|
||||
&handle, nullptr,
|
||||
[](void* arg) -> void* {
|
||||
static_cast<PThreadWrapper*>(arg)->func();
|
||||
return nullptr;
|
||||
},
|
||||
this);
|
||||
result != 0)
|
||||
{
|
||||
ERROR_LOG_FMT(COMMON, "pthread_create: {}", Common::StrerrorString(result));
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace UnixUtil
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,10 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__linux__) && HAVE_BLUEZ
|
||||
#include <bluetooth/bluetooth.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "Common/Network.h"
|
||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
||||
|
||||
namespace WiimoteReal
|
||||
@@ -13,14 +15,10 @@ namespace WiimoteReal
|
||||
class WiimoteLinux final : public Wiimote
|
||||
{
|
||||
public:
|
||||
WiimoteLinux(bdaddr_t bdaddr);
|
||||
explicit WiimoteLinux(Common::BluetoothAddress bdaddr);
|
||||
~WiimoteLinux() override;
|
||||
std::string GetId() const override
|
||||
{
|
||||
char bdaddr_str[18] = {};
|
||||
ba2str(&m_bdaddr, bdaddr_str);
|
||||
return bdaddr_str;
|
||||
}
|
||||
|
||||
std::string GetId() const override;
|
||||
|
||||
protected:
|
||||
bool ConnectInternal() override;
|
||||
@@ -31,11 +29,10 @@ protected:
|
||||
int IOWrite(u8 const* buf, size_t len) override;
|
||||
|
||||
private:
|
||||
bdaddr_t m_bdaddr; // Bluetooth address
|
||||
int m_cmd_sock; // Command socket
|
||||
int m_int_sock; // Interrupt socket
|
||||
int m_wakeup_pipe_w;
|
||||
int m_wakeup_pipe_r;
|
||||
const Common::BluetoothAddress m_bdaddr;
|
||||
const int m_wakeup_fd{-1}; // Used to kick the read thread.
|
||||
int m_cmd_sock{-1}; // Command socket
|
||||
int m_int_sock{-1}; // Interrupt socket
|
||||
};
|
||||
|
||||
class WiimoteScannerLinux final : public WiimoteScannerBackend
|
||||
@@ -43,16 +40,23 @@ class WiimoteScannerLinux final : public WiimoteScannerBackend
|
||||
public:
|
||||
WiimoteScannerLinux();
|
||||
~WiimoteScannerLinux() override;
|
||||
|
||||
bool IsReady() const override;
|
||||
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&) override;
|
||||
void Update() override {} // not needed on Linux
|
||||
void RequestStopSearching() override {} // not needed on Linux
|
||||
private:
|
||||
int m_device_id;
|
||||
int m_device_sock;
|
||||
void Update() override;
|
||||
void RequestStopSearching() override;
|
||||
|
||||
void AddAutoConnectAddresses(std::vector<Wiimote*>&);
|
||||
private:
|
||||
bool Open();
|
||||
void Close();
|
||||
|
||||
int m_device_id{-1};
|
||||
int m_device_sock{-1};
|
||||
|
||||
// FYI: Atomic because UI calls IsReady.
|
||||
std::atomic<bool> m_is_device_open{};
|
||||
};
|
||||
|
||||
} // namespace WiimoteReal
|
||||
|
||||
#else
|
||||
|
||||
@@ -33,6 +33,9 @@ constexpr int REPORT_HID_HEADER_SIZE = 1;
|
||||
|
||||
constexpr u32 WIIMOTE_DEFAULT_TIMEOUT = 1000;
|
||||
|
||||
// Multiple of 1.28 seconds. Wii games use a value of 3.
|
||||
constexpr u8 BLUETOOTH_INQUIRY_LENGTH = 3;
|
||||
|
||||
// The 4 most significant bits of the first byte of an outgoing command must be
|
||||
// 0x50 if sending on the command channel and 0xA0 if sending on the interrupt
|
||||
// channel. On Mac and Linux we use interrupt channel; on Windows, command.
|
||||
@@ -172,7 +175,10 @@ class WiimoteScannerBackend
|
||||
{
|
||||
public:
|
||||
virtual ~WiimoteScannerBackend() = default;
|
||||
|
||||
// Note: Invoked from UI thread.
|
||||
virtual bool IsReady() const = 0;
|
||||
|
||||
virtual void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&) = 0;
|
||||
// function called when not looking for more Wiimotes
|
||||
virtual void Update() = 0;
|
||||
|
||||
Reference in New Issue
Block a user