ringcon.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <span>
  6. #include "common/common_types.h"
  7. #include "hid_core/hidbus/hidbus_base.h"
  8. namespace Core::HID {
  9. class EmulatedController;
  10. } // namespace Core::HID
  11. namespace Service::HID {
  12. class RingController final : public HidbusBase {
  13. public:
  14. explicit RingController(Core::System& system_, KernelHelpers::ServiceContext& service_context_);
  15. ~RingController() override;
  16. void OnInit() override;
  17. void OnRelease() override;
  18. // Updates ringcon transfer memory
  19. void OnUpdate() override;
  20. // Returns the device ID of the joycon
  21. u8 GetDeviceId() const override;
  22. // Assigns a command from data
  23. bool SetCommand(std::span<const u8> data) override;
  24. // Returns a reply from a command
  25. std::vector<u8> GetReply() const override;
  26. private:
  27. // These values are obtained from a real ring controller
  28. static constexpr s16 idle_value = 2280;
  29. static constexpr s16 idle_deadzone = 120;
  30. static constexpr s16 range = 2500;
  31. // Most missing command names are leftovers from other firmware versions
  32. enum class RingConCommands : u32 {
  33. GetFirmwareVersion = 0x00020000,
  34. ReadId = 0x00020100,
  35. JoyPolling = 0x00020101,
  36. Unknown1 = 0x00020104,
  37. c20105 = 0x00020105,
  38. Unknown2 = 0x00020204,
  39. Unknown3 = 0x00020304,
  40. Unknown4 = 0x00020404,
  41. ReadUnkCal = 0x00020504,
  42. ReadFactoryCal = 0x00020A04,
  43. Unknown5 = 0x00021104,
  44. Unknown6 = 0x00021204,
  45. Unknown7 = 0x00021304,
  46. ReadUserCal = 0x00021A04,
  47. ReadRepCount = 0x00023104,
  48. ReadTotalPushCount = 0x00023204,
  49. ResetRepCount = 0x04013104,
  50. Unknown8 = 0x04011104,
  51. Unknown9 = 0x04011204,
  52. Unknown10 = 0x04011304,
  53. SaveCalData = 0x10011A04,
  54. Error = 0xFFFFFFFF,
  55. };
  56. enum class DataValid : u32 {
  57. Valid,
  58. BadCRC,
  59. Cal,
  60. };
  61. struct FirmwareVersion {
  62. u8 sub;
  63. u8 main;
  64. };
  65. static_assert(sizeof(FirmwareVersion) == 0x2, "FirmwareVersion is an invalid size");
  66. struct FactoryCalibration {
  67. s32_le os_max;
  68. s32_le hk_max;
  69. s32_le zero_min;
  70. s32_le zero_max;
  71. };
  72. static_assert(sizeof(FactoryCalibration) == 0x10, "FactoryCalibration is an invalid size");
  73. struct CalibrationValue {
  74. s16 value;
  75. u16 crc;
  76. };
  77. static_assert(sizeof(CalibrationValue) == 0x4, "CalibrationValue is an invalid size");
  78. struct UserCalibration {
  79. CalibrationValue os_max;
  80. CalibrationValue hk_max;
  81. CalibrationValue zero;
  82. };
  83. static_assert(sizeof(UserCalibration) == 0xC, "UserCalibration is an invalid size");
  84. struct SaveCalData {
  85. RingConCommands command;
  86. UserCalibration calibration;
  87. INSERT_PADDING_BYTES_NOINIT(4);
  88. };
  89. static_assert(sizeof(SaveCalData) == 0x14, "SaveCalData is an invalid size");
  90. static_assert(std::is_trivially_copyable_v<SaveCalData>,
  91. "SaveCalData must be trivially copyable");
  92. struct FirmwareVersionReply {
  93. DataValid status;
  94. FirmwareVersion firmware;
  95. INSERT_PADDING_BYTES(0x2);
  96. };
  97. static_assert(sizeof(FirmwareVersionReply) == 0x8, "FirmwareVersionReply is an invalid size");
  98. struct Cmd020105Reply {
  99. DataValid status;
  100. u8 data;
  101. INSERT_PADDING_BYTES(0x3);
  102. };
  103. static_assert(sizeof(Cmd020105Reply) == 0x8, "Cmd020105Reply is an invalid size");
  104. struct StatusReply {
  105. DataValid status;
  106. };
  107. static_assert(sizeof(StatusReply) == 0x4, "StatusReply is an invalid size");
  108. struct GetThreeByteReply {
  109. DataValid status;
  110. std::array<u8, 3> data;
  111. u8 crc;
  112. };
  113. static_assert(sizeof(GetThreeByteReply) == 0x8, "GetThreeByteReply is an invalid size");
  114. struct ReadUnkCalReply {
  115. DataValid status;
  116. u16 data;
  117. INSERT_PADDING_BYTES(0x2);
  118. };
  119. static_assert(sizeof(ReadUnkCalReply) == 0x8, "ReadUnkCalReply is an invalid size");
  120. struct ReadFactoryCalReply {
  121. DataValid status;
  122. FactoryCalibration calibration;
  123. };
  124. static_assert(sizeof(ReadFactoryCalReply) == 0x14, "ReadFactoryCalReply is an invalid size");
  125. struct ReadUserCalReply {
  126. DataValid status;
  127. UserCalibration calibration;
  128. INSERT_PADDING_BYTES(0x4);
  129. };
  130. static_assert(sizeof(ReadUserCalReply) == 0x14, "ReadUserCalReply is an invalid size");
  131. struct ReadIdReply {
  132. DataValid status;
  133. u16 id_l_x0;
  134. u16 id_l_x0_2;
  135. u16 id_l_x4;
  136. u16 id_h_x0;
  137. u16 id_h_x0_2;
  138. u16 id_h_x4;
  139. };
  140. static_assert(sizeof(ReadIdReply) == 0x10, "ReadIdReply is an invalid size");
  141. struct ErrorReply {
  142. DataValid status;
  143. INSERT_PADDING_BYTES(0x3);
  144. };
  145. static_assert(sizeof(ErrorReply) == 0x8, "ErrorReply is an invalid size");
  146. struct RingConData {
  147. DataValid status;
  148. s16_le data;
  149. INSERT_PADDING_BYTES(0x2);
  150. };
  151. static_assert(sizeof(RingConData) == 0x8, "RingConData is an invalid size");
  152. // Returns RingConData struct with pressure sensor values
  153. RingConData GetSensorValue() const;
  154. // Returns 8 byte reply with firmware version
  155. std::vector<u8> GetFirmwareVersionReply() const;
  156. // Returns 16 byte reply with ID values
  157. std::vector<u8> GetReadIdReply() const;
  158. // (STUBBED) Returns 8 byte reply
  159. std::vector<u8> GetC020105Reply() const;
  160. // (STUBBED) Returns 8 byte empty reply
  161. std::vector<u8> GetReadUnkCalReply() const;
  162. // Returns 20 byte reply with factory calibration values
  163. std::vector<u8> GetReadFactoryCalReply() const;
  164. // Returns 20 byte reply with user calibration values
  165. std::vector<u8> GetReadUserCalReply() const;
  166. // Returns 8 byte reply
  167. std::vector<u8> GetReadRepCountReply() const;
  168. // Returns 8 byte reply
  169. std::vector<u8> GetReadTotalPushCountReply() const;
  170. // Returns 8 byte reply
  171. std::vector<u8> GetResetRepCountReply() const;
  172. // Returns 4 byte save data reply
  173. std::vector<u8> GetSaveDataReply() const;
  174. // Returns 8 byte error reply
  175. std::vector<u8> GetErrorReply() const;
  176. // Returns 8 bit redundancy check from provided data
  177. u8 GetCrcValue(const std::vector<u8>& data) const;
  178. // Converts structs to an u8 vector equivalent
  179. template <typename T>
  180. std::vector<u8> GetDataVector(const T& reply) const;
  181. RingConCommands command{RingConCommands::Error};
  182. // These counters are used in multitasking mode while the switch is sleeping
  183. // Total steps taken
  184. u8 total_rep_count = 0;
  185. // Total times the ring was pushed
  186. u8 total_push_count = 0;
  187. const u8 device_id = 0x20;
  188. const FirmwareVersion version = {
  189. .sub = 0x0,
  190. .main = 0x2c,
  191. };
  192. const FactoryCalibration factory_calibration = {
  193. .os_max = idle_value + range + idle_deadzone,
  194. .hk_max = idle_value - range - idle_deadzone,
  195. .zero_min = idle_value - idle_deadzone,
  196. .zero_max = idle_value + idle_deadzone,
  197. };
  198. UserCalibration user_calibration = {
  199. .os_max = {.value = range, .crc = 228},
  200. .hk_max = {.value = -range, .crc = 239},
  201. .zero = {.value = idle_value, .crc = 225},
  202. };
  203. Core::HID::EmulatedController* input;
  204. };
  205. } // namespace Service::HID