diff options
| -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) { | |||
| 36 | server_manager->RegisterNamedService( | 36 | server_manager->RegisterNamedService( |
| 37 | "hid:sys", std::make_shared<IHidSystemServer>(system, resource_manager, firmware_settings)); | 37 | "hid:sys", std::make_shared<IHidSystemServer>(system, resource_manager, firmware_settings)); |
| 38 | 38 | ||
| 39 | server_manager->RegisterNamedService("hidbus", std::make_shared<HidBus>(system)); | 39 | server_manager->RegisterNamedService("hidbus", std::make_shared<Hidbus>(system)); |
| 40 | 40 | ||
| 41 | server_manager->RegisterNamedService("irs", std::make_shared<IRS::IRS>(system)); | 41 | server_manager->RegisterNamedService("irs", std::make_shared<IRS::IRS>(system)); |
| 42 | server_manager->RegisterNamedService("irs:sys", std::make_shared<IRS::IRS_SYS>(system)); | 42 | 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 @@ | |||
| 9 | #include "core/hle/kernel/k_readable_event.h" | 9 | #include "core/hle/kernel/k_readable_event.h" |
| 10 | #include "core/hle/kernel/k_shared_memory.h" | 10 | #include "core/hle/kernel/k_shared_memory.h" |
| 11 | #include "core/hle/kernel/k_transfer_memory.h" | 11 | #include "core/hle/kernel/k_transfer_memory.h" |
| 12 | #include "core/hle/service/cmif_serialization.h" | ||
| 12 | #include "core/hle/service/hid/hidbus.h" | 13 | #include "core/hle/service/hid/hidbus.h" |
| 13 | #include "core/hle/service/ipc_helpers.h" | 14 | #include "core/hle/service/ipc_helpers.h" |
| 14 | #include "core/hle/service/service.h" | 15 | #include "core/hle/service/service.h" |
| @@ -22,25 +23,25 @@ namespace Service::HID { | |||
| 22 | // (15ms, 66Hz) | 23 | // (15ms, 66Hz) |
| 23 | constexpr auto hidbus_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; | 24 | constexpr auto hidbus_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; |
| 24 | 25 | ||
| 25 | HidBus::HidBus(Core::System& system_) | 26 | Hidbus::Hidbus(Core::System& system_) |
| 26 | : ServiceFramework{system_, "hidbus"}, service_context{system_, service_name} { | 27 | : ServiceFramework{system_, "hidbus"}, service_context{system_, service_name} { |
| 27 | 28 | ||
| 28 | // clang-format off | 29 | // clang-format off |
| 29 | static const FunctionInfo functions[] = { | 30 | static const FunctionInfo functions[] = { |
| 30 | {1, &HidBus::GetBusHandle, "GetBusHandle"}, | 31 | {1, C<&Hidbus::GetBusHandle>, "GetBusHandle"}, |
| 31 | {2, &HidBus::IsExternalDeviceConnected, "IsExternalDeviceConnected"}, | 32 | {2, C<&Hidbus::IsExternalDeviceConnected>, "IsExternalDeviceConnected"}, |
| 32 | {3, &HidBus::Initialize, "Initialize"}, | 33 | {3, C<&Hidbus::Initialize>, "Initialize"}, |
| 33 | {4, &HidBus::Finalize, "Finalize"}, | 34 | {4, C<&Hidbus::Finalize>, "Finalize"}, |
| 34 | {5, &HidBus::EnableExternalDevice, "EnableExternalDevice"}, | 35 | {5, C<&Hidbus::EnableExternalDevice>, "EnableExternalDevice"}, |
| 35 | {6, &HidBus::GetExternalDeviceId, "GetExternalDeviceId"}, | 36 | {6, C<&Hidbus::GetExternalDeviceId>, "GetExternalDeviceId"}, |
| 36 | {7, &HidBus::SendCommandAsync, "SendCommandAsync"}, | 37 | {7, C<&Hidbus::SendCommandAsync>, "SendCommandAsync"}, |
| 37 | {8, &HidBus::GetSendCommandAsynceResult, "GetSendCommandAsynceResult"}, | 38 | {8, C<&Hidbus::GetSendCommandAsynceResult>, "GetSendCommandAsynceResult"}, |
| 38 | {9, &HidBus::SetEventForSendCommandAsycResult, "SetEventForSendCommandAsycResult"}, | 39 | {9, C<&Hidbus::SetEventForSendCommandAsycResult>, "SetEventForSendCommandAsycResult"}, |
| 39 | {10, &HidBus::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, | 40 | {10, C<&Hidbus::GetSharedMemoryHandle>, "GetSharedMemoryHandle"}, |
| 40 | {11, &HidBus::EnableJoyPollingReceiveMode, "EnableJoyPollingReceiveMode"}, | 41 | {11, C<&Hidbus::EnableJoyPollingReceiveMode>, "EnableJoyPollingReceiveMode"}, |
| 41 | {12, &HidBus::DisableJoyPollingReceiveMode, "DisableJoyPollingReceiveMode"}, | 42 | {12, C<&Hidbus::DisableJoyPollingReceiveMode>, "DisableJoyPollingReceiveMode"}, |
| 42 | {13, nullptr, "GetPollingData"}, | 43 | {13, nullptr, "GetPollingData"}, |
| 43 | {14, &HidBus::SetStatusManagerType, "SetStatusManagerType"}, | 44 | {14, C<&Hidbus::SetStatusManagerType>, "SetStatusManagerType"}, |
| 44 | }; | 45 | }; |
| 45 | // clang-format on | 46 | // clang-format on |
| 46 | 47 | ||
| @@ -60,11 +61,11 @@ HidBus::HidBus(Core::System& system_) | |||
| 60 | hidbus_update_event); | 61 | hidbus_update_event); |
| 61 | } | 62 | } |
| 62 | 63 | ||
| 63 | HidBus::~HidBus() { | 64 | Hidbus::~Hidbus() { |
| 64 | system.CoreTiming().UnscheduleEvent(hidbus_update_event); | 65 | system.CoreTiming().UnscheduleEvent(hidbus_update_event); |
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) { | 68 | void Hidbus::UpdateHidbus(std::chrono::nanoseconds ns_late) { |
| 68 | if (is_hidbus_enabled) { | 69 | if (is_hidbus_enabled) { |
| 69 | for (std::size_t i = 0; i < devices.size(); ++i) { | 70 | for (std::size_t i = 0; i < devices.size(); ++i) { |
| 70 | if (!devices[i].is_device_initialized) { | 71 | if (!devices[i].is_device_initialized) { |
| @@ -84,7 +85,7 @@ void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) { | |||
| 84 | } | 85 | } |
| 85 | } | 86 | } |
| 86 | 87 | ||
| 87 | std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) const { | 88 | std::optional<std::size_t> Hidbus::GetDeviceIndexFromHandle(BusHandle handle) const { |
| 88 | for (std::size_t i = 0; i < devices.size(); ++i) { | 89 | for (std::size_t i = 0; i < devices.size(); ++i) { |
| 89 | const auto& device_handle = devices[i].handle; | 90 | const auto& device_handle = devices[i].handle; |
| 90 | if (handle.abstracted_pad_id == device_handle.abstracted_pad_id && | 91 | if (handle.abstracted_pad_id == device_handle.abstracted_pad_id && |
| @@ -98,20 +99,11 @@ std::optional<std::size_t> HidBus::GetDeviceIndexFromHandle(BusHandle handle) co | |||
| 98 | return std::nullopt; | 99 | return std::nullopt; |
| 99 | } | 100 | } |
| 100 | 101 | ||
| 101 | void HidBus::GetBusHandle(HLERequestContext& ctx) { | 102 | Result Hidbus::GetBusHandle(Out<bool> out_is_valid, Out<BusHandle> out_bus_handle, |
| 102 | IPC::RequestParser rp{ctx}; | 103 | Core::HID::NpadIdType npad_id, BusType bus_type, |
| 103 | struct Parameters { | 104 | AppletResourceUserId aruid) { |
| 104 | Core::HID::NpadIdType npad_id; | 105 | LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}", npad_id, |
| 105 | INSERT_PADDING_WORDS_NOINIT(1); | 106 | bus_type, aruid.pid); |
| 106 | BusType bus_type; | ||
| 107 | u64 applet_resource_user_id; | ||
| 108 | }; | ||
| 109 | static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); | ||
| 110 | |||
| 111 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 112 | |||
| 113 | LOG_INFO(Service_HID, "called, npad_id={}, bus_type={}, applet_resource_user_id={}", | ||
| 114 | parameters.npad_id, parameters.bus_type, parameters.applet_resource_user_id); | ||
| 115 | 107 | ||
| 116 | bool is_handle_found = 0; | 108 | bool is_handle_found = 0; |
| 117 | std::size_t handle_index = 0; | 109 | std::size_t handle_index = 0; |
| @@ -121,8 +113,8 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) { | |||
| 121 | if (!handle.is_valid) { | 113 | if (!handle.is_valid) { |
| 122 | continue; | 114 | continue; |
| 123 | } | 115 | } |
| 124 | if (static_cast<Core::HID::NpadIdType>(handle.player_number) == parameters.npad_id && | 116 | if (handle.player_number.As<Core::HID::NpadIdType>() == npad_id && |
| 125 | handle.bus_type_id == static_cast<u8>(parameters.bus_type)) { | 117 | handle.bus_type_id == static_cast<u8>(bus_type)) { |
| 126 | is_handle_found = true; | 118 | is_handle_found = true; |
| 127 | handle_index = i; | 119 | handle_index = i; |
| 128 | break; | 120 | break; |
| @@ -135,388 +127,231 @@ void HidBus::GetBusHandle(HLERequestContext& ctx) { | |||
| 135 | if (devices[i].handle.is_valid) { | 127 | if (devices[i].handle.is_valid) { |
| 136 | continue; | 128 | continue; |
| 137 | } | 129 | } |
| 138 | devices[i].handle = { | 130 | devices[i].handle.raw = 0; |
| 139 | .abstracted_pad_id = static_cast<u8>(i), | 131 | devices[i].handle.abstracted_pad_id.Assign(i); |
| 140 | .internal_index = static_cast<u8>(i), | 132 | devices[i].handle.internal_index.Assign(i); |
| 141 | .player_number = static_cast<u8>(parameters.npad_id), | 133 | devices[i].handle.player_number.Assign(static_cast<u8>(npad_id)); |
| 142 | .bus_type_id = static_cast<u8>(parameters.bus_type), | 134 | devices[i].handle.bus_type_id.Assign(static_cast<u8>(bus_type)); |
| 143 | .is_valid = true, | 135 | devices[i].handle.is_valid.Assign(true); |
| 144 | }; | ||
| 145 | handle_index = i; | 136 | handle_index = i; |
| 146 | break; | 137 | break; |
| 147 | } | 138 | } |
| 148 | } | 139 | } |
| 149 | 140 | ||
| 150 | struct OutData { | 141 | *out_is_valid = true; |
| 151 | bool is_valid; | 142 | *out_bus_handle = devices[handle_index].handle; |
| 152 | INSERT_PADDING_BYTES(7); | 143 | R_SUCCEED(); |
| 153 | BusHandle handle; | ||
| 154 | }; | ||
| 155 | static_assert(sizeof(OutData) == 0x10, "OutData has incorrect size."); | ||
| 156 | |||
| 157 | const OutData out_data{ | ||
| 158 | .is_valid = true, | ||
| 159 | .handle = devices[handle_index].handle, | ||
| 160 | }; | ||
| 161 | |||
| 162 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 163 | rb.Push(ResultSuccess); | ||
| 164 | rb.PushRaw(out_data); | ||
| 165 | } | 144 | } |
| 166 | 145 | ||
| 167 | void HidBus::IsExternalDeviceConnected(HLERequestContext& ctx) { | 146 | Result Hidbus::IsExternalDeviceConnected(Out<bool> out_is_connected, BusHandle bus_handle) { |
| 168 | IPC::RequestParser rp{ctx}; | ||
| 169 | const auto bus_handle_{rp.PopRaw<BusHandle>()}; | ||
| 170 | |||
| 171 | LOG_INFO(Service_HID, | 147 | LOG_INFO(Service_HID, |
| 172 | "Called, abstracted_pad_id={}, bus_type={}, internal_index={}, " | 148 | "Called, abstracted_pad_id={}, bus_type={}, internal_index={}, " |
| 173 | "player_number={}, is_valid={}", | 149 | "player_number={}, is_valid={}", |
| 174 | bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, | 150 | bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, |
| 175 | bus_handle_.player_number, bus_handle_.is_valid); | 151 | bus_handle.player_number, bus_handle.is_valid); |
| 176 | 152 | ||
| 177 | const auto device_index = GetDeviceIndexFromHandle(bus_handle_); | 153 | const auto device_index = GetDeviceIndexFromHandle(bus_handle); |
| 178 | 154 | ||
| 179 | if (device_index) { | 155 | R_UNLESS(device_index.has_value(), ResultUnknown); |
| 180 | const auto& device = devices[device_index.value()].device; | ||
| 181 | const bool is_attached = device->IsDeviceActivated(); | ||
| 182 | 156 | ||
| 183 | IPC::ResponseBuilder rb{ctx, 3}; | 157 | *out_is_connected = devices[device_index.value()].device->IsDeviceActivated(); |
| 184 | rb.Push(ResultSuccess); | 158 | R_SUCCEED(); |
| 185 | rb.Push(is_attached); | ||
| 186 | return; | ||
| 187 | } | ||
| 188 | |||
| 189 | LOG_ERROR(Service_HID, "Invalid handle"); | ||
| 190 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 191 | rb.Push(ResultUnknown); | ||
| 192 | return; | ||
| 193 | } | 159 | } |
| 194 | 160 | ||
| 195 | void HidBus::Initialize(HLERequestContext& ctx) { | 161 | Result Hidbus::Initialize(BusHandle bus_handle, AppletResourceUserId aruid) { |
| 196 | IPC::RequestParser rp{ctx}; | ||
| 197 | const auto bus_handle_{rp.PopRaw<BusHandle>()}; | ||
| 198 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 199 | |||
| 200 | LOG_INFO(Service_HID, | 162 | LOG_INFO(Service_HID, |
| 201 | "called, abstracted_pad_id={} bus_type={} internal_index={} " | 163 | "called, abstracted_pad_id={} bus_type={} internal_index={} " |
| 202 | "player_number={} is_valid={}, applet_resource_user_id={}", | 164 | "player_number={} is_valid={}, applet_resource_user_id={}", |
| 203 | bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, | 165 | bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, |
| 204 | bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id); | 166 | bus_handle.player_number, bus_handle.is_valid, aruid.pid); |
| 205 | 167 | ||
| 206 | is_hidbus_enabled = true; | 168 | is_hidbus_enabled = true; |
| 207 | 169 | ||
| 208 | const auto device_index = GetDeviceIndexFromHandle(bus_handle_); | 170 | const auto device_index = GetDeviceIndexFromHandle(bus_handle); |
| 209 | |||
| 210 | if (device_index) { | ||
| 211 | const auto entry_index = devices[device_index.value()].handle.internal_index; | ||
| 212 | auto& cur_entry = hidbus_status.entries[entry_index]; | ||
| 213 | |||
| 214 | if (bus_handle_.internal_index == 0 && Settings::values.enable_ring_controller) { | ||
| 215 | MakeDevice<RingController>(bus_handle_); | ||
| 216 | devices[device_index.value()].is_device_initialized = true; | ||
| 217 | devices[device_index.value()].device->ActivateDevice(); | ||
| 218 | cur_entry.is_in_focus = true; | ||
| 219 | cur_entry.is_connected = true; | ||
| 220 | cur_entry.is_connected_result = ResultSuccess; | ||
| 221 | cur_entry.is_enabled = false; | ||
| 222 | cur_entry.is_polling_mode = false; | ||
| 223 | } else { | ||
| 224 | MakeDevice<HidbusStubbed>(bus_handle_); | ||
| 225 | devices[device_index.value()].is_device_initialized = true; | ||
| 226 | cur_entry.is_in_focus = true; | ||
| 227 | cur_entry.is_connected = false; | ||
| 228 | cur_entry.is_connected_result = ResultSuccess; | ||
| 229 | cur_entry.is_enabled = false; | ||
| 230 | cur_entry.is_polling_mode = false; | ||
| 231 | } | ||
| 232 | |||
| 233 | std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status, | ||
| 234 | sizeof(hidbus_status)); | ||
| 235 | |||
| 236 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 237 | rb.Push(ResultSuccess); | ||
| 238 | return; | ||
| 239 | } | ||
| 240 | 171 | ||
| 241 | LOG_ERROR(Service_HID, "Invalid handle"); | 172 | R_UNLESS(device_index.has_value(), ResultUnknown); |
| 242 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 243 | rb.Push(ResultUnknown); | ||
| 244 | return; | ||
| 245 | } | ||
| 246 | 173 | ||
| 247 | void HidBus::Finalize(HLERequestContext& ctx) { | 174 | const auto entry_index = devices[device_index.value()].handle.internal_index; |
| 248 | IPC::RequestParser rp{ctx}; | 175 | auto& cur_entry = hidbus_status.entries[entry_index]; |
| 249 | const auto bus_handle_{rp.PopRaw<BusHandle>()}; | ||
| 250 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 251 | |||
| 252 | LOG_INFO(Service_HID, | ||
| 253 | "called, abstracted_pad_id={}, bus_type={}, internal_index={}, " | ||
| 254 | "player_number={}, is_valid={}, applet_resource_user_id={}", | ||
| 255 | bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, | ||
| 256 | bus_handle_.player_number, bus_handle_.is_valid, applet_resource_user_id); | ||
| 257 | |||
| 258 | const auto device_index = GetDeviceIndexFromHandle(bus_handle_); | ||
| 259 | |||
| 260 | if (device_index) { | ||
| 261 | const auto entry_index = devices[device_index.value()].handle.internal_index; | ||
| 262 | auto& cur_entry = hidbus_status.entries[entry_index]; | ||
| 263 | auto& device = devices[device_index.value()].device; | ||
| 264 | devices[device_index.value()].is_device_initialized = false; | ||
| 265 | device->DeactivateDevice(); | ||
| 266 | 176 | ||
| 177 | if (bus_handle.internal_index == 0 && Settings::values.enable_ring_controller) { | ||
| 178 | MakeDevice<RingController>(bus_handle); | ||
| 179 | devices[device_index.value()].is_device_initialized = true; | ||
| 180 | devices[device_index.value()].device->ActivateDevice(); | ||
| 181 | cur_entry.is_in_focus = true; | ||
| 182 | cur_entry.is_connected = true; | ||
| 183 | cur_entry.is_connected_result = ResultSuccess; | ||
| 184 | cur_entry.is_enabled = false; | ||
| 185 | cur_entry.is_polling_mode = false; | ||
| 186 | } else { | ||
| 187 | MakeDevice<HidbusStubbed>(bus_handle); | ||
| 188 | devices[device_index.value()].is_device_initialized = true; | ||
| 267 | cur_entry.is_in_focus = true; | 189 | cur_entry.is_in_focus = true; |
| 268 | cur_entry.is_connected = false; | 190 | cur_entry.is_connected = false; |
| 269 | cur_entry.is_connected_result = ResultSuccess; | 191 | cur_entry.is_connected_result = ResultSuccess; |
| 270 | cur_entry.is_enabled = false; | 192 | cur_entry.is_enabled = false; |
| 271 | cur_entry.is_polling_mode = false; | 193 | cur_entry.is_polling_mode = false; |
| 272 | std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status, | ||
| 273 | sizeof(hidbus_status)); | ||
| 274 | |||
| 275 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 276 | rb.Push(ResultSuccess); | ||
| 277 | return; | ||
| 278 | } | 194 | } |
| 279 | 195 | ||
| 280 | LOG_ERROR(Service_HID, "Invalid handle"); | 196 | std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status, |
| 281 | IPC::ResponseBuilder rb{ctx, 2}; | 197 | sizeof(hidbus_status)); |
| 282 | rb.Push(ResultUnknown); | 198 | R_SUCCEED(); |
| 283 | return; | ||
| 284 | } | 199 | } |
| 285 | 200 | ||
| 286 | void HidBus::EnableExternalDevice(HLERequestContext& ctx) { | 201 | Result Hidbus::Finalize(BusHandle bus_handle, AppletResourceUserId aruid) { |
| 287 | IPC::RequestParser rp{ctx}; | 202 | LOG_INFO(Service_HID, |
| 288 | struct Parameters { | 203 | "called, abstracted_pad_id={}, bus_type={}, internal_index={}, " |
| 289 | bool enable; | 204 | "player_number={}, is_valid={}, applet_resource_user_id={}", |
| 290 | INSERT_PADDING_BYTES_NOINIT(7); | 205 | bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, |
| 291 | BusHandle bus_handle; | 206 | bus_handle.player_number, bus_handle.is_valid, aruid.pid); |
| 292 | u64 inval; | 207 | |
| 293 | u64 applet_resource_user_id; | 208 | const auto device_index = GetDeviceIndexFromHandle(bus_handle); |
| 294 | }; | 209 | |
| 295 | static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size."); | 210 | R_UNLESS(device_index.has_value(), ResultUnknown); |
| 296 | 211 | ||
| 297 | const auto parameters{rp.PopRaw<Parameters>()}; | 212 | const auto entry_index = devices[device_index.value()].handle.internal_index; |
| 213 | auto& cur_entry = hidbus_status.entries[entry_index]; | ||
| 214 | auto& device = devices[device_index.value()].device; | ||
| 215 | devices[device_index.value()].is_device_initialized = false; | ||
| 216 | device->DeactivateDevice(); | ||
| 217 | |||
| 218 | cur_entry.is_in_focus = true; | ||
| 219 | cur_entry.is_connected = false; | ||
| 220 | cur_entry.is_connected_result = ResultSuccess; | ||
| 221 | cur_entry.is_enabled = false; | ||
| 222 | cur_entry.is_polling_mode = false; | ||
| 223 | std::memcpy(system.Kernel().GetHidBusSharedMem().GetPointer(), &hidbus_status, | ||
| 224 | sizeof(hidbus_status)); | ||
| 225 | R_SUCCEED(); | ||
| 226 | } | ||
| 298 | 227 | ||
| 228 | Result Hidbus::EnableExternalDevice(bool is_enabled, BusHandle bus_handle, u64 inval, | ||
| 229 | AppletResourceUserId aruid) { | ||
| 299 | LOG_DEBUG(Service_HID, | 230 | LOG_DEBUG(Service_HID, |
| 300 | "called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, " | 231 | "called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, " |
| 301 | "player_number={}, is_valid={}, inval={}, applet_resource_user_id{}", | 232 | "player_number={}, is_valid={}, inval={}, applet_resource_user_id{}", |
| 302 | parameters.enable, parameters.bus_handle.abstracted_pad_id, | 233 | is_enabled, bus_handle.abstracted_pad_id, bus_handle.bus_type_id, |
| 303 | parameters.bus_handle.bus_type_id, parameters.bus_handle.internal_index, | 234 | bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid, inval, |
| 304 | parameters.bus_handle.player_number, parameters.bus_handle.is_valid, parameters.inval, | 235 | aruid.pid); |
| 305 | parameters.applet_resource_user_id); | ||
| 306 | |||
| 307 | const auto device_index = GetDeviceIndexFromHandle(parameters.bus_handle); | ||
| 308 | |||
| 309 | if (device_index) { | ||
| 310 | auto& device = devices[device_index.value()].device; | ||
| 311 | device->Enable(parameters.enable); | ||
| 312 | 236 | ||
| 313 | IPC::ResponseBuilder rb{ctx, 2}; | 237 | const auto device_index = GetDeviceIndexFromHandle(bus_handle); |
| 314 | rb.Push(ResultSuccess); | ||
| 315 | return; | ||
| 316 | } | ||
| 317 | 238 | ||
| 318 | LOG_ERROR(Service_HID, "Invalid handle"); | 239 | R_UNLESS(device_index.has_value(), ResultUnknown); |
| 319 | IPC::ResponseBuilder rb{ctx, 2}; | 240 | devices[device_index.value()].device->Enable(is_enabled); |
| 320 | rb.Push(ResultUnknown); | 241 | R_SUCCEED(); |
| 321 | return; | ||
| 322 | } | 242 | } |
| 323 | 243 | ||
| 324 | void HidBus::GetExternalDeviceId(HLERequestContext& ctx) { | 244 | Result Hidbus::GetExternalDeviceId(Out<u32> out_device_id, BusHandle bus_handle) { |
| 325 | IPC::RequestParser rp{ctx}; | ||
| 326 | const auto bus_handle_{rp.PopRaw<BusHandle>()}; | ||
| 327 | |||
| 328 | LOG_DEBUG(Service_HID, | 245 | LOG_DEBUG(Service_HID, |
| 329 | "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " | 246 | "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " |
| 330 | "is_valid={}", | 247 | "is_valid={}", |
| 331 | bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, | 248 | bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, |
| 332 | bus_handle_.player_number, bus_handle_.is_valid); | 249 | bus_handle.player_number, bus_handle.is_valid); |
| 333 | |||
| 334 | const auto device_index = GetDeviceIndexFromHandle(bus_handle_); | ||
| 335 | |||
| 336 | if (device_index) { | ||
| 337 | const auto& device = devices[device_index.value()].device; | ||
| 338 | u32 device_id = device->GetDeviceId(); | ||
| 339 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 340 | rb.Push(ResultSuccess); | ||
| 341 | rb.Push<u32>(device_id); | ||
| 342 | return; | ||
| 343 | } | ||
| 344 | 250 | ||
| 345 | LOG_ERROR(Service_HID, "Invalid handle"); | 251 | const auto device_index = GetDeviceIndexFromHandle(bus_handle); |
| 346 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 347 | rb.Push(ResultUnknown); | ||
| 348 | return; | ||
| 349 | } | ||
| 350 | 252 | ||
| 351 | void HidBus::SendCommandAsync(HLERequestContext& ctx) { | 253 | R_UNLESS(device_index.has_value(), ResultUnknown); |
| 352 | IPC::RequestParser rp{ctx}; | ||
| 353 | const auto data = ctx.ReadBuffer(); | ||
| 354 | const auto bus_handle_{rp.PopRaw<BusHandle>()}; | ||
| 355 | 254 | ||
| 255 | *out_device_id = devices[device_index.value()].device->GetDeviceId(); | ||
| 256 | R_SUCCEED(); | ||
| 257 | } | ||
| 258 | |||
| 259 | Result Hidbus::SendCommandAsync(BusHandle bus_handle, | ||
| 260 | InBuffer<BufferAttr_HipcAutoSelect> buffer_data) { | ||
| 356 | LOG_DEBUG(Service_HID, | 261 | LOG_DEBUG(Service_HID, |
| 357 | "called, data_size={}, abstracted_pad_id={}, bus_type={}, internal_index={}, " | 262 | "called, data_size={}, abstracted_pad_id={}, bus_type={}, internal_index={}, " |
| 358 | "player_number={}, is_valid={}", | 263 | "player_number={}, is_valid={}", |
| 359 | data.size(), bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, | 264 | buffer_data.size(), bus_handle.abstracted_pad_id, bus_handle.bus_type_id, |
| 360 | bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid); | 265 | bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid); |
| 361 | 266 | ||
| 362 | const auto device_index = GetDeviceIndexFromHandle(bus_handle_); | 267 | const auto device_index = GetDeviceIndexFromHandle(bus_handle); |
| 363 | 268 | ||
| 364 | if (device_index) { | 269 | R_UNLESS(device_index.has_value(), ResultUnknown); |
| 365 | auto& device = devices[device_index.value()].device; | ||
| 366 | device->SetCommand(data); | ||
| 367 | |||
| 368 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 369 | rb.Push(ResultSuccess); | ||
| 370 | return; | ||
| 371 | } | ||
| 372 | 270 | ||
| 373 | LOG_ERROR(Service_HID, "Invalid handle"); | 271 | devices[device_index.value()].device->SetCommand(buffer_data); |
| 374 | IPC::ResponseBuilder rb{ctx, 2}; | 272 | R_SUCCEED(); |
| 375 | rb.Push(ResultUnknown); | ||
| 376 | return; | ||
| 377 | }; | 273 | }; |
| 378 | 274 | ||
| 379 | void HidBus::GetSendCommandAsynceResult(HLERequestContext& ctx) { | 275 | Result Hidbus::GetSendCommandAsynceResult(Out<u64> out_data_size, BusHandle bus_handle, |
| 380 | IPC::RequestParser rp{ctx}; | 276 | OutBuffer<BufferAttr_HipcAutoSelect> out_buffer_data) { |
| 381 | const auto bus_handle_{rp.PopRaw<BusHandle>()}; | ||
| 382 | |||
| 383 | LOG_DEBUG(Service_HID, | 277 | LOG_DEBUG(Service_HID, |
| 384 | "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " | 278 | "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " |
| 385 | "is_valid={}", | 279 | "is_valid={}", |
| 386 | bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, | 280 | bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, |
| 387 | bus_handle_.player_number, bus_handle_.is_valid); | 281 | bus_handle.player_number, bus_handle.is_valid); |
| 388 | |||
| 389 | const auto device_index = GetDeviceIndexFromHandle(bus_handle_); | ||
| 390 | 282 | ||
| 391 | if (device_index) { | 283 | const auto device_index = GetDeviceIndexFromHandle(bus_handle); |
| 392 | const auto& device = devices[device_index.value()].device; | ||
| 393 | const std::vector<u8> data = device->GetReply(); | ||
| 394 | const u64 data_size = ctx.WriteBuffer(data); | ||
| 395 | 284 | ||
| 396 | IPC::ResponseBuilder rb{ctx, 4}; | 285 | R_UNLESS(device_index.has_value(), ResultUnknown); |
| 397 | rb.Push(ResultSuccess); | ||
| 398 | rb.Push<u64>(data_size); | ||
| 399 | return; | ||
| 400 | } | ||
| 401 | 286 | ||
| 402 | LOG_ERROR(Service_HID, "Invalid handle"); | 287 | *out_data_size = devices[device_index.value()].device->GetReply(out_buffer_data); |
| 403 | IPC::ResponseBuilder rb{ctx, 2}; | 288 | R_SUCCEED(); |
| 404 | rb.Push(ResultUnknown); | ||
| 405 | return; | ||
| 406 | }; | 289 | }; |
| 407 | 290 | ||
| 408 | void HidBus::SetEventForSendCommandAsycResult(HLERequestContext& ctx) { | 291 | Result Hidbus::SetEventForSendCommandAsycResult(OutCopyHandle<Kernel::KReadableEvent> out_event, |
| 409 | IPC::RequestParser rp{ctx}; | 292 | BusHandle bus_handle) { |
| 410 | const auto bus_handle_{rp.PopRaw<BusHandle>()}; | ||
| 411 | |||
| 412 | LOG_INFO(Service_HID, | 293 | LOG_INFO(Service_HID, |
| 413 | "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " | 294 | "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " |
| 414 | "is_valid={}", | 295 | "is_valid={}", |
| 415 | bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, | 296 | bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, |
| 416 | bus_handle_.player_number, bus_handle_.is_valid); | 297 | bus_handle.player_number, bus_handle.is_valid); |
| 417 | 298 | ||
| 418 | const auto device_index = GetDeviceIndexFromHandle(bus_handle_); | 299 | const auto device_index = GetDeviceIndexFromHandle(bus_handle); |
| 419 | 300 | ||
| 420 | if (device_index) { | 301 | R_UNLESS(device_index.has_value(), ResultUnknown); |
| 421 | const auto& device = devices[device_index.value()].device; | ||
| 422 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 423 | rb.Push(ResultSuccess); | ||
| 424 | rb.PushCopyObjects(device->GetSendCommandAsycEvent()); | ||
| 425 | return; | ||
| 426 | } | ||
| 427 | 302 | ||
| 428 | LOG_ERROR(Service_HID, "Invalid handle"); | 303 | *out_event = &devices[device_index.value()].device->GetSendCommandAsycEvent(); |
| 429 | IPC::ResponseBuilder rb{ctx, 2}; | 304 | R_SUCCEED(); |
| 430 | rb.Push(ResultUnknown); | ||
| 431 | return; | ||
| 432 | }; | 305 | }; |
| 433 | 306 | ||
| 434 | void HidBus::GetSharedMemoryHandle(HLERequestContext& ctx) { | 307 | Result Hidbus::GetSharedMemoryHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory) { |
| 435 | LOG_DEBUG(Service_HID, "called"); | 308 | LOG_DEBUG(Service_HID, "called"); |
| 436 | 309 | ||
| 437 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 310 | *out_shared_memory = &system.Kernel().GetHidBusSharedMem(); |
| 438 | rb.Push(ResultSuccess); | 311 | R_SUCCEED(); |
| 439 | rb.PushCopyObjects(&system.Kernel().GetHidBusSharedMem()); | ||
| 440 | } | 312 | } |
| 441 | 313 | ||
| 442 | void HidBus::EnableJoyPollingReceiveMode(HLERequestContext& ctx) { | 314 | Result Hidbus::EnableJoyPollingReceiveMode(u32 t_mem_size, JoyPollingMode polling_mode, |
| 443 | IPC::RequestParser rp{ctx}; | 315 | BusHandle bus_handle, |
| 444 | const auto t_mem_size{rp.Pop<u32>()}; | 316 | InCopyHandle<Kernel::KTransferMemory> t_mem) { |
| 445 | const auto t_mem_handle{ctx.GetCopyHandle(0)}; | ||
| 446 | const auto polling_mode_{rp.PopEnum<JoyPollingMode>()}; | ||
| 447 | const auto bus_handle_{rp.PopRaw<BusHandle>()}; | ||
| 448 | |||
| 449 | ASSERT_MSG(t_mem_size == 0x1000, "t_mem_size is not 0x1000 bytes"); | 317 | ASSERT_MSG(t_mem_size == 0x1000, "t_mem_size is not 0x1000 bytes"); |
| 450 | 318 | ASSERT_MSG(t_mem->GetSize() == t_mem_size, "t_mem has incorrect size"); | |
| 451 | auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle); | ||
| 452 | |||
| 453 | if (t_mem.IsNull()) { | ||
| 454 | LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); | ||
| 455 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 456 | rb.Push(ResultUnknown); | ||
| 457 | return; | ||
| 458 | } | ||
| 459 | |||
| 460 | ASSERT_MSG(t_mem->GetSize() == 0x1000, "t_mem has incorrect size"); | ||
| 461 | 319 | ||
| 462 | LOG_INFO(Service_HID, | 320 | LOG_INFO(Service_HID, |
| 463 | "called, t_mem_handle=0x{:08X}, polling_mode={}, abstracted_pad_id={}, bus_type={}, " | 321 | "called, polling_mode={}, abstracted_pad_id={}, bus_type={}, " |
| 464 | "internal_index={}, player_number={}, is_valid={}", | 322 | "internal_index={}, player_number={}, is_valid={}", |
| 465 | t_mem_handle, polling_mode_, bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, | 323 | polling_mode, bus_handle.abstracted_pad_id, bus_handle.bus_type_id, |
| 466 | bus_handle_.internal_index, bus_handle_.player_number, bus_handle_.is_valid); | 324 | bus_handle.internal_index, bus_handle.player_number, bus_handle.is_valid); |
| 467 | 325 | ||
| 468 | const auto device_index = GetDeviceIndexFromHandle(bus_handle_); | 326 | const auto device_index = GetDeviceIndexFromHandle(bus_handle); |
| 469 | 327 | ||
| 470 | if (device_index) { | 328 | R_UNLESS(device_index.has_value(), ResultUnknown); |
| 471 | auto& device = devices[device_index.value()].device; | ||
| 472 | device->SetPollingMode(polling_mode_); | ||
| 473 | device->SetTransferMemoryAddress(t_mem->GetSourceAddress()); | ||
| 474 | 329 | ||
| 475 | IPC::ResponseBuilder rb{ctx, 2}; | 330 | auto& device = devices[device_index.value()].device; |
| 476 | rb.Push(ResultSuccess); | 331 | device->SetPollingMode(polling_mode); |
| 477 | return; | 332 | device->SetTransferMemoryAddress(t_mem->GetSourceAddress()); |
| 478 | } | 333 | R_SUCCEED(); |
| 479 | |||
| 480 | LOG_ERROR(Service_HID, "Invalid handle"); | ||
| 481 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 482 | rb.Push(ResultUnknown); | ||
| 483 | return; | ||
| 484 | } | 334 | } |
| 485 | 335 | ||
| 486 | void HidBus::DisableJoyPollingReceiveMode(HLERequestContext& ctx) { | 336 | Result Hidbus::DisableJoyPollingReceiveMode(BusHandle bus_handle) { |
| 487 | IPC::RequestParser rp{ctx}; | ||
| 488 | const auto bus_handle_{rp.PopRaw<BusHandle>()}; | ||
| 489 | |||
| 490 | LOG_INFO(Service_HID, | 337 | LOG_INFO(Service_HID, |
| 491 | "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " | 338 | "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, " |
| 492 | "is_valid={}", | 339 | "is_valid={}", |
| 493 | bus_handle_.abstracted_pad_id, bus_handle_.bus_type_id, bus_handle_.internal_index, | 340 | bus_handle.abstracted_pad_id, bus_handle.bus_type_id, bus_handle.internal_index, |
| 494 | bus_handle_.player_number, bus_handle_.is_valid); | 341 | bus_handle.player_number, bus_handle.is_valid); |
| 495 | 342 | ||
| 496 | const auto device_index = GetDeviceIndexFromHandle(bus_handle_); | 343 | const auto device_index = GetDeviceIndexFromHandle(bus_handle); |
| 497 | 344 | ||
| 498 | if (device_index) { | 345 | R_UNLESS(device_index.has_value(), ResultUnknown); |
| 499 | auto& device = devices[device_index.value()].device; | ||
| 500 | device->DisablePollingMode(); | ||
| 501 | |||
| 502 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 503 | rb.Push(ResultSuccess); | ||
| 504 | return; | ||
| 505 | } | ||
| 506 | 346 | ||
| 507 | LOG_ERROR(Service_HID, "Invalid handle"); | 347 | auto& device = devices[device_index.value()].device; |
| 508 | IPC::ResponseBuilder rb{ctx, 2}; | 348 | device->DisablePollingMode(); |
| 509 | rb.Push(ResultUnknown); | 349 | R_SUCCEED(); |
| 510 | return; | ||
| 511 | } | 350 | } |
| 512 | 351 | ||
| 513 | void HidBus::SetStatusManagerType(HLERequestContext& ctx) { | 352 | Result Hidbus::SetStatusManagerType(StatusManagerType manager_type) { |
| 514 | IPC::RequestParser rp{ctx}; | ||
| 515 | const auto manager_type{rp.PopEnum<StatusManagerType>()}; | ||
| 516 | |||
| 517 | LOG_WARNING(Service_HID, "(STUBBED) called, manager_type={}", manager_type); | 353 | LOG_WARNING(Service_HID, "(STUBBED) called, manager_type={}", manager_type); |
| 518 | 354 | R_SUCCEED(); | |
| 519 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 520 | rb.Push(ResultSuccess); | ||
| 521 | }; | 355 | }; |
| 356 | |||
| 522 | } // namespace Service::HID | 357 | } // 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 @@ | |||
| 5 | 5 | ||
| 6 | #include <functional> | 6 | #include <functional> |
| 7 | 7 | ||
| 8 | #include "core/hle/service/cmif_types.h" | ||
| 8 | #include "core/hle/service/kernel_helpers.h" | 9 | #include "core/hle/service/kernel_helpers.h" |
| 9 | #include "core/hle/service/service.h" | 10 | #include "core/hle/service/service.h" |
| 11 | #include "hid_core/hid_types.h" | ||
| 10 | #include "hid_core/hidbus/hidbus_base.h" | 12 | #include "hid_core/hidbus/hidbus_base.h" |
| 11 | 13 | ||
| 12 | namespace Core::Timing { | 14 | namespace Core::Timing { |
| @@ -19,10 +21,10 @@ class System; | |||
| 19 | 21 | ||
| 20 | namespace Service::HID { | 22 | namespace Service::HID { |
| 21 | 23 | ||
| 22 | class HidBus final : public ServiceFramework<HidBus> { | 24 | class Hidbus final : public ServiceFramework<Hidbus> { |
| 23 | public: | 25 | public: |
| 24 | explicit HidBus(Core::System& system_); | 26 | explicit Hidbus(Core::System& system_); |
| 25 | ~HidBus() override; | 27 | ~Hidbus() override; |
| 26 | 28 | ||
| 27 | private: | 29 | private: |
| 28 | static const std::size_t max_number_of_handles = 0x13; | 30 | static const std::size_t max_number_of_handles = 0x13; |
| @@ -41,7 +43,7 @@ private: | |||
| 41 | }; | 43 | }; |
| 42 | 44 | ||
| 43 | // This is nn::hidbus::BusType | 45 | // This is nn::hidbus::BusType |
| 44 | enum class BusType : u32 { | 46 | enum class BusType : u64 { |
| 45 | LeftJoyRail, | 47 | LeftJoyRail, |
| 46 | RightJoyRail, | 48 | RightJoyRail, |
| 47 | InternalBus, // Lark microphone | 49 | InternalBus, // Lark microphone |
| @@ -51,11 +53,15 @@ private: | |||
| 51 | 53 | ||
| 52 | // This is nn::hidbus::BusHandle | 54 | // This is nn::hidbus::BusHandle |
| 53 | struct BusHandle { | 55 | struct BusHandle { |
| 54 | u32 abstracted_pad_id; | 56 | union { |
| 55 | u8 internal_index; | 57 | u64 raw{}; |
| 56 | u8 player_number; | 58 | |
| 57 | u8 bus_type_id; | 59 | BitField<0, 32, u64> abstracted_pad_id; |
| 58 | bool is_valid; | 60 | BitField<32, 8, u64> internal_index; |
| 61 | BitField<40, 8, u64> player_number; | ||
| 62 | BitField<48, 8, u64> bus_type_id; | ||
| 63 | BitField<56, 1, u64> is_valid; | ||
| 64 | }; | ||
| 59 | }; | 65 | }; |
| 60 | static_assert(sizeof(BusHandle) == 0x8, "BusHandle is an invalid size"); | 66 | static_assert(sizeof(BusHandle) == 0x8, "BusHandle is an invalid size"); |
| 61 | 67 | ||
| @@ -94,19 +100,38 @@ private: | |||
| 94 | std::unique_ptr<HidbusBase> device{nullptr}; | 100 | std::unique_ptr<HidbusBase> device{nullptr}; |
| 95 | }; | 101 | }; |
| 96 | 102 | ||
| 97 | void GetBusHandle(HLERequestContext& ctx); | 103 | Result GetBusHandle(Out<bool> out_is_valid, Out<BusHandle> out_bus_handle, |
| 98 | void IsExternalDeviceConnected(HLERequestContext& ctx); | 104 | Core::HID::NpadIdType npad_id, BusType bus_type, |
| 99 | void Initialize(HLERequestContext& ctx); | 105 | AppletResourceUserId aruid); |
| 100 | void Finalize(HLERequestContext& ctx); | 106 | |
| 101 | void EnableExternalDevice(HLERequestContext& ctx); | 107 | Result IsExternalDeviceConnected(Out<bool> out_is_connected, BusHandle bus_handle); |
| 102 | void GetExternalDeviceId(HLERequestContext& ctx); | 108 | |
| 103 | void SendCommandAsync(HLERequestContext& ctx); | 109 | Result Initialize(BusHandle bus_handle, AppletResourceUserId aruid); |
| 104 | void GetSendCommandAsynceResult(HLERequestContext& ctx); | 110 | |
| 105 | void SetEventForSendCommandAsycResult(HLERequestContext& ctx); | 111 | Result Finalize(BusHandle bus_handle, AppletResourceUserId aruid); |
| 106 | void GetSharedMemoryHandle(HLERequestContext& ctx); | 112 | |
| 107 | void EnableJoyPollingReceiveMode(HLERequestContext& ctx); | 113 | Result EnableExternalDevice(bool is_enabled, BusHandle bus_handle, u64 inval, |
| 108 | void DisableJoyPollingReceiveMode(HLERequestContext& ctx); | 114 | AppletResourceUserId aruid); |
| 109 | void SetStatusManagerType(HLERequestContext& ctx); | 115 | |
| 116 | Result GetExternalDeviceId(Out<u32> out_device_id, BusHandle bus_handle); | ||
| 117 | |||
| 118 | Result SendCommandAsync(BusHandle bus_handle, InBuffer<BufferAttr_HipcAutoSelect> buffer_data); | ||
| 119 | |||
| 120 | Result GetSendCommandAsynceResult(Out<u64> out_data_size, BusHandle bus_handle, | ||
| 121 | OutBuffer<BufferAttr_HipcAutoSelect> out_buffer_data); | ||
| 122 | |||
| 123 | Result SetEventForSendCommandAsycResult(OutCopyHandle<Kernel::KReadableEvent> out_event, | ||
| 124 | BusHandle bus_handle); | ||
| 125 | |||
| 126 | Result GetSharedMemoryHandle(OutCopyHandle<Kernel::KSharedMemory> out_shared_memory); | ||
| 127 | |||
| 128 | Result EnableJoyPollingReceiveMode(u32 t_mem_size, JoyPollingMode polling_mode, | ||
| 129 | BusHandle bus_handle, | ||
| 130 | InCopyHandle<Kernel::KTransferMemory> t_mem); | ||
| 131 | |||
| 132 | Result DisableJoyPollingReceiveMode(BusHandle bus_handle); | ||
| 133 | |||
| 134 | Result SetStatusManagerType(StatusManagerType manager_type); | ||
| 110 | 135 | ||
| 111 | void UpdateHidbus(std::chrono::nanoseconds ns_late); | 136 | void UpdateHidbus(std::chrono::nanoseconds ns_late); |
| 112 | std::optional<std::size_t> GetDeviceIndexFromHandle(BusHandle handle) const; | 137 | 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: | |||
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | // Returns a reply from a command | 162 | // Returns a reply from a command |
| 163 | virtual std::vector<u8> GetReply() const { | 163 | virtual u64 GetReply(std::span<u8> out_data) const { |
| 164 | return {}; | 164 | return {}; |
| 165 | } | 165 | } |
| 166 | 166 | ||
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 { | |||
| 90 | return device_id; | 90 | return device_id; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | std::vector<u8> RingController::GetReply() const { | 93 | u64 RingController::GetReply(std::span<u8> out_data) const { |
| 94 | const RingConCommands current_command = command; | 94 | const RingConCommands current_command = command; |
| 95 | 95 | ||
| 96 | switch (current_command) { | 96 | switch (current_command) { |
| 97 | case RingConCommands::GetFirmwareVersion: | 97 | case RingConCommands::GetFirmwareVersion: |
| 98 | return GetFirmwareVersionReply(); | 98 | return GetFirmwareVersionReply(out_data); |
| 99 | case RingConCommands::ReadId: | 99 | case RingConCommands::ReadId: |
| 100 | return GetReadIdReply(); | 100 | return GetReadIdReply(out_data); |
| 101 | case RingConCommands::c20105: | 101 | case RingConCommands::c20105: |
| 102 | return GetC020105Reply(); | 102 | return GetC020105Reply(out_data); |
| 103 | case RingConCommands::ReadUnkCal: | 103 | case RingConCommands::ReadUnkCal: |
| 104 | return GetReadUnkCalReply(); | 104 | return GetReadUnkCalReply(out_data); |
| 105 | case RingConCommands::ReadFactoryCal: | 105 | case RingConCommands::ReadFactoryCal: |
| 106 | return GetReadFactoryCalReply(); | 106 | return GetReadFactoryCalReply(out_data); |
| 107 | case RingConCommands::ReadUserCal: | 107 | case RingConCommands::ReadUserCal: |
| 108 | return GetReadUserCalReply(); | 108 | return GetReadUserCalReply(out_data); |
| 109 | case RingConCommands::ReadRepCount: | 109 | case RingConCommands::ReadRepCount: |
| 110 | return GetReadRepCountReply(); | 110 | return GetReadRepCountReply(out_data); |
| 111 | case RingConCommands::ReadTotalPushCount: | 111 | case RingConCommands::ReadTotalPushCount: |
| 112 | return GetReadTotalPushCountReply(); | 112 | return GetReadTotalPushCountReply(out_data); |
| 113 | case RingConCommands::ResetRepCount: | 113 | case RingConCommands::ResetRepCount: |
| 114 | return GetResetRepCountReply(); | 114 | return GetResetRepCountReply(out_data); |
| 115 | case RingConCommands::SaveCalData: | 115 | case RingConCommands::SaveCalData: |
| 116 | return GetSaveDataReply(); | 116 | return GetSaveDataReply(out_data); |
| 117 | default: | 117 | default: |
| 118 | return GetErrorReply(); | 118 | return GetErrorReply(out_data); |
| 119 | } | 119 | } |
| 120 | } | 120 | } |
| 121 | 121 | ||
| @@ -163,16 +163,16 @@ bool RingController::SetCommand(std::span<const u8> data) { | |||
| 163 | } | 163 | } |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | std::vector<u8> RingController::GetFirmwareVersionReply() const { | 166 | u64 RingController::GetFirmwareVersionReply(std::span<u8> out_data) const { |
| 167 | const FirmwareVersionReply reply{ | 167 | const FirmwareVersionReply reply{ |
| 168 | .status = DataValid::Valid, | 168 | .status = DataValid::Valid, |
| 169 | .firmware = version, | 169 | .firmware = version, |
| 170 | }; | 170 | }; |
| 171 | 171 | ||
| 172 | return GetDataVector(reply); | 172 | return GetData(reply, out_data); |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | std::vector<u8> RingController::GetReadIdReply() const { | 175 | u64 RingController::GetReadIdReply(std::span<u8> out_data) const { |
| 176 | // The values are hardcoded from a real joycon | 176 | // The values are hardcoded from a real joycon |
| 177 | const ReadIdReply reply{ | 177 | const ReadIdReply reply{ |
| 178 | .status = DataValid::Valid, | 178 | .status = DataValid::Valid, |
| @@ -184,83 +184,83 @@ std::vector<u8> RingController::GetReadIdReply() const { | |||
| 184 | .id_h_x4 = 8245, | 184 | .id_h_x4 = 8245, |
| 185 | }; | 185 | }; |
| 186 | 186 | ||
| 187 | return GetDataVector(reply); | 187 | return GetData(reply, out_data); |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | std::vector<u8> RingController::GetC020105Reply() const { | 190 | u64 RingController::GetC020105Reply(std::span<u8> out_data) const { |
| 191 | const Cmd020105Reply reply{ | 191 | const Cmd020105Reply reply{ |
| 192 | .status = DataValid::Valid, | 192 | .status = DataValid::Valid, |
| 193 | .data = 1, | 193 | .data = 1, |
| 194 | }; | 194 | }; |
| 195 | 195 | ||
| 196 | return GetDataVector(reply); | 196 | return GetData(reply, out_data); |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | std::vector<u8> RingController::GetReadUnkCalReply() const { | 199 | u64 RingController::GetReadUnkCalReply(std::span<u8> out_data) const { |
| 200 | const ReadUnkCalReply reply{ | 200 | const ReadUnkCalReply reply{ |
| 201 | .status = DataValid::Valid, | 201 | .status = DataValid::Valid, |
| 202 | .data = 0, | 202 | .data = 0, |
| 203 | }; | 203 | }; |
| 204 | 204 | ||
| 205 | return GetDataVector(reply); | 205 | return GetData(reply, out_data); |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | std::vector<u8> RingController::GetReadFactoryCalReply() const { | 208 | u64 RingController::GetReadFactoryCalReply(std::span<u8> out_data) const { |
| 209 | const ReadFactoryCalReply reply{ | 209 | const ReadFactoryCalReply reply{ |
| 210 | .status = DataValid::Valid, | 210 | .status = DataValid::Valid, |
| 211 | .calibration = factory_calibration, | 211 | .calibration = factory_calibration, |
| 212 | }; | 212 | }; |
| 213 | 213 | ||
| 214 | return GetDataVector(reply); | 214 | return GetData(reply, out_data); |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | std::vector<u8> RingController::GetReadUserCalReply() const { | 217 | u64 RingController::GetReadUserCalReply(std::span<u8> out_data) const { |
| 218 | const ReadUserCalReply reply{ | 218 | const ReadUserCalReply reply{ |
| 219 | .status = DataValid::Valid, | 219 | .status = DataValid::Valid, |
| 220 | .calibration = user_calibration, | 220 | .calibration = user_calibration, |
| 221 | }; | 221 | }; |
| 222 | 222 | ||
| 223 | return GetDataVector(reply); | 223 | return GetData(reply, out_data); |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | std::vector<u8> RingController::GetReadRepCountReply() const { | 226 | u64 RingController::GetReadRepCountReply(std::span<u8> out_data) const { |
| 227 | const GetThreeByteReply reply{ | 227 | const GetThreeByteReply reply{ |
| 228 | .status = DataValid::Valid, | 228 | .status = DataValid::Valid, |
| 229 | .data = {total_rep_count, 0, 0}, | 229 | .data = {total_rep_count, 0, 0}, |
| 230 | .crc = GetCrcValue({total_rep_count, 0, 0, 0}), | 230 | .crc = GetCrcValue({total_rep_count, 0, 0, 0}), |
| 231 | }; | 231 | }; |
| 232 | 232 | ||
| 233 | return GetDataVector(reply); | 233 | return GetData(reply, out_data); |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | std::vector<u8> RingController::GetReadTotalPushCountReply() const { | 236 | u64 RingController::GetReadTotalPushCountReply(std::span<u8> out_data) const { |
| 237 | const GetThreeByteReply reply{ | 237 | const GetThreeByteReply reply{ |
| 238 | .status = DataValid::Valid, | 238 | .status = DataValid::Valid, |
| 239 | .data = {total_push_count, 0, 0}, | 239 | .data = {total_push_count, 0, 0}, |
| 240 | .crc = GetCrcValue({total_push_count, 0, 0, 0}), | 240 | .crc = GetCrcValue({total_push_count, 0, 0, 0}), |
| 241 | }; | 241 | }; |
| 242 | 242 | ||
| 243 | return GetDataVector(reply); | 243 | return GetData(reply, out_data); |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | std::vector<u8> RingController::GetResetRepCountReply() const { | 246 | u64 RingController::GetResetRepCountReply(std::span<u8> out_data) const { |
| 247 | return GetReadRepCountReply(); | 247 | return GetReadRepCountReply(out_data); |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | std::vector<u8> RingController::GetSaveDataReply() const { | 250 | u64 RingController::GetSaveDataReply(std::span<u8> out_data) const { |
| 251 | const StatusReply reply{ | 251 | const StatusReply reply{ |
| 252 | .status = DataValid::Valid, | 252 | .status = DataValid::Valid, |
| 253 | }; | 253 | }; |
| 254 | 254 | ||
| 255 | return GetDataVector(reply); | 255 | return GetData(reply, out_data); |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | std::vector<u8> RingController::GetErrorReply() const { | 258 | u64 RingController::GetErrorReply(std::span<u8> out_data) const { |
| 259 | const ErrorReply reply{ | 259 | const ErrorReply reply{ |
| 260 | .status = DataValid::BadCRC, | 260 | .status = DataValid::BadCRC, |
| 261 | }; | 261 | }; |
| 262 | 262 | ||
| 263 | return GetDataVector(reply); | 263 | return GetData(reply, out_data); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | u8 RingController::GetCrcValue(const std::vector<u8>& data) const { | 266 | u8 RingController::GetCrcValue(const std::vector<u8>& data) const { |
| @@ -281,12 +281,11 @@ u8 RingController::GetCrcValue(const std::vector<u8>& data) const { | |||
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | template <typename T> | 283 | template <typename T> |
| 284 | std::vector<u8> RingController::GetDataVector(const T& reply) const { | 284 | u64 RingController::GetData(const T& reply, std::span<u8> out_data) const { |
| 285 | static_assert(std::is_trivially_copyable_v<T>); | 285 | static_assert(std::is_trivially_copyable_v<T>); |
| 286 | std::vector<u8> data; | 286 | const auto data_size = static_cast<u64>(std::min(sizeof(reply), out_data.size())); |
| 287 | data.resize(sizeof(reply)); | 287 | std::memcpy(out_data.data(), &reply, data_size); |
| 288 | std::memcpy(data.data(), &reply, sizeof(reply)); | 288 | return data_size; |
| 289 | return data; | ||
| 290 | } | 289 | } |
| 291 | 290 | ||
| 292 | } // namespace Service::HID | 291 | } // 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: | |||
| 34 | bool SetCommand(std::span<const u8> data) override; | 34 | bool SetCommand(std::span<const u8> data) override; |
| 35 | 35 | ||
| 36 | // Returns a reply from a command | 36 | // Returns a reply from a command |
| 37 | std::vector<u8> GetReply() const override; | 37 | u64 GetReply(std::span<u8> data) const override; |
| 38 | 38 | ||
| 39 | private: | 39 | private: |
| 40 | // These values are obtained from a real ring controller | 40 | // These values are obtained from a real ring controller |
| @@ -184,44 +184,44 @@ private: | |||
| 184 | RingConData GetSensorValue() const; | 184 | RingConData GetSensorValue() const; |
| 185 | 185 | ||
| 186 | // Returns 8 byte reply with firmware version | 186 | // Returns 8 byte reply with firmware version |
| 187 | std::vector<u8> GetFirmwareVersionReply() const; | 187 | u64 GetFirmwareVersionReply(std::span<u8> out_data) const; |
| 188 | 188 | ||
| 189 | // Returns 16 byte reply with ID values | 189 | // Returns 16 byte reply with ID values |
| 190 | std::vector<u8> GetReadIdReply() const; | 190 | u64 GetReadIdReply(std::span<u8> out_data) const; |
| 191 | 191 | ||
| 192 | // (STUBBED) Returns 8 byte reply | 192 | // (STUBBED) Returns 8 byte reply |
| 193 | std::vector<u8> GetC020105Reply() const; | 193 | u64 GetC020105Reply(std::span<u8> out_data) const; |
| 194 | 194 | ||
| 195 | // (STUBBED) Returns 8 byte empty reply | 195 | // (STUBBED) Returns 8 byte empty reply |
| 196 | std::vector<u8> GetReadUnkCalReply() const; | 196 | u64 GetReadUnkCalReply(std::span<u8> out_data) const; |
| 197 | 197 | ||
| 198 | // Returns 20 byte reply with factory calibration values | 198 | // Returns 20 byte reply with factory calibration values |
| 199 | std::vector<u8> GetReadFactoryCalReply() const; | 199 | u64 GetReadFactoryCalReply(std::span<u8> out_data) const; |
| 200 | 200 | ||
| 201 | // Returns 20 byte reply with user calibration values | 201 | // Returns 20 byte reply with user calibration values |
| 202 | std::vector<u8> GetReadUserCalReply() const; | 202 | u64 GetReadUserCalReply(std::span<u8> out_data) const; |
| 203 | 203 | ||
| 204 | // Returns 8 byte reply | 204 | // Returns 8 byte reply |
| 205 | std::vector<u8> GetReadRepCountReply() const; | 205 | u64 GetReadRepCountReply(std::span<u8> out_data) const; |
| 206 | 206 | ||
| 207 | // Returns 8 byte reply | 207 | // Returns 8 byte reply |
| 208 | std::vector<u8> GetReadTotalPushCountReply() const; | 208 | u64 GetReadTotalPushCountReply(std::span<u8> out_data) const; |
| 209 | 209 | ||
| 210 | // Returns 8 byte reply | 210 | // Returns 8 byte reply |
| 211 | std::vector<u8> GetResetRepCountReply() const; | 211 | u64 GetResetRepCountReply(std::span<u8> out_data) const; |
| 212 | 212 | ||
| 213 | // Returns 4 byte save data reply | 213 | // Returns 4 byte save data reply |
| 214 | std::vector<u8> GetSaveDataReply() const; | 214 | u64 GetSaveDataReply(std::span<u8> out_data) const; |
| 215 | 215 | ||
| 216 | // Returns 8 byte error reply | 216 | // Returns 8 byte error reply |
| 217 | std::vector<u8> GetErrorReply() const; | 217 | u64 GetErrorReply(std::span<u8> out_data) const; |
| 218 | 218 | ||
| 219 | // Returns 8 bit redundancy check from provided data | 219 | // Returns 8 bit redundancy check from provided data |
| 220 | u8 GetCrcValue(const std::vector<u8>& data) const; | 220 | u8 GetCrcValue(const std::vector<u8>& data) const; |
| 221 | 221 | ||
| 222 | // Converts structs to an u8 vector equivalent | 222 | // Converts structs to an u8 vector equivalent |
| 223 | template <typename T> | 223 | template <typename T> |
| 224 | std::vector<u8> GetDataVector(const T& reply) const; | 224 | u64 GetData(const T& reply, std::span<u8> out_data) const; |
| 225 | 225 | ||
| 226 | RingConCommands command{RingConCommands::Error}; | 226 | RingConCommands command{RingConCommands::Error}; |
| 227 | 227 | ||
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 { | |||
| 38 | return DEVICE_ID; | 38 | return DEVICE_ID; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | std::vector<u8> Starlink::GetReply() const { | 41 | u64 Starlink::GetReply(std::span<u8> out_data) const { |
| 42 | return {}; | 42 | return {}; |
| 43 | } | 43 | } |
| 44 | 44 | ||
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: | |||
| 31 | bool SetCommand(std::span<const u8> data) override; | 31 | bool SetCommand(std::span<const u8> data) override; |
| 32 | 32 | ||
| 33 | // Returns a reply from a command | 33 | // Returns a reply from a command |
| 34 | std::vector<u8> GetReply() const override; | 34 | u64 GetReply(std::span<u8> out_data) const override; |
| 35 | }; | 35 | }; |
| 36 | 36 | ||
| 37 | } // namespace Service::HID | 37 | } // 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 { | |||
| 38 | return DEVICE_ID; | 38 | return DEVICE_ID; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | std::vector<u8> HidbusStubbed::GetReply() const { | 41 | u64 HidbusStubbed::GetReply(std::span<u8> out_data) const { |
| 42 | return {}; | 42 | return {}; |
| 43 | } | 43 | } |
| 44 | 44 | ||
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: | |||
| 31 | bool SetCommand(std::span<const u8> data) override; | 31 | bool SetCommand(std::span<const u8> data) override; |
| 32 | 32 | ||
| 33 | // Returns a reply from a command | 33 | // Returns a reply from a command |
| 34 | std::vector<u8> GetReply() const override; | 34 | u64 GetReply(std::span<u8> out_data) const override; |
| 35 | }; | 35 | }; |
| 36 | 36 | ||
| 37 | } // namespace Service::HID | 37 | } // namespace Service::HID |