From 4c6f2c2547e1d97f12ebe708fac693a6183bbc45 Mon Sep 17 00:00:00 2001 From: german77 Date: Mon, 20 Sep 2021 16:57:55 -0500 Subject: input_common: Move touch and analog from button. Move udp protocol --- src/input_common/udp/client.cpp | 2 +- src/input_common/udp/protocol.cpp | 78 ------------ src/input_common/udp/protocol.h | 259 -------------------------------------- 3 files changed, 1 insertion(+), 338 deletions(-) delete mode 100644 src/input_common/udp/protocol.cpp delete mode 100644 src/input_common/udp/protocol.h (limited to 'src/input_common/udp') diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index b9512aa2e..bcc29c4e0 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp @@ -11,7 +11,7 @@ #include "common/logging/log.h" #include "common/settings.h" #include "input_common/udp/client.h" -#include "input_common/udp/protocol.h" +#include "input_common/helpers/udp_protocol.h" using boost::asio::ip::udp; diff --git a/src/input_common/udp/protocol.cpp b/src/input_common/udp/protocol.cpp deleted file mode 100644 index 5e50bd612..000000000 --- a/src/input_common/udp/protocol.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2018 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include -#include "common/logging/log.h" -#include "input_common/udp/protocol.h" - -namespace InputCommon::CemuhookUDP { - -static constexpr std::size_t GetSizeOfResponseType(Type t) { - switch (t) { - case Type::Version: - return sizeof(Response::Version); - case Type::PortInfo: - return sizeof(Response::PortInfo); - case Type::PadData: - return sizeof(Response::PadData); - } - return 0; -} - -namespace Response { - -/** - * Returns Type if the packet is valid, else none - * - * Note: Modifies the buffer to zero out the crc (since thats the easiest way to check without - * copying the buffer) - */ -std::optional Validate(u8* data, std::size_t size) { - if (size < sizeof(Header)) { - return std::nullopt; - } - Header header{}; - std::memcpy(&header, data, sizeof(Header)); - if (header.magic != SERVER_MAGIC) { - LOG_ERROR(Input, "UDP Packet has an unexpected magic value"); - return std::nullopt; - } - if (header.protocol_version != PROTOCOL_VERSION) { - LOG_ERROR(Input, "UDP Packet protocol mismatch"); - return std::nullopt; - } - if (header.type < Type::Version || header.type > Type::PadData) { - LOG_ERROR(Input, "UDP Packet is an unknown type"); - return std::nullopt; - } - - // Packet size must equal sizeof(Header) + sizeof(Data) - // and also verify that the packet info mentions the correct size. Since the spec includes the - // type of the packet as part of the data, we need to include it in size calculations here - // ie: payload_length == sizeof(T) + sizeof(Type) - const std::size_t data_len = GetSizeOfResponseType(header.type); - if (header.payload_length != data_len + sizeof(Type) || size < data_len + sizeof(Header)) { - LOG_ERROR( - Input, - "UDP Packet payload length doesn't match. Received: {} PayloadLength: {} Expected: {}", - size, header.payload_length, data_len + sizeof(Type)); - return std::nullopt; - } - - const u32 crc32 = header.crc; - boost::crc_32_type result; - // zero out the crc in the buffer and then run the crc against it - std::memset(&data[offsetof(Header, crc)], 0, sizeof(u32_le)); - - result.process_bytes(data, data_len + sizeof(Header)); - if (crc32 != result.checksum()) { - LOG_ERROR(Input, "UDP Packet CRC check failed. Offset: {}", offsetof(Header, crc)); - return std::nullopt; - } - return header.type; -} -} // namespace Response - -} // namespace InputCommon::CemuhookUDP diff --git a/src/input_common/udp/protocol.h b/src/input_common/udp/protocol.h deleted file mode 100644 index 1bdc9209e..000000000 --- a/src/input_common/udp/protocol.h +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2018 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include - -#include - -#include "common/bit_field.h" -#include "common/swap.h" - -namespace InputCommon::CemuhookUDP { - -constexpr std::size_t MAX_PACKET_SIZE = 100; -constexpr u16 PROTOCOL_VERSION = 1001; -constexpr u32 CLIENT_MAGIC = 0x43555344; // DSUC (but flipped for LE) -constexpr u32 SERVER_MAGIC = 0x53555344; // DSUS (but flipped for LE) - -enum class Type : u32 { - Version = 0x00100000, - PortInfo = 0x00100001, - PadData = 0x00100002, -}; - -struct Header { - u32_le magic{}; - u16_le protocol_version{}; - u16_le payload_length{}; - u32_le crc{}; - u32_le id{}; - ///> 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 - ///> the data - Type type{}; -}; -static_assert(sizeof(Header) == 20, "UDP Message Header struct has wrong size"); -static_assert(std::is_trivially_copyable_v
, "UDP Message Header is not trivially copyable"); - -using MacAddress = std::array; -constexpr MacAddress EMPTY_MAC_ADDRESS = {0, 0, 0, 0, 0, 0}; - -#pragma pack(push, 1) -template -struct Message { - Header header{}; - T data; -}; -#pragma pack(pop) - -template -constexpr Type GetMessageType(); - -namespace Request { - -struct Version {}; -/** - * Requests the server to send information about what controllers are plugged into the ports - * In citra's case, we only have one controller, so for simplicity's sake, we can just send a - * request explicitly for the first controller port and leave it at that. In the future it would be - * nice to make this configurable - */ -constexpr u32 MAX_PORTS = 4; -struct PortInfo { - u32_le pad_count{}; ///> Number of ports to request data for - std::array port; -}; -static_assert(std::is_trivially_copyable_v, - "UDP Request PortInfo is not trivially copyable"); - -/** - * Request the latest pad information from the server. If the server hasn't received this message - * from the client in a reasonable time frame, the server will stop sending updates. The default - * timeout seems to be 5 seconds. - */ -struct PadData { - enum class Flags : u8 { - AllPorts, - Id, - Mac, - }; - /// Determines which method will be used as a look up for the controller - Flags flags{}; - /// Index of the port of the controller to retrieve data about - u8 port_id{}; - /// Mac address of the controller to retrieve data about - MacAddress mac; -}; -static_assert(sizeof(PadData) == 8, "UDP Request PadData struct has wrong size"); -static_assert(std::is_trivially_copyable_v, - "UDP Request PadData is not trivially copyable"); - -/** - * Creates a message with the proper header data that can be sent to the server. - * @param data Request body to send - * @param client_id ID of the udp client (usually not checked on the server) - */ -template -Message Create(const T data, const u32 client_id = 0) { - boost::crc_32_type crc; - Header header{ - CLIENT_MAGIC, PROTOCOL_VERSION, sizeof(T) + sizeof(Type), 0, client_id, GetMessageType(), - }; - Message message{header, data}; - crc.process_bytes(&message, sizeof(Message)); - message.header.crc = crc.checksum(); - return message; -} -} // namespace Request - -namespace Response { - -struct Version { - u16_le version{}; -}; -static_assert(sizeof(Version) == 2, "UDP Response Version struct has wrong size"); -static_assert(std::is_trivially_copyable_v, - "UDP Response Version is not trivially copyable"); - -struct PortInfo { - u8 id{}; - u8 state{}; - u8 model{}; - u8 connection_type{}; - MacAddress mac; - u8 battery{}; - u8 is_pad_active{}; -}; -static_assert(sizeof(PortInfo) == 12, "UDP Response PortInfo struct has wrong size"); -static_assert(std::is_trivially_copyable_v, - "UDP Response PortInfo is not trivially copyable"); - -struct TouchPad { - u8 is_active{}; - u8 id{}; - u16_le x{}; - u16_le y{}; -}; -static_assert(sizeof(TouchPad) == 6, "UDP Response TouchPad struct has wrong size "); - -#pragma pack(push, 1) -struct PadData { - PortInfo info{}; - u32_le packet_counter{}; - - u16_le digital_button{}; - // The following union isn't trivially copyable but we don't use this input anyway. - // union DigitalButton { - // u16_le button; - // BitField<0, 1, u16> button_1; // Share - // BitField<1, 1, u16> button_2; // L3 - // BitField<2, 1, u16> button_3; // R3 - // BitField<3, 1, u16> button_4; // Options - // BitField<4, 1, u16> button_5; // Up - // BitField<5, 1, u16> button_6; // Right - // BitField<6, 1, u16> button_7; // Down - // BitField<7, 1, u16> button_8; // Left - // BitField<8, 1, u16> button_9; // L2 - // BitField<9, 1, u16> button_10; // R2 - // BitField<10, 1, u16> button_11; // L1 - // BitField<11, 1, u16> button_12; // R1 - // BitField<12, 1, u16> button_13; // Triangle - // BitField<13, 1, u16> button_14; // Circle - // BitField<14, 1, u16> button_15; // Cross - // BitField<15, 1, u16> button_16; // Square - // } digital_button; - - u8 home; - /// If the device supports a "click" on the touchpad, this will change to 1 when a click happens - u8 touch_hard_press{}; - u8 left_stick_x{}; - u8 left_stick_y{}; - u8 right_stick_x{}; - u8 right_stick_y{}; - - struct AnalogButton { - u8 button_8{}; - u8 button_7{}; - u8 button_6{}; - u8 button_5{}; - u8 button_12{}; - u8 button_11{}; - u8 button_10{}; - u8 button_9{}; - u8 button_16{}; - u8 button_15{}; - u8 button_14{}; - u8 button_13{}; - } analog_button; - - std::array touch; - - u64_le motion_timestamp; - - struct Accelerometer { - float x{}; - float y{}; - float z{}; - } accel; - - struct Gyroscope { - float pitch{}; - float yaw{}; - float roll{}; - } gyro; -}; -#pragma pack(pop) - -static_assert(sizeof(PadData) == 80, "UDP Response PadData struct has wrong size "); -static_assert(std::is_trivially_copyable_v, - "UDP Response PadData is not trivially copyable"); - -static_assert(sizeof(Message) == MAX_PACKET_SIZE, - "UDP MAX_PACKET_SIZE is no longer larger than Message"); - -static_assert(sizeof(PadData::AnalogButton) == 12, - "UDP Response AnalogButton 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 - * @param data array of bytes sent from the server - * @return boost::none if it failed to parse or Type if it succeeded. The client can then safely - * copy the data into the appropriate struct for that Type - */ -std::optional Validate(u8* data, std::size_t size); - -} // namespace Response - -template <> -constexpr Type GetMessageType() { - return Type::Version; -} -template <> -constexpr Type GetMessageType() { - return Type::PortInfo; -} -template <> -constexpr Type GetMessageType() { - return Type::PadData; -} -template <> -constexpr Type GetMessageType() { - return Type::Version; -} -template <> -constexpr Type GetMessageType() { - return Type::PortInfo; -} -template <> -constexpr Type GetMessageType() { - return Type::PadData; -} -} // namespace InputCommon::CemuhookUDP -- cgit v1.2.3