diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/hid/hid.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/hid/hidbus.cpp | 481 | ||||
-rw-r--r-- | src/core/hle/service/hid/hidbus.h | 69 | ||||
-rw-r--r-- | src/hid_core/hidbus/hidbus_base.h | 2 | ||||
-rw-r--r-- | src/hid_core/hidbus/ringcon.cpp | 77 | ||||
-rw-r--r-- | src/hid_core/hidbus/ringcon.h | 26 | ||||
-rw-r--r-- | src/hid_core/hidbus/starlink.cpp | 2 | ||||
-rw-r--r-- | src/hid_core/hidbus/starlink.h | 2 | ||||
-rw-r--r-- | src/hid_core/hidbus/stubbed.cpp | 2 | ||||
-rw-r--r-- | src/hid_core/hidbus/stubbed.h | 2 |
10 files changed, 262 insertions, 403 deletions
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index b60fb9139..1fa9cfbfb 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -36,7 +36,7 @@ void LoopProcess(Core::System& system) { server_manager->RegisterNamedService( "hid:sys", std::make_shared<IHidSystemServer>(system, resource_manager, firmware_settings)); - server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system)); + server_manager->RegisterNamedService("hidbus", std::make_shared<Hidbus>(system)); server_manager->RegisterNamedService("irs", std::make_shared<IRS::IRS>(system)); server_manager->RegisterNamedService("irs:sys", std::make_shared<IRS::IRS_SYS>(system)); diff --git a/src/core/hle/service/hid/hidbus.cpp b/src/core/hle/service/hid/hidbus.cpp index c903ee8b8..4fb002bc4 100644 --- a/src/core/hle/service/hid/hidbus.cpp +++ b/src/core/hle/service/hid/hidbus.cpp @@ -9,6 +9,7 @@ #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_shared_memory.h" #include "core/hle/kernel/k_transfer_memory.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/hid/hidbus.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/service.h" @@ -22,25 +23,25 @@ namespace Service::HID { // (15ms, 66Hz) constexpr auto hidbus_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; -HidBus::HidBus(Core::System& system_) +Hidbus::Hidbus(Core::System& system_) : ServiceFramework{system_, "hidbus"}, service_context{system_, service_name} { // clang-format off static const FunctionInfo functions[] = { - {1, &HidBus::GetBusHandle, "GetBusHandle"}, - {2, &HidBus::IsExternalDeviceConnected, "IsExternalDeviceConnected"}, - {3, &HidBus::Initialize, "Initialize"}, - {4, &HidBus::Finalize, "Finalize"}, - {5, &HidBus::EnableExternalDevice, "EnableExternalDevice"}, - {6, &HidBus::GetExternalDeviceId, "GetExternalDeviceId"}, - {7, &HidBus::SendCommandAsync, "SendCommandAsync"}, - {8, &HidBus::GetSendCommandAsynceResult, "GetSendCommandAsynceResult"}, - {9, &HidBus::SetEventForSendCommandAsycResult, "SetEventForSendCommandAsycResult"}, - {10, &HidBus::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, - {11, &HidBus::EnableJoyPollingReceiveMode, "EnableJoyPollingReceiveMode"}, - {12, &HidBus::DisableJoyPollingReceiveMode, "DisableJoyPollingReceiveMode"}, + {1, C<&Hidbus::GetBusHandle>, "GetBusHandle"}, + {2, C<&Hidbus::IsExternalDeviceConnected>, "IsExternalDeviceConnected"}, + {3, C<&Hidbus::Initialize>, "Initialize"}, + {4, C<&Hidbus::Finalize>, "Finalize"}, + {5, C<&Hidbus::EnableExternalDevice>, "EnableExternalDevice"}, + {6, C<&Hidbus::GetExternalDeviceId>, "GetExternalDeviceId"}, + {7, C<&Hidbus::SendCommandAsync>, "SendCommandAsync"}, + {8, C<&Hidbus::GetSendCommandAsynceResult>, "GetSendCommandAsynceResult"}, + {9, C<&Hidbus::SetEventForSendCommandAsycResult>, "SetEventForSendCommandAsycResult"}, + {10, C<&Hidbus::GetSharedMemoryHandle>, "GetSharedMemoryHandle"}, + {11, C<&Hidbus::EnableJoyPollingReceiveMode>, "EnableJoyPollingReceiveMode"}, + {12, C<&Hidbus::DisableJoyPollingReceiveMode>, "DisableJoyPollingReceiveMode"}, {13, nullptr, "GetPollingData"}, - {14, &HidBus::SetStatusManagerType, "SetStatusManagerType"}, + {14, C<&Hidbus::SetStatusManagerType>, "SetStatusManagerType"}, }; // clang-format on @@ -60,11 +61,11 @@ HidBus::HidBus(Core::System& system_) hidbus_update_event); } -HidBus::~HidBus() { +Hidbus::~Hidbus() { system.CoreTiming().UnscheduleEvent(hidbus_update_event); } -void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) { +void Hidbus::UpdateHidbus(std::chrono::nanoseconds ns_late) { if (is_hidbus_enabled) { for (std::size_t i = 0; i < devices.size(); ++i) { if (!devices[i].is_device_initialized) { @@ -84,7 +85,7 @@ void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) { } } -std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) const { +std::optional<std::size_t> Hidbus::GetDeviceIndexFromHandle(BusHandle handle) const { for (std::size_t i = 0; i < devices.size(); ++i) { const auto& device_handle = devices[i].handle; if (handle.abstracted_pad_id == device_handle.abstracted_pad_id && @@ -98,20 +99,11 @@ std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) co return std::nullopt; } -void HidBus::GetBusHandle(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - struct Parameters { - Core::HID::NpadIdType npad_id; - INSERT_PADDING_WORDS_NOINIT(1); - BusType bus_type; - u64 applet_resource_user_id; - }; - static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); - - const auto parameters{rp.PopRaw<Parameters>()}; - - LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}", - parameters.npad_id, parameters.bus_type, parameters.applet_resource_user_id); +Result Hidbus::GetBusHandle(Out<bool> out_is_valid, Out<BusHandle> out_bus_handle, + Core::HID::NpadIdType npad_id, BusType bus_type, + AppletResourceUserId aruid) { + LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}", npad_id, + bus_type, aruid.pid); bool is_handle_found = 0; std::size_t handle_index = 0; @@ -121,8 +113,8 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) { if (!handle.is_valid) { continue; } - if (static_cast<Core::HID::NpadIdType>(handle.player_number) == parameters.npad_id && - handle.bus_type_id == static_cast<u8>(parameters.bus_type)) { + if (handle.player_number.As<Core::HID::NpadIdType>() == npad_id && + handle.bus_type_id == static_cast<u8>(bus_type)) { is_handle_found = true; handle_index = i; break; @@ -135,388 +127,231 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) { if (devices[i].handle.is_valid) { continue; } - devices[i].handle = { - .abstracted_pad_id = static_cast<u8>(i), - .internal_index = static_cast<u8>(i), - .player_number = static_cast<u8>(parameters.npad_id), - .bus_type_id = static_cast<u8>(parameters.bus_type), - .is_valid = true, - }; + devices[i].handle.raw = 0; + devices[i].handle.abstracted_pad_id.Assign(i); + devices[i].handle.internal_index.Assign(i); + devices[i].handle.player_number.Assign(static_cast<u8>(npad_id)); + devices[i].handle.bus_type_id.Assign(static_cast<u8>(bus_type)); + devices[i].handle.is_valid.Assign(true); handle_index = i; break; } } - struct OutData { - bool is_valid; - INSERT_PADDING_BYTES(7); - BusHandle handle; - }; - static_assert(sizeof(OutData) == 0x10, "OutData has incorrect size."); - - const OutData out_data{ - .is_valid = true, - .handle = devices[handle_index].handle, - }; - - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(ResultSuccess); - rb.PushRaw(out_data); + *out_is_valid = true; + *out_bus_handle = devices[handle_index].handle; + R_SUCCEED(); } -void HidBus::IsExternalDeviceConnected(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto bus_handle_{rp.PopRaw<BusHandle>()}; - +Result Hidbus::IsExternalDeviceConnected(Out<bool> out_is_connected, BusHandle bus_handle) { LOG_INFO(Service_HID, "Called, abstracted_pad_id={}, bus_type={}, internal_index={}, " "player_number={}, is_valid={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, - bus_handle_.player_number, bus_handle_.is_valid); + bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, + bus_handle.player_number, bus_handle.is_valid); - const auto device_index = GetDeviceIndexFromHandle(bus_handle_); + const auto device_index = GetDeviceIndexFromHandle(bus_handle); - if (device_index) { - const auto& device = devices[device_index.value()].device; - const bool is_attached = device->IsDeviceActivated(); + R_UNLESS(device_index.has_value(), ResultUnknown); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(is_attached); - return; - } - - LOG_ERROR(Service_HID, "Invalid handle"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; + *out_is_connected = devices[device_index.value()].device->IsDeviceActivated(); + R_SUCCEED(); } -void HidBus::Initialize(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto bus_handle_{rp.PopRaw<BusHandle>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - +Result Hidbus::Initialize(BusHandle bus_handle, AppletResourceUserId aruid) { LOG_INFO(Service_HID, "called, abstracted_pad_id={} bus_type={} internal_index={} " "player_number={} is_valid={}, applet_resource_user_id={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, - bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id); + bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, + bus_handle.player_number, bus_handle.is_valid, aruid.pid); is_hidbus_enabled = true; - const auto device_index = GetDeviceIndexFromHandle(bus_handle_); - - if (device_index) { - const auto entry_index = devices[device_index.value()].handle.internal_index; - auto& cur_entry = hidbus_status.entries[entry_index]; - - if (bus_handle_.internal_index == 0 && Settings::values.enable_ring_controller) { - MakeDevice<RingController>(bus_handle_); - devices[device_index.value()].is_device_initialized = true; - devices[device_index.value()].device->ActivateDevice(); - cur_entry.is_in_focus = true; - cur_entry.is_connected = true; - cur_entry.is_connected_result = ResultSuccess; - cur_entry.is_enabled = false; - cur_entry.is_polling_mode = false; - } else { - MakeDevice<HidbusStubbed>(bus_handle_); - devices[device_index.value()].is_device_initialized = true; - cur_entry.is_in_focus = true; - cur_entry.is_connected = false; - cur_entry.is_connected_result = ResultSuccess; - cur_entry.is_enabled = false; - cur_entry.is_polling_mode = false; - } - - std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status, - sizeof(hidbus_status)); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - return; - } + const auto device_index = GetDeviceIndexFromHandle(bus_handle); - LOG_ERROR(Service_HID, "Invalid handle"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; -} + R_UNLESS(device_index.has_value(), ResultUnknown); -void HidBus::Finalize(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto bus_handle_{rp.PopRaw<BusHandle>()}; - const auto applet_resource_user_id{rp.Pop<u64>()}; - - LOG_INFO(Service_HID, - "called, abstracted_pad_id={}, bus_type={}, internal_index={}, " - "player_number={}, is_valid={}, applet_resource_user_id={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, - bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id); - - const auto device_index = GetDeviceIndexFromHandle(bus_handle_); - - if (device_index) { - const auto entry_index = devices[device_index.value()].handle.internal_index; - auto& cur_entry = hidbus_status.entries[entry_index]; - auto& device = devices[device_index.value()].device; - devices[device_index.value()].is_device_initialized = false; - device->DeactivateDevice(); + const auto entry_index = devices[device_index.value()].handle.internal_index; + auto& cur_entry = hidbus_status.entries[entry_index]; + if (bus_handle.internal_index == 0 && Settings::values.enable_ring_controller) { + MakeDevice<RingController>(bus_handle); + devices[device_index.value()].is_device_initialized = true; + devices[device_index.value()].device->ActivateDevice(); + cur_entry.is_in_focus = true; + cur_entry.is_connected = true; + cur_entry.is_connected_result = ResultSuccess; + cur_entry.is_enabled = false; + cur_entry.is_polling_mode = false; + } else { + MakeDevice<HidbusStubbed>(bus_handle); + devices[device_index.value()].is_device_initialized = true; cur_entry.is_in_focus = true; cur_entry.is_connected = false; cur_entry.is_connected_result = ResultSuccess; cur_entry.is_enabled = false; cur_entry.is_polling_mode = false; - std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status, - sizeof(hidbus_status)); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - return; } - LOG_ERROR(Service_HID, "Invalid handle"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; + std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status, + sizeof(hidbus_status)); + R_SUCCEED(); } -void HidBus::EnableExternalDevice(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - struct Parameters { - bool enable; - INSERT_PADDING_BYTES_NOINIT(7); - BusHandle bus_handle; - u64 inval; - u64 applet_resource_user_id; - }; - static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size."); - - const auto parameters{rp.PopRaw<Parameters>()}; +Result Hidbus::Finalize(BusHandle bus_handle, AppletResourceUserId aruid) { + LOG_INFO(Service_HID, + "called, abstracted_pad_id={}, bus_type={}, internal_index={}, " + "player_number={}, is_valid={}, applet_resource_user_id={}", + bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, + bus_handle.player_number, bus_handle.is_valid, aruid.pid); + + const auto device_index = GetDeviceIndexFromHandle(bus_handle); + + R_UNLESS(device_index.has_value(), ResultUnknown); + + const auto entry_index = devices[device_index.value()].handle.internal_index; + auto& cur_entry = hidbus_status.entries[entry_index]; + auto& device = devices[device_index.value()].device; + devices[device_index.value()].is_device_initialized = false; + device->DeactivateDevice(); + + cur_entry.is_in_focus = true; + cur_entry.is_connected = false; + cur_entry.is_connected_result = ResultSuccess; + cur_entry.is_enabled = false; + cur_entry.is_polling_mode = false; + std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status, + sizeof(hidbus_status)); + R_SUCCEED(); +} +Result Hidbus::EnableExternalDevice(bool is_enabled, BusHandle bus_handle, u64 inval, + AppletResourceUserId aruid) { LOG_DEBUG(Service_HID, "called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, " "player_number={}, is_valid={}, inval={}, applet_resource_user_id{}", - parameters.enable, parameters.bus_handle.abstracted_pad_id, - parameters.bus_handle.bus_type_id, parameters.bus_handle.internal_index, - parameters.bus_handle.player_number, parameters.bus_handle.is_valid, parameters.inval, - parameters.applet_resource_user_id); - - const auto device_index = GetDeviceIndexFromHandle(parameters.bus_handle); - - if (device_index) { - auto& device = devices[device_index.value()].device; - device->Enable(parameters.enable); + is_enabled, bus_handle.abstracted_pad_id, bus_handle.bus_type_id, + bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid, inval, + aruid.pid); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - return; - } + const auto device_index = GetDeviceIndexFromHandle(bus_handle); - LOG_ERROR(Service_HID, "Invalid handle"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; + R_UNLESS(device_index.has_value(), ResultUnknown); + devices[device_index.value()].device->Enable(is_enabled); + R_SUCCEED(); } -void HidBus::GetExternalDeviceId(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto bus_handle_{rp.PopRaw<BusHandle>()}; - +Result Hidbus::GetExternalDeviceId(Out<u32> out_device_id, BusHandle bus_handle) { LOG_DEBUG(Service_HID, "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " "is_valid={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, - bus_handle_.player_number, bus_handle_.is_valid); - - const auto device_index = GetDeviceIndexFromHandle(bus_handle_); - - if (device_index) { - const auto& device = devices[device_index.value()].device; - u32 device_id = device->GetDeviceId(); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push<u32>(device_id); - return; - } + bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, + bus_handle.player_number, bus_handle.is_valid); - LOG_ERROR(Service_HID, "Invalid handle"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; -} + const auto device_index = GetDeviceIndexFromHandle(bus_handle); -void HidBus::SendCommandAsync(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto data = ctx.ReadBuffer(); - const auto bus_handle_{rp.PopRaw<BusHandle>()}; + R_UNLESS(device_index.has_value(), ResultUnknown); + *out_device_id = devices[device_index.value()].device->GetDeviceId(); + R_SUCCEED(); +} + +Result Hidbus::SendCommandAsync(BusHandle bus_handle, + InBuffer<BufferAttr_HipcAutoSelect> buffer_data) { LOG_DEBUG(Service_HID, "called, data_size={}, abstracted_pad_id={}, bus_type={}, internal_index={}, " "player_number={}, is_valid={}", - data.size(), bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, - bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid); + buffer_data.size(), bus_handle.abstracted_pad_id, bus_handle.bus_type_id, + bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid); - const auto device_index = GetDeviceIndexFromHandle(bus_handle_); + const auto device_index = GetDeviceIndexFromHandle(bus_handle); - if (device_index) { - auto& device = devices[device_index.value()].device; - device->SetCommand(data); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - return; - } + R_UNLESS(device_index.has_value(), ResultUnknown); - LOG_ERROR(Service_HID, "Invalid handle"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; + devices[device_index.value()].device->SetCommand(buffer_data); + R_SUCCEED(); }; -void HidBus::GetSendCommandAsynceResult(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto bus_handle_{rp.PopRaw<BusHandle>()}; - +Result Hidbus::GetSendCommandAsynceResult(Out<u64> out_data_size, BusHandle bus_handle, + OutBuffer<BufferAttr_HipcAutoSelect> out_buffer_data) { LOG_DEBUG(Service_HID, "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " "is_valid={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, - bus_handle_.player_number, bus_handle_.is_valid); - - const auto device_index = GetDeviceIndexFromHandle(bus_handle_); + bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, + bus_handle.player_number, bus_handle.is_valid); - if (device_index) { - const auto& device = devices[device_index.value()].device; - const std::vector<u8> data = device->GetReply(); - const u64 data_size = ctx.WriteBuffer(data); + const auto device_index = GetDeviceIndexFromHandle(bus_handle); - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - rb.Push<u64>(data_size); - return; - } + R_UNLESS(device_index.has_value(), ResultUnknown); - LOG_ERROR(Service_HID, "Invalid handle"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; + *out_data_size = devices[device_index.value()].device->GetReply(out_buffer_data); + R_SUCCEED(); }; -void HidBus::SetEventForSendCommandAsycResult(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto bus_handle_{rp.PopRaw<BusHandle>()}; - +Result Hidbus::SetEventForSendCommandAsycResult(OutCopyHandle<Kernel::KReadableEvent> out_event, + BusHandle bus_handle) { LOG_INFO(Service_HID, "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " "is_valid={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, - bus_handle_.player_number, bus_handle_.is_valid); + bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, + bus_handle.player_number, bus_handle.is_valid); - const auto device_index = GetDeviceIndexFromHandle(bus_handle_); + const auto device_index = GetDeviceIndexFromHandle(bus_handle); - if (device_index) { - const auto& device = devices[device_index.value()].device; - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(device->GetSendCommandAsycEvent()); - return; - } + R_UNLESS(device_index.has_value(), ResultUnknown); - LOG_ERROR(Service_HID, "Invalid handle"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; + *out_event = &devices[device_index.value()].device->GetSendCommandAsycEvent(); + R_SUCCEED(); }; -void HidBus::GetSharedMemoryHandle(HLERequestContext& ctx) { +Result Hidbus::GetSharedMemoryHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) { LOG_DEBUG(Service_HID, "called"); - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(&system.Kernel().GetHidBusSharedMem()); + *out_shared_memory = &system.Kernel().GetHidBusSharedMem(); + R_SUCCEED(); } -void HidBus::EnableJoyPollingReceiveMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto t_mem_size{rp.Pop<u32>()}; - const auto t_mem_handle{ctx.GetCopyHandle(0)}; - const auto polling_mode_{rp.PopEnum<JoyPollingMode>()}; - const auto bus_handle_{rp.PopRaw<BusHandle>()}; - +Result Hidbus::EnableJoyPollingReceiveMode(u32 t_mem_size, JoyPollingMode polling_mode, + BusHandle bus_handle, + InCopyHandle<Kernel::KTransferMemory> t_mem) { ASSERT_MSG(t_mem_size == 0x1000, "t_mem_size is not 0x1000 bytes"); - - auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle); - - if (t_mem.IsNull()) { - LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; - } - - ASSERT_MSG(t_mem->GetSize() == 0x1000, "t_mem has incorrect size"); + ASSERT_MSG(t_mem->GetSize() == t_mem_size, "t_mem has incorrect size"); LOG_INFO(Service_HID, - "called, t_mem_handle=0x{:08X}, polling_mode={}, abstracted_pad_id={}, bus_type={}, " + "called, polling_mode={}, abstracted_pad_id={}, bus_type={}, " "internal_index={}, player_number={}, is_valid={}", - t_mem_handle, polling_mode_, bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, - bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid); + polling_mode, bus_handle.abstracted_pad_id, bus_handle.bus_type_id, + bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid); - const auto device_index = GetDeviceIndexFromHandle(bus_handle_); + const auto device_index = GetDeviceIndexFromHandle(bus_handle); - if (device_index) { - auto& device = devices[device_index.value()].device; - device->SetPollingMode(polling_mode_); - device->SetTransferMemoryAddress(t_mem->GetSourceAddress()); + R_UNLESS(device_index.has_value(), ResultUnknown); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - return; - } - - LOG_ERROR(Service_HID, "Invalid handle"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; + auto& device = devices[device_index.value()].device; + device->SetPollingMode(polling_mode); + device->SetTransferMemoryAddress(t_mem->GetSourceAddress()); + R_SUCCEED(); } -void HidBus::DisableJoyPollingReceiveMode(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto bus_handle_{rp.PopRaw<BusHandle>()}; - +Result Hidbus::DisableJoyPollingReceiveMode(BusHandle bus_handle) { LOG_INFO(Service_HID, "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " "is_valid={}", - bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, - bus_handle_.player_number, bus_handle_.is_valid); + bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, + bus_handle.player_number, bus_handle.is_valid); - const auto device_index = GetDeviceIndexFromHandle(bus_handle_); + const auto device_index = GetDeviceIndexFromHandle(bus_handle); - if (device_index) { - auto& device = devices[device_index.value()].device; - device->DisablePollingMode(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - return; - } + R_UNLESS(device_index.has_value(), ResultUnknown); - LOG_ERROR(Service_HID, "Invalid handle"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; + auto& device = devices[device_index.value()].device; + device->DisablePollingMode(); + R_SUCCEED(); } -void HidBus::SetStatusManagerType(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto manager_type{rp.PopEnum<StatusManagerType>()}; - +Result Hidbus::SetStatusManagerType(StatusManagerType manager_type) { LOG_WARNING(Service_HID, "(STUBBED) called, manager_type={}", manager_type); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); }; + } // namespace Service::HID diff --git a/src/core/hle/service/hid/hidbus.h b/src/core/hle/service/hid/hidbus.h index 03d9f6863..af4d95667 100644 --- a/src/core/hle/service/hid/hidbus.h +++ b/src/core/hle/service/hid/hidbus.h @@ -5,8 +5,10 @@ #include <functional> +#include "core/hle/service/cmif_types.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/service.h" +#include "hid_core/hid_types.h" #include "hid_core/hidbus/hidbus_base.h" namespace Core::Timing { @@ -19,10 +21,10 @@ class System; namespace Service::HID { -class HidBus final : public ServiceFramework<HidBus> { +class Hidbus final : public ServiceFramework<Hidbus> { public: - explicit HidBus(Core::System& system_); - ~HidBus() override; + explicit Hidbus(Core::System& system_); + ~Hidbus() override; private: static const std::size_t max_number_of_handles = 0x13; @@ -41,7 +43,7 @@ private: }; // This is nn::hidbus::BusType - enum class BusType : u32 { + enum class BusType : u64 { LeftJoyRail, RightJoyRail, InternalBus, // Lark microphone @@ -51,11 +53,15 @@ private: // This is nn::hidbus::BusHandle struct BusHandle { - u32 abstracted_pad_id; - u8 internal_index; - u8 player_number; - u8 bus_type_id; - bool is_valid; + union { + u64 raw{}; + + BitField<0, 32, u64> abstracted_pad_id; + BitField<32, 8, u64> internal_index; + BitField<40, 8, u64> player_number; + BitField<48, 8, u64> bus_type_id; + BitField<56, 1, u64> is_valid; + }; }; static_assert(sizeof(BusHandle) == 0x8, "BusHandle is an invalid size"); @@ -94,19 +100,38 @@ private: std::unique_ptr<HidbusBase> device{nullptr}; }; - void GetBusHandle(HLERequestContext& ctx); - void IsExternalDeviceConnected(HLERequestContext& ctx); - void Initialize(HLERequestContext& ctx); - void Finalize(HLERequestContext& ctx); - void EnableExternalDevice(HLERequestContext& ctx); - void GetExternalDeviceId(HLERequestContext& ctx); - void SendCommandAsync(HLERequestContext& ctx); - void GetSendCommandAsynceResult(HLERequestContext& ctx); - void SetEventForSendCommandAsycResult(HLERequestContext& ctx); - void GetSharedMemoryHandle(HLERequestContext& ctx); - void EnableJoyPollingReceiveMode(HLERequestContext& ctx); - void DisableJoyPollingReceiveMode(HLERequestContext& ctx); - void SetStatusManagerType(HLERequestContext& ctx); + Result GetBusHandle(Out<bool> out_is_valid, Out<BusHandle> out_bus_handle, + Core::HID::NpadIdType npad_id, BusType bus_type, + AppletResourceUserId aruid); + + Result IsExternalDeviceConnected(Out<bool> out_is_connected, BusHandle bus_handle); + + Result Initialize(BusHandle bus_handle, AppletResourceUserId aruid); + + Result Finalize(BusHandle bus_handle, AppletResourceUserId aruid); + + Result EnableExternalDevice(bool is_enabled, BusHandle bus_handle, u64 inval, + AppletResourceUserId aruid); + + Result GetExternalDeviceId(Out<u32> out_device_id, BusHandle bus_handle); + + Result SendCommandAsync(BusHandle bus_handle, InBuffer<BufferAttr_HipcAutoSelect> buffer_data); + + Result GetSendCommandAsynceResult(Out<u64> out_data_size, BusHandle bus_handle, + OutBuffer<BufferAttr_HipcAutoSelect> out_buffer_data); + + Result SetEventForSendCommandAsycResult(OutCopyHandle<Kernel::KReadableEvent> out_event, + BusHandle bus_handle); + + Result GetSharedMemoryHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory); + + Result EnableJoyPollingReceiveMode(u32 t_mem_size, JoyPollingMode polling_mode, + BusHandle bus_handle, + InCopyHandle<Kernel::KTransferMemory> t_mem); + + Result DisableJoyPollingReceiveMode(BusHandle bus_handle); + + Result SetStatusManagerType(StatusManagerType manager_type); void UpdateHidbus(std::chrono::nanoseconds ns_late); std::optional<std::size_t> GetDeviceIndexFromHandle(BusHandle handle) const; diff --git a/src/hid_core/hidbus/hidbus_base.h b/src/hid_core/hidbus/hidbus_base.h index ec41684e1..c948606e4 100644 --- a/src/hid_core/hidbus/hidbus_base.h +++ b/src/hid_core/hidbus/hidbus_base.h @@ -160,7 +160,7 @@ public: } // Returns a reply from a command - virtual std::vector<u8> GetReply() const { + virtual u64 GetReply(std::span<u8> out_data) const { return {}; } diff --git a/src/hid_core/hidbus/ringcon.cpp b/src/hid_core/hidbus/ringcon.cpp index cedf25c16..4f5eaa505 100644 --- a/src/hid_core/hidbus/ringcon.cpp +++ b/src/hid_core/hidbus/ringcon.cpp @@ -90,32 +90,32 @@ u8 RingController::GetDeviceId() const { return device_id; } -std::vector<u8> RingController::GetReply() const { +u64 RingController::GetReply(std::span<u8> out_data) const { const RingConCommands current_command = command; switch (current_command) { case RingConCommands::GetFirmwareVersion: - return GetFirmwareVersionReply(); + return GetFirmwareVersionReply(out_data); case RingConCommands::ReadId: - return GetReadIdReply(); + return GetReadIdReply(out_data); case RingConCommands::c20105: - return GetC020105Reply(); + return GetC020105Reply(out_data); case RingConCommands::ReadUnkCal: - return GetReadUnkCalReply(); + return GetReadUnkCalReply(out_data); case RingConCommands::ReadFactoryCal: - return GetReadFactoryCalReply(); + return GetReadFactoryCalReply(out_data); case RingConCommands::ReadUserCal: - return GetReadUserCalReply(); + return GetReadUserCalReply(out_data); case RingConCommands::ReadRepCount: - return GetReadRepCountReply(); + return GetReadRepCountReply(out_data); case RingConCommands::ReadTotalPushCount: - return GetReadTotalPushCountReply(); + return GetReadTotalPushCountReply(out_data); case RingConCommands::ResetRepCount: - return GetResetRepCountReply(); + return GetResetRepCountReply(out_data); case RingConCommands::SaveCalData: - return GetSaveDataReply(); + return GetSaveDataReply(out_data); default: - return GetErrorReply(); + return GetErrorReply(out_data); } } @@ -163,16 +163,16 @@ bool RingController::SetCommand(std::span<const u8> data) { } } -std::vector<u8> RingController::GetFirmwareVersionReply() const { +u64 RingController::GetFirmwareVersionReply(std::span<u8> out_data) const { const FirmwareVersionReply reply{ .status = DataValid::Valid, .firmware = version, }; - return GetDataVector(reply); + return GetData(reply, out_data); } -std::vector<u8> RingController::GetReadIdReply() const { +u64 RingController::GetReadIdReply(std::span<u8> out_data) const { // The values are hardcoded from a real joycon const ReadIdReply reply{ .status = DataValid::Valid, @@ -184,83 +184,83 @@ std::vector<u8> RingController::GetReadIdReply() const { .id_h_x4 = 8245, }; - return GetDataVector(reply); + return GetData(reply, out_data); } -std::vector<u8> RingController::GetC020105Reply() const { +u64 RingController::GetC020105Reply(std::span<u8> out_data) const { const Cmd020105Reply reply{ .status = DataValid::Valid, .data = 1, }; - return GetDataVector(reply); + return GetData(reply, out_data); } -std::vector<u8> RingController::GetReadUnkCalReply() const { +u64 RingController::GetReadUnkCalReply(std::span<u8> out_data) const { const ReadUnkCalReply reply{ .status = DataValid::Valid, .data = 0, }; - return GetDataVector(reply); + return GetData(reply, out_data); } -std::vector<u8> RingController::GetReadFactoryCalReply() const { +u64 RingController::GetReadFactoryCalReply(std::span<u8> out_data) const { const ReadFactoryCalReply reply{ .status = DataValid::Valid, .calibration = factory_calibration, }; - return GetDataVector(reply); + return GetData(reply, out_data); } -std::vector<u8> RingController::GetReadUserCalReply() const { +u64 RingController::GetReadUserCalReply(std::span<u8> out_data) const { const ReadUserCalReply reply{ .status = DataValid::Valid, .calibration = user_calibration, }; - return GetDataVector(reply); + return GetData(reply, out_data); } -std::vector<u8> RingController::GetReadRepCountReply() const { +u64 RingController::GetReadRepCountReply(std::span<u8> out_data) const { const GetThreeByteReply reply{ .status = DataValid::Valid, .data = {total_rep_count, 0, 0}, .crc = GetCrcValue({total_rep_count, 0, 0, 0}), }; - return GetDataVector(reply); + return GetData(reply, out_data); } -std::vector<u8> RingController::GetReadTotalPushCountReply() const { +u64 RingController::GetReadTotalPushCountReply(std::span<u8> out_data) const { const GetThreeByteReply reply{ .status = DataValid::Valid, .data = {total_push_count, 0, 0}, .crc = GetCrcValue({total_push_count, 0, 0, 0}), }; - return GetDataVector(reply); + return GetData(reply, out_data); } -std::vector<u8> RingController::GetResetRepCountReply() const { - return GetReadRepCountReply(); +u64 RingController::GetResetRepCountReply(std::span<u8> out_data) const { + return GetReadRepCountReply(out_data); } -std::vector<u8> RingController::GetSaveDataReply() const { +u64 RingController::GetSaveDataReply(std::span<u8> out_data) const { const StatusReply reply{ .status = DataValid::Valid, }; - return GetDataVector(reply); + return GetData(reply, out_data); } -std::vector<u8> RingController::GetErrorReply() const { +u64 RingController::GetErrorReply(std::span<u8> out_data) const { const ErrorReply reply{ .status = DataValid::BadCRC, }; - return GetDataVector(reply); + return GetData(reply, out_data); } u8 RingController::GetCrcValue(const std::vector<u8>& data) const { @@ -281,12 +281,11 @@ u8 RingController::GetCrcValue(const std::vector<u8>& data) const { } template <typename T> -std::vector<u8> RingController::GetDataVector(const T& reply) const { +u64 RingController::GetData(const T& reply, std::span<u8> out_data) const { static_assert(std::is_trivially_copyable_v<T>); - std::vector<u8> data; - data.resize(sizeof(reply)); - std::memcpy(data.data(), &reply, sizeof(reply)); - return data; + const auto data_size = static_cast<u64>(std::min(sizeof(reply), out_data.size())); + std::memcpy(out_data.data(), &reply, data_size); + return data_size; } } // namespace Service::HID diff --git a/src/hid_core/hidbus/ringcon.h b/src/hid_core/hidbus/ringcon.h index 0953e8100..a48eeed45 100644 --- a/src/hid_core/hidbus/ringcon.h +++ b/src/hid_core/hidbus/ringcon.h @@ -34,7 +34,7 @@ public: bool SetCommand(std::span<const u8> data) override; // Returns a reply from a command - std::vector<u8> GetReply() const override; + u64 GetReply(std::span<u8> data) const override; private: // These values are obtained from a real ring controller @@ -184,44 +184,44 @@ private: RingConData GetSensorValue() const; // Returns 8 byte reply with firmware version - std::vector<u8> GetFirmwareVersionReply() const; + u64 GetFirmwareVersionReply(std::span<u8> out_data) const; // Returns 16 byte reply with ID values - std::vector<u8> GetReadIdReply() const; + u64 GetReadIdReply(std::span<u8> out_data) const; // (STUBBED) Returns 8 byte reply - std::vector<u8> GetC020105Reply() const; + u64 GetC020105Reply(std::span<u8> out_data) const; // (STUBBED) Returns 8 byte empty reply - std::vector<u8> GetReadUnkCalReply() const; + u64 GetReadUnkCalReply(std::span<u8> out_data) const; // Returns 20 byte reply with factory calibration values - std::vector<u8> GetReadFactoryCalReply() const; + u64 GetReadFactoryCalReply(std::span<u8> out_data) const; // Returns 20 byte reply with user calibration values - std::vector<u8> GetReadUserCalReply() const; + u64 GetReadUserCalReply(std::span<u8> out_data) const; // Returns 8 byte reply - std::vector<u8> GetReadRepCountReply() const; + u64 GetReadRepCountReply(std::span<u8> out_data) const; // Returns 8 byte reply - std::vector<u8> GetReadTotalPushCountReply() const; + u64 GetReadTotalPushCountReply(std::span<u8> out_data) const; // Returns 8 byte reply - std::vector<u8> GetResetRepCountReply() const; + u64 GetResetRepCountReply(std::span<u8> out_data) const; // Returns 4 byte save data reply - std::vector<u8> GetSaveDataReply() const; + u64 GetSaveDataReply(std::span<u8> out_data) const; // Returns 8 byte error reply - std::vector<u8> GetErrorReply() const; + u64 GetErrorReply(std::span<u8> out_data) const; // Returns 8 bit redundancy check from provided data u8 GetCrcValue(const std::vector<u8>& data) const; // Converts structs to an u8 vector equivalent template <typename T> - std::vector<u8> GetDataVector(const T& reply) const; + u64 GetData(const T& reply, std::span<u8> out_data) const; RingConCommands command{RingConCommands::Error}; diff --git a/src/hid_core/hidbus/starlink.cpp b/src/hid_core/hidbus/starlink.cpp index 31b263aa1..1c4df1d8c 100644 --- a/src/hid_core/hidbus/starlink.cpp +++ b/src/hid_core/hidbus/starlink.cpp @@ -38,7 +38,7 @@ u8 Starlink::GetDeviceId() const { return DEVICE_ID; } -std::vector<u8> Starlink::GetReply() const { +u64 Starlink::GetReply(std::span<u8> out_data) const { return {}; } diff --git a/src/hid_core/hidbus/starlink.h b/src/hid_core/hidbus/starlink.h index ee37763b4..695b69748 100644 --- a/src/hid_core/hidbus/starlink.h +++ b/src/hid_core/hidbus/starlink.h @@ -31,7 +31,7 @@ public: bool SetCommand(std::span<const u8> data) override; // Returns a reply from a command - std::vector<u8> GetReply() const override; + u64 GetReply(std::span<u8> out_data) const override; }; } // namespace Service::HID diff --git a/src/hid_core/hidbus/stubbed.cpp b/src/hid_core/hidbus/stubbed.cpp index f16051aa9..658922a4f 100644 --- a/src/hid_core/hidbus/stubbed.cpp +++ b/src/hid_core/hidbus/stubbed.cpp @@ -38,7 +38,7 @@ u8 HidbusStubbed::GetDeviceId() const { return DEVICE_ID; } -std::vector<u8> HidbusStubbed::GetReply() const { +u64 HidbusStubbed::GetReply(std::span<u8> out_data) const { return {}; } diff --git a/src/hid_core/hidbus/stubbed.h b/src/hid_core/hidbus/stubbed.h index 7a711cea0..f05280b3a 100644 --- a/src/hid_core/hidbus/stubbed.h +++ b/src/hid_core/hidbus/stubbed.h @@ -31,7 +31,7 @@ public: bool SetCommand(std::span<const u8> data) override; // Returns a reply from a command - std::vector<u8> GetReply() const override; + u64 GetReply(std::span<u8> out_data) const override; }; } // namespace Service::HID |