summaryrefslogtreecommitdiff
path: root/src/input_common/helpers/joycon_protocol/ringcon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/helpers/joycon_protocol/ringcon.cpp')
-rw-r--r--src/input_common/helpers/joycon_protocol/ringcon.cpp132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/input_common/helpers/joycon_protocol/ringcon.cpp b/src/input_common/helpers/joycon_protocol/ringcon.cpp
new file mode 100644
index 000000000..2d137b85d
--- /dev/null
+++ b/src/input_common/helpers/joycon_protocol/ringcon.cpp
@@ -0,0 +1,132 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/logging/log.h"
5#include "input_common/helpers/joycon_protocol/ringcon.h"
6
7namespace InputCommon::Joycon {
8
9RingConProtocol::RingConProtocol(std::shared_ptr<JoyconHandle> handle)
10 : JoyconCommonProtocol(handle) {}
11
12DriverResult RingConProtocol::EnableRingCon() {
13 LOG_DEBUG(Input, "Enable Ringcon");
14 DriverResult result{DriverResult::Success};
15 SetBlocking();
16
17 if (result == DriverResult::Success) {
18 result = SetReportMode(ReportMode::STANDARD_FULL_60HZ);
19 }
20 if (result == DriverResult::Success) {
21 result = EnableMCU(true);
22 }
23 if (result == DriverResult::Success) {
24 const MCUConfig config{
25 .command = MCUCommand::ConfigureMCU,
26 .sub_command = MCUSubCommand::SetDeviceMode,
27 .mode = MCUMode::Standby,
28 .crc = {},
29 };
30 result = ConfigureMCU(config);
31 }
32
33 SetNonBlocking();
34 return result;
35}
36
37DriverResult RingConProtocol::DisableRingCon() {
38 LOG_DEBUG(Input, "Disable RingCon");
39 DriverResult result{DriverResult::Success};
40 SetBlocking();
41
42 if (result == DriverResult::Success) {
43 result = EnableMCU(false);
44 }
45
46 is_enabled = false;
47
48 SetNonBlocking();
49 return result;
50}
51
52DriverResult RingConProtocol::StartRingconPolling() {
53 LOG_DEBUG(Input, "Enable Ringcon");
54 bool is_connected = false;
55 DriverResult result{DriverResult::Success};
56 SetBlocking();
57
58 if (result == DriverResult::Success) {
59 result = WaitSetMCUMode(ReportMode::STANDARD_FULL_60HZ, MCUMode::Standby);
60 }
61 if (result == DriverResult::Success) {
62 result = IsRingConnected(is_connected);
63 }
64 if (result == DriverResult::Success && is_connected) {
65 LOG_INFO(Input, "Ringcon detected");
66 result = ConfigureRing();
67 }
68 if (result == DriverResult::Success) {
69 is_enabled = true;
70 }
71
72 SetNonBlocking();
73 return result;
74}
75
76DriverResult RingConProtocol::IsRingConnected(bool& is_connected) {
77 LOG_DEBUG(Input, "IsRingConnected");
78 constexpr std::size_t max_tries = 28;
79 std::vector<u8> output;
80 std::size_t tries = 0;
81 is_connected = false;
82
83 do {
84 std::vector<u8> empty_data(0);
85 const auto result = SendSubCommand(SubCommand::UNKNOWN_RINGCON, empty_data, output);
86
87 if (result != DriverResult::Success) {
88 return result;
89 }
90
91 if (tries++ >= max_tries) {
92 return DriverResult::NoDeviceDetected;
93 }
94 } while (output[14] != 0x59 || output[16] != 0x20);
95
96 is_connected = true;
97 return DriverResult::Success;
98}
99
100DriverResult RingConProtocol::ConfigureRing() {
101 LOG_DEBUG(Input, "ConfigureRing");
102 constexpr std::size_t max_tries = 28;
103 DriverResult result{DriverResult::Success};
104 std::vector<u8> output;
105 std::size_t tries = 0;
106
107 do {
108 std::vector<u8> ring_config{0x06, 0x03, 0x25, 0x06, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x16,
109 0xED, 0x34, 0x36, 0x00, 0x00, 0x00, 0x0A, 0x64, 0x0B, 0xE6,
110 0xA9, 0x22, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x90, 0xA8, 0xE1, 0x34, 0x36};
112 result = SendSubCommand(SubCommand::UNKNOWN_RINGCON3, ring_config, output);
113
114 if (result != DriverResult::Success) {
115 return result;
116 }
117 if (tries++ >= max_tries) {
118 return DriverResult::NoDeviceDetected;
119 }
120 } while (output[14] != 0x5C);
121
122 std::vector<u8> ringcon_data{0x04, 0x01, 0x01, 0x02};
123 result = SendSubCommand(SubCommand::UNKNOWN_RINGCON2, ringcon_data, output);
124
125 return result;
126}
127
128bool RingConProtocol::IsEnabled() {
129 return is_enabled;
130}
131
132} // namespace InputCommon::Joycon