client.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Copyright 2018 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <functional>
  6. #include <memory>
  7. #include <mutex>
  8. #include <optional>
  9. #include <string>
  10. #include <thread>
  11. #include <tuple>
  12. #include "common/common_types.h"
  13. #include "common/param_package.h"
  14. #include "common/thread.h"
  15. #include "common/threadsafe_queue.h"
  16. #include "common/vector_math.h"
  17. #include "core/frontend/input.h"
  18. #include "input_common/motion_input.h"
  19. namespace InputCommon::CemuhookUDP {
  20. constexpr char DEFAULT_SRV[] = "127.0.0.1:26760";
  21. class Socket;
  22. namespace Response {
  23. struct PadData;
  24. struct PortInfo;
  25. struct TouchPad;
  26. struct Version;
  27. } // namespace Response
  28. enum class PadMotion {
  29. GyroX,
  30. GyroY,
  31. GyroZ,
  32. AccX,
  33. AccY,
  34. AccZ,
  35. Undefined,
  36. };
  37. enum class PadTouch {
  38. Click,
  39. Undefined,
  40. };
  41. struct UDPPadStatus {
  42. std::string host{"127.0.0.1"};
  43. u16 port{26760};
  44. std::size_t pad_index{};
  45. PadMotion motion{PadMotion::Undefined};
  46. f32 motion_value{0.0f};
  47. };
  48. struct DeviceStatus {
  49. std::mutex update_mutex;
  50. Input::MotionStatus motion_status;
  51. std::tuple<float, float, bool> touch_status;
  52. // calibration data for scaling the device's touch area to 3ds
  53. struct CalibrationData {
  54. u16 min_x{};
  55. u16 min_y{};
  56. u16 max_x{};
  57. u16 max_y{};
  58. };
  59. std::optional<CalibrationData> touch_calibration;
  60. };
  61. class Client {
  62. public:
  63. // Initialize the UDP client capture and read sequence
  64. Client();
  65. // Close and release the client
  66. ~Client();
  67. // Used for polling
  68. void BeginConfiguration();
  69. void EndConfiguration();
  70. std::vector<Common::ParamPackage> GetInputDevices() const;
  71. bool DeviceConnected(std::size_t pad) const;
  72. void ReloadSockets();
  73. Common::SPSCQueue<UDPPadStatus>& GetPadQueue();
  74. const Common::SPSCQueue<UDPPadStatus>& GetPadQueue() const;
  75. DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad);
  76. const DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad) const;
  77. Input::TouchStatus& GetTouchState();
  78. const Input::TouchStatus& GetTouchState() const;
  79. private:
  80. struct PadData {
  81. std::size_t pad_index{};
  82. bool connected{};
  83. DeviceStatus status;
  84. u64 packet_sequence{};
  85. // Realtime values
  86. // motion is initalized with PID values for drift correction on joycons
  87. InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f};
  88. std::chrono::time_point<std::chrono::steady_clock> last_update;
  89. };
  90. struct ClientConnection {
  91. ClientConnection();
  92. ~ClientConnection();
  93. std::string host{"127.0.0.1"};
  94. u16 port{26760};
  95. s8 active{-1};
  96. std::unique_ptr<Socket> socket;
  97. std::thread thread;
  98. };
  99. // For shutting down, clear all data, join all threads, release usb
  100. void Reset();
  101. // Translates configuration to client number
  102. std::size_t GetClientNumber(std::string_view host, u16 port) const;
  103. void OnVersion(Response::Version);
  104. void OnPortInfo(Response::PortInfo);
  105. void OnPadData(Response::PadData, std::size_t client);
  106. void StartCommunication(std::size_t client, const std::string& host, u16 port);
  107. void UpdateYuzuSettings(std::size_t client, std::size_t pad_index,
  108. const Common::Vec3<float>& acc, const Common::Vec3<float>& gyro);
  109. // Returns an unused finger id, if there is no fingers available std::nullopt will be
  110. // returned
  111. std::optional<std::size_t> GetUnusedFingerID() const;
  112. // Merges and updates all touch inputs into the touch_status array
  113. void UpdateTouchInput(Response::TouchPad& touch_pad, std::size_t client, std::size_t id);
  114. bool configuring = false;
  115. // Allocate clients for 8 udp servers
  116. static constexpr std::size_t MAX_UDP_CLIENTS = 8;
  117. static constexpr std::size_t PADS_PER_CLIENT = 4;
  118. // Each client can have up 2 touch inputs
  119. static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2;
  120. std::array<PadData, MAX_UDP_CLIENTS * PADS_PER_CLIENT> pads{};
  121. std::array<ClientConnection, MAX_UDP_CLIENTS> clients{};
  122. Common::SPSCQueue<UDPPadStatus> pad_queue{};
  123. Input::TouchStatus touch_status{};
  124. std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{};
  125. };
  126. /// An async job allowing configuration of the touchpad calibration.
  127. class CalibrationConfigurationJob {
  128. public:
  129. enum class Status {
  130. Initialized,
  131. Ready,
  132. Stage1Completed,
  133. Completed,
  134. };
  135. /**
  136. * Constructs and starts the job with the specified parameter.
  137. *
  138. * @param status_callback Callback for job status updates
  139. * @param data_callback Called when calibration data is ready
  140. */
  141. explicit CalibrationConfigurationJob(const std::string& host, u16 port,
  142. std::function<void(Status)> status_callback,
  143. std::function<void(u16, u16, u16, u16)> data_callback);
  144. ~CalibrationConfigurationJob();
  145. void Stop();
  146. private:
  147. Common::Event complete_event;
  148. };
  149. void TestCommunication(const std::string& host, u16 port,
  150. const std::function<void()>& success_callback,
  151. const std::function<void()>& failure_callback);
  152. } // namespace InputCommon::CemuhookUDP