summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/CMakeLists.txt14
-rw-r--r--src/core/hle/service/hid/errors.h3
-rw-r--r--src/core/hle/service/hid/irs.cpp290
-rw-r--r--src/core/hle/service/hid/irs.h291
-rw-r--r--src/core/hle/service/hid/irsensor/clustering_processor.cpp36
-rw-r--r--src/core/hle/service/hid/irsensor/clustering_processor.h74
-rw-r--r--src/core/hle/service/hid/irsensor/image_transfer_processor.cpp154
-rw-r--r--src/core/hle/service/hid/irsensor/image_transfer_processor.h73
-rw-r--r--src/core/hle/service/hid/irsensor/ir_led_processor.cpp29
-rw-r--r--src/core/hle/service/hid/irsensor/ir_led_processor.h47
-rw-r--r--src/core/hle/service/hid/irsensor/moment_processor.cpp36
-rw-r--r--src/core/hle/service/hid/irsensor/moment_processor.h61
-rw-r--r--src/core/hle/service/hid/irsensor/pointing_processor.cpp28
-rw-r--r--src/core/hle/service/hid/irsensor/pointing_processor.h62
-rw-r--r--src/core/hle/service/hid/irsensor/processor_base.cpp67
-rw-r--r--src/core/hle/service/hid/irsensor/processor_base.h33
-rw-r--r--src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp31
-rw-r--r--src/core/hle/service/hid/irsensor/tera_plugin_processor.h53
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};
18constexpr Result InvalidNpadId{ErrorModule::HID, 709}; 18constexpr Result InvalidNpadId{ErrorModule::HID, 709};
19constexpr Result NpadNotConnected{ErrorModule::HID, 710}; 19constexpr Result NpadNotConnected{ErrorModule::HID, 710};
20 20
21constexpr ResultCode InvalidProcessorState{ErrorModule::Irsensor, 78};
22constexpr 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
13namespace Service::HID { 25namespace 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}
57IRS::~IRS() = default;
41 58
42void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) { 59void 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) {
75void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { 92void 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
95void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) { 118void 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
116void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { 148void 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
137void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { 179void 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
164void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) { 228void 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
186void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) { 269void 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
203void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) { 295void 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
227void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) { 319void 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
243void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) { 344void 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
263void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) { 370void 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
279void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) { 392void 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
299void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { 414void 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
326void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) { 454void 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
343void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { 480void 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
363void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) { 506void 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
381IRS::~IRS() = default; 524ResultCode 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
535Core::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
383IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} { 541IRS_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
9namespace Core { 11namespace Core {
10class System; 12class System;
11} 13}
12 14
15namespace Core::HID {
16class EmulatedController;
17} // namespace Core::HID
18
13namespace Service::HID { 19namespace Service::HID {
14 20
15class IRS final : public ServiceFramework<IRS> { 21class IRS final : public ServiceFramework<IRS> {
@@ -18,234 +24,19 @@ public:
18 ~IRS() override; 24 ~IRS() override;
19 25
20private: 26private:
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
270class IRS_SYS final : public ServiceFramework<IRS_SYS> { 111class 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
6namespace Service::HID {
7ClusteringProcessor::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
16ClusteringProcessor::~ClusteringProcessor() = default;
17
18void ClusteringProcessor::StartProcessor() {}
19
20void ClusteringProcessor::SuspendProcessor() {}
21
22void ClusteringProcessor::StopProcessor() {}
23
24void 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
10namespace Service::HID {
11class ClusteringProcessor final : public ProcessorBase {
12public:
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
28private:
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
8namespace Service::HID {
9ImageTransferProcessor::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
28ImageTransferProcessor::~ImageTransferProcessor() {
29 npad_device->DeleteCallback(callback_key);
30};
31
32void 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
42void ImageTransferProcessor::SuspendProcessor() {}
43
44void ImageTransferProcessor::StopProcessor() {}
45
46void 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
108void 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
124void 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
141void ImageTransferProcessor::SetTransferMemoryPointer(u8* t_mem) {
142 is_transfer_memory_set = true;
143 transfer_memory = t_mem;
144}
145
146Core::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
10namespace Core::HID {
11class EmulatedController;
12} // namespace Core::HID
13
14namespace Service::HID {
15class ImageTransferProcessor final : public ProcessorBase {
16public:
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
40private:
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
6namespace Service::HID {
7IrLedProcessor::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
16IrLedProcessor::~IrLedProcessor() = default;
17
18void IrLedProcessor::StartProcessor() {}
19
20void IrLedProcessor::SuspendProcessor() {}
21
22void IrLedProcessor::StopProcessor() {}
23
24void 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
11namespace Service::HID {
12class IrLedProcessor final : public ProcessorBase {
13public:
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
29private:
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
6namespace Service::HID {
7MomentProcessor::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
16MomentProcessor::~MomentProcessor() = default;
17
18void MomentProcessor::StartProcessor() {}
19
20void MomentProcessor::SuspendProcessor() {}
21
22void MomentProcessor::StopProcessor() {}
23
24void 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
11namespace Service::HID {
12class MomentProcessor final : public ProcessorBase {
13public:
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
29private:
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
6namespace Service::HID {
7PointingProcessor::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
16PointingProcessor::~PointingProcessor() = default;
17
18void PointingProcessor::StartProcessor() {}
19
20void PointingProcessor::SuspendProcessor() {}
21
22void PointingProcessor::StopProcessor() {}
23
24void 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
11namespace Service::HID {
12class PointingProcessor final : public ProcessorBase {
13public:
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
29private:
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
6namespace Service::HID {
7
8ProcessorBase::ProcessorBase() {}
9ProcessorBase::~ProcessorBase() = default;
10
11bool ProcessorBase::IsProcessorActive() const {
12 return is_active;
13}
14
15std::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
32std::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
49std::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
9namespace Service::HID {
10class ProcessorBase {
11public:
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
21protected:
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
6namespace Service::HID {
7TeraPluginProcessor::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
16TeraPluginProcessor::~TeraPluginProcessor() = default;
17
18void TeraPluginProcessor::StartProcessor() {}
19
20void TeraPluginProcessor::SuspendProcessor() {}
21
22void TeraPluginProcessor::StopProcessor() {}
23
24void 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
11namespace Service::HID {
12class TeraPluginProcessor final : public ProcessorBase {
13public:
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
29private:
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