mirror of
https://github.com/citra-mirror/citra.git
synced 2024-08-20 02:13:23 +02:00
input_common/udp: Port various changes from yuzu (#5133)
This commit is contained in:
parent
026a63bcf7
commit
32cbb1bc77
@ -30,7 +30,7 @@ public:
|
|||||||
|
|
||||||
template <class Duration>
|
template <class Duration>
|
||||||
bool WaitFor(const std::chrono::duration<Duration>& time) {
|
bool WaitFor(const std::chrono::duration<Duration>& time) {
|
||||||
std::unique_lock lk(mutex);
|
std::unique_lock lk{mutex};
|
||||||
if (!condvar.wait_for(lk, time, [this] { return is_set; }))
|
if (!condvar.wait_for(lk, time, [this] { return is_set; }))
|
||||||
return false;
|
return false;
|
||||||
is_set = false;
|
is_set = false;
|
||||||
|
@ -32,8 +32,16 @@ public:
|
|||||||
SocketCallback callback)
|
SocketCallback callback)
|
||||||
: callback(std::move(callback)), timer(io_service),
|
: callback(std::move(callback)), timer(io_service),
|
||||||
socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(client_id),
|
socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(client_id),
|
||||||
pad_index(pad_index),
|
pad_index(pad_index) {
|
||||||
send_endpoint(udp::endpoint(boost::asio::ip::make_address_v4(host), port)) {}
|
boost::system::error_code ec{};
|
||||||
|
auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
|
||||||
|
if (ec.value() != boost::system::errc::success) {
|
||||||
|
LOG_ERROR(Input, "Invalid IPv4 address \"{}\" provided to socket", host);
|
||||||
|
ipv4 = boost::asio::ip::address_v4{};
|
||||||
|
}
|
||||||
|
|
||||||
|
send_endpoint = {udp::endpoint(ipv4, port)};
|
||||||
|
}
|
||||||
|
|
||||||
void Stop() {
|
void Stop() {
|
||||||
io_service.stop();
|
io_service.stop();
|
||||||
@ -85,17 +93,18 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HandleSend(const boost::system::error_code& error) {
|
void HandleSend(const boost::system::error_code& error) {
|
||||||
|
boost::system::error_code _ignored{};
|
||||||
// Send a request for getting port info for the pad
|
// Send a request for getting port info for the pad
|
||||||
Request::PortInfo port_info{1, {pad_index, 0, 0, 0}};
|
Request::PortInfo port_info{1, {pad_index, 0, 0, 0}};
|
||||||
auto port_message = Request::Create(port_info, client_id);
|
const auto port_message = Request::Create(port_info, client_id);
|
||||||
std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE);
|
std::memcpy(&send_buffer1, &port_message, PORT_INFO_SIZE);
|
||||||
std::size_t len = socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint);
|
socket.send_to(boost::asio::buffer(send_buffer1), send_endpoint, {}, _ignored);
|
||||||
|
|
||||||
// Send a request for getting pad data for the pad
|
// Send a request for getting pad data for the pad
|
||||||
Request::PadData pad_data{Request::PadData::Flags::Id, pad_index, EMPTY_MAC_ADDRESS};
|
Request::PadData pad_data{Request::PadData::Flags::Id, pad_index, EMPTY_MAC_ADDRESS};
|
||||||
auto pad_message = Request::Create(pad_data, client_id);
|
const auto pad_message = Request::Create(pad_data, client_id);
|
||||||
std::memcpy(send_buffer2.data(), &pad_message, PAD_DATA_SIZE);
|
std::memcpy(send_buffer2.data(), &pad_message, PAD_DATA_SIZE);
|
||||||
std::size_t len2 = socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint);
|
socket.send_to(boost::asio::buffer(send_buffer2), send_endpoint, {}, _ignored);
|
||||||
StartSend(timer.expiry());
|
StartSend(timer.expiry());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,8 +113,8 @@ private:
|
|||||||
boost::asio::basic_waitable_timer<clock> timer;
|
boost::asio::basic_waitable_timer<clock> timer;
|
||||||
udp::socket socket;
|
udp::socket socket;
|
||||||
|
|
||||||
u32 client_id;
|
u32 client_id{};
|
||||||
u8 pad_index;
|
u8 pad_index{};
|
||||||
|
|
||||||
static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>);
|
static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>);
|
||||||
static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>);
|
static constexpr std::size_t PAD_DATA_SIZE = sizeof(Message<Request::PadData>);
|
||||||
@ -170,16 +179,16 @@ void Client::OnPadData(Response::PadData data) {
|
|||||||
|
|
||||||
// TODO: add a setting for "click" touch. Click touch refers to a device that differentiates
|
// TODO: add a setting for "click" touch. Click touch refers to a device that differentiates
|
||||||
// between a simple "tap" and a hard press that causes the touch screen to click.
|
// between a simple "tap" and a hard press that causes the touch screen to click.
|
||||||
bool is_active = data.touch_1.is_active != 0;
|
const bool is_active = data.touch_1.is_active != 0;
|
||||||
|
|
||||||
float x = 0;
|
float x = 0;
|
||||||
float y = 0;
|
float y = 0;
|
||||||
|
|
||||||
if (is_active && status->touch_calibration) {
|
if (is_active && status->touch_calibration) {
|
||||||
u16 min_x = status->touch_calibration->min_x;
|
const u16 min_x = status->touch_calibration->min_x;
|
||||||
u16 max_x = status->touch_calibration->max_x;
|
const u16 max_x = status->touch_calibration->max_x;
|
||||||
u16 min_y = status->touch_calibration->min_y;
|
const u16 min_y = status->touch_calibration->min_y;
|
||||||
u16 max_y = status->touch_calibration->max_y;
|
const u16 max_y = status->touch_calibration->max_y;
|
||||||
|
|
||||||
x = (std::clamp(static_cast<u16>(data.touch_1.x), min_x, max_x) - min_x) /
|
x = (std::clamp(static_cast<u16>(data.touch_1.x), min_x, max_x) - min_x) /
|
||||||
static_cast<float>(max_x - min_x);
|
static_cast<float>(max_x - min_x);
|
||||||
@ -212,10 +221,11 @@ void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 clie
|
|||||||
bool result = success_event.WaitFor(std::chrono::seconds(8));
|
bool result = success_event.WaitFor(std::chrono::seconds(8));
|
||||||
socket.Stop();
|
socket.Stop();
|
||||||
worker_thread.join();
|
worker_thread.join();
|
||||||
if (result)
|
if (result) {
|
||||||
success_callback();
|
success_callback();
|
||||||
else
|
} else {
|
||||||
failure_callback();
|
failure_callback();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
@ -228,8 +238,10 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
|
|||||||
std::thread([=] {
|
std::thread([=] {
|
||||||
constexpr u16 CALIBRATION_THRESHOLD = 100;
|
constexpr u16 CALIBRATION_THRESHOLD = 100;
|
||||||
|
|
||||||
u16 min_x{UINT16_MAX}, min_y{UINT16_MAX};
|
u16 min_x{UINT16_MAX};
|
||||||
u16 max_x, max_y;
|
u16 min_y{UINT16_MAX};
|
||||||
|
u16 max_x{};
|
||||||
|
u16 max_y{};
|
||||||
|
|
||||||
Status current_status{Status::Initialized};
|
Status current_status{Status::Initialized};
|
||||||
SocketCallback callback{[](Response::Version version) {}, [](Response::PortInfo info) {},
|
SocketCallback callback{[](Response::Version version) {}, [](Response::PortInfo info) {},
|
||||||
@ -239,8 +251,9 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
|
|||||||
current_status = Status::Ready;
|
current_status = Status::Ready;
|
||||||
status_callback(current_status);
|
status_callback(current_status);
|
||||||
}
|
}
|
||||||
if (!data.touch_1.is_active)
|
if (!data.touch_1.is_active) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
LOG_DEBUG(Input, "Current touch: {} {}", data.touch_1.x,
|
LOG_DEBUG(Input, "Current touch: {} {}", data.touch_1.x,
|
||||||
data.touch_1.y);
|
data.touch_1.y);
|
||||||
min_x = std::min(min_x, static_cast<u16>(data.touch_1.x));
|
min_x = std::min(min_x, static_cast<u16>(data.touch_1.x));
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
namespace InputCommon::CemuhookUDP {
|
namespace InputCommon::CemuhookUDP {
|
||||||
|
|
||||||
static constexpr u16 DEFAULT_PORT = 26760;
|
constexpr u16 DEFAULT_PORT = 26760;
|
||||||
static constexpr const char* DEFAULT_ADDR = "127.0.0.1";
|
constexpr char DEFAULT_ADDR[] = "127.0.0.1";
|
||||||
|
|
||||||
class Socket;
|
class Socket;
|
||||||
|
|
||||||
@ -35,10 +35,10 @@ struct DeviceStatus {
|
|||||||
|
|
||||||
// calibration data for scaling the device's touch area to 3ds
|
// calibration data for scaling the device's touch area to 3ds
|
||||||
struct CalibrationData {
|
struct CalibrationData {
|
||||||
u16 min_x;
|
u16 min_x{};
|
||||||
u16 min_y;
|
u16 min_y{};
|
||||||
u16 max_x;
|
u16 max_x{};
|
||||||
u16 max_y;
|
u16 max_y{};
|
||||||
};
|
};
|
||||||
std::optional<CalibrationData> touch_calibration;
|
std::optional<CalibrationData> touch_calibration;
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
namespace InputCommon::CemuhookUDP {
|
namespace InputCommon::CemuhookUDP {
|
||||||
|
|
||||||
static const std::size_t GetSizeOfResponseType(Type t) {
|
static constexpr std::size_t GetSizeOfResponseType(Type t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case Type::Version:
|
case Type::Version:
|
||||||
return sizeof(Response::Version);
|
return sizeof(Response::Version);
|
||||||
@ -31,22 +31,21 @@ namespace Response {
|
|||||||
*/
|
*/
|
||||||
std::optional<Type> Validate(u8* data, std::size_t size) {
|
std::optional<Type> Validate(u8* data, std::size_t size) {
|
||||||
if (size < sizeof(Header)) {
|
if (size < sizeof(Header)) {
|
||||||
LOG_DEBUG(Input, "Invalid UDP packet received");
|
return std::nullopt;
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
Header header;
|
Header header{};
|
||||||
std::memcpy(&header, data, sizeof(Header));
|
std::memcpy(&header, data, sizeof(Header));
|
||||||
if (header.magic != SERVER_MAGIC) {
|
if (header.magic != SERVER_MAGIC) {
|
||||||
LOG_ERROR(Input, "UDP Packet has an unexpected magic value");
|
LOG_ERROR(Input, "UDP Packet has an unexpected magic value");
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
if (header.protocol_version != PROTOCOL_VERSION) {
|
if (header.protocol_version != PROTOCOL_VERSION) {
|
||||||
LOG_ERROR(Input, "UDP Packet protocol mismatch");
|
LOG_ERROR(Input, "UDP Packet protocol mismatch");
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
if (header.type < Type::Version || header.type > Type::PadData) {
|
if (header.type < Type::Version || header.type > Type::PadData) {
|
||||||
LOG_ERROR(Input, "UDP Packet is an unknown type");
|
LOG_ERROR(Input, "UDP Packet is an unknown type");
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Packet size must equal sizeof(Header) + sizeof(Data)
|
// Packet size must equal sizeof(Header) + sizeof(Data)
|
||||||
@ -59,7 +58,7 @@ std::optional<Type> Validate(u8* data, std::size_t size) {
|
|||||||
Input,
|
Input,
|
||||||
"UDP Packet payload length doesn't match. Received: {} PayloadLength: {} Expected: {}",
|
"UDP Packet payload length doesn't match. Received: {} PayloadLength: {} Expected: {}",
|
||||||
size, header.payload_length, data_len + sizeof(Type));
|
size, header.payload_length, data_len + sizeof(Type));
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 crc32 = header.crc;
|
const u32 crc32 = header.crc;
|
||||||
@ -70,7 +69,7 @@ std::optional<Type> Validate(u8* data, std::size_t size) {
|
|||||||
result.process_bytes(data, data_len + sizeof(Header));
|
result.process_bytes(data, data_len + sizeof(Header));
|
||||||
if (crc32 != result.checksum()) {
|
if (crc32 != result.checksum()) {
|
||||||
LOG_ERROR(Input, "UDP Packet CRC check failed. Offset: {}", offsetof(Header, crc));
|
LOG_ERROR(Input, "UDP Packet CRC check failed. Offset: {}", offsetof(Header, crc));
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return header.type;
|
return header.type;
|
||||||
}
|
}
|
||||||
|
@ -25,15 +25,15 @@ enum class Type : u32 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Header {
|
struct Header {
|
||||||
u32_le magic;
|
u32_le magic{};
|
||||||
u16_le protocol_version;
|
u16_le protocol_version{};
|
||||||
u16_le payload_length;
|
u16_le payload_length{};
|
||||||
u32_le crc;
|
u32_le crc{};
|
||||||
u32_le id;
|
u32_le id{};
|
||||||
///> In the protocol, the type of the packet is not part of the header, but its convenient to
|
///> In the protocol, the type of the packet is not part of the header, but its convenient to
|
||||||
///> include in the header so the callee doesn't have to duplicate the type twice when building
|
///> include in the header so the callee doesn't have to duplicate the type twice when building
|
||||||
///> the data
|
///> the data
|
||||||
Type type;
|
Type type{};
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Header) == 20, "UDP Message Header struct has wrong size");
|
static_assert(sizeof(Header) == 20, "UDP Message Header struct has wrong size");
|
||||||
static_assert(std::is_trivially_copyable_v<Header>, "UDP Message Header is not trivially copyable");
|
static_assert(std::is_trivially_copyable_v<Header>, "UDP Message Header is not trivially copyable");
|
||||||
@ -44,7 +44,7 @@ constexpr MacAddress EMPTY_MAC_ADDRESS = {0, 0, 0, 0, 0, 0};
|
|||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Message {
|
struct Message {
|
||||||
Header header;
|
Header header{};
|
||||||
T data;
|
T data;
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
@ -63,7 +63,7 @@ struct Version {};
|
|||||||
*/
|
*/
|
||||||
constexpr u32 MAX_PORTS = 4;
|
constexpr u32 MAX_PORTS = 4;
|
||||||
struct PortInfo {
|
struct PortInfo {
|
||||||
u32_le pad_count; ///> Number of ports to request data for
|
u32_le pad_count{}; ///> Number of ports to request data for
|
||||||
std::array<u8, MAX_PORTS> port;
|
std::array<u8, MAX_PORTS> port;
|
||||||
};
|
};
|
||||||
static_assert(std::is_trivially_copyable_v<PortInfo>,
|
static_assert(std::is_trivially_copyable_v<PortInfo>,
|
||||||
@ -81,9 +81,9 @@ struct PadData {
|
|||||||
Mac,
|
Mac,
|
||||||
};
|
};
|
||||||
/// Determines which method will be used as a look up for the controller
|
/// Determines which method will be used as a look up for the controller
|
||||||
Flags flags;
|
Flags flags{};
|
||||||
/// Index of the port of the controller to retrieve data about
|
/// Index of the port of the controller to retrieve data about
|
||||||
u8 port_id;
|
u8 port_id{};
|
||||||
/// Mac address of the controller to retrieve data about
|
/// Mac address of the controller to retrieve data about
|
||||||
MacAddress mac;
|
MacAddress mac;
|
||||||
};
|
};
|
||||||
@ -112,20 +112,20 @@ Message<T> Create(const T data, const u32 client_id = 0) {
|
|||||||
namespace Response {
|
namespace Response {
|
||||||
|
|
||||||
struct Version {
|
struct Version {
|
||||||
u16_le version;
|
u16_le version{};
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Version) == 2, "UDP Response Version struct has wrong size");
|
static_assert(sizeof(Version) == 2, "UDP Response Version struct has wrong size");
|
||||||
static_assert(std::is_trivially_copyable_v<Version>,
|
static_assert(std::is_trivially_copyable_v<Version>,
|
||||||
"UDP Response Version is not trivially copyable");
|
"UDP Response Version is not trivially copyable");
|
||||||
|
|
||||||
struct PortInfo {
|
struct PortInfo {
|
||||||
u8 id;
|
u8 id{};
|
||||||
u8 state;
|
u8 state{};
|
||||||
u8 model;
|
u8 model{};
|
||||||
u8 connection_type;
|
u8 connection_type{};
|
||||||
MacAddress mac;
|
MacAddress mac;
|
||||||
u8 battery;
|
u8 battery{};
|
||||||
u8 is_pad_active;
|
u8 is_pad_active{};
|
||||||
};
|
};
|
||||||
static_assert(sizeof(PortInfo) == 12, "UDP Response PortInfo struct has wrong size");
|
static_assert(sizeof(PortInfo) == 12, "UDP Response PortInfo struct has wrong size");
|
||||||
static_assert(std::is_trivially_copyable_v<PortInfo>,
|
static_assert(std::is_trivially_copyable_v<PortInfo>,
|
||||||
@ -133,10 +133,10 @@ static_assert(std::is_trivially_copyable_v<PortInfo>,
|
|||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct PadData {
|
struct PadData {
|
||||||
PortInfo info;
|
PortInfo info{};
|
||||||
u32_le packet_counter;
|
u32_le packet_counter{};
|
||||||
|
|
||||||
u16_le digital_button;
|
u16_le digital_button{};
|
||||||
// The following union isn't trivially copyable but we don't use this input anyway.
|
// The following union isn't trivially copyable but we don't use this input anyway.
|
||||||
// union DigitalButton {
|
// union DigitalButton {
|
||||||
// u16_le button;
|
// u16_le button;
|
||||||
@ -160,46 +160,46 @@ struct PadData {
|
|||||||
|
|
||||||
u8 home;
|
u8 home;
|
||||||
/// If the device supports a "click" on the touchpad, this will change to 1 when a click happens
|
/// If the device supports a "click" on the touchpad, this will change to 1 when a click happens
|
||||||
u8 touch_hard_press;
|
u8 touch_hard_press{};
|
||||||
u8 left_stick_x;
|
u8 left_stick_x{};
|
||||||
u8 left_stick_y;
|
u8 left_stick_y{};
|
||||||
u8 right_stick_x;
|
u8 right_stick_x{};
|
||||||
u8 right_stick_y;
|
u8 right_stick_y{};
|
||||||
|
|
||||||
struct AnalogButton {
|
struct AnalogButton {
|
||||||
u8 button_8;
|
u8 button_8{};
|
||||||
u8 button_7;
|
u8 button_7{};
|
||||||
u8 button_6;
|
u8 button_6{};
|
||||||
u8 button_5;
|
u8 button_5{};
|
||||||
u8 button_12;
|
u8 button_12{};
|
||||||
u8 button_11;
|
u8 button_11{};
|
||||||
u8 button_10;
|
u8 button_10{};
|
||||||
u8 button_9;
|
u8 button_9{};
|
||||||
u8 button_16;
|
u8 button_16{};
|
||||||
u8 button_15;
|
u8 button_15{};
|
||||||
u8 button_14;
|
u8 button_14{};
|
||||||
u8 button_13;
|
u8 button_13{};
|
||||||
} analog_button;
|
} analog_button;
|
||||||
|
|
||||||
struct TouchPad {
|
struct TouchPad {
|
||||||
u8 is_active;
|
u8 is_active{};
|
||||||
u8 id;
|
u8 id{};
|
||||||
u16_le x;
|
u16_le x{};
|
||||||
u16_le y;
|
u16_le y{};
|
||||||
} touch_1, touch_2;
|
} touch_1, touch_2;
|
||||||
|
|
||||||
u64_le motion_timestamp;
|
u64_le motion_timestamp;
|
||||||
|
|
||||||
struct Accelerometer {
|
struct Accelerometer {
|
||||||
float x;
|
float x{};
|
||||||
float y;
|
float y{};
|
||||||
float z;
|
float z{};
|
||||||
} accel;
|
} accel;
|
||||||
|
|
||||||
struct Gyroscope {
|
struct Gyroscope {
|
||||||
float pitch;
|
float pitch{};
|
||||||
float yaw;
|
float yaw{};
|
||||||
float roll;
|
float roll{};
|
||||||
} gyro;
|
} gyro;
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
@ -211,6 +211,13 @@ static_assert(std::is_trivially_copyable_v<PadData>,
|
|||||||
static_assert(sizeof(Message<PadData>) == MAX_PACKET_SIZE,
|
static_assert(sizeof(Message<PadData>) == MAX_PACKET_SIZE,
|
||||||
"UDP MAX_PACKET_SIZE is no longer larger than Message<PadData>");
|
"UDP MAX_PACKET_SIZE is no longer larger than Message<PadData>");
|
||||||
|
|
||||||
|
static_assert(sizeof(PadData::AnalogButton) == 12,
|
||||||
|
"UDP Response AnalogButton struct has wrong size ");
|
||||||
|
static_assert(sizeof(PadData::TouchPad) == 6, "UDP Response TouchPad struct has wrong size ");
|
||||||
|
static_assert(sizeof(PadData::Accelerometer) == 12,
|
||||||
|
"UDP Response Accelerometer struct has wrong size ");
|
||||||
|
static_assert(sizeof(PadData::Gyroscope) == 12, "UDP Response Gyroscope struct has wrong size ");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Response Message from the data
|
* Create a Response Message from the data
|
||||||
* @param data array of bytes sent from the server
|
* @param data array of bytes sent from the server
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include "common/param_package.h"
|
#include "common/param_package.h"
|
||||||
#include "core/frontend/input.h"
|
#include "core/frontend/input.h"
|
||||||
@ -43,7 +44,7 @@ public:
|
|||||||
std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override {
|
std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override {
|
||||||
{
|
{
|
||||||
std::lock_guard guard(status->update_mutex);
|
std::lock_guard guard(status->update_mutex);
|
||||||
status->touch_calibration.emplace();
|
status->touch_calibration = DeviceStatus::CalibrationData{};
|
||||||
// These default values work well for DS4 but probably not other touch inputs
|
// These default values work well for DS4 but probably not other touch inputs
|
||||||
status->touch_calibration->min_x = params.Get("min_x", 100);
|
status->touch_calibration->min_x = params.Get("min_x", 100);
|
||||||
status->touch_calibration->min_y = params.Get("min_y", 50);
|
status->touch_calibration->min_y = params.Get("min_y", 50);
|
||||||
|
Loading…
Reference in New Issue
Block a user