diff options
Diffstat (limited to 'src/input_common/helpers/joycon_protocol/nfc.cpp')
| -rw-r--r-- | src/input_common/helpers/joycon_protocol/nfc.cpp | 183 |
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 | ||
| 13 | DriverResult NfcProtocol::EnableNfc() { | 13 | DriverResult 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 | ||
| 42 | DriverResult NfcProtocol::DisableNfc() { | 41 | DriverResult 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 | ||
| 57 | DriverResult NfcProtocol::StartNFCPollingMode() { | 55 | DriverResult 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 | ||
| 77 | DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) { | 74 | DriverResult 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 | ||
| 103 | bool NfcProtocol::HasAmiibo() { | 99 | bool 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 |
| 174 | loop1: | ||
| 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 |
| 237 | loop1: | ||
| 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 | ||
| 341 | DriverResult NfcProtocol::SendReadAmiiboRequest(std::vector<u8>& output, std::size_t ntag_pages) { | 331 | DriverResult 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 | ||
| 366 | NFCReadBlockCommand NfcProtocol::GetReadBlockCommand(std::size_t pages) const { | 356 | NFCReadBlockCommand 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 | ||
| 411 | bool NfcProtocol::IsEnabled() const { | 396 | bool NfcProtocol::IsEnabled() const { |