diff options
Diffstat (limited to '')
18 files changed, 1091 insertions, 291 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 1f8439f91..32cc2f392 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -478,6 +478,20 @@ add_library(core STATIC | |||
| 478 | hle/service/hid/hidbus/starlink.h | 478 | hle/service/hid/hidbus/starlink.h |
| 479 | hle/service/hid/hidbus/stubbed.cpp | 479 | hle/service/hid/hidbus/stubbed.cpp |
| 480 | hle/service/hid/hidbus/stubbed.h | 480 | hle/service/hid/hidbus/stubbed.h |
| 481 | hle/service/hid/irsensor/clustering_processor.cpp | ||
| 482 | hle/service/hid/irsensor/clustering_processor.h | ||
| 483 | hle/service/hid/irsensor/image_transfer_processor.cpp | ||
| 484 | hle/service/hid/irsensor/image_transfer_processor.h | ||
| 485 | hle/service/hid/irsensor/ir_led_processor.cpp | ||
| 486 | hle/service/hid/irsensor/ir_led_processor.h | ||
| 487 | hle/service/hid/irsensor/moment_processor.cpp | ||
| 488 | hle/service/hid/irsensor/moment_processor.h | ||
| 489 | hle/service/hid/irsensor/pointing_processor.cpp | ||
| 490 | hle/service/hid/irsensor/pointing_processor.h | ||
| 491 | hle/service/hid/irsensor/processor_base.cpp | ||
| 492 | hle/service/hid/irsensor/processor_base.h | ||
| 493 | hle/service/hid/irsensor/tera_plugin_processor.cpp | ||
| 494 | hle/service/hid/irsensor/tera_plugin_processor.h | ||
| 481 | hle/service/jit/jit_context.cpp | 495 | hle/service/jit/jit_context.cpp |
| 482 | hle/service/jit/jit_context.h | 496 | hle/service/jit/jit_context.h |
| 483 | hle/service/jit/jit.cpp | 497 | hle/service/jit/jit.cpp |
diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h index 46282f42e..1bd62461c 100644 --- a/src/core/hle/service/hid/errors.h +++ b/src/core/hle/service/hid/errors.h | |||
| @@ -18,4 +18,7 @@ constexpr Result NpadIsSameType{ErrorModule::HID, 602}; | |||
| 18 | constexpr Result InvalidNpadId{ErrorModule::HID, 709}; | 18 | constexpr Result InvalidNpadId{ErrorModule::HID, 709}; |
| 19 | constexpr Result NpadNotConnected{ErrorModule::HID, 710}; | 19 | constexpr Result NpadNotConnected{ErrorModule::HID, 710}; |
| 20 | 20 | ||
| 21 | constexpr ResultCode InvalidProcessorState{ErrorModule::Irsensor, 78}; | ||
| 22 | constexpr ResultCode InvalidIrCameraHandle{ErrorModule::Irsensor, 204}; | ||
| 23 | |||
| 21 | } // namespace Service::HID | 24 | } // namespace Service::HID |
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index d2a91d913..53a31df79 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp | |||
| @@ -1,14 +1,26 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <algorithm> | ||
| 5 | #include <random> | ||
| 6 | |||
| 4 | #include "core/core.h" | 7 | #include "core/core.h" |
| 5 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 9 | #include "core/hid/emulated_controller.h" | ||
| 10 | #include "core/hid/hid_core.h" | ||
| 6 | #include "core/hle/ipc_helpers.h" | 11 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/k_shared_memory.h" | 12 | #include "core/hle/kernel/k_shared_memory.h" |
| 8 | #include "core/hle/kernel/k_transfer_memory.h" | 13 | #include "core/hle/kernel/k_transfer_memory.h" |
| 9 | #include "core/hle/kernel/kernel.h" | 14 | #include "core/hle/kernel/kernel.h" |
| 10 | #include "core/hle/service/hid/errors.h" | 15 | #include "core/hle/service/hid/errors.h" |
| 11 | #include "core/hle/service/hid/irs.h" | 16 | #include "core/hle/service/hid/irs.h" |
| 17 | #include "core/hle/service/hid/irsensor/clustering_processor.h" | ||
| 18 | #include "core/hle/service/hid/irsensor/image_transfer_processor.h" | ||
| 19 | #include "core/hle/service/hid/irsensor/ir_led_processor.h" | ||
| 20 | #include "core/hle/service/hid/irsensor/moment_processor.h" | ||
| 21 | #include "core/hle/service/hid/irsensor/pointing_processor.h" | ||
| 22 | #include "core/hle/service/hid/irsensor/tera_plugin_processor.h" | ||
| 23 | #include "core/memory.h" | ||
| 12 | 24 | ||
| 13 | namespace Service::HID { | 25 | namespace Service::HID { |
| 14 | 26 | ||
| @@ -36,8 +48,13 @@ IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} { | |||
| 36 | }; | 48 | }; |
| 37 | // clang-format on | 49 | // clang-format on |
| 38 | 50 | ||
| 51 | u8* raw_shared_memory = system.Kernel().GetIrsSharedMem().GetPointer(); | ||
| 39 | RegisterHandlers(functions); | 52 | RegisterHandlers(functions); |
| 53 | shared_memory = std::construct_at(reinterpret_cast<StatusManager*>(raw_shared_memory)); | ||
| 54 | |||
| 55 | npad_device = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); | ||
| 40 | } | 56 | } |
| 57 | IRS::~IRS() = default; | ||
| 41 | 58 | ||
| 42 | void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) { | 59 | void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) { |
| 43 | IPC::RequestParser rp{ctx}; | 60 | IPC::RequestParser rp{ctx}; |
| @@ -75,7 +92,7 @@ void IRS::GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx) { | |||
| 75 | void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { | 92 | void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { |
| 76 | IPC::RequestParser rp{ctx}; | 93 | IPC::RequestParser rp{ctx}; |
| 77 | struct Parameters { | 94 | struct Parameters { |
| 78 | IrCameraHandle camera_handle; | 95 | Core::IrSensor::IrCameraHandle camera_handle; |
| 79 | INSERT_PADDING_WORDS_NOINIT(1); | 96 | INSERT_PADDING_WORDS_NOINIT(1); |
| 80 | u64 applet_resource_user_id; | 97 | u64 applet_resource_user_id; |
| 81 | }; | 98 | }; |
| @@ -88,17 +105,23 @@ void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { | |||
| 88 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | 105 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, |
| 89 | parameters.applet_resource_user_id); | 106 | parameters.applet_resource_user_id); |
| 90 | 107 | ||
| 108 | auto result = IsIrCameraHandleValid(parameters.camera_handle); | ||
| 109 | if (result.IsSuccess()) { | ||
| 110 | // TODO: Stop Image processor | ||
| 111 | result = ResultSuccess; | ||
| 112 | } | ||
| 113 | |||
| 91 | IPC::ResponseBuilder rb{ctx, 2}; | 114 | IPC::ResponseBuilder rb{ctx, 2}; |
| 92 | rb.Push(ResultSuccess); | 115 | rb.Push(result); |
| 93 | } | 116 | } |
| 94 | 117 | ||
| 95 | void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) { | 118 | void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) { |
| 96 | IPC::RequestParser rp{ctx}; | 119 | IPC::RequestParser rp{ctx}; |
| 97 | struct Parameters { | 120 | struct Parameters { |
| 98 | IrCameraHandle camera_handle; | 121 | Core::IrSensor::IrCameraHandle camera_handle; |
| 99 | INSERT_PADDING_WORDS_NOINIT(1); | 122 | INSERT_PADDING_WORDS_NOINIT(1); |
| 100 | u64 applet_resource_user_id; | 123 | u64 applet_resource_user_id; |
| 101 | PackedMomentProcessorConfig processor_config; | 124 | Core::IrSensor::PackedMomentProcessorConfig processor_config; |
| 102 | }; | 125 | }; |
| 103 | static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size."); | 126 | static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size."); |
| 104 | 127 | ||
| @@ -109,17 +132,26 @@ void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) { | |||
| 109 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | 132 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, |
| 110 | parameters.applet_resource_user_id); | 133 | parameters.applet_resource_user_id); |
| 111 | 134 | ||
| 135 | const auto result = IsIrCameraHandleValid(parameters.camera_handle); | ||
| 136 | |||
| 137 | if (result.IsSuccess()) { | ||
| 138 | auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); | ||
| 139 | MakeProcessor<MomentProcessor>(parameters.camera_handle, device); | ||
| 140 | auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle); | ||
| 141 | image_transfer_processor.SetConfig(parameters.processor_config); | ||
| 142 | } | ||
| 143 | |||
| 112 | IPC::ResponseBuilder rb{ctx, 2}; | 144 | IPC::ResponseBuilder rb{ctx, 2}; |
| 113 | rb.Push(ResultSuccess); | 145 | rb.Push(result); |
| 114 | } | 146 | } |
| 115 | 147 | ||
| 116 | void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { | 148 | void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { |
| 117 | IPC::RequestParser rp{ctx}; | 149 | IPC::RequestParser rp{ctx}; |
| 118 | struct Parameters { | 150 | struct Parameters { |
| 119 | IrCameraHandle camera_handle; | 151 | Core::IrSensor::IrCameraHandle camera_handle; |
| 120 | INSERT_PADDING_WORDS_NOINIT(1); | 152 | INSERT_PADDING_WORDS_NOINIT(1); |
| 121 | u64 applet_resource_user_id; | 153 | u64 applet_resource_user_id; |
| 122 | PackedClusteringProcessorConfig processor_config; | 154 | Core::IrSensor::PackedClusteringProcessorConfig processor_config; |
| 123 | }; | 155 | }; |
| 124 | static_assert(sizeof(Parameters) == 0x40, "Parameters has incorrect size."); | 156 | static_assert(sizeof(Parameters) == 0x40, "Parameters has incorrect size."); |
| 125 | 157 | ||
| @@ -130,17 +162,27 @@ void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { | |||
| 130 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | 162 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, |
| 131 | parameters.applet_resource_user_id); | 163 | parameters.applet_resource_user_id); |
| 132 | 164 | ||
| 165 | auto result = IsIrCameraHandleValid(parameters.camera_handle); | ||
| 166 | |||
| 167 | if (result.IsSuccess()) { | ||
| 168 | auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); | ||
| 169 | MakeProcessor<ClusteringProcessor>(parameters.camera_handle, device); | ||
| 170 | auto& image_transfer_processor = | ||
| 171 | GetProcessor<ClusteringProcessor>(parameters.camera_handle); | ||
| 172 | image_transfer_processor.SetConfig(parameters.processor_config); | ||
| 173 | } | ||
| 174 | |||
| 133 | IPC::ResponseBuilder rb{ctx, 2}; | 175 | IPC::ResponseBuilder rb{ctx, 2}; |
| 134 | rb.Push(ResultSuccess); | 176 | rb.Push(result); |
| 135 | } | 177 | } |
| 136 | 178 | ||
| 137 | void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { | 179 | void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { |
| 138 | IPC::RequestParser rp{ctx}; | 180 | IPC::RequestParser rp{ctx}; |
| 139 | struct Parameters { | 181 | struct Parameters { |
| 140 | IrCameraHandle camera_handle; | 182 | Core::IrSensor::IrCameraHandle camera_handle; |
| 141 | INSERT_PADDING_WORDS_NOINIT(1); | 183 | INSERT_PADDING_WORDS_NOINIT(1); |
| 142 | u64 applet_resource_user_id; | 184 | u64 applet_resource_user_id; |
| 143 | PackedImageTransferProcessorConfig processor_config; | 185 | Core::IrSensor::PackedImageTransferProcessorConfig processor_config; |
| 144 | u32 transfer_memory_size; | 186 | u32 transfer_memory_size; |
| 145 | }; | 187 | }; |
| 146 | static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size."); | 188 | static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size."); |
| @@ -151,20 +193,42 @@ void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { | |||
| 151 | auto t_mem = | 193 | auto t_mem = |
| 152 | system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); | 194 | system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); |
| 153 | 195 | ||
| 154 | LOG_WARNING(Service_IRS, | 196 | if (t_mem.IsNull()) { |
| 155 | "(STUBBED) called, npad_type={}, npad_id={}, transfer_memory_size={}, " | 197 | LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); |
| 156 | "applet_resource_user_id={}", | 198 | IPC::ResponseBuilder rb{ctx, 2}; |
| 157 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | 199 | rb.Push(ResultUnknown); |
| 158 | parameters.transfer_memory_size, parameters.applet_resource_user_id); | 200 | return; |
| 201 | } | ||
| 202 | |||
| 203 | ASSERT_MSG(t_mem->GetSize() == parameters.transfer_memory_size, "t_mem has incorrect size"); | ||
| 204 | |||
| 205 | u8* transfer_memory = system.Memory().GetPointer(t_mem->GetSourceAddress()); | ||
| 206 | |||
| 207 | LOG_INFO(Service_IRS, | ||
| 208 | "called, npad_type={}, npad_id={}, transfer_memory_size={}, transfer_memory_size={}, " | ||
| 209 | "applet_resource_user_id={}", | ||
| 210 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | ||
| 211 | parameters.transfer_memory_size, t_mem->GetSize(), parameters.applet_resource_user_id); | ||
| 212 | |||
| 213 | const auto result = IsIrCameraHandleValid(parameters.camera_handle); | ||
| 214 | |||
| 215 | if (result.IsSuccess()) { | ||
| 216 | auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); | ||
| 217 | MakeProcessorWithCoreContext<ImageTransferProcessor>(parameters.camera_handle, device); | ||
| 218 | auto& image_transfer_processor = | ||
| 219 | GetProcessor<ImageTransferProcessor>(parameters.camera_handle); | ||
| 220 | image_transfer_processor.SetConfig(parameters.processor_config); | ||
| 221 | image_transfer_processor.SetTransferMemoryPointer(transfer_memory); | ||
| 222 | } | ||
| 159 | 223 | ||
| 160 | IPC::ResponseBuilder rb{ctx, 2}; | 224 | IPC::ResponseBuilder rb{ctx, 2}; |
| 161 | rb.Push(ResultSuccess); | 225 | rb.Push(result); |
| 162 | } | 226 | } |
| 163 | 227 | ||
| 164 | void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) { | 228 | void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) { |
| 165 | IPC::RequestParser rp{ctx}; | 229 | IPC::RequestParser rp{ctx}; |
| 166 | struct Parameters { | 230 | struct Parameters { |
| 167 | IrCameraHandle camera_handle; | 231 | Core::IrSensor::IrCameraHandle camera_handle; |
| 168 | INSERT_PADDING_WORDS_NOINIT(1); | 232 | INSERT_PADDING_WORDS_NOINIT(1); |
| 169 | u64 applet_resource_user_id; | 233 | u64 applet_resource_user_id; |
| 170 | }; | 234 | }; |
| @@ -172,21 +236,40 @@ void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) { | |||
| 172 | 236 | ||
| 173 | const auto parameters{rp.PopRaw<Parameters>()}; | 237 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 174 | 238 | ||
| 175 | LOG_WARNING(Service_IRS, | 239 | LOG_DEBUG(Service_IRS, "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", |
| 176 | "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", | 240 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, |
| 177 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | 241 | parameters.applet_resource_user_id); |
| 178 | parameters.applet_resource_user_id); | 242 | |
| 243 | const auto result = IsIrCameraHandleValid(parameters.camera_handle); | ||
| 244 | if (result.IsError()) { | ||
| 245 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 246 | rb.Push(result); | ||
| 247 | return; | ||
| 248 | } | ||
| 179 | 249 | ||
| 180 | IPC::ResponseBuilder rb{ctx, 5}; | 250 | const auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); |
| 251 | |||
| 252 | if (device.mode != Core::IrSensor::IrSensorMode::ImageTransferProcessor) { | ||
| 253 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 254 | rb.Push(InvalidProcessorState); | ||
| 255 | return; | ||
| 256 | } | ||
| 257 | |||
| 258 | std::vector<u8> data{}; | ||
| 259 | const auto& image_transfer_processor = | ||
| 260 | GetProcessor<ImageTransferProcessor>(parameters.camera_handle); | ||
| 261 | const auto& state = image_transfer_processor.GetState(data); | ||
| 262 | |||
| 263 | ctx.WriteBuffer(data); | ||
| 264 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 181 | rb.Push(ResultSuccess); | 265 | rb.Push(ResultSuccess); |
| 182 | rb.PushRaw<u64>(system.CoreTiming().GetCPUTicks()); | 266 | rb.PushRaw(state); |
| 183 | rb.PushRaw<u32>(0); | ||
| 184 | } | 267 | } |
| 185 | 268 | ||
| 186 | void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) { | 269 | void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) { |
| 187 | IPC::RequestParser rp{ctx}; | 270 | IPC::RequestParser rp{ctx}; |
| 188 | const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; | 271 | const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; |
| 189 | const auto processor_config{rp.PopRaw<PackedTeraPluginProcessorConfig>()}; | 272 | const auto processor_config{rp.PopRaw<Core::IrSensor::PackedTeraPluginProcessorConfig>()}; |
| 190 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 273 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 191 | 274 | ||
| 192 | LOG_WARNING(Service_IRS, | 275 | LOG_WARNING(Service_IRS, |
| @@ -196,8 +279,17 @@ void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) { | |||
| 196 | processor_config.required_mcu_version.major, | 279 | processor_config.required_mcu_version.major, |
| 197 | processor_config.required_mcu_version.minor, applet_resource_user_id); | 280 | processor_config.required_mcu_version.minor, applet_resource_user_id); |
| 198 | 281 | ||
| 282 | const auto result = IsIrCameraHandleValid(camera_handle); | ||
| 283 | |||
| 284 | if (result.IsSuccess()) { | ||
| 285 | auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle); | ||
| 286 | MakeProcessor<TeraPluginProcessor>(camera_handle, device); | ||
| 287 | auto& image_transfer_processor = GetProcessor<TeraPluginProcessor>(camera_handle); | ||
| 288 | image_transfer_processor.SetConfig(processor_config); | ||
| 289 | } | ||
| 290 | |||
| 199 | IPC::ResponseBuilder rb{ctx, 2}; | 291 | IPC::ResponseBuilder rb{ctx, 2}; |
| 200 | rb.Push(ResultSuccess); | 292 | rb.Push(result); |
| 201 | } | 293 | } |
| 202 | 294 | ||
| 203 | void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) { | 295 | void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) { |
| @@ -211,13 +303,13 @@ void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) { | |||
| 211 | return; | 303 | return; |
| 212 | } | 304 | } |
| 213 | 305 | ||
| 214 | IrCameraHandle camera_handle{ | 306 | Core::IrSensor::IrCameraHandle camera_handle{ |
| 215 | .npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)), | 307 | .npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)), |
| 216 | .npad_type = Core::HID::NpadStyleIndex::None, | 308 | .npad_type = Core::HID::NpadStyleIndex::None, |
| 217 | }; | 309 | }; |
| 218 | 310 | ||
| 219 | LOG_WARNING(Service_IRS, "(STUBBED) called, npad_id={}, camera_npad_id={}, camera_npad_type={}", | 311 | LOG_INFO(Service_IRS, "called, npad_id={}, camera_npad_id={}, camera_npad_type={}", npad_id, |
| 220 | npad_id, camera_handle.npad_id, camera_handle.npad_type); | 312 | camera_handle.npad_id, camera_handle.npad_type); |
| 221 | 313 | ||
| 222 | IPC::ResponseBuilder rb{ctx, 3}; | 314 | IPC::ResponseBuilder rb{ctx, 3}; |
| 223 | rb.Push(ResultSuccess); | 315 | rb.Push(ResultSuccess); |
| @@ -226,8 +318,8 @@ void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) { | |||
| 226 | 318 | ||
| 227 | void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) { | 319 | void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) { |
| 228 | IPC::RequestParser rp{ctx}; | 320 | IPC::RequestParser rp{ctx}; |
| 229 | const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; | 321 | const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; |
| 230 | const auto processor_config{rp.PopRaw<PackedPointingProcessorConfig>()}; | 322 | const auto processor_config{rp.PopRaw<Core::IrSensor::PackedPointingProcessorConfig>()}; |
| 231 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 323 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 232 | 324 | ||
| 233 | LOG_WARNING( | 325 | LOG_WARNING( |
| @@ -236,14 +328,23 @@ void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) { | |||
| 236 | camera_handle.npad_type, camera_handle.npad_id, processor_config.required_mcu_version.major, | 328 | camera_handle.npad_type, camera_handle.npad_id, processor_config.required_mcu_version.major, |
| 237 | processor_config.required_mcu_version.minor, applet_resource_user_id); | 329 | processor_config.required_mcu_version.minor, applet_resource_user_id); |
| 238 | 330 | ||
| 331 | auto result = IsIrCameraHandleValid(camera_handle); | ||
| 332 | |||
| 333 | if (result.IsSuccess()) { | ||
| 334 | auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle); | ||
| 335 | MakeProcessor<PointingProcessor>(camera_handle, device); | ||
| 336 | auto& image_transfer_processor = GetProcessor<PointingProcessor>(camera_handle); | ||
| 337 | image_transfer_processor.SetConfig(processor_config); | ||
| 338 | } | ||
| 339 | |||
| 239 | IPC::ResponseBuilder rb{ctx, 2}; | 340 | IPC::ResponseBuilder rb{ctx, 2}; |
| 240 | rb.Push(ResultSuccess); | 341 | rb.Push(result); |
| 241 | } | 342 | } |
| 242 | 343 | ||
| 243 | void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) { | 344 | void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) { |
| 244 | IPC::RequestParser rp{ctx}; | 345 | IPC::RequestParser rp{ctx}; |
| 245 | struct Parameters { | 346 | struct Parameters { |
| 246 | IrCameraHandle camera_handle; | 347 | Core::IrSensor::IrCameraHandle camera_handle; |
| 247 | INSERT_PADDING_WORDS_NOINIT(1); | 348 | INSERT_PADDING_WORDS_NOINIT(1); |
| 248 | u64 applet_resource_user_id; | 349 | u64 applet_resource_user_id; |
| 249 | }; | 350 | }; |
| @@ -256,14 +357,20 @@ void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) { | |||
| 256 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | 357 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, |
| 257 | parameters.applet_resource_user_id); | 358 | parameters.applet_resource_user_id); |
| 258 | 359 | ||
| 360 | auto result = IsIrCameraHandleValid(parameters.camera_handle); | ||
| 361 | if (result.IsSuccess()) { | ||
| 362 | // TODO: Suspend image processor | ||
| 363 | result = ResultSuccess; | ||
| 364 | } | ||
| 365 | |||
| 259 | IPC::ResponseBuilder rb{ctx, 2}; | 366 | IPC::ResponseBuilder rb{ctx, 2}; |
| 260 | rb.Push(ResultSuccess); | 367 | rb.Push(result); |
| 261 | } | 368 | } |
| 262 | 369 | ||
| 263 | void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) { | 370 | void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) { |
| 264 | IPC::RequestParser rp{ctx}; | 371 | IPC::RequestParser rp{ctx}; |
| 265 | const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; | 372 | const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; |
| 266 | const auto mcu_version{rp.PopRaw<PackedMcuVersion>()}; | 373 | const auto mcu_version{rp.PopRaw<Core::IrSensor::PackedMcuVersion>()}; |
| 267 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 374 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 268 | 375 | ||
| 269 | LOG_WARNING( | 376 | LOG_WARNING( |
| @@ -272,37 +379,45 @@ void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) { | |||
| 272 | camera_handle.npad_type, camera_handle.npad_id, applet_resource_user_id, mcu_version.major, | 379 | camera_handle.npad_type, camera_handle.npad_id, applet_resource_user_id, mcu_version.major, |
| 273 | mcu_version.minor); | 380 | mcu_version.minor); |
| 274 | 381 | ||
| 382 | auto result = IsIrCameraHandleValid(camera_handle); | ||
| 383 | if (result.IsSuccess()) { | ||
| 384 | // TODO: Check firmware version | ||
| 385 | result = ResultSuccess; | ||
| 386 | } | ||
| 387 | |||
| 275 | IPC::ResponseBuilder rb{ctx, 2}; | 388 | IPC::ResponseBuilder rb{ctx, 2}; |
| 276 | rb.Push(ResultSuccess); | 389 | rb.Push(result); |
| 277 | } | 390 | } |
| 278 | 391 | ||
| 279 | void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) { | 392 | void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) { |
| 280 | IPC::RequestParser rp{ctx}; | 393 | IPC::RequestParser rp{ctx}; |
| 281 | struct Parameters { | 394 | const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; |
| 282 | IrCameraHandle camera_handle; | 395 | const auto function_level{rp.PopRaw<Core::IrSensor::PackedFunctionLevel>()}; |
| 283 | PackedFunctionLevel function_level; | 396 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 284 | u64 applet_resource_user_id; | ||
| 285 | }; | ||
| 286 | static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); | ||
| 287 | |||
| 288 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 289 | 397 | ||
| 290 | LOG_WARNING(Service_IRS, | 398 | LOG_WARNING( |
| 291 | "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", | 399 | Service_IRS, |
| 292 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | 400 | "(STUBBED) called, npad_type={}, npad_id={}, function_level={}, applet_resource_user_id={}", |
| 293 | parameters.applet_resource_user_id); | 401 | camera_handle.npad_type, camera_handle.npad_id, function_level.function_level, |
| 402 | applet_resource_user_id); | ||
| 403 | |||
| 404 | auto result = IsIrCameraHandleValid(camera_handle); | ||
| 405 | if (result.IsSuccess()) { | ||
| 406 | // TODO: Set Function level | ||
| 407 | result = ResultSuccess; | ||
| 408 | } | ||
| 294 | 409 | ||
| 295 | IPC::ResponseBuilder rb{ctx, 2}; | 410 | IPC::ResponseBuilder rb{ctx, 2}; |
| 296 | rb.Push(ResultSuccess); | 411 | rb.Push(result); |
| 297 | } | 412 | } |
| 298 | 413 | ||
| 299 | void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { | 414 | void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { |
| 300 | IPC::RequestParser rp{ctx}; | 415 | IPC::RequestParser rp{ctx}; |
| 301 | struct Parameters { | 416 | struct Parameters { |
| 302 | IrCameraHandle camera_handle; | 417 | Core::IrSensor::IrCameraHandle camera_handle; |
| 303 | INSERT_PADDING_WORDS_NOINIT(1); | 418 | INSERT_PADDING_WORDS_NOINIT(1); |
| 304 | u64 applet_resource_user_id; | 419 | u64 applet_resource_user_id; |
| 305 | PackedImageTransferProcessorExConfig processor_config; | 420 | Core::IrSensor::PackedImageTransferProcessorExConfig processor_config; |
| 306 | u64 transfer_memory_size; | 421 | u64 transfer_memory_size; |
| 307 | }; | 422 | }; |
| 308 | static_assert(sizeof(Parameters) == 0x38, "Parameters has incorrect size."); | 423 | static_assert(sizeof(Parameters) == 0x38, "Parameters has incorrect size."); |
| @@ -313,20 +428,33 @@ void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { | |||
| 313 | auto t_mem = | 428 | auto t_mem = |
| 314 | system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); | 429 | system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); |
| 315 | 430 | ||
| 316 | LOG_WARNING(Service_IRS, | 431 | u8* transfer_memory = system.Memory().GetPointer(t_mem->GetSourceAddress()); |
| 317 | "(STUBBED) called, npad_type={}, npad_id={}, transfer_memory_size={}, " | 432 | |
| 318 | "applet_resource_user_id={}", | 433 | LOG_INFO(Service_IRS, |
| 319 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | 434 | "called, npad_type={}, npad_id={}, transfer_memory_size={}, " |
| 320 | parameters.transfer_memory_size, parameters.applet_resource_user_id); | 435 | "applet_resource_user_id={}", |
| 436 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | ||
| 437 | parameters.transfer_memory_size, parameters.applet_resource_user_id); | ||
| 438 | |||
| 439 | auto result = IsIrCameraHandleValid(parameters.camera_handle); | ||
| 440 | |||
| 441 | if (result.IsSuccess()) { | ||
| 442 | auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); | ||
| 443 | MakeProcessorWithCoreContext<ImageTransferProcessor>(parameters.camera_handle, device); | ||
| 444 | auto& image_transfer_processor = | ||
| 445 | GetProcessor<ImageTransferProcessor>(parameters.camera_handle); | ||
| 446 | image_transfer_processor.SetConfig(parameters.processor_config); | ||
| 447 | image_transfer_processor.SetTransferMemoryPointer(transfer_memory); | ||
| 448 | } | ||
| 321 | 449 | ||
| 322 | IPC::ResponseBuilder rb{ctx, 2}; | 450 | IPC::ResponseBuilder rb{ctx, 2}; |
| 323 | rb.Push(ResultSuccess); | 451 | rb.Push(result); |
| 324 | } | 452 | } |
| 325 | 453 | ||
| 326 | void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) { | 454 | void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) { |
| 327 | IPC::RequestParser rp{ctx}; | 455 | IPC::RequestParser rp{ctx}; |
| 328 | const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; | 456 | const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; |
| 329 | const auto processor_config{rp.PopRaw<PackedIrLedProcessorConfig>()}; | 457 | const auto processor_config{rp.PopRaw<Core::IrSensor::PackedIrLedProcessorConfig>()}; |
| 330 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 458 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 331 | 459 | ||
| 332 | LOG_WARNING(Service_IRS, | 460 | LOG_WARNING(Service_IRS, |
| @@ -336,14 +464,23 @@ void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) { | |||
| 336 | processor_config.required_mcu_version.major, | 464 | processor_config.required_mcu_version.major, |
| 337 | processor_config.required_mcu_version.minor, applet_resource_user_id); | 465 | processor_config.required_mcu_version.minor, applet_resource_user_id); |
| 338 | 466 | ||
| 467 | auto result = IsIrCameraHandleValid(camera_handle); | ||
| 468 | |||
| 469 | if (result.IsSuccess()) { | ||
| 470 | auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle); | ||
| 471 | MakeProcessor<IrLedProcessor>(camera_handle, device); | ||
| 472 | auto& image_transfer_processor = GetProcessor<IrLedProcessor>(camera_handle); | ||
| 473 | image_transfer_processor.SetConfig(processor_config); | ||
| 474 | } | ||
| 475 | |||
| 339 | IPC::ResponseBuilder rb{ctx, 2}; | 476 | IPC::ResponseBuilder rb{ctx, 2}; |
| 340 | rb.Push(ResultSuccess); | 477 | rb.Push(result); |
| 341 | } | 478 | } |
| 342 | 479 | ||
| 343 | void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { | 480 | void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { |
| 344 | IPC::RequestParser rp{ctx}; | 481 | IPC::RequestParser rp{ctx}; |
| 345 | struct Parameters { | 482 | struct Parameters { |
| 346 | IrCameraHandle camera_handle; | 483 | Core::IrSensor::IrCameraHandle camera_handle; |
| 347 | INSERT_PADDING_WORDS_NOINIT(1); | 484 | INSERT_PADDING_WORDS_NOINIT(1); |
| 348 | u64 applet_resource_user_id; | 485 | u64 applet_resource_user_id; |
| 349 | }; | 486 | }; |
| @@ -356,14 +493,20 @@ void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { | |||
| 356 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | 493 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, |
| 357 | parameters.applet_resource_user_id); | 494 | parameters.applet_resource_user_id); |
| 358 | 495 | ||
| 496 | auto result = IsIrCameraHandleValid(parameters.camera_handle); | ||
| 497 | if (result.IsSuccess()) { | ||
| 498 | // TODO: Stop image processor async | ||
| 499 | result = ResultSuccess; | ||
| 500 | } | ||
| 501 | |||
| 359 | IPC::ResponseBuilder rb{ctx, 2}; | 502 | IPC::ResponseBuilder rb{ctx, 2}; |
| 360 | rb.Push(ResultSuccess); | 503 | rb.Push(result); |
| 361 | } | 504 | } |
| 362 | 505 | ||
| 363 | void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) { | 506 | void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) { |
| 364 | IPC::RequestParser rp{ctx}; | 507 | IPC::RequestParser rp{ctx}; |
| 365 | struct Parameters { | 508 | struct Parameters { |
| 366 | PackedFunctionLevel function_level; | 509 | Core::IrSensor::PackedFunctionLevel function_level; |
| 367 | INSERT_PADDING_WORDS_NOINIT(1); | 510 | INSERT_PADDING_WORDS_NOINIT(1); |
| 368 | u64 applet_resource_user_id; | 511 | u64 applet_resource_user_id; |
| 369 | }; | 512 | }; |
| @@ -378,7 +521,22 @@ void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) { | |||
| 378 | rb.Push(ResultSuccess); | 521 | rb.Push(ResultSuccess); |
| 379 | } | 522 | } |
| 380 | 523 | ||
| 381 | IRS::~IRS() = default; | 524 | ResultCode IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const { |
| 525 | if (camera_handle.npad_id > | ||
| 526 | static_cast<u8>(NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) { | ||
| 527 | return InvalidIrCameraHandle; | ||
| 528 | } | ||
| 529 | if (camera_handle.npad_type != Core::HID::NpadStyleIndex::None) { | ||
| 530 | return InvalidIrCameraHandle; | ||
| 531 | } | ||
| 532 | return ResultSuccess; | ||
| 533 | } | ||
| 534 | |||
| 535 | Core::IrSensor::DeviceFormat& IRS::GetIrCameraSharedMemoryDeviceEntry( | ||
| 536 | const Core::IrSensor::IrCameraHandle& camera_handle) { | ||
| 537 | ASSERT_MSG(sizeof(StatusManager::device) > camera_handle.npad_id, "invalid npad_id"); | ||
| 538 | return shared_memory->device[camera_handle.npad_id]; | ||
| 539 | } | ||
| 382 | 540 | ||
| 383 | IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} { | 541 | IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} { |
| 384 | // clang-format off | 542 | // clang-format off |
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h index 361dc2213..ae7f7719b 100644 --- a/src/core/hle/service/hid/irs.h +++ b/src/core/hle/service/hid/irs.h | |||
| @@ -4,12 +4,18 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "core/hid/hid_types.h" | 6 | #include "core/hid/hid_types.h" |
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 7 | #include "core/hle/service/service.h" | 9 | #include "core/hle/service/service.h" |
| 8 | 10 | ||
| 9 | namespace Core { | 11 | namespace Core { |
| 10 | class System; | 12 | class System; |
| 11 | } | 13 | } |
| 12 | 14 | ||
| 15 | namespace Core::HID { | ||
| 16 | class EmulatedController; | ||
| 17 | } // namespace Core::HID | ||
| 18 | |||
| 13 | namespace Service::HID { | 19 | namespace Service::HID { |
| 14 | 20 | ||
| 15 | class IRS final : public ServiceFramework<IRS> { | 21 | class IRS final : public ServiceFramework<IRS> { |
| @@ -18,234 +24,19 @@ public: | |||
| 18 | ~IRS() override; | 24 | ~IRS() override; |
| 19 | 25 | ||
| 20 | private: | 26 | private: |
| 21 | // This is nn::irsensor::IrCameraStatus | 27 | // This is nn::irsensor::detail::AruidFormat |
| 22 | enum IrCameraStatus : u32 { | 28 | struct AruidFormat { |
| 23 | Available, | 29 | u64 sensor_aruid; |
| 24 | Unsupported, | 30 | u64 sensor_aruid_status; |
| 25 | Unconnected, | ||
| 26 | }; | ||
| 27 | |||
| 28 | // This is nn::irsensor::IrCameraInternalStatus | ||
| 29 | enum IrCameraInternalStatus : u32 { | ||
| 30 | Stopped, | ||
| 31 | FirmwareUpdateNeeded, | ||
| 32 | Unkown2, | ||
| 33 | Unkown3, | ||
| 34 | Unkown4, | ||
| 35 | FirmwareVersionRequested, | ||
| 36 | FirmwareVersionIsInvalid, | ||
| 37 | Ready, | ||
| 38 | Setting, | ||
| 39 | }; | ||
| 40 | |||
| 41 | // This is nn::irsensor::detail::StatusManager::IrSensorMode | ||
| 42 | enum IrSensorMode : u64 { | ||
| 43 | None, | ||
| 44 | MomentProcessor, | ||
| 45 | ClusteringProcessor, | ||
| 46 | ImageTransferProcessor, | ||
| 47 | PointingProcessorMarker, | ||
| 48 | TeraPluginProcessor, | ||
| 49 | IrLedProcessor, | ||
| 50 | }; | ||
| 51 | |||
| 52 | // This is nn::irsensor::ImageProcessorStatus | ||
| 53 | enum ImageProcessorStatus : u8 { | ||
| 54 | stopped, | ||
| 55 | running, | ||
| 56 | }; | ||
| 57 | |||
| 58 | // This is nn::irsensor::ImageTransferProcessorFormat | ||
| 59 | enum ImageTransferProcessorFormat : u8 { | ||
| 60 | Size320x240, | ||
| 61 | Size160x120, | ||
| 62 | Size80x60, | ||
| 63 | Size40x30, | ||
| 64 | Size20x15, | ||
| 65 | }; | ||
| 66 | |||
| 67 | // This is nn::irsensor::AdaptiveClusteringMode | ||
| 68 | enum AdaptiveClusteringMode : u8 { | ||
| 69 | StaticFov, | ||
| 70 | DynamicFov, | ||
| 71 | }; | ||
| 72 | |||
| 73 | // This is nn::irsensor::AdaptiveClusteringTargetDistance | ||
| 74 | enum AdaptiveClusteringTargetDistance : u8 { | ||
| 75 | Near, | ||
| 76 | Middle, | ||
| 77 | Far, | ||
| 78 | }; | ||
| 79 | |||
| 80 | // This is nn::irsensor::IrsHandAnalysisMode | ||
| 81 | enum IrsHandAnalysisMode : u8 { | ||
| 82 | Silhouette, | ||
| 83 | Image, | ||
| 84 | SilhoueteAndImage, | ||
| 85 | SilhuetteOnly, | ||
| 86 | }; | ||
| 87 | |||
| 88 | // This is nn::irsensor::IrSensorFunctionLevel | ||
| 89 | enum IrSensorFunctionLevel : u8 { | ||
| 90 | unknown0, | ||
| 91 | unknown1, | ||
| 92 | unknown2, | ||
| 93 | unknown3, | ||
| 94 | unknown4, | ||
| 95 | }; | ||
| 96 | |||
| 97 | // This is nn::irsensor::IrCameraHandle | ||
| 98 | struct IrCameraHandle { | ||
| 99 | u8 npad_id{}; | ||
| 100 | Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None}; | ||
| 101 | INSERT_PADDING_BYTES(2); | ||
| 102 | }; | ||
| 103 | static_assert(sizeof(IrCameraHandle) == 4, "IrCameraHandle is an invalid size"); | ||
| 104 | |||
| 105 | struct IrsRect { | ||
| 106 | s16 x; | ||
| 107 | s16 y; | ||
| 108 | s16 width; | ||
| 109 | s16 height; | ||
| 110 | }; | 31 | }; |
| 32 | static_assert(sizeof(AruidFormat) == 0x10, "AruidFormat is an invalid size"); | ||
| 111 | 33 | ||
| 112 | // This is nn::irsensor::PackedMcuVersion | 34 | // This is nn::irsensor::detail::StatusManager |
| 113 | struct PackedMcuVersion { | 35 | struct StatusManager { |
| 114 | u16 major; | 36 | std::array<Core::IrSensor::DeviceFormat, 9> device; |
| 115 | u16 minor; | 37 | std::array<AruidFormat, 5> aruid; |
| 116 | }; | 38 | }; |
| 117 | static_assert(sizeof(PackedMcuVersion) == 4, "PackedMcuVersion is an invalid size"); | 39 | static_assert(sizeof(StatusManager) == 0x8000, "StatusManager is an invalid size"); |
| 118 | |||
| 119 | // This is nn::irsensor::MomentProcessorConfig | ||
| 120 | struct MomentProcessorConfig { | ||
| 121 | u64 exposire_time; | ||
| 122 | u8 light_target; | ||
| 123 | u8 gain; | ||
| 124 | u8 is_negative_used; | ||
| 125 | INSERT_PADDING_BYTES(7); | ||
| 126 | IrsRect window_of_interest; | ||
| 127 | u8 preprocess; | ||
| 128 | u8 preprocess_intensity_threshold; | ||
| 129 | INSERT_PADDING_BYTES(5); | ||
| 130 | }; | ||
| 131 | static_assert(sizeof(MomentProcessorConfig) == 0x28, | ||
| 132 | "MomentProcessorConfig is an invalid size"); | ||
| 133 | |||
| 134 | // This is nn::irsensor::PackedMomentProcessorConfig | ||
| 135 | struct PackedMomentProcessorConfig { | ||
| 136 | u64 exposire_time; | ||
| 137 | u8 light_target; | ||
| 138 | u8 gain; | ||
| 139 | u8 is_negative_used; | ||
| 140 | INSERT_PADDING_BYTES(5); | ||
| 141 | IrsRect window_of_interest; | ||
| 142 | PackedMcuVersion required_mcu_version; | ||
| 143 | u8 preprocess; | ||
| 144 | u8 preprocess_intensity_threshold; | ||
| 145 | INSERT_PADDING_BYTES(2); | ||
| 146 | }; | ||
| 147 | static_assert(sizeof(PackedMomentProcessorConfig) == 0x20, | ||
| 148 | "PackedMomentProcessorConfig is an invalid size"); | ||
| 149 | |||
| 150 | // This is nn::irsensor::ClusteringProcessorConfig | ||
| 151 | struct ClusteringProcessorConfig { | ||
| 152 | u64 exposire_time; | ||
| 153 | u32 light_target; | ||
| 154 | u32 gain; | ||
| 155 | u8 is_negative_used; | ||
| 156 | INSERT_PADDING_BYTES(7); | ||
| 157 | IrsRect window_of_interest; | ||
| 158 | u32 pixel_count_min; | ||
| 159 | u32 pixel_count_max; | ||
| 160 | u32 object_intensity_min; | ||
| 161 | u8 is_external_light_filter_enabled; | ||
| 162 | INSERT_PADDING_BYTES(3); | ||
| 163 | }; | ||
| 164 | static_assert(sizeof(ClusteringProcessorConfig) == 0x30, | ||
| 165 | "ClusteringProcessorConfig is an invalid size"); | ||
| 166 | |||
| 167 | // This is nn::irsensor::PackedClusteringProcessorConfig | ||
| 168 | struct PackedClusteringProcessorConfig { | ||
| 169 | u64 exposire_time; | ||
| 170 | u8 light_target; | ||
| 171 | u8 gain; | ||
| 172 | u8 is_negative_used; | ||
| 173 | INSERT_PADDING_BYTES(5); | ||
| 174 | IrsRect window_of_interest; | ||
| 175 | PackedMcuVersion required_mcu_version; | ||
| 176 | u32 pixel_count_min; | ||
| 177 | u32 pixel_count_max; | ||
| 178 | u32 object_intensity_min; | ||
| 179 | u8 is_external_light_filter_enabled; | ||
| 180 | INSERT_PADDING_BYTES(2); | ||
| 181 | }; | ||
| 182 | static_assert(sizeof(PackedClusteringProcessorConfig) == 0x30, | ||
| 183 | "PackedClusteringProcessorConfig is an invalid size"); | ||
| 184 | |||
| 185 | // This is nn::irsensor::PackedImageTransferProcessorConfig | ||
| 186 | struct PackedImageTransferProcessorConfig { | ||
| 187 | u64 exposire_time; | ||
| 188 | u8 light_target; | ||
| 189 | u8 gain; | ||
| 190 | u8 is_negative_used; | ||
| 191 | INSERT_PADDING_BYTES(5); | ||
| 192 | PackedMcuVersion required_mcu_version; | ||
| 193 | u8 format; | ||
| 194 | INSERT_PADDING_BYTES(3); | ||
| 195 | }; | ||
| 196 | static_assert(sizeof(PackedImageTransferProcessorConfig) == 0x18, | ||
| 197 | "PackedImageTransferProcessorConfig is an invalid size"); | ||
| 198 | |||
| 199 | // This is nn::irsensor::PackedTeraPluginProcessorConfig | ||
| 200 | struct PackedTeraPluginProcessorConfig { | ||
| 201 | PackedMcuVersion required_mcu_version; | ||
| 202 | u8 mode; | ||
| 203 | INSERT_PADDING_BYTES(3); | ||
| 204 | }; | ||
| 205 | static_assert(sizeof(PackedTeraPluginProcessorConfig) == 0x8, | ||
| 206 | "PackedTeraPluginProcessorConfig is an invalid size"); | ||
| 207 | |||
| 208 | // This is nn::irsensor::PackedPointingProcessorConfig | ||
| 209 | struct PackedPointingProcessorConfig { | ||
| 210 | IrsRect window_of_interest; | ||
| 211 | PackedMcuVersion required_mcu_version; | ||
| 212 | }; | ||
| 213 | static_assert(sizeof(PackedPointingProcessorConfig) == 0xC, | ||
| 214 | "PackedPointingProcessorConfig is an invalid size"); | ||
| 215 | |||
| 216 | // This is nn::irsensor::PackedFunctionLevel | ||
| 217 | struct PackedFunctionLevel { | ||
| 218 | IrSensorFunctionLevel function_level; | ||
| 219 | INSERT_PADDING_BYTES(3); | ||
| 220 | }; | ||
| 221 | static_assert(sizeof(PackedFunctionLevel) == 0x4, "PackedFunctionLevel is an invalid size"); | ||
| 222 | |||
| 223 | // This is nn::irsensor::PackedImageTransferProcessorExConfig | ||
| 224 | struct PackedImageTransferProcessorExConfig { | ||
| 225 | u64 exposire_time; | ||
| 226 | u8 light_target; | ||
| 227 | u8 gain; | ||
| 228 | u8 is_negative_used; | ||
| 229 | INSERT_PADDING_BYTES(5); | ||
| 230 | PackedMcuVersion required_mcu_version; | ||
| 231 | ImageTransferProcessorFormat origin_format; | ||
| 232 | ImageTransferProcessorFormat trimming_format; | ||
| 233 | u16 trimming_start_x; | ||
| 234 | u16 trimming_start_y; | ||
| 235 | u8 is_external_light_filter_enabled; | ||
| 236 | INSERT_PADDING_BYTES(3); | ||
| 237 | }; | ||
| 238 | static_assert(sizeof(PackedImageTransferProcessorExConfig) == 0x20, | ||
| 239 | "PackedImageTransferProcessorExConfig is an invalid size"); | ||
| 240 | |||
| 241 | // This is nn::irsensor::PackedIrLedProcessorConfig | ||
| 242 | struct PackedIrLedProcessorConfig { | ||
| 243 | PackedMcuVersion required_mcu_version; | ||
| 244 | u8 light_target; | ||
| 245 | INSERT_PADDING_BYTES(3); | ||
| 246 | }; | ||
| 247 | static_assert(sizeof(PackedIrLedProcessorConfig) == 0x8, | ||
| 248 | "PackedIrLedProcessorConfig is an invalid size"); | ||
| 249 | 40 | ||
| 250 | void ActivateIrsensor(Kernel::HLERequestContext& ctx); | 41 | void ActivateIrsensor(Kernel::HLERequestContext& ctx); |
| 251 | void DeactivateIrsensor(Kernel::HLERequestContext& ctx); | 42 | void DeactivateIrsensor(Kernel::HLERequestContext& ctx); |
| @@ -265,6 +56,56 @@ private: | |||
| 265 | void RunIrLedProcessor(Kernel::HLERequestContext& ctx); | 56 | void RunIrLedProcessor(Kernel::HLERequestContext& ctx); |
| 266 | void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); | 57 | void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); |
| 267 | void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); | 58 | void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); |
| 59 | |||
| 60 | ResultCode IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const; | ||
| 61 | Core::IrSensor::DeviceFormat& GetIrCameraSharedMemoryDeviceEntry( | ||
| 62 | const Core::IrSensor::IrCameraHandle& camera_handle); | ||
| 63 | |||
| 64 | template <typename T> | ||
| 65 | void MakeProcessor(const Core::IrSensor::IrCameraHandle& handle, | ||
| 66 | Core::IrSensor::DeviceFormat& device_state) { | ||
| 67 | const auto index = static_cast<std::size_t>(handle.npad_id); | ||
| 68 | if (index > sizeof(processors)) { | ||
| 69 | LOG_CRITICAL(Service_IRS, "Invalid index {}", index); | ||
| 70 | return; | ||
| 71 | } | ||
| 72 | processors[index] = std::make_unique<T>(device_state); | ||
| 73 | } | ||
| 74 | |||
| 75 | template <typename T> | ||
| 76 | void MakeProcessorWithCoreContext(const Core::IrSensor::IrCameraHandle& handle, | ||
| 77 | Core::IrSensor::DeviceFormat& device_state) { | ||
| 78 | const auto index = static_cast<std::size_t>(handle.npad_id); | ||
| 79 | if (index > sizeof(processors)) { | ||
| 80 | LOG_CRITICAL(Service_IRS, "Invalid index {}", index); | ||
| 81 | return; | ||
| 82 | } | ||
| 83 | processors[index] = std::make_unique<T>(system.HIDCore(), device_state, index); | ||
| 84 | } | ||
| 85 | |||
| 86 | template <typename T> | ||
| 87 | T& GetProcessor(const Core::IrSensor::IrCameraHandle& handle) { | ||
| 88 | const auto index = static_cast<std::size_t>(handle.npad_id); | ||
| 89 | if (index > sizeof(processors)) { | ||
| 90 | LOG_CRITICAL(Service_IRS, "Invalid index {}", index); | ||
| 91 | return static_cast<T&>(*processors[0]); | ||
| 92 | } | ||
| 93 | return static_cast<T&>(*processors[index]); | ||
| 94 | } | ||
| 95 | |||
| 96 | template <typename T> | ||
| 97 | const T& GetProcessor(const Core::IrSensor::IrCameraHandle& handle) const { | ||
| 98 | const auto index = static_cast<std::size_t>(handle.npad_id); | ||
| 99 | if (index > sizeof(processors)) { | ||
| 100 | LOG_CRITICAL(Service_IRS, "Invalid index {}", index); | ||
| 101 | return static_cast<T&>(*processors[0]); | ||
| 102 | } | ||
| 103 | return static_cast<T&>(*processors[index]); | ||
| 104 | } | ||
| 105 | |||
| 106 | Core::HID::EmulatedController* npad_device = nullptr; | ||
| 107 | StatusManager* shared_memory = nullptr; | ||
| 108 | std::array<std::unique_ptr<ProcessorBase>, 9> processors{}; | ||
| 268 | }; | 109 | }; |
| 269 | 110 | ||
| 270 | class IRS_SYS final : public ServiceFramework<IRS_SYS> { | 111 | class IRS_SYS final : public ServiceFramework<IRS_SYS> { |
diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.cpp b/src/core/hle/service/hid/irsensor/clustering_processor.cpp new file mode 100644 index 000000000..aac3e4fec --- /dev/null +++ b/src/core/hle/service/hid/irsensor/clustering_processor.cpp | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/clustering_processor.h" | ||
| 5 | |||
| 6 | namespace Service::HID { | ||
| 7 | ClusteringProcessor::ClusteringProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | device.state.start = 0; | ||
| 13 | device.state.count = 0; | ||
| 14 | } | ||
| 15 | |||
| 16 | ClusteringProcessor::~ClusteringProcessor() = default; | ||
| 17 | |||
| 18 | void ClusteringProcessor::StartProcessor() {} | ||
| 19 | |||
| 20 | void ClusteringProcessor::SuspendProcessor() {} | ||
| 21 | |||
| 22 | void ClusteringProcessor::StopProcessor() {} | ||
| 23 | |||
| 24 | void ClusteringProcessor::SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config) { | ||
| 25 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 26 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 27 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 28 | current_config.camera_config.light_target = | ||
| 29 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 30 | current_config.pixel_count_min = config.pixel_count_min; | ||
| 31 | current_config.pixel_count_max = config.pixel_count_max; | ||
| 32 | current_config.is_external_light_filter_enabled = config.is_external_light_filter_enabled; | ||
| 33 | current_config.object_intensity_min = config.object_intensity_min; | ||
| 34 | } | ||
| 35 | |||
| 36 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.h b/src/core/hle/service/hid/irsensor/clustering_processor.h new file mode 100644 index 000000000..58b2acf1c --- /dev/null +++ b/src/core/hle/service/hid/irsensor/clustering_processor.h | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 9 | |||
| 10 | namespace Service::HID { | ||
| 11 | class ClusteringProcessor final : public ProcessorBase { | ||
| 12 | public: | ||
| 13 | explicit ClusteringProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 14 | ~ClusteringProcessor() override; | ||
| 15 | |||
| 16 | // Called when the processor is initialized | ||
| 17 | void StartProcessor() override; | ||
| 18 | |||
| 19 | // Called when the processor is suspended | ||
| 20 | void SuspendProcessor() override; | ||
| 21 | |||
| 22 | // Called when the processor is stopped | ||
| 23 | void StopProcessor() override; | ||
| 24 | |||
| 25 | // Sets config parameters of the camera | ||
| 26 | void SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config); | ||
| 27 | |||
| 28 | private: | ||
| 29 | // This is nn::irsensor::ClusteringProcessorConfig | ||
| 30 | struct ClusteringProcessorConfig { | ||
| 31 | Core::IrSensor::CameraConfig camera_config; | ||
| 32 | Core::IrSensor::IrsRect window_of_interest; | ||
| 33 | u32 pixel_count_min; | ||
| 34 | u32 pixel_count_max; | ||
| 35 | u32 object_intensity_min; | ||
| 36 | bool is_external_light_filter_enabled; | ||
| 37 | INSERT_PADDING_BYTES(3); | ||
| 38 | }; | ||
| 39 | static_assert(sizeof(ClusteringProcessorConfig) == 0x30, | ||
| 40 | "ClusteringProcessorConfig is an invalid size"); | ||
| 41 | |||
| 42 | // This is nn::irsensor::AdaptiveClusteringProcessorConfig | ||
| 43 | struct AdaptiveClusteringProcessorConfig { | ||
| 44 | Core::IrSensor::AdaptiveClusteringMode mode; | ||
| 45 | Core::IrSensor::AdaptiveClusteringTargetDistance target_distance; | ||
| 46 | }; | ||
| 47 | static_assert(sizeof(AdaptiveClusteringProcessorConfig) == 0x8, | ||
| 48 | "AdaptiveClusteringProcessorConfig is an invalid size"); | ||
| 49 | |||
| 50 | // This is nn::irsensor::ClusteringData | ||
| 51 | struct ClusteringData { | ||
| 52 | f32 average_intensity; | ||
| 53 | Core::IrSensor::IrsCentroid centroid; | ||
| 54 | u32 pixel_count; | ||
| 55 | Core::IrSensor::IrsRect bound; | ||
| 56 | }; | ||
| 57 | static_assert(sizeof(ClusteringData) == 0x18, "ClusteringData is an invalid size"); | ||
| 58 | |||
| 59 | // This is nn::irsensor::ClusteringProcessorState | ||
| 60 | struct ClusteringProcessorState { | ||
| 61 | s64 sampling_number; | ||
| 62 | u64 timestamp; | ||
| 63 | u8 object_count; | ||
| 64 | INSERT_PADDING_BYTES(3); | ||
| 65 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 66 | std::array<ClusteringData, 0x10> data; | ||
| 67 | }; | ||
| 68 | static_assert(sizeof(ClusteringProcessorState) == 0x198, | ||
| 69 | "ClusteringProcessorState is an invalid size"); | ||
| 70 | |||
| 71 | ClusteringProcessorConfig current_config{}; | ||
| 72 | Core::IrSensor::DeviceFormat& device; | ||
| 73 | }; | ||
| 74 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp new file mode 100644 index 000000000..703e825e6 --- /dev/null +++ b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp | |||
| @@ -0,0 +1,154 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hid/emulated_controller.h" | ||
| 5 | #include "core/hid/hid_core.h" | ||
| 6 | #include "core/hle/service/hid/irsensor/image_transfer_processor.h" | ||
| 7 | |||
| 8 | namespace Service::HID { | ||
| 9 | ImageTransferProcessor::ImageTransferProcessor(Core::HID::HIDCore& hid_core_, | ||
| 10 | Core::IrSensor::DeviceFormat& device_format, | ||
| 11 | std::size_t npad_index) | ||
| 12 | : device{device_format} { | ||
| 13 | npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index); | ||
| 14 | |||
| 15 | Core::HID::ControllerUpdateCallback engine_callback{ | ||
| 16 | .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, | ||
| 17 | .is_npad_service = true, | ||
| 18 | }; | ||
| 19 | callback_key = npad_device->SetCallback(engine_callback); | ||
| 20 | |||
| 21 | device.mode = Core::IrSensor::IrSensorMode::ImageTransferProcessor; | ||
| 22 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 23 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 24 | device.state.start = 0; | ||
| 25 | device.state.count = 0; | ||
| 26 | } | ||
| 27 | |||
| 28 | ImageTransferProcessor::~ImageTransferProcessor() { | ||
| 29 | npad_device->DeleteCallback(callback_key); | ||
| 30 | }; | ||
| 31 | |||
| 32 | void ImageTransferProcessor::StartProcessor() { | ||
| 33 | is_active = true; | ||
| 34 | device.camera_status = Core::IrSensor::IrCameraStatus::Available; | ||
| 35 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; | ||
| 36 | device.state.start = 0; | ||
| 37 | device.state.count = 1; | ||
| 38 | processor_state.sampling_number = 0; | ||
| 39 | processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; | ||
| 40 | } | ||
| 41 | |||
| 42 | void ImageTransferProcessor::SuspendProcessor() {} | ||
| 43 | |||
| 44 | void ImageTransferProcessor::StopProcessor() {} | ||
| 45 | |||
| 46 | void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { | ||
| 47 | if (type != Core::HID::ControllerTriggerType::IrSensor) { | ||
| 48 | return; | ||
| 49 | } | ||
| 50 | if (!is_transfer_memory_set) { | ||
| 51 | return; | ||
| 52 | } | ||
| 53 | |||
| 54 | const auto camera_data = npad_device->GetCamera(); | ||
| 55 | |||
| 56 | // This indicates how much ambient light is precent | ||
| 57 | processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; | ||
| 58 | processor_state.sampling_number = camera_data.sample; | ||
| 59 | |||
| 60 | if (camera_data.format != current_config.origin_format) { | ||
| 61 | LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format, | ||
| 62 | current_config.origin_format); | ||
| 63 | memset(transfer_memory, 0, GetDataSize(current_config.trimming_format)); | ||
| 64 | return; | ||
| 65 | } | ||
| 66 | |||
| 67 | if (current_config.origin_format > current_config.trimming_format) { | ||
| 68 | LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}", | ||
| 69 | current_config.origin_format, current_config.trimming_format); | ||
| 70 | memset(transfer_memory, 0, GetDataSize(current_config.trimming_format)); | ||
| 71 | return; | ||
| 72 | } | ||
| 73 | |||
| 74 | std::vector<u8> window_data{}; | ||
| 75 | const auto origin_width = GetDataWidth(current_config.origin_format); | ||
| 76 | const auto origin_height = GetDataHeight(current_config.origin_format); | ||
| 77 | const auto trimming_width = GetDataWidth(current_config.trimming_format); | ||
| 78 | const auto trimming_height = GetDataHeight(current_config.trimming_format); | ||
| 79 | window_data.resize(GetDataSize(current_config.trimming_format)); | ||
| 80 | |||
| 81 | if (trimming_width + current_config.trimming_start_x > origin_width || | ||
| 82 | trimming_height + current_config.trimming_start_y > origin_height) { | ||
| 83 | LOG_WARNING(Service_IRS, | ||
| 84 | "Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})", | ||
| 85 | current_config.trimming_start_x, current_config.trimming_start_y, | ||
| 86 | trimming_width, trimming_height, origin_width, origin_height); | ||
| 87 | memset(transfer_memory, 0, GetDataSize(current_config.trimming_format)); | ||
| 88 | return; | ||
| 89 | } | ||
| 90 | |||
| 91 | for (std::size_t y = 0; y < trimming_height; y++) { | ||
| 92 | for (std::size_t x = 0; x < trimming_width; x++) { | ||
| 93 | const std::size_t window_index = (y * trimming_width) + x; | ||
| 94 | const std::size_t origin_index = | ||
| 95 | ((y + current_config.trimming_start_y) * origin_width) + x + | ||
| 96 | current_config.trimming_start_x; | ||
| 97 | window_data[window_index] = camera_data.data[origin_index]; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | memcpy(transfer_memory, window_data.data(), GetDataSize(current_config.trimming_format)); | ||
| 102 | |||
| 103 | if (!IsProcessorActive()) { | ||
| 104 | StartProcessor(); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | void ImageTransferProcessor::SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config) { | ||
| 109 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 110 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 111 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 112 | current_config.camera_config.light_target = | ||
| 113 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 114 | current_config.origin_format = | ||
| 115 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format); | ||
| 116 | current_config.trimming_format = | ||
| 117 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format); | ||
| 118 | current_config.trimming_start_x = 0; | ||
| 119 | current_config.trimming_start_y = 0; | ||
| 120 | |||
| 121 | npad_device->SetCameraFormat(current_config.origin_format); | ||
| 122 | } | ||
| 123 | |||
| 124 | void ImageTransferProcessor::SetConfig( | ||
| 125 | Core::IrSensor::PackedImageTransferProcessorExConfig config) { | ||
| 126 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 127 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 128 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 129 | current_config.camera_config.light_target = | ||
| 130 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 131 | current_config.origin_format = | ||
| 132 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.origin_format); | ||
| 133 | current_config.trimming_format = | ||
| 134 | static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.trimming_format); | ||
| 135 | current_config.trimming_start_x = config.trimming_start_x; | ||
| 136 | current_config.trimming_start_y = config.trimming_start_y; | ||
| 137 | |||
| 138 | npad_device->SetCameraFormat(current_config.origin_format); | ||
| 139 | } | ||
| 140 | |||
| 141 | void ImageTransferProcessor::SetTransferMemoryPointer(u8* t_mem) { | ||
| 142 | is_transfer_memory_set = true; | ||
| 143 | transfer_memory = t_mem; | ||
| 144 | } | ||
| 145 | |||
| 146 | Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState( | ||
| 147 | std::vector<u8>& data) const { | ||
| 148 | const auto size = GetDataSize(current_config.trimming_format); | ||
| 149 | data.resize(size); | ||
| 150 | memcpy(data.data(), transfer_memory, size); | ||
| 151 | return processor_state; | ||
| 152 | } | ||
| 153 | |||
| 154 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/image_transfer_processor.h b/src/core/hle/service/hid/irsensor/image_transfer_processor.h new file mode 100644 index 000000000..b557eaf20 --- /dev/null +++ b/src/core/hle/service/hid/irsensor/image_transfer_processor.h | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 9 | |||
| 10 | namespace Core::HID { | ||
| 11 | class EmulatedController; | ||
| 12 | } // namespace Core::HID | ||
| 13 | |||
| 14 | namespace Service::HID { | ||
| 15 | class ImageTransferProcessor final : public ProcessorBase { | ||
| 16 | public: | ||
| 17 | explicit ImageTransferProcessor(Core::HID::HIDCore& hid_core_, | ||
| 18 | Core::IrSensor::DeviceFormat& device_format, | ||
| 19 | std::size_t npad_index); | ||
| 20 | ~ImageTransferProcessor() override; | ||
| 21 | |||
| 22 | // Called when the processor is initialized | ||
| 23 | void StartProcessor() override; | ||
| 24 | |||
| 25 | // Called when the processor is suspended | ||
| 26 | void SuspendProcessor() override; | ||
| 27 | |||
| 28 | // Called when the processor is stopped | ||
| 29 | void StopProcessor() override; | ||
| 30 | |||
| 31 | // Sets config parameters of the camera | ||
| 32 | void SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config); | ||
| 33 | void SetConfig(Core::IrSensor::PackedImageTransferProcessorExConfig config); | ||
| 34 | |||
| 35 | // Transfer memory where the image data will be stored | ||
| 36 | void SetTransferMemoryPointer(u8* t_mem); | ||
| 37 | |||
| 38 | Core::IrSensor::ImageTransferProcessorState GetState(std::vector<u8>& data) const; | ||
| 39 | |||
| 40 | private: | ||
| 41 | // This is nn::irsensor::ImageTransferProcessorConfig | ||
| 42 | struct ImageTransferProcessorConfig { | ||
| 43 | Core::IrSensor::CameraConfig camera_config; | ||
| 44 | Core::IrSensor::ImageTransferProcessorFormat format; | ||
| 45 | }; | ||
| 46 | static_assert(sizeof(ImageTransferProcessorConfig) == 0x20, | ||
| 47 | "ImageTransferProcessorConfig is an invalid size"); | ||
| 48 | |||
| 49 | // This is nn::irsensor::ImageTransferProcessorExConfig | ||
| 50 | struct ImageTransferProcessorExConfig { | ||
| 51 | Core::IrSensor::CameraConfig camera_config; | ||
| 52 | Core::IrSensor::ImageTransferProcessorFormat origin_format; | ||
| 53 | Core::IrSensor::ImageTransferProcessorFormat trimming_format; | ||
| 54 | u16 trimming_start_x; | ||
| 55 | u16 trimming_start_y; | ||
| 56 | bool is_external_light_filter_enabled; | ||
| 57 | INSERT_PADDING_BYTES(3); | ||
| 58 | }; | ||
| 59 | static_assert(sizeof(ImageTransferProcessorExConfig) == 0x28, | ||
| 60 | "ImageTransferProcessorExConfig is an invalid size"); | ||
| 61 | |||
| 62 | void OnControllerUpdate(Core::HID::ControllerTriggerType type); | ||
| 63 | |||
| 64 | ImageTransferProcessorExConfig current_config{}; | ||
| 65 | Core::IrSensor::ImageTransferProcessorState processor_state{}; | ||
| 66 | Core::IrSensor::DeviceFormat& device; | ||
| 67 | Core::HID::EmulatedController* npad_device; | ||
| 68 | int callback_key{}; | ||
| 69 | |||
| 70 | u8* transfer_memory = nullptr; | ||
| 71 | bool is_transfer_memory_set = false; | ||
| 72 | }; | ||
| 73 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/ir_led_processor.cpp b/src/core/hle/service/hid/irsensor/ir_led_processor.cpp new file mode 100644 index 000000000..656e17c95 --- /dev/null +++ b/src/core/hle/service/hid/irsensor/ir_led_processor.cpp | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/ir_led_processor.h" | ||
| 5 | |||
| 6 | namespace Service::HID { | ||
| 7 | IrLedProcessor::IrLedProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::IrLedProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | device.state.start = 0; | ||
| 13 | device.state.count = 0; | ||
| 14 | } | ||
| 15 | |||
| 16 | IrLedProcessor::~IrLedProcessor() = default; | ||
| 17 | |||
| 18 | void IrLedProcessor::StartProcessor() {} | ||
| 19 | |||
| 20 | void IrLedProcessor::SuspendProcessor() {} | ||
| 21 | |||
| 22 | void IrLedProcessor::StopProcessor() {} | ||
| 23 | |||
| 24 | void IrLedProcessor::SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config) { | ||
| 25 | current_config.light_target = | ||
| 26 | static_cast<Core::IrSensor::CameraLightTarget>(config.light_target); | ||
| 27 | } | ||
| 28 | |||
| 29 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/ir_led_processor.h b/src/core/hle/service/hid/irsensor/ir_led_processor.h new file mode 100644 index 000000000..cb04d0b94 --- /dev/null +++ b/src/core/hle/service/hid/irsensor/ir_led_processor.h | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | class IrLedProcessor final : public ProcessorBase { | ||
| 13 | public: | ||
| 14 | explicit IrLedProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 15 | ~IrLedProcessor() override; | ||
| 16 | |||
| 17 | // Called when the processor is initialized | ||
| 18 | void StartProcessor() override; | ||
| 19 | |||
| 20 | // Called when the processor is suspended | ||
| 21 | void SuspendProcessor() override; | ||
| 22 | |||
| 23 | // Called when the processor is stopped | ||
| 24 | void StopProcessor() override; | ||
| 25 | |||
| 26 | // Sets config parameters of the camera | ||
| 27 | void SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config); | ||
| 28 | |||
| 29 | private: | ||
| 30 | // This is nn::irsensor::IrLedProcessorConfig | ||
| 31 | struct IrLedProcessorConfig { | ||
| 32 | Core::IrSensor::CameraLightTarget light_target; | ||
| 33 | }; | ||
| 34 | static_assert(sizeof(IrLedProcessorConfig) == 0x4, "IrLedProcessorConfig is an invalid size"); | ||
| 35 | |||
| 36 | struct IrLedProcessorState { | ||
| 37 | s64 sampling_number; | ||
| 38 | u64 timestamp; | ||
| 39 | std::array<u8, 0x8> data; | ||
| 40 | }; | ||
| 41 | static_assert(sizeof(IrLedProcessorState) == 0x18, "IrLedProcessorState is an invalid size"); | ||
| 42 | |||
| 43 | IrLedProcessorConfig current_config{}; | ||
| 44 | Core::IrSensor::DeviceFormat& device; | ||
| 45 | }; | ||
| 46 | |||
| 47 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/moment_processor.cpp b/src/core/hle/service/hid/irsensor/moment_processor.cpp new file mode 100644 index 000000000..fb36be577 --- /dev/null +++ b/src/core/hle/service/hid/irsensor/moment_processor.cpp | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/moment_processor.h" | ||
| 5 | |||
| 6 | namespace Service::HID { | ||
| 7 | MomentProcessor::MomentProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::MomentProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | device.state.start = 0; | ||
| 13 | device.state.count = 0; | ||
| 14 | } | ||
| 15 | |||
| 16 | MomentProcessor::~MomentProcessor() = default; | ||
| 17 | |||
| 18 | void MomentProcessor::StartProcessor() {} | ||
| 19 | |||
| 20 | void MomentProcessor::SuspendProcessor() {} | ||
| 21 | |||
| 22 | void MomentProcessor::StopProcessor() {} | ||
| 23 | |||
| 24 | void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) { | ||
| 25 | current_config.camera_config.exposure_time = config.camera_config.exposure_time; | ||
| 26 | current_config.camera_config.gain = config.camera_config.gain; | ||
| 27 | current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; | ||
| 28 | current_config.camera_config.light_target = | ||
| 29 | static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); | ||
| 30 | current_config.window_of_interest = config.window_of_interest; | ||
| 31 | current_config.preprocess = | ||
| 32 | static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess); | ||
| 33 | current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold; | ||
| 34 | } | ||
| 35 | |||
| 36 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/moment_processor.h b/src/core/hle/service/hid/irsensor/moment_processor.h new file mode 100644 index 000000000..63cdadfda --- /dev/null +++ b/src/core/hle/service/hid/irsensor/moment_processor.h | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | class MomentProcessor final : public ProcessorBase { | ||
| 13 | public: | ||
| 14 | explicit MomentProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 15 | ~MomentProcessor() override; | ||
| 16 | |||
| 17 | // Called when the processor is initialized | ||
| 18 | void StartProcessor() override; | ||
| 19 | |||
| 20 | // Called when the processor is suspended | ||
| 21 | void SuspendProcessor() override; | ||
| 22 | |||
| 23 | // Called when the processor is stopped | ||
| 24 | void StopProcessor() override; | ||
| 25 | |||
| 26 | // Sets config parameters of the camera | ||
| 27 | void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config); | ||
| 28 | |||
| 29 | private: | ||
| 30 | // This is nn::irsensor::MomentProcessorConfig | ||
| 31 | struct MomentProcessorConfig { | ||
| 32 | Core::IrSensor::CameraConfig camera_config; | ||
| 33 | Core::IrSensor::IrsRect window_of_interest; | ||
| 34 | Core::IrSensor::MomentProcessorPreprocess preprocess; | ||
| 35 | u32 preprocess_intensity_threshold; | ||
| 36 | }; | ||
| 37 | static_assert(sizeof(MomentProcessorConfig) == 0x28, | ||
| 38 | "MomentProcessorConfig is an invalid size"); | ||
| 39 | |||
| 40 | // This is nn::irsensor::MomentStatistic | ||
| 41 | struct MomentStatistic { | ||
| 42 | f32 average_intensity; | ||
| 43 | Core::IrSensor::IrsCentroid centroid; | ||
| 44 | }; | ||
| 45 | static_assert(sizeof(MomentStatistic) == 0xC, "MomentStatistic is an invalid size"); | ||
| 46 | |||
| 47 | // This is nn::irsensor::MomentProcessorState | ||
| 48 | struct MomentProcessorState { | ||
| 49 | s64 sampling_number; | ||
| 50 | u64 timestamp; | ||
| 51 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 52 | INSERT_PADDING_BYTES(4); | ||
| 53 | std::array<MomentStatistic, 0x30> stadistic; | ||
| 54 | }; | ||
| 55 | static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size"); | ||
| 56 | |||
| 57 | MomentProcessorConfig current_config{}; | ||
| 58 | Core::IrSensor::DeviceFormat& device; | ||
| 59 | }; | ||
| 60 | |||
| 61 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/pointing_processor.cpp b/src/core/hle/service/hid/irsensor/pointing_processor.cpp new file mode 100644 index 000000000..7eb123636 --- /dev/null +++ b/src/core/hle/service/hid/irsensor/pointing_processor.cpp | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/pointing_processor.h" | ||
| 5 | |||
| 6 | namespace Service::HID { | ||
| 7 | PointingProcessor::PointingProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::PointingProcessorMarker; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | device.state.start = 0; | ||
| 13 | device.state.count = 0; | ||
| 14 | } | ||
| 15 | |||
| 16 | PointingProcessor::~PointingProcessor() = default; | ||
| 17 | |||
| 18 | void PointingProcessor::StartProcessor() {} | ||
| 19 | |||
| 20 | void PointingProcessor::SuspendProcessor() {} | ||
| 21 | |||
| 22 | void PointingProcessor::StopProcessor() {} | ||
| 23 | |||
| 24 | void PointingProcessor::SetConfig(Core::IrSensor::PackedPointingProcessorConfig config) { | ||
| 25 | current_config.window_of_interest = config.window_of_interest; | ||
| 26 | } | ||
| 27 | |||
| 28 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/pointing_processor.h b/src/core/hle/service/hid/irsensor/pointing_processor.h new file mode 100644 index 000000000..2f67eff91 --- /dev/null +++ b/src/core/hle/service/hid/irsensor/pointing_processor.h | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | class PointingProcessor final : public ProcessorBase { | ||
| 13 | public: | ||
| 14 | explicit PointingProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 15 | ~PointingProcessor() override; | ||
| 16 | |||
| 17 | // Called when the processor is initialized | ||
| 18 | void StartProcessor() override; | ||
| 19 | |||
| 20 | // Called when the processor is suspended | ||
| 21 | void SuspendProcessor() override; | ||
| 22 | |||
| 23 | // Called when the processor is stopped | ||
| 24 | void StopProcessor() override; | ||
| 25 | |||
| 26 | // Sets config parameters of the camera | ||
| 27 | void SetConfig(Core::IrSensor::PackedPointingProcessorConfig config); | ||
| 28 | |||
| 29 | private: | ||
| 30 | // This is nn::irsensor::PointingProcessorConfig | ||
| 31 | struct PointingProcessorConfig { | ||
| 32 | Core::IrSensor::IrsRect window_of_interest; | ||
| 33 | }; | ||
| 34 | static_assert(sizeof(PointingProcessorConfig) == 0x8, | ||
| 35 | "PointingProcessorConfig is an invalid size"); | ||
| 36 | |||
| 37 | struct PointingProcessorMarkerData { | ||
| 38 | u8 pointing_status; | ||
| 39 | INSERT_PADDING_BYTES(3); | ||
| 40 | u32 unknown; | ||
| 41 | float unkown_float1; | ||
| 42 | float position_x; | ||
| 43 | float position_y; | ||
| 44 | float unkown_float2; | ||
| 45 | Core::IrSensor::IrsRect window_of_interest; | ||
| 46 | }; | ||
| 47 | static_assert(sizeof(PointingProcessorMarkerData) == 0x20, | ||
| 48 | "PointingProcessorMarkerData is an invalid size"); | ||
| 49 | |||
| 50 | struct PointingProcessorMarkerState { | ||
| 51 | s64 sampling_number; | ||
| 52 | u64 timestamp; | ||
| 53 | std::array<PointingProcessorMarkerData, 0x3> data; | ||
| 54 | }; | ||
| 55 | static_assert(sizeof(PointingProcessorMarkerState) == 0x70, | ||
| 56 | "PointingProcessorMarkerState is an invalid size"); | ||
| 57 | |||
| 58 | PointingProcessorConfig current_config{}; | ||
| 59 | Core::IrSensor::DeviceFormat& device; | ||
| 60 | }; | ||
| 61 | |||
| 62 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/processor_base.cpp b/src/core/hle/service/hid/irsensor/processor_base.cpp new file mode 100644 index 000000000..bc8025375 --- /dev/null +++ b/src/core/hle/service/hid/irsensor/processor_base.cpp | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 5 | |||
| 6 | namespace Service::HID { | ||
| 7 | |||
| 8 | ProcessorBase::ProcessorBase() {} | ||
| 9 | ProcessorBase::~ProcessorBase() = default; | ||
| 10 | |||
| 11 | bool ProcessorBase::IsProcessorActive() const { | ||
| 12 | return is_active; | ||
| 13 | } | ||
| 14 | |||
| 15 | std::size_t ProcessorBase::GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 16 | switch (format) { | ||
| 17 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 18 | return 320 * 240; | ||
| 19 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 20 | return 160 * 120; | ||
| 21 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 22 | return 80 * 60; | ||
| 23 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 24 | return 40 * 30; | ||
| 25 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 26 | return 20 * 15; | ||
| 27 | default: | ||
| 28 | return 0; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | std::size_t ProcessorBase::GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 33 | switch (format) { | ||
| 34 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 35 | return 320; | ||
| 36 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 37 | return 160; | ||
| 38 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 39 | return 80; | ||
| 40 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 41 | return 40; | ||
| 42 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 43 | return 20; | ||
| 44 | default: | ||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | std::size_t ProcessorBase::GetDataHeight( | ||
| 50 | Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 51 | switch (format) { | ||
| 52 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 53 | return 240; | ||
| 54 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 55 | return 120; | ||
| 56 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 57 | return 60; | ||
| 58 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 59 | return 30; | ||
| 60 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 61 | return 15; | ||
| 62 | default: | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/processor_base.h b/src/core/hle/service/hid/irsensor/processor_base.h new file mode 100644 index 000000000..49831aab6 --- /dev/null +++ b/src/core/hle/service/hid/irsensor/processor_base.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "core/hid/irs_types.h" | ||
| 8 | |||
| 9 | namespace Service::HID { | ||
| 10 | class ProcessorBase { | ||
| 11 | public: | ||
| 12 | explicit ProcessorBase(); | ||
| 13 | virtual ~ProcessorBase(); | ||
| 14 | |||
| 15 | virtual void StartProcessor() = 0; | ||
| 16 | virtual void SuspendProcessor() = 0; | ||
| 17 | virtual void StopProcessor() = 0; | ||
| 18 | |||
| 19 | bool IsProcessorActive() const; | ||
| 20 | |||
| 21 | protected: | ||
| 22 | /// Returns the number of bytes the image uses | ||
| 23 | std::size_t GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 24 | |||
| 25 | /// Returns the width of the image | ||
| 26 | std::size_t GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 27 | |||
| 28 | /// Returns the height of the image | ||
| 29 | std::size_t GetDataHeight(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 30 | |||
| 31 | bool is_active{false}; | ||
| 32 | }; | ||
| 33 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp b/src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp new file mode 100644 index 000000000..deec22072 --- /dev/null +++ b/src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include "core/hle/service/hid/irsensor/tera_plugin_processor.h" | ||
| 5 | |||
| 6 | namespace Service::HID { | ||
| 7 | TeraPluginProcessor::TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::TeraPluginProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | device.state.start = 0; | ||
| 13 | device.state.count = 0; | ||
| 14 | } | ||
| 15 | |||
| 16 | TeraPluginProcessor::~TeraPluginProcessor() = default; | ||
| 17 | |||
| 18 | void TeraPluginProcessor::StartProcessor() {} | ||
| 19 | |||
| 20 | void TeraPluginProcessor::SuspendProcessor() {} | ||
| 21 | |||
| 22 | void TeraPluginProcessor::StopProcessor() {} | ||
| 23 | |||
| 24 | void TeraPluginProcessor::SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config) { | ||
| 25 | current_config.mode = config.mode; | ||
| 26 | current_config.unknown_1 = config.unknown_1; | ||
| 27 | current_config.unknown_2 = config.unknown_2; | ||
| 28 | current_config.unknown_3 = config.unknown_3; | ||
| 29 | } | ||
| 30 | |||
| 31 | } // namespace Service::HID | ||
diff --git a/src/core/hle/service/hid/irsensor/tera_plugin_processor.h b/src/core/hle/service/hid/irsensor/tera_plugin_processor.h new file mode 100644 index 000000000..60f8057a5 --- /dev/null +++ b/src/core/hle/service/hid/irsensor/tera_plugin_processor.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/bit_field.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "core/hid/irs_types.h" | ||
| 9 | #include "core/hle/service/hid/irsensor/processor_base.h" | ||
| 10 | |||
| 11 | namespace Service::HID { | ||
| 12 | class TeraPluginProcessor final : public ProcessorBase { | ||
| 13 | public: | ||
| 14 | explicit TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 15 | ~TeraPluginProcessor() override; | ||
| 16 | |||
| 17 | // Called when the processor is initialized | ||
| 18 | void StartProcessor() override; | ||
| 19 | |||
| 20 | // Called when the processor is suspended | ||
| 21 | void SuspendProcessor() override; | ||
| 22 | |||
| 23 | // Called when the processor is stopped | ||
| 24 | void StopProcessor() override; | ||
| 25 | |||
| 26 | // Sets config parameters of the camera | ||
| 27 | void SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config); | ||
| 28 | |||
| 29 | private: | ||
| 30 | // This is nn::irsensor::TeraPluginProcessorConfig | ||
| 31 | struct TeraPluginProcessorConfig { | ||
| 32 | u8 mode; | ||
| 33 | u8 unknown_1; | ||
| 34 | u8 unknown_2; | ||
| 35 | u8 unknown_3; | ||
| 36 | }; | ||
| 37 | static_assert(sizeof(TeraPluginProcessorConfig) == 0x4, | ||
| 38 | "TeraPluginProcessorConfig is an invalid size"); | ||
| 39 | |||
| 40 | struct TeraPluginProcessorState { | ||
| 41 | s64 sampling_number; | ||
| 42 | u64 timestamp; | ||
| 43 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 44 | std::array<u8, 0x12c> data; | ||
| 45 | }; | ||
| 46 | static_assert(sizeof(TeraPluginProcessorState) == 0x140, | ||
| 47 | "TeraPluginProcessorState is an invalid size"); | ||
| 48 | |||
| 49 | TeraPluginProcessorConfig current_config{}; | ||
| 50 | Core::IrSensor::DeviceFormat& device; | ||
| 51 | }; | ||
| 52 | |||
| 53 | } // namespace Service::HID | ||