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