summaryrefslogtreecommitdiff
path: root/src/input_common/helpers/joycon_protocol/nfc.cpp
diff options
context:
space:
mode:
authorGravatar german772023-01-13 23:29:05 -0600
committerGravatar Narr the Reg2023-01-20 00:51:45 -0600
commit340f15d1fa79594dbe12a6e19140ba012751b533 (patch)
tree7a9ef54a17f927e4b8cf98dd32dd6d41c0d75201 /src/input_common/helpers/joycon_protocol/nfc.cpp
parentcore: hid: Only set the polling mode to the correct side (diff)
downloadyuzu-340f15d1fa79594dbe12a6e19140ba012751b533.tar.gz
yuzu-340f15d1fa79594dbe12a6e19140ba012751b533.tar.xz
yuzu-340f15d1fa79594dbe12a6e19140ba012751b533.zip
input_common: Address byte review
Diffstat (limited to 'src/input_common/helpers/joycon_protocol/nfc.cpp')
-rw-r--r--src/input_common/helpers/joycon_protocol/nfc.cpp183
1 files changed, 84 insertions, 99 deletions
diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp
index 8755e310b..5c0f71722 100644
--- a/src/input_common/helpers/joycon_protocol/nfc.cpp
+++ b/src/input_common/helpers/joycon_protocol/nfc.cpp
@@ -12,8 +12,8 @@ NfcProtocol::NfcProtocol(std::shared_ptr<JoyconHandle> handle)
12 12
13DriverResult NfcProtocol::EnableNfc() { 13DriverResult NfcProtocol::EnableNfc() {
14 LOG_INFO(Input, "Enable NFC"); 14 LOG_INFO(Input, "Enable NFC");
15 ScopedSetBlocking sb(this);
15 DriverResult result{DriverResult::Success}; 16 DriverResult result{DriverResult::Success};
16 SetBlocking();
17 17
18 if (result == DriverResult::Success) { 18 if (result == DriverResult::Success) {
19 result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ); 19 result = SetReportMode(ReportMode::NFC_IR_MODE_60HZ);
@@ -35,14 +35,13 @@ DriverResult NfcProtocol::EnableNfc() {
35 result = ConfigureMCU(config); 35 result = ConfigureMCU(config);
36 } 36 }
37 37
38 SetNonBlocking();
39 return result; 38 return result;
40} 39}
41 40
42DriverResult NfcProtocol::DisableNfc() { 41DriverResult NfcProtocol::DisableNfc() {
43 LOG_DEBUG(Input, "Disable NFC"); 42 LOG_DEBUG(Input, "Disable NFC");
43 ScopedSetBlocking sb(this);
44 DriverResult result{DriverResult::Success}; 44 DriverResult result{DriverResult::Success};
45 SetBlocking();
46 45
47 if (result == DriverResult::Success) { 46 if (result == DriverResult::Success) {
48 result = EnableMCU(false); 47 result = EnableMCU(false);
@@ -50,15 +49,14 @@ DriverResult NfcProtocol::DisableNfc() {
50 49
51 is_enabled = false; 50 is_enabled = false;
52 51
53 SetNonBlocking();
54 return result; 52 return result;
55} 53}
56 54
57DriverResult NfcProtocol::StartNFCPollingMode() { 55DriverResult NfcProtocol::StartNFCPollingMode() {
58 LOG_DEBUG(Input, "Start NFC pooling Mode"); 56 LOG_DEBUG(Input, "Start NFC pooling Mode");
57 ScopedSetBlocking sb(this);
59 DriverResult result{DriverResult::Success}; 58 DriverResult result{DriverResult::Success};
60 TagFoundData tag_data{}; 59 TagFoundData tag_data{};
61 SetBlocking();
62 60
63 if (result == DriverResult::Success) { 61 if (result == DriverResult::Success) {
64 result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC); 62 result = WaitSetMCUMode(ReportMode::NFC_IR_MODE_60HZ, MCUMode::NFC);
@@ -70,15 +68,14 @@ DriverResult NfcProtocol::StartNFCPollingMode() {
70 is_enabled = true; 68 is_enabled = true;
71 } 69 }
72 70
73 SetNonBlocking();
74 return result; 71 return result;
75} 72}
76 73
77DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) { 74DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
78 LOG_DEBUG(Input, "Start NFC pooling Mode"); 75 LOG_DEBUG(Input, "Start NFC pooling Mode");
76 ScopedSetBlocking sb(this);
79 DriverResult result{DriverResult::Success}; 77 DriverResult result{DriverResult::Success};
80 TagFoundData tag_data{}; 78 TagFoundData tag_data{};
81 SetBlocking();
82 79
83 if (result == DriverResult::Success) { 80 if (result == DriverResult::Success) {
84 result = StartPolling(tag_data); 81 result = StartPolling(tag_data);
@@ -96,20 +93,18 @@ DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
96 result = GetAmiiboData(data); 93 result = GetAmiiboData(data);
97 } 94 }
98 95
99 SetNonBlocking();
100 return result; 96 return result;
101} 97}
102 98
103bool NfcProtocol::HasAmiibo() { 99bool NfcProtocol::HasAmiibo() {
100 ScopedSetBlocking sb(this);
104 DriverResult result{DriverResult::Success}; 101 DriverResult result{DriverResult::Success};
105 TagFoundData tag_data{}; 102 TagFoundData tag_data{};
106 SetBlocking();
107 103
108 if (result == DriverResult::Success) { 104 if (result == DriverResult::Success) {
109 result = StartPolling(tag_data); 105 result = StartPolling(tag_data);
110 } 106 }
111 107
112 SetNonBlocking();
113 return result == DriverResult::Success; 108 return result == DriverResult::Success;
114} 109}
115 110
@@ -169,55 +164,53 @@ DriverResult NfcProtocol::ReadTag(const TagFoundData& data) {
169 LOG_INFO(Input, "Tag detected, type={}, uuid={}", data.type, uuid_string); 164 LOG_INFO(Input, "Tag detected, type={}, uuid={}", data.type, uuid_string);
170 165
171 tries = 0; 166 tries = 0;
172 std::size_t ntag_pages = 0; 167 NFCPages ntag_pages = NFCPages::Block0;
173 // Read Tag data 168 // Read Tag data
174loop1:
175 while (true) { 169 while (true) {
176 auto result = SendReadAmiiboRequest(output, ntag_pages); 170 auto result = SendReadAmiiboRequest(output, ntag_pages);
171 const auto mcu_report = static_cast<MCUReport>(output[49]);
172 const auto nfc_status = static_cast<NFCStatus>(output[56]);
177 173
178 int attempt = 0; 174 if (result != DriverResult::Success) {
179 while (1) { 175 return result;
180 if (attempt != 0) { 176 }
181 result = GetMCUDataResponse(ReportMode::NFC_IR_MODE_60HZ, output); 177
178 if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) &&
179 nfc_status == NFCStatus::TagLost) {
180 return DriverResult::ErrorReadingData;
181 }
182
183 if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07 && output[52] == 0x01) {
184 if (data.type != 2) {
185 continue;
182 } 186 }
183 if ((output[49] == 0x3a || output[49] == 0x2a) && output[56] == 0x07) { 187 switch (output[74]) {
188 case 0:
189 ntag_pages = NFCPages::Block135;
190 break;
191 case 3:
192 ntag_pages = NFCPages::Block45;
193 break;
194 case 4:
195 ntag_pages = NFCPages::Block231;
196 break;
197 default:
184 return DriverResult::ErrorReadingData; 198 return DriverResult::ErrorReadingData;
185 } 199 }
186 if (output[49] == 0x3a && output[51] == 0x07 && output[52] == 0x01) { 200 continue;
187 if (data.type != 2) {
188 goto loop1;
189 }
190 switch (output[74]) {
191 case 0:
192 ntag_pages = 135;
193 break;
194 case 3:
195 ntag_pages = 45;
196 break;
197 case 4:
198 ntag_pages = 231;
199 break;
200 default:
201 return DriverResult::ErrorReadingData;
202 }
203 goto loop1;
204 }
205 if (output[49] == 0x2a && output[56] == 0x04) {
206 // finished
207 SendStopPollingRequest(output);
208 return DriverResult::Success;
209 }
210 if (output[49] == 0x2a) {
211 goto loop1;
212 }
213 if (attempt++ > 6) {
214 goto loop1;
215 }
216 } 201 }
217 202
218 if (result != DriverResult::Success) { 203 if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) {
219 return result; 204 // finished
205 SendStopPollingRequest(output);
206 return DriverResult::Success;
207 }
208
209 // Ignore other state reports
210 if (mcu_report == MCUReport::NFCState) {
211 continue;
220 } 212 }
213
221 if (tries++ > timeout_limit) { 214 if (tries++ > timeout_limit) {
222 return DriverResult::Timeout; 215 return DriverResult::Timeout;
223 } 216 }
@@ -231,47 +224,44 @@ DriverResult NfcProtocol::GetAmiiboData(std::vector<u8>& ntag_data) {
231 std::vector<u8> output; 224 std::vector<u8> output;
232 std::size_t tries = 0; 225 std::size_t tries = 0;
233 226
234 std::size_t ntag_pages = 135; 227 NFCPages ntag_pages = NFCPages::Block135;
235 std::size_t ntag_buffer_pos = 0; 228 std::size_t ntag_buffer_pos = 0;
236 // Read Tag data 229 // Read Tag data
237loop1:
238 while (true) { 230 while (true) {
239 auto result = SendReadAmiiboRequest(output, ntag_pages); 231 auto result = SendReadAmiiboRequest(output, ntag_pages);
232 const auto mcu_report = static_cast<MCUReport>(output[49]);
233 const auto nfc_status = static_cast<NFCStatus>(output[56]);
240 234
241 int attempt = 0; 235 if (result != DriverResult::Success) {
242 while (1) { 236 return result;
243 if (attempt != 0) { 237 }
244 result = GetMCUDataResponse(ReportMode::NFC_IR_MODE_60HZ, output); 238
245 } 239 if ((mcu_report == MCUReport::NFCReadData || mcu_report == MCUReport::NFCState) &&
246 if ((output[49] == 0x3a || output[49] == 0x2a) && output[56] == 0x07) { 240 nfc_status == NFCStatus::TagLost) {
247 return DriverResult::ErrorReadingData; 241 return DriverResult::ErrorReadingData;
248 } 242 }
249 if (output[49] == 0x3a && output[51] == 0x07) { 243
250 std::size_t payload_size = (output[54] << 8 | output[55]) & 0x7FF; 244 if (mcu_report == MCUReport::NFCReadData && output[51] == 0x07) {
251 if (output[52] == 0x01) { 245 std::size_t payload_size = (output[54] << 8 | output[55]) & 0x7FF;
252 memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 116, 246 if (output[52] == 0x01) {
253 payload_size - 60); 247 memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 116, payload_size - 60);
254 ntag_buffer_pos += payload_size - 60; 248 ntag_buffer_pos += payload_size - 60;
255 } else { 249 } else {
256 memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 56, payload_size); 250 memcpy(ntag_data.data() + ntag_buffer_pos, output.data() + 56, payload_size);
257 }
258 goto loop1;
259 }
260 if (output[49] == 0x2a && output[56] == 0x04) {
261 LOG_INFO(Input, "Finished reading amiibo");
262 return DriverResult::Success;
263 }
264 if (output[49] == 0x2a) {
265 goto loop1;
266 }
267 if (attempt++ > 4) {
268 goto loop1;
269 } 251 }
252 continue;
270 } 253 }
271 254
272 if (result != DriverResult::Success) { 255 if (mcu_report == MCUReport::NFCState && nfc_status == NFCStatus::LastPackage) {
273 return result; 256 LOG_INFO(Input, "Finished reading amiibo");
257 return DriverResult::Success;
258 }
259
260 // Ignore other state reports
261 if (mcu_report == MCUReport::NFCState) {
262 continue;
274 } 263 }
264
275 if (tries++ > timeout_limit) { 265 if (tries++ > timeout_limit) {
276 return DriverResult::Timeout; 266 return DriverResult::Timeout;
277 } 267 }
@@ -298,7 +288,7 @@ DriverResult NfcProtocol::SendStartPollingRequest(std::vector<u8>& output) {
298 .crc = {}, 288 .crc = {},
299 }; 289 };
300 290
301 std::vector<u8> request_data(sizeof(NFCRequestState)); 291 std::array<u8, sizeof(NFCRequestState)> request_data{};
302 memcpy(request_data.data(), &request, sizeof(NFCRequestState)); 292 memcpy(request_data.data(), &request, sizeof(NFCRequestState));
303 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); 293 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
304 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); 294 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
@@ -315,7 +305,7 @@ DriverResult NfcProtocol::SendStopPollingRequest(std::vector<u8>& output) {
315 .crc = {}, 305 .crc = {},
316 }; 306 };
317 307
318 std::vector<u8> request_data(sizeof(NFCRequestState)); 308 std::array<u8, sizeof(NFCRequestState)> request_data{};
319 memcpy(request_data.data(), &request, sizeof(NFCRequestState)); 309 memcpy(request_data.data(), &request, sizeof(NFCRequestState));
320 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); 310 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
321 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); 311 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
@@ -338,7 +328,7 @@ DriverResult NfcProtocol::SendStartWaitingRecieveRequest(std::vector<u8>& output
338 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); 328 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
339} 329}
340 330
341DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, std::size_t ntag_pages) { 331DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, NFCPages ntag_pages) {
342 NFCRequestState request{ 332 NFCRequestState request{
343 .sub_command = MCUSubCommand::ReadDeviceMode, 333 .sub_command = MCUSubCommand::ReadDeviceMode,
344 .command_argument = NFCReadCommand::Ntag, 334 .command_argument = NFCReadCommand::Ntag,
@@ -357,20 +347,19 @@ DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, std::si
357 .crc = {}, 347 .crc = {},
358 }; 348 };
359 349
360 std::vector<u8> request_data(sizeof(NFCRequestState)); 350 std::array<u8, sizeof(NFCRequestState)> request_data{};
361 memcpy(request_data.data(), &request, sizeof(NFCRequestState)); 351 memcpy(request_data.data(), &request, sizeof(NFCRequestState));
362 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36); 352 request_data[37] = CalculateMCU_CRC8(request_data.data() + 1, 36);
363 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output); 353 return SendMCUData(ReportMode::NFC_IR_MODE_60HZ, SubCommand::STATE, request_data, output);
364} 354}
365 355
366NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const { 356NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(NFCPages pages) const {
367 if (pages == 0) { 357 switch (pages) {
358 case NFCPages::Block0:
368 return { 359 return {
369 .block_count = 1, 360 .block_count = 1,
370 }; 361 };
371 } 362 case NFCPages::Block45:
372
373 if (pages == 45) {
374 return { 363 return {
375 .block_count = 1, 364 .block_count = 1,
376 .blocks = 365 .blocks =
@@ -378,9 +367,7 @@ NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const {
378 NFCReadBlock{0x00, 0x2C}, 367 NFCReadBlock{0x00, 0x2C},
379 }, 368 },
380 }; 369 };
381 } 370 case NFCPages::Block135:
382
383 if (pages == 135) {
384 return { 371 return {
385 .block_count = 3, 372 .block_count = 3,
386 .blocks = 373 .blocks =
@@ -390,9 +377,7 @@ NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const {
390 {0x78, 0x86}, 377 {0x78, 0x86},
391 }, 378 },
392 }; 379 };
393 } 380 case NFCPages::Block231:
394
395 if (pages == 231) {
396 return { 381 return {
397 .block_count = 4, 382 .block_count = 4,
398 .blocks = 383 .blocks =
@@ -403,9 +388,9 @@ NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const {
403 {0xb4, 0xe6}, 388 {0xb4, 0xe6},
404 }, 389 },
405 }; 390 };
406 } 391 default:
407 392 return {};
408 return {}; 393 };
409} 394}
410 395
411bool NfcProtocol::IsEnabled() const { 396bool NfcProtocol::IsEnabled() const {