summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/input_common/drivers/joycon.cpp9
-rw-r--r--src/input_common/drivers/joycon.h3
-rw-r--r--src/input_common/helpers/joycon_protocol/common_protocol.cpp2
-rw-r--r--src/input_common/helpers/joycon_protocol/joycon_types.h2
-rw-r--r--src/input_common/helpers/joycon_protocol/nfc.cpp151
-rw-r--r--src/input_common/helpers/joycon_protocol/nfc.h6
6 files changed, 70 insertions, 103 deletions
diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp
index 8b57ebe07..653862a72 100644
--- a/src/input_common/drivers/joycon.cpp
+++ b/src/input_common/drivers/joycon.cpp
@@ -195,8 +195,8 @@ void Joycons::RegisterNewDevice(SDL_hid_device_info* device_info) {
195 OnMotionUpdate(port, type, id, value); 195 OnMotionUpdate(port, type, id, value);
196 }}, 196 }},
197 .on_ring_data = {[this](f32 ring_data) { OnRingConUpdate(ring_data); }}, 197 .on_ring_data = {[this](f32 ring_data) { OnRingConUpdate(ring_data); }},
198 .on_amiibo_data = {[this, port](const std::vector<u8>& amiibo_data) { 198 .on_amiibo_data = {[this, port, type](const std::vector<u8>& amiibo_data) {
199 OnAmiiboUpdate(port, amiibo_data); 199 OnAmiiboUpdate(port, type, amiibo_data);
200 }}, 200 }},
201 .on_camera_data = {[this, port](const std::vector<u8>& camera_data, 201 .on_camera_data = {[this, port](const std::vector<u8>& camera_data,
202 Joycon::IrsResolution format) { 202 Joycon::IrsResolution format) {
@@ -398,8 +398,9 @@ void Joycons::OnRingConUpdate(f32 ring_data) {
398 SetAxis(identifier, 100, ring_data); 398 SetAxis(identifier, 100, ring_data);
399} 399}
400 400
401void Joycons::OnAmiiboUpdate(std::size_t port, const std::vector<u8>& amiibo_data) { 401void Joycons::OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type,
402 const auto identifier = GetIdentifier(port, Joycon::ControllerType::Right); 402 const std::vector<u8>& amiibo_data) {
403 const auto identifier = GetIdentifier(port, type);
403 const auto nfc_state = amiibo_data.empty() ? Common::Input::NfcState::AmiiboRemoved 404 const auto nfc_state = amiibo_data.empty() ? Common::Input::NfcState::AmiiboRemoved
404 : Common::Input::NfcState::NewAmiibo; 405 : Common::Input::NfcState::NewAmiibo;
405 SetNfc(identifier, {nfc_state, amiibo_data}); 406 SetNfc(identifier, {nfc_state, amiibo_data});
diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h
index 5b40817e2..e3f0ad78f 100644
--- a/src/input_common/drivers/joycon.h
+++ b/src/input_common/drivers/joycon.h
@@ -81,7 +81,8 @@ private:
81 void OnMotionUpdate(std::size_t port, Joycon::ControllerType type, int id, 81 void OnMotionUpdate(std::size_t port, Joycon::ControllerType type, int id,
82 const Joycon::MotionData& value); 82 const Joycon::MotionData& value);
83 void OnRingConUpdate(f32 ring_data); 83 void OnRingConUpdate(f32 ring_data);
84 void OnAmiiboUpdate(std::size_t port, const std::vector<u8>& amiibo_data); 84 void OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type,
85 const std::vector<u8>& amiibo_data);
85 void OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data, 86 void OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data,
86 Joycon::IrsResolution format); 87 Joycon::IrsResolution format);
87 88
diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
index 077d72cd0..51669261a 100644
--- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp
+++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp
@@ -265,7 +265,7 @@ DriverResult JoyconCommonProtocol::SendMCUData(ReportMode report_mode, MCUSubCom
265 265
266DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMode mode) { 266DriverResult JoyconCommonProtocol::WaitSetMCUMode(ReportMode report_mode, MCUMode mode) {
267 MCUCommandResponse output{}; 267 MCUCommandResponse output{};
268 constexpr std::size_t MaxTries{8}; 268 constexpr std::size_t MaxTries{16};
269 std::size_t tries{}; 269 std::size_t tries{};
270 270
271 do { 271 do {
diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h
index 1c8d294b0..353dc744d 100644
--- a/src/input_common/helpers/joycon_protocol/joycon_types.h
+++ b/src/input_common/helpers/joycon_protocol/joycon_types.h
@@ -577,8 +577,8 @@ static_assert(sizeof(NFCPollingCommandData) == 0x05, "NFCPollingCommandData is a
577 577
578struct NFCRequestState { 578struct NFCRequestState {
579 NFCReadCommand command_argument; 579 NFCReadCommand command_argument;
580 u8 packet_id;
581 INSERT_PADDING_BYTES(0x1); 580 INSERT_PADDING_BYTES(0x1);
581 u8 packet_id;
582 MCUPacketFlag packet_flag; 582 MCUPacketFlag packet_flag;
583 u8 data_length; 583 u8 data_length;
584 union { 584 union {
diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp
index 14818ae33..46c9e9489 100644
--- a/src/input_common/helpers/joycon_protocol/nfc.cpp
+++ b/src/input_common/helpers/joycon_protocol/nfc.cpp
@@ -65,6 +65,20 @@ DriverResult NfcProtocol::StartNFCPollingMode() {
65 result = WaitUntilNfcIsReady(); 65 result = WaitUntilNfcIsReady();
66 } 66 }
67 if (result == DriverResult::Success) { 67 if (result == DriverResult::Success) {
68 MCUCommandResponse output{};
69 result = SendStopPollingRequest(output);
70 }
71 if (result == DriverResult::Success) {
72 result = WaitUntilNfcIsReady();
73 }
74 if (result == DriverResult::Success) {
75 MCUCommandResponse output{};
76 result = SendStartPollingRequest(output);
77 }
78 if (result == DriverResult::Success) {
79 result = WaitUntilNfcIsPolling();
80 }
81 if (result == DriverResult::Success) {
68 is_enabled = true; 82 is_enabled = true;
69 } 83 }
70 84
@@ -77,24 +91,21 @@ DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
77 } 91 }
78 update_counter = 0; 92 update_counter = 0;
79 93
80 LOG_DEBUG(Input, "Start NFC pooling Mode"); 94 LOG_DEBUG(Input, "Scan for amiibos");
81 ScopedSetBlocking sb(this); 95 ScopedSetBlocking sb(this);
82 DriverResult result{DriverResult::Success}; 96 DriverResult result{DriverResult::Success};
83 TagFoundData tag_data{}; 97 TagFoundData tag_data{};
84 98
85 if (result == DriverResult::Success) { 99 if (result == DriverResult::Success) {
86 result = StartPolling(tag_data); 100 result = IsTagInRange(tag_data);
87 }
88 if (result == DriverResult::Success) {
89 result = ReadTag(tag_data);
90 }
91 if (result == DriverResult::Success) {
92 result = WaitUntilNfcIsReady();
93 }
94 if (result == DriverResult::Success) {
95 result = StartPolling(tag_data, 7);
96 } 101 }
102
97 if (result == DriverResult::Success) { 103 if (result == DriverResult::Success) {
104 std::string uuid_string;
105 for (auto& content : tag_data.uuid) {
106 uuid_string += fmt::format(" {:02x}", content);
107 }
108 LOG_INFO(Input, "Tag detected, type={}, uuid={}", tag_data.type, uuid_string);
98 result = GetAmiiboData(data); 109 result = GetAmiiboData(data);
99 } 110 }
100 111
@@ -102,12 +113,17 @@ DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
102} 113}
103 114
104bool NfcProtocol::HasAmiibo() { 115bool NfcProtocol::HasAmiibo() {
116 if (update_counter++ < AMIIBO_UPDATE_DELAY) {
117 return true;
118 }
119 update_counter = 0;
120
105 ScopedSetBlocking sb(this); 121 ScopedSetBlocking sb(this);
106 DriverResult result{DriverResult::Success}; 122 DriverResult result{DriverResult::Success};
107 TagFoundData tag_data{}; 123 TagFoundData tag_data{};
108 124
109 if (result == DriverResult::Success) { 125 if (result == DriverResult::Success) {
110 result = StartPolling(tag_data); 126 result = IsTagInRange(tag_data, 7);
111 } 127 }
112 128
113 return result == DriverResult::Success; 129 return result == DriverResult::Success;
@@ -119,7 +135,7 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() {
119 std::size_t tries = 0; 135 std::size_t tries = 0;
120 136
121 do { 137 do {
122 auto result = SendStartWaitingRecieveRequest(output); 138 auto result = SendNextPackageRequest(output, {});
123 139
124 if (result != DriverResult::Success) { 140 if (result != DriverResult::Success) {
125 return result; 141 return result;
@@ -134,13 +150,14 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() {
134 return DriverResult::Success; 150 return DriverResult::Success;
135} 151}
136 152
137DriverResult NfcProtocol::StartPolling(TagFoundData& data, std::size_t timeout_limit) { 153DriverResult NfcProtocol::WaitUntilNfcIsPolling() {
138 LOG_DEBUG(Input, "Start Polling for tag"); 154 constexpr std::size_t timeout_limit = 10;
139 MCUCommandResponse output{}; 155 MCUCommandResponse output{};
140 std::size_t tries = 0; 156 std::size_t tries = 0;
141 157
142 do { 158 do {
143 const auto result = SendStartPollingRequest(output); 159 auto result = SendNextPackageRequest(output, {});
160
144 if (result != DriverResult::Success) { 161 if (result != DriverResult::Success) {
145 return result; 162 return result;
146 } 163 }
@@ -149,94 +166,50 @@ DriverResult NfcProtocol::StartPolling(TagFoundData& data, std::size_t timeout_l
149 } 166 }
150 } while (output.mcu_report != MCUReport::NFCState || 167 } while (output.mcu_report != MCUReport::NFCState ||
151 (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 || 168 (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 ||
152 output.mcu_data[6] != 0x09); 169 output.mcu_data[5] != 0x31 || output.mcu_data[6] != 0x01);
153
154 data.type = output.mcu_data[12];
155 data.uuid.resize(output.mcu_data[14]);
156 memcpy(data.uuid.data(), output.mcu_data.data() + 15, data.uuid.size());
157 170
158 return DriverResult::Success; 171 return DriverResult::Success;
159} 172}
160 173
161DriverResult NfcProtocol::ReadTag(const TagFoundData& data) { 174DriverResult NfcProtocol::IsTagInRange(TagFoundData& data, std::size_t timeout_limit) {
162 constexpr std::size_t timeout_limit = 10;
163 MCUCommandResponse output{}; 175 MCUCommandResponse output{};
164 std::size_t tries = 0; 176 std::size_t tries = 0;
165 177
166 std::string uuid_string; 178 do {
167 for (auto& content : data.uuid) { 179 const auto result = SendNextPackageRequest(output, {});
168 uuid_string += fmt::format(" {:02x}", content);
169 }
170
171 LOG_INFO(Input, "Tag detected, type={}, uuid={}", data.type, uuid_string);
172
173 tries = 0;
174 NFCPages ntag_pages = NFCPages::Block0;
175 // Read Tag data
176 while (true) {
177 auto result = SendReadAmiiboRequest(output, ntag_pages);
178 const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]);
179
180 if (result != DriverResult::Success) { 180 if (result != DriverResult::Success) {
181 return result; 181 return result;
182 } 182 }
183
184 if ((output.mcu_report == MCUReport::NFCReadData ||
185 output.mcu_report == MCUReport::NFCState) &&
186 nfc_status == NFCStatus::TagLost) {
187 return DriverResult::ErrorReadingData;
188 }
189
190 if (output.mcu_report == MCUReport::NFCReadData && output.mcu_data[1] == 0x07 &&
191 output.mcu_data[2] == 0x01) {
192 if (data.type != 2) {
193 continue;
194 }
195 switch (output.mcu_data[24]) {
196 case 0:
197 ntag_pages = NFCPages::Block135;
198 break;
199 case 3:
200 ntag_pages = NFCPages::Block45;
201 break;
202 case 4:
203 ntag_pages = NFCPages::Block231;
204 break;
205 default:
206 return DriverResult::ErrorReadingData;
207 }
208 continue;
209 }
210
211 if (output.mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) {
212 // finished
213 SendStopPollingRequest(output);
214 return DriverResult::Success;
215 }
216
217 // Ignore other state reports
218 if (output.mcu_report == MCUReport::NFCState) {
219 continue;
220 }
221
222 if (tries++ > timeout_limit) { 183 if (tries++ > timeout_limit) {
223 return DriverResult::Timeout; 184 return DriverResult::Timeout;
224 } 185 }
225 } 186 } while (output.mcu_report != MCUReport::NFCState ||
187 (output.mcu_data[1] << 8) + output.mcu_data[0] != 0x0500 ||
188 (output.mcu_data[6] != 0x09 && output.mcu_data[6] != 0x04));
189
190 data.type = output.mcu_data[12];
191 data.uuid.resize(output.mcu_data[14]);
192 memcpy(data.uuid.data(), output.mcu_data.data() + 15, data.uuid.size());
226 193
227 return DriverResult::Success; 194 return DriverResult::Success;
228} 195}
229 196
230DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) { 197DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
231 constexpr std::size_t timeout_limit = 10; 198 constexpr std::size_t timeout_limit = 60;
232 MCUCommandResponse output{}; 199 MCUCommandResponse output{};
233 std::size_t tries = 0; 200 std::size_t tries = 0;
234 201
235 NFCPages ntag_pages = NFCPages::Block135; 202 u8 package_index = 0;
236 std::size_t ntag_buffer_pos = 0; 203 std::size_t ntag_buffer_pos = 0;
204 auto result = SendReadAmiiboRequest(output, NFCPages::Block135);
205
206 if (result != DriverResult::Success) {
207 return result;
208 }
209
237 // Read Tag data 210 // Read Tag data
238 while (true) { 211 while (tries++ < timeout_limit) {
239 auto result = SendReadAmiiboRequest(output, ntag_pages); 212 result = SendNextPackageRequest(output, package_index);
240 const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]); 213 const auto nfc_status = static_cast<NFCStatus>(output.mcu_data[6]);
241 214
242 if (result != DriverResult::Success) { 215 if (result != DriverResult::Success) {
@@ -259,6 +232,7 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
259 memcpy(ntag_data.data() + ntag_buffer_pos, output.mcu_data.data() + 6, 232 memcpy(ntag_data.data() + ntag_buffer_pos, output.mcu_data.data() + 6,
260 payload_size); 233 payload_size);
261 } 234 }
235 package_index++;
262 continue; 236 continue;
263 } 237 }
264 238
@@ -266,18 +240,9 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
266 LOG_INFO(Input, "Finished reading amiibo"); 240 LOG_INFO(Input, "Finished reading amiibo");
267 return DriverResult::Success; 241 return DriverResult::Success;
268 } 242 }
269
270 // Ignore other state reports
271 if (output.mcu_report == MCUReport::NFCState) {
272 continue;
273 }
274
275 if (tries++ > timeout_limit) {
276 return DriverResult::Timeout;
277 }
278 } 243 }
279 244
280 return DriverResult::Success; 245 return DriverResult::Timeout;
281} 246}
282 247
283DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output) { 248DriverResult NfcProtocol::SendStartPollingRequest(MCUCommandResponse& output) {
@@ -321,10 +286,10 @@ DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandResponse& output) {
321 output); 286 output);
322} 287}
323 288
324DriverResult NfcProtocol::SendStartWaitingRecieveRequest(MCUCommandResponse& output) { 289DriverResult NfcProtocol::SendNextPackageRequest(MCUCommandResponse& output, u8 packet_id) {
325 NFCRequestState request{ 290 NFCRequestState request{
326 .command_argument = NFCReadCommand::StartWaitingRecieve, 291 .command_argument = NFCReadCommand::StartWaitingRecieve,
327 .packet_id = 0x0, 292 .packet_id = packet_id,
328 .packet_flag = MCUPacketFlag::LastCommandPacket, 293 .packet_flag = MCUPacketFlag::LastCommandPacket,
329 .data_length = 0, 294 .data_length = 0,
330 .raw_data = {}, 295 .raw_data = {},
diff --git a/src/input_common/helpers/joycon_protocol/nfc.h b/src/input_common/helpers/joycon_protocol/nfc.h
index 4cb992d1d..c9e9af03f 100644
--- a/src/input_common/helpers/joycon_protocol/nfc.h
+++ b/src/input_common/helpers/joycon_protocol/nfc.h
@@ -42,9 +42,9 @@ private:
42 42
43 DriverResult WaitUntilNfcIsReady(); 43 DriverResult WaitUntilNfcIsReady();
44 44
45 DriverResult StartPolling(TagFoundData& data, std::size_t timeout_limit = 1); 45 DriverResult WaitUntilNfcIsPolling();
46 46
47 DriverResult ReadTag(const TagFoundData& data); 47 DriverResult IsTagInRange(TagFoundData& data, std::size_t timeout_limit = 1);
48 48
49 DriverResult GetAmiiboData(std::vector<u8>& data); 49 DriverResult GetAmiiboData(std::vector<u8>& data);
50 50
@@ -52,7 +52,7 @@ private:
52 52
53 DriverResult SendStopPollingRequest(MCUCommandResponse& output); 53 DriverResult SendStopPollingRequest(MCUCommandResponse& output);
54 54
55 DriverResult SendStartWaitingRecieveRequest(MCUCommandResponse& output); 55 DriverResult SendNextPackageRequest(MCUCommandResponse& output, u8 packet_id);
56 56
57 DriverResult SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages); 57 DriverResult SendReadAmiiboRequest(MCUCommandResponse& output, NFCPages ntag_pages);
58 58