summaryrefslogtreecommitdiffstats
path: root/src/input_common/drivers
diff options
context:
space:
mode:
authorNarr the Reg <juangerman-13@hotmail.com>2023-06-17 05:57:21 +0200
committerNarr the Reg <juangerman-13@hotmail.com>2023-06-22 01:54:58 +0200
commit84d43489c5df9f450efb0293cc58161d08e3b882 (patch)
treec4d45b021c78392956dc58d409a34632fe135d2b /src/input_common/drivers
parentMerge pull request #10783 from liamwhite/memory (diff)
downloadyuzu-84d43489c5df9f450efb0293cc58161d08e3b882.tar
yuzu-84d43489c5df9f450efb0293cc58161d08e3b882.tar.gz
yuzu-84d43489c5df9f450efb0293cc58161d08e3b882.tar.bz2
yuzu-84d43489c5df9f450efb0293cc58161d08e3b882.tar.lz
yuzu-84d43489c5df9f450efb0293cc58161d08e3b882.tar.xz
yuzu-84d43489c5df9f450efb0293cc58161d08e3b882.tar.zst
yuzu-84d43489c5df9f450efb0293cc58161d08e3b882.zip
Diffstat (limited to '')
-rw-r--r--src/input_common/drivers/joycon.cpp133
-rw-r--r--src/input_common/drivers/joycon.h18
-rw-r--r--src/input_common/drivers/virtual_amiibo.cpp130
-rw-r--r--src/input_common/drivers/virtual_amiibo.h16
4 files changed, 271 insertions, 26 deletions
diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp
index b2b5677c8..52494e0d9 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) {
OnMotionUpdate(port, type, id, value);
}},
.on_ring_data = {[this](f32 ring_data) { OnRingConUpdate(ring_data); }},
- .on_amiibo_data = {[this, port, type](const std::vector<u8>& amiibo_data) {
- OnAmiiboUpdate(port, type, amiibo_data);
+ .on_amiibo_data = {[this, port, type](const Joycon::TagInfo& tag_info) {
+ OnAmiiboUpdate(port, type, tag_info);
}},
.on_camera_data = {[this, port](const std::vector<u8>& camera_data,
Joycon::IrsResolution format) {
@@ -291,13 +291,105 @@ Common::Input::NfcState Joycons::SupportsNfc(const PadIdentifier& identifier_) c
return Common::Input::NfcState::Success;
};
+Common::Input::NfcState Joycons::StartNfcPolling(const PadIdentifier& identifier) {
+ auto handle = GetHandle(identifier);
+ if (handle == nullptr) {
+ return Common::Input::NfcState::Unknown;
+ }
+ return TranslateDriverResult(handle->StartNfcPolling());
+};
+
+Common::Input::NfcState Joycons::StopNfcPolling(const PadIdentifier& identifier) {
+ auto handle = GetHandle(identifier);
+ if (handle == nullptr) {
+ return Common::Input::NfcState::Unknown;
+ }
+ return TranslateDriverResult(handle->StopNfcPolling());
+};
+
+Common::Input::NfcState Joycons::ReadAmiiboData(const PadIdentifier& identifier,
+ std::vector<u8>& out_data) {
+ auto handle = GetHandle(identifier);
+ if (handle == nullptr) {
+ return Common::Input::NfcState::Unknown;
+ }
+ return TranslateDriverResult(handle->ReadAmiiboData(out_data));
+}
+
Common::Input::NfcState Joycons::WriteNfcData(const PadIdentifier& identifier,
const std::vector<u8>& data) {
auto handle = GetHandle(identifier);
- if (handle->WriteNfcData(data) != Joycon::DriverResult::Success) {
- return Common::Input::NfcState::WriteFailed;
+ if (handle == nullptr) {
+ return Common::Input::NfcState::Unknown;
}
- return Common::Input::NfcState::Success;
+ return TranslateDriverResult(handle->WriteNfcData(data));
+};
+
+Common::Input::NfcState Joycons::ReadMifareData(const PadIdentifier& identifier,
+ const Common::Input::MifareRequest& request,
+ Common::Input::MifareRequest& data) {
+ auto handle = GetHandle(identifier);
+ if (handle == nullptr) {
+ return Common::Input::NfcState::Unknown;
+ }
+
+ const auto command = static_cast<Joycon::MifareCmd>(request.data[0].command);
+ std::vector<Joycon::MifareReadChunk> read_request{};
+ for (const auto& request_data : request.data) {
+ if (request_data.command == 0) {
+ continue;
+ }
+ Joycon::MifareReadChunk chunk = {
+ .command = command,
+ .sector_key = {},
+ .sector = request_data.sector,
+ };
+ memcpy(chunk.sector_key.data(), request_data.key.data(),
+ sizeof(Joycon::MifareReadChunk::sector_key));
+ read_request.emplace_back(chunk);
+ }
+
+ std::vector<Joycon::MifareReadData> read_data(read_request.size());
+ const auto result = handle->ReadMifareData(read_request, read_data);
+ if (result == Joycon::DriverResult::Success) {
+ for (std::size_t i = 0; i < read_request.size(); i++) {
+ data.data[i] = {
+ .command = static_cast<u8>(command),
+ .sector = read_data[i].sector,
+ .key = {},
+ .data = read_data[i].data,
+ };
+ }
+ }
+ return TranslateDriverResult(result);
+};
+
+Common::Input::NfcState Joycons::WriteMifareData(const PadIdentifier& identifier,
+ const Common::Input::MifareRequest& request) {
+ auto handle = GetHandle(identifier);
+ if (handle == nullptr) {
+ return Common::Input::NfcState::Unknown;
+ }
+
+ const auto command = static_cast<Joycon::MifareCmd>(request.data[0].command);
+ std::vector<Joycon::MifareWriteChunk> write_request{};
+ for (const auto& request_data : request.data) {
+ if (request_data.command == 0) {
+ continue;
+ }
+ Joycon::MifareWriteChunk chunk = {
+ .command = command,
+ .sector_key = {},
+ .sector = request_data.sector,
+ .data = {},
+ };
+ memcpy(chunk.sector_key.data(), request_data.key.data(),
+ sizeof(Joycon::MifareReadChunk::sector_key));
+ memcpy(chunk.data.data(), request_data.data.data(), sizeof(Joycon::MifareWriteChunk::data));
+ write_request.emplace_back(chunk);
+ }
+
+ return TranslateDriverResult(handle->WriteMifareData(write_request));
};
Common::Input::DriverResult Joycons::SetPollingMode(const PadIdentifier& identifier,
@@ -403,11 +495,20 @@ void Joycons::OnRingConUpdate(f32 ring_data) {
}
void Joycons::OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type,
- const std::vector<u8>& amiibo_data) {
+ const Joycon::TagInfo& tag_info) {
const auto identifier = GetIdentifier(port, type);
- const auto nfc_state = amiibo_data.empty() ? Common::Input::NfcState::AmiiboRemoved
- : Common::Input::NfcState::NewAmiibo;
- SetNfc(identifier, {nfc_state, amiibo_data});
+ const auto nfc_state = tag_info.uuid_length == 0 ? Common::Input::NfcState::AmiiboRemoved
+ : Common::Input::NfcState::NewAmiibo;
+
+ const Common::Input::NfcStatus nfc_status{
+ .state = nfc_state,
+ .uuid_length = tag_info.uuid_length,
+ .protocol = tag_info.protocol,
+ .tag_type = tag_info.tag_type,
+ .uuid = tag_info.uuid,
+ };
+
+ SetNfc(identifier, nfc_status);
}
void Joycons::OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data,
@@ -726,4 +827,18 @@ std::string Joycons::JoyconName(Joycon::ControllerType type) const {
return "Unknown Switch Controller";
}
}
+
+Common::Input::NfcState Joycons::TranslateDriverResult(Joycon::DriverResult result) const {
+ switch (result) {
+ case Joycon::DriverResult::Success:
+ return Common::Input::NfcState::Success;
+ case Joycon::DriverResult::Disabled:
+ return Common::Input::NfcState::WrongDeviceState;
+ case Joycon::DriverResult::NotSupported:
+ return Common::Input::NfcState::NotSupported;
+ default:
+ return Common::Input::NfcState::Unknown;
+ }
+}
+
} // namespace InputCommon
diff --git a/src/input_common/drivers/joycon.h b/src/input_common/drivers/joycon.h
index e3f0ad78f..4c323d7d6 100644
--- a/src/input_common/drivers/joycon.h
+++ b/src/input_common/drivers/joycon.h
@@ -15,6 +15,7 @@ using SerialNumber = std::array<u8, 15>;
struct Battery;
struct Color;
struct MotionData;
+struct TagInfo;
enum class ControllerType : u8;
enum class DriverResult;
enum class IrsResolution;
@@ -39,9 +40,18 @@ public:
Common::Input::DriverResult SetCameraFormat(const PadIdentifier& identifier,
Common::Input::CameraFormat camera_format) override;
- Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override;
- Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_,
+ Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier) const override;
+ Common::Input::NfcState StartNfcPolling(const PadIdentifier& identifier) override;
+ Common::Input::NfcState StopNfcPolling(const PadIdentifier& identifier) override;
+ Common::Input::NfcState ReadAmiiboData(const PadIdentifier& identifier,
+ std::vector<u8>& out_data) override;
+ Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier,
const std::vector<u8>& data) override;
+ Common::Input::NfcState ReadMifareData(const PadIdentifier& identifier,
+ const Common::Input::MifareRequest& request,
+ Common::Input::MifareRequest& out_data) override;
+ Common::Input::NfcState WriteMifareData(const PadIdentifier& identifier,
+ const Common::Input::MifareRequest& request) override;
Common::Input::DriverResult SetPollingMode(
const PadIdentifier& identifier, const Common::Input::PollingMode polling_mode) override;
@@ -82,7 +92,7 @@ private:
const Joycon::MotionData& value);
void OnRingConUpdate(f32 ring_data);
void OnAmiiboUpdate(std::size_t port, Joycon::ControllerType type,
- const std::vector<u8>& amiibo_data);
+ const Joycon::TagInfo& amiibo_data);
void OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data,
Joycon::IrsResolution format);
@@ -102,6 +112,8 @@ private:
/// Returns the name of the device in text format
std::string JoyconName(Joycon::ControllerType type) const;
+ Common::Input::NfcState TranslateDriverResult(Joycon::DriverResult result) const;
+
std::jthread scan_thread;
// Joycon types are split by type to ease supporting dualjoycon configurations
diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp
index 6435b8af8..180eb53ef 100644
--- a/src/input_common/drivers/virtual_amiibo.cpp
+++ b/src/input_common/drivers/virtual_amiibo.cpp
@@ -29,14 +29,13 @@ Common::Input::DriverResult VirtualAmiibo::SetPollingMode(
switch (polling_mode) {
case Common::Input::PollingMode::NFC:
- if (state == State::Initialized) {
- state = State::WaitingForAmiibo;
- }
+ state = State::Initialized;
return Common::Input::DriverResult::Success;
default:
- if (state == State::AmiiboIsOpen) {
+ if (state == State::TagNearby) {
CloseAmiibo();
}
+ state = State::Disabled;
return Common::Input::DriverResult::NotSupported;
}
}
@@ -45,6 +44,39 @@ Common::Input::NfcState VirtualAmiibo::SupportsNfc(
[[maybe_unused]] const PadIdentifier& identifier_) const {
return Common::Input::NfcState::Success;
}
+Common::Input::NfcState VirtualAmiibo::StartNfcPolling(const PadIdentifier& identifier_) {
+ if (state != State::Initialized) {
+ return Common::Input::NfcState::WrongDeviceState;
+ }
+ state = State::WaitingForAmiibo;
+ return Common::Input::NfcState::Success;
+}
+
+Common::Input::NfcState VirtualAmiibo::StopNfcPolling(const PadIdentifier& identifier_) {
+ if (state == State::Disabled) {
+ return Common::Input::NfcState::WrongDeviceState;
+ }
+ if (state == State::TagNearby) {
+ CloseAmiibo();
+ }
+ state = State::Initialized;
+ return Common::Input::NfcState::Success;
+}
+
+Common::Input::NfcState VirtualAmiibo::ReadAmiiboData(const PadIdentifier& identifier_,
+ std::vector<u8>& out_data) {
+ if (state != State::TagNearby) {
+ return Common::Input::NfcState::WrongDeviceState;
+ }
+
+ if (status.tag_type != 1U << 1) {
+ return Common::Input::NfcState::InvalidTagType;
+ }
+
+ out_data.resize(nfc_data.size());
+ memcpy(out_data.data(), nfc_data.data(), nfc_data.size());
+ return Common::Input::NfcState::Success;
+}
Common::Input::NfcState VirtualAmiibo::WriteNfcData(
[[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) {
@@ -66,6 +98,69 @@ Common::Input::NfcState VirtualAmiibo::WriteNfcData(
return Common::Input::NfcState::Success;
}
+Common::Input::NfcState VirtualAmiibo::ReadMifareData(const PadIdentifier& identifier_,
+ const Common::Input::MifareRequest& request,
+ Common::Input::MifareRequest& out_data) {
+ if (state != State::TagNearby) {
+ return Common::Input::NfcState::WrongDeviceState;
+ }
+
+ if (status.tag_type != 1U << 6) {
+ return Common::Input::NfcState::InvalidTagType;
+ }
+
+ for (std::size_t i = 0; i < request.data.size(); i++) {
+ if (request.data[i].command == 0) {
+ continue;
+ }
+ out_data.data[i].command = request.data[i].command;
+ out_data.data[i].sector = request.data[i].sector;
+
+ const std::size_t sector_index =
+ request.data[i].sector * sizeof(Common::Input::MifareData::data);
+
+ if (nfc_data.size() < sector_index + sizeof(Common::Input::MifareData::data)) {
+ return Common::Input::NfcState::WriteFailed;
+ }
+
+ // Ignore the sector key as we don't support it
+ memcpy(out_data.data[i].data.data(), nfc_data.data() + sector_index,
+ sizeof(Common::Input::MifareData::data));
+ }
+
+ return Common::Input::NfcState::Success;
+}
+
+Common::Input::NfcState VirtualAmiibo::WriteMifareData(
+ const PadIdentifier& identifier_, const Common::Input::MifareRequest& request) {
+ if (state != State::TagNearby) {
+ return Common::Input::NfcState::WrongDeviceState;
+ }
+
+ if (status.tag_type != 1U << 6) {
+ return Common::Input::NfcState::InvalidTagType;
+ }
+
+ for (std::size_t i = 0; i < request.data.size(); i++) {
+ if (request.data[i].command == 0) {
+ continue;
+ }
+
+ const std::size_t sector_index =
+ request.data[i].sector * sizeof(Common::Input::MifareData::data);
+
+ if (nfc_data.size() < sector_index + sizeof(Common::Input::MifareData::data)) {
+ return Common::Input::NfcState::WriteFailed;
+ }
+
+ // Ignore the sector key as we don't support it
+ memcpy(nfc_data.data() + sector_index, request.data[i].data.data(),
+ sizeof(Common::Input::MifareData::data));
+ }
+
+ return Common::Input::NfcState::Success;
+}
+
VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const {
return state;
}
@@ -112,23 +207,31 @@ VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(std::span<u8> data) {
case AmiiboSizeWithoutPassword:
case AmiiboSizeWithSignature:
nfc_data.resize(AmiiboSize);
+ status.tag_type = 1U << 1;
+ status.uuid_length = 7;
break;
case MifareSize:
nfc_data.resize(MifareSize);
+ status.tag_type = 1U << 6;
+ status.uuid_length = 4;
break;
default:
return Info::NotAnAmiibo;
}
- state = State::AmiiboIsOpen;
+ status.uuid = {};
+ status.protocol = 1;
+ state = State::TagNearby;
+ status.state = Common::Input::NfcState::NewAmiibo,
memcpy(nfc_data.data(), data.data(), data.size_bytes());
- SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data});
+ memcpy(status.uuid.data(), nfc_data.data(), status.uuid_length);
+ SetNfc(identifier, status);
return Info::Success;
}
VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() {
- if (state == State::AmiiboIsOpen) {
- SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data});
+ if (state == State::TagNearby) {
+ SetNfc(identifier, status);
return Info::Success;
}
@@ -136,9 +239,14 @@ VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() {
}
VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() {
- state = polling_mode == Common::Input::PollingMode::NFC ? State::WaitingForAmiibo
- : State::Initialized;
- SetNfc(identifier, {Common::Input::NfcState::AmiiboRemoved, {}});
+ if (state != State::TagNearby) {
+ return Info::Success;
+ }
+
+ state = State::WaitingForAmiibo;
+ status.state = Common::Input::NfcState::AmiiboRemoved;
+ SetNfc(identifier, status);
+ status.tag_type = 0;
return Info::Success;
}
diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h
index 09ca09e68..490f38e05 100644
--- a/src/input_common/drivers/virtual_amiibo.h
+++ b/src/input_common/drivers/virtual_amiibo.h
@@ -20,9 +20,10 @@ namespace InputCommon {
class VirtualAmiibo final : public InputEngine {
public:
enum class State {
+ Disabled,
Initialized,
WaitingForAmiibo,
- AmiiboIsOpen,
+ TagNearby,
};
enum class Info {
@@ -41,9 +42,17 @@ public:
const PadIdentifier& identifier_, const Common::Input::PollingMode polling_mode_) override;
Common::Input::NfcState SupportsNfc(const PadIdentifier& identifier_) const override;
-
+ Common::Input::NfcState StartNfcPolling(const PadIdentifier& identifier_) override;
+ Common::Input::NfcState StopNfcPolling(const PadIdentifier& identifier_) override;
+ Common::Input::NfcState ReadAmiiboData(const PadIdentifier& identifier_,
+ std::vector<u8>& out_data) override;
Common::Input::NfcState WriteNfcData(const PadIdentifier& identifier_,
const std::vector<u8>& data) override;
+ Common::Input::NfcState ReadMifareData(const PadIdentifier& identifier_,
+ const Common::Input::MifareRequest& data,
+ Common::Input::MifareRequest& out_data) override;
+ Common::Input::NfcState WriteMifareData(const PadIdentifier& identifier_,
+ const Common::Input::MifareRequest& data) override;
State GetCurrentState() const;
@@ -61,8 +70,9 @@ private:
static constexpr std::size_t MifareSize = 0x400;
std::string file_path{};
- State state{State::Initialized};
+ State state{State::Disabled};
std::vector<u8> nfc_data;
+ Common::Input::NfcStatus status;
Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Passive};
};
} // namespace InputCommon