summaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/service/hid/errors.h7
-rw-r--r--src/core/hle/service/hid/hid.cpp4
-rw-r--r--src/core/hle/service/hid/irs.cpp324
-rw-r--r--src/core/hle/service/hid/irs.h295
-rw-r--r--src/core/hle/service/hid/irsensor/clustering_processor.cpp34
-rw-r--r--src/core/hle/service/hid/irsensor/clustering_processor.h74
-rw-r--r--src/core/hle/service/hid/irsensor/image_transfer_processor.cpp150
-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.cpp27
-rw-r--r--src/core/hle/service/hid/irsensor/ir_led_processor.h47
-rw-r--r--src/core/hle/service/hid/irsensor/moment_processor.cpp34
-rw-r--r--src/core/hle/service/hid/irsensor/moment_processor.h61
-rw-r--r--src/core/hle/service/hid/irsensor/pointing_processor.cpp26
-rw-r--r--src/core/hle/service/hid/irsensor/pointing_processor.h61
-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.cpp29
-rw-r--r--src/core/hle/service/hid/irsensor/tera_plugin_processor.h53
18 files changed, 1091 insertions, 308 deletions
diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h
index 46282f42e..4613a4e60 100644
--- a/src/core/hle/service/hid/errors.h
+++ b/src/core/hle/service/hid/errors.h
@@ -19,3 +19,10 @@ constexpr Result InvalidNpadId{ErrorModule::HID, 709};
19constexpr Result NpadNotConnected{ErrorModule::HID, 710}; 19constexpr Result NpadNotConnected{ErrorModule::HID, 710};
20 20
21} // namespace Service::HID 21} // namespace Service::HID
22
23namespace Service::IRS {
24
25constexpr Result InvalidProcessorState{ErrorModule::Irsensor, 78};
26constexpr Result InvalidIrCameraHandle{ErrorModule::Irsensor, 204};
27
28} // namespace Service::IRS
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 89bb12442..5ecbddf94 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -2345,8 +2345,8 @@ void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system
2345 std::make_shared<HidSys>(system)->InstallAsService(service_manager); 2345 std::make_shared<HidSys>(system)->InstallAsService(service_manager);
2346 std::make_shared<HidTmp>(system)->InstallAsService(service_manager); 2346 std::make_shared<HidTmp>(system)->InstallAsService(service_manager);
2347 2347
2348 std::make_shared<IRS>(system)->InstallAsService(service_manager); 2348 std::make_shared<Service::IRS::IRS>(system)->InstallAsService(service_manager);
2349 std::make_shared<IRS_SYS>(system)->InstallAsService(service_manager); 2349 std::make_shared<Service::IRS::IRS_SYS>(system)->InstallAsService(service_manager);
2350 2350
2351 std::make_shared<XCD_SYS>(system)->InstallAsService(service_manager); 2351 std::make_shared<XCD_SYS>(system)->InstallAsService(service_manager);
2352} 2352}
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp
index d2a91d913..d5107e41f 100644
--- a/src/core/hle/service/hid/irs.cpp
+++ b/src/core/hle/service/hid/irs.cpp
@@ -1,16 +1,28 @@
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::IRS {
14 26
15IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} { 27IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} {
16 // clang-format off 28 // clang-format off
@@ -36,14 +48,19 @@ 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};
44 const auto applet_resource_user_id{rp.Pop<u64>()}; 61 const auto applet_resource_user_id{rp.Pop<u64>()};
45 62
46 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", 63 LOG_WARNING(Service_IRS, "(STUBBED) called, applet_resource_user_id={}",
47 applet_resource_user_id); 64 applet_resource_user_id);
48 65
49 IPC::ResponseBuilder rb{ctx, 2}; 66 IPC::ResponseBuilder rb{ctx, 2};
@@ -54,7 +71,7 @@ void IRS::DeactivateIrsensor(Kernel::HLERequestContext& ctx) {
54 IPC::RequestParser rp{ctx}; 71 IPC::RequestParser rp{ctx};
55 const auto applet_resource_user_id{rp.Pop<u64>()}; 72 const auto applet_resource_user_id{rp.Pop<u64>()};
56 73
57 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", 74 LOG_WARNING(Service_IRS, "(STUBBED) called, applet_resource_user_id={}",
58 applet_resource_user_id); 75 applet_resource_user_id);
59 76
60 IPC::ResponseBuilder rb{ctx, 2}; 77 IPC::ResponseBuilder rb{ctx, 2};
@@ -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,19 +132,28 @@ 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) == 0x38, "Parameters has incorrect size.");
125 157
126 const auto parameters{rp.PopRaw<Parameters>()}; 158 const auto parameters{rp.PopRaw<Parameters>()};
127 159
@@ -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_IRS, "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,32 +236,68 @@ 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 }
249
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 }
179 257
180 IPC::ResponseBuilder rb{ctx, 5}; 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 struct Parameters {
189 const auto processor_config{rp.PopRaw<PackedTeraPluginProcessorConfig>()}; 272 Core::IrSensor::IrCameraHandle camera_handle;
190 const auto applet_resource_user_id{rp.Pop<u64>()}; 273 Core::IrSensor::PackedTeraPluginProcessorConfig processor_config;
274 INSERT_PADDING_WORDS_NOINIT(1);
275 u64 applet_resource_user_id;
276 };
277 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
191 278
192 LOG_WARNING(Service_IRS, 279 const auto parameters{rp.PopRaw<Parameters>()};
193 "(STUBBED) called, npad_type={}, npad_id={}, mode={}, mcu_version={}.{}, " 280
194 "applet_resource_user_id={}", 281 LOG_WARNING(
195 camera_handle.npad_type, camera_handle.npad_id, processor_config.mode, 282 Service_IRS,
196 processor_config.required_mcu_version.major, 283 "(STUBBED) called, npad_type={}, npad_id={}, mode={}, mcu_version={}.{}, "
197 processor_config.required_mcu_version.minor, applet_resource_user_id); 284 "applet_resource_user_id={}",
285 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
286 parameters.processor_config.mode, parameters.processor_config.required_mcu_version.major,
287 parameters.processor_config.required_mcu_version.minor, parameters.applet_resource_user_id);
288
289 const auto result = IsIrCameraHandleValid(parameters.camera_handle);
290
291 if (result.IsSuccess()) {
292 auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
293 MakeProcessor<TeraPluginProcessor>(parameters.camera_handle, device);
294 auto& image_transfer_processor =
295 GetProcessor<TeraPluginProcessor>(parameters.camera_handle);
296 image_transfer_processor.SetConfig(parameters.processor_config);
297 }
198 298
199 IPC::ResponseBuilder rb{ctx, 2}; 299 IPC::ResponseBuilder rb{ctx, 2};
200 rb.Push(ResultSuccess); 300 rb.Push(result);
201} 301}
202 302
203void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) { 303void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) {
@@ -207,17 +307,17 @@ void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) {
207 if (npad_id > Core::HID::NpadIdType::Player8 && npad_id != Core::HID::NpadIdType::Invalid && 307 if (npad_id > Core::HID::NpadIdType::Player8 && npad_id != Core::HID::NpadIdType::Invalid &&
208 npad_id != Core::HID::NpadIdType::Handheld) { 308 npad_id != Core::HID::NpadIdType::Handheld) {
209 IPC::ResponseBuilder rb{ctx, 2}; 309 IPC::ResponseBuilder rb{ctx, 2};
210 rb.Push(InvalidNpadId); 310 rb.Push(Service::HID::InvalidNpadId);
211 return; 311 return;
212 } 312 }
213 313
214 IrCameraHandle camera_handle{ 314 Core::IrSensor::IrCameraHandle camera_handle{
215 .npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)), 315 .npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)),
216 .npad_type = Core::HID::NpadStyleIndex::None, 316 .npad_type = Core::HID::NpadStyleIndex::None,
217 }; 317 };
218 318
219 LOG_WARNING(Service_IRS, "(STUBBED) called, npad_id={}, camera_npad_id={}, camera_npad_type={}", 319 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); 320 camera_handle.npad_id, camera_handle.npad_type);
221 321
222 IPC::ResponseBuilder rb{ctx, 3}; 322 IPC::ResponseBuilder rb{ctx, 3};
223 rb.Push(ResultSuccess); 323 rb.Push(ResultSuccess);
@@ -226,8 +326,8 @@ void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) {
226 326
227void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) { 327void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) {
228 IPC::RequestParser rp{ctx}; 328 IPC::RequestParser rp{ctx};
229 const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; 329 const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
230 const auto processor_config{rp.PopRaw<PackedPointingProcessorConfig>()}; 330 const auto processor_config{rp.PopRaw<Core::IrSensor::PackedPointingProcessorConfig>()};
231 const auto applet_resource_user_id{rp.Pop<u64>()}; 331 const auto applet_resource_user_id{rp.Pop<u64>()};
232 332
233 LOG_WARNING( 333 LOG_WARNING(
@@ -236,14 +336,23 @@ void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) {
236 camera_handle.npad_type, camera_handle.npad_id, processor_config.required_mcu_version.major, 336 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); 337 processor_config.required_mcu_version.minor, applet_resource_user_id);
238 338
339 auto result = IsIrCameraHandleValid(camera_handle);
340
341 if (result.IsSuccess()) {
342 auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle);
343 MakeProcessor<PointingProcessor>(camera_handle, device);
344 auto& image_transfer_processor = GetProcessor<PointingProcessor>(camera_handle);
345 image_transfer_processor.SetConfig(processor_config);
346 }
347
239 IPC::ResponseBuilder rb{ctx, 2}; 348 IPC::ResponseBuilder rb{ctx, 2};
240 rb.Push(ResultSuccess); 349 rb.Push(result);
241} 350}
242 351
243void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) { 352void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) {
244 IPC::RequestParser rp{ctx}; 353 IPC::RequestParser rp{ctx};
245 struct Parameters { 354 struct Parameters {
246 IrCameraHandle camera_handle; 355 Core::IrSensor::IrCameraHandle camera_handle;
247 INSERT_PADDING_WORDS_NOINIT(1); 356 INSERT_PADDING_WORDS_NOINIT(1);
248 u64 applet_resource_user_id; 357 u64 applet_resource_user_id;
249 }; 358 };
@@ -256,14 +365,20 @@ void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) {
256 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 365 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
257 parameters.applet_resource_user_id); 366 parameters.applet_resource_user_id);
258 367
368 auto result = IsIrCameraHandleValid(parameters.camera_handle);
369 if (result.IsSuccess()) {
370 // TODO: Suspend image processor
371 result = ResultSuccess;
372 }
373
259 IPC::ResponseBuilder rb{ctx, 2}; 374 IPC::ResponseBuilder rb{ctx, 2};
260 rb.Push(ResultSuccess); 375 rb.Push(result);
261} 376}
262 377
263void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) { 378void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) {
264 IPC::RequestParser rp{ctx}; 379 IPC::RequestParser rp{ctx};
265 const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; 380 const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
266 const auto mcu_version{rp.PopRaw<PackedMcuVersion>()}; 381 const auto mcu_version{rp.PopRaw<Core::IrSensor::PackedMcuVersion>()};
267 const auto applet_resource_user_id{rp.Pop<u64>()}; 382 const auto applet_resource_user_id{rp.Pop<u64>()};
268 383
269 LOG_WARNING( 384 LOG_WARNING(
@@ -272,37 +387,45 @@ void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) {
272 camera_handle.npad_type, camera_handle.npad_id, applet_resource_user_id, mcu_version.major, 387 camera_handle.npad_type, camera_handle.npad_id, applet_resource_user_id, mcu_version.major,
273 mcu_version.minor); 388 mcu_version.minor);
274 389
390 auto result = IsIrCameraHandleValid(camera_handle);
391 if (result.IsSuccess()) {
392 // TODO: Check firmware version
393 result = ResultSuccess;
394 }
395
275 IPC::ResponseBuilder rb{ctx, 2}; 396 IPC::ResponseBuilder rb{ctx, 2};
276 rb.Push(ResultSuccess); 397 rb.Push(result);
277} 398}
278 399
279void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) { 400void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) {
280 IPC::RequestParser rp{ctx}; 401 IPC::RequestParser rp{ctx};
281 struct Parameters { 402 const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
282 IrCameraHandle camera_handle; 403 const auto function_level{rp.PopRaw<Core::IrSensor::PackedFunctionLevel>()};
283 PackedFunctionLevel function_level; 404 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 405
290 LOG_WARNING(Service_IRS, 406 LOG_WARNING(
291 "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", 407 Service_IRS,
292 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 408 "(STUBBED) called, npad_type={}, npad_id={}, function_level={}, applet_resource_user_id={}",
293 parameters.applet_resource_user_id); 409 camera_handle.npad_type, camera_handle.npad_id, function_level.function_level,
410 applet_resource_user_id);
411
412 auto result = IsIrCameraHandleValid(camera_handle);
413 if (result.IsSuccess()) {
414 // TODO: Set Function level
415 result = ResultSuccess;
416 }
294 417
295 IPC::ResponseBuilder rb{ctx, 2}; 418 IPC::ResponseBuilder rb{ctx, 2};
296 rb.Push(ResultSuccess); 419 rb.Push(result);
297} 420}
298 421
299void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { 422void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) {
300 IPC::RequestParser rp{ctx}; 423 IPC::RequestParser rp{ctx};
301 struct Parameters { 424 struct Parameters {
302 IrCameraHandle camera_handle; 425 Core::IrSensor::IrCameraHandle camera_handle;
303 INSERT_PADDING_WORDS_NOINIT(1); 426 INSERT_PADDING_WORDS_NOINIT(1);
304 u64 applet_resource_user_id; 427 u64 applet_resource_user_id;
305 PackedImageTransferProcessorExConfig processor_config; 428 Core::IrSensor::PackedImageTransferProcessorExConfig processor_config;
306 u64 transfer_memory_size; 429 u64 transfer_memory_size;
307 }; 430 };
308 static_assert(sizeof(Parameters) == 0x38, "Parameters has incorrect size."); 431 static_assert(sizeof(Parameters) == 0x38, "Parameters has incorrect size.");
@@ -313,20 +436,33 @@ void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) {
313 auto t_mem = 436 auto t_mem =
314 system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); 437 system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle);
315 438
316 LOG_WARNING(Service_IRS, 439 u8* transfer_memory = system.Memory().GetPointer(t_mem->GetSourceAddress());
317 "(STUBBED) called, npad_type={}, npad_id={}, transfer_memory_size={}, " 440
318 "applet_resource_user_id={}", 441 LOG_INFO(Service_IRS,
319 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 442 "called, npad_type={}, npad_id={}, transfer_memory_size={}, "
320 parameters.transfer_memory_size, parameters.applet_resource_user_id); 443 "applet_resource_user_id={}",
444 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
445 parameters.transfer_memory_size, parameters.applet_resource_user_id);
446
447 auto result = IsIrCameraHandleValid(parameters.camera_handle);
448
449 if (result.IsSuccess()) {
450 auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle);
451 MakeProcessorWithCoreContext<ImageTransferProcessor>(parameters.camera_handle, device);
452 auto& image_transfer_processor =
453 GetProcessor<ImageTransferProcessor>(parameters.camera_handle);
454 image_transfer_processor.SetConfig(parameters.processor_config);
455 image_transfer_processor.SetTransferMemoryPointer(transfer_memory);
456 }
321 457
322 IPC::ResponseBuilder rb{ctx, 2}; 458 IPC::ResponseBuilder rb{ctx, 2};
323 rb.Push(ResultSuccess); 459 rb.Push(result);
324} 460}
325 461
326void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) { 462void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) {
327 IPC::RequestParser rp{ctx}; 463 IPC::RequestParser rp{ctx};
328 const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; 464 const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
329 const auto processor_config{rp.PopRaw<PackedIrLedProcessorConfig>()}; 465 const auto processor_config{rp.PopRaw<Core::IrSensor::PackedIrLedProcessorConfig>()};
330 const auto applet_resource_user_id{rp.Pop<u64>()}; 466 const auto applet_resource_user_id{rp.Pop<u64>()};
331 467
332 LOG_WARNING(Service_IRS, 468 LOG_WARNING(Service_IRS,
@@ -336,14 +472,23 @@ void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) {
336 processor_config.required_mcu_version.major, 472 processor_config.required_mcu_version.major,
337 processor_config.required_mcu_version.minor, applet_resource_user_id); 473 processor_config.required_mcu_version.minor, applet_resource_user_id);
338 474
475 auto result = IsIrCameraHandleValid(camera_handle);
476
477 if (result.IsSuccess()) {
478 auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle);
479 MakeProcessor<IrLedProcessor>(camera_handle, device);
480 auto& image_transfer_processor = GetProcessor<IrLedProcessor>(camera_handle);
481 image_transfer_processor.SetConfig(processor_config);
482 }
483
339 IPC::ResponseBuilder rb{ctx, 2}; 484 IPC::ResponseBuilder rb{ctx, 2};
340 rb.Push(ResultSuccess); 485 rb.Push(result);
341} 486}
342 487
343void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { 488void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) {
344 IPC::RequestParser rp{ctx}; 489 IPC::RequestParser rp{ctx};
345 struct Parameters { 490 struct Parameters {
346 IrCameraHandle camera_handle; 491 Core::IrSensor::IrCameraHandle camera_handle;
347 INSERT_PADDING_WORDS_NOINIT(1); 492 INSERT_PADDING_WORDS_NOINIT(1);
348 u64 applet_resource_user_id; 493 u64 applet_resource_user_id;
349 }; 494 };
@@ -356,14 +501,20 @@ void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) {
356 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, 501 parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
357 parameters.applet_resource_user_id); 502 parameters.applet_resource_user_id);
358 503
504 auto result = IsIrCameraHandleValid(parameters.camera_handle);
505 if (result.IsSuccess()) {
506 // TODO: Stop image processor async
507 result = ResultSuccess;
508 }
509
359 IPC::ResponseBuilder rb{ctx, 2}; 510 IPC::ResponseBuilder rb{ctx, 2};
360 rb.Push(ResultSuccess); 511 rb.Push(result);
361} 512}
362 513
363void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) { 514void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) {
364 IPC::RequestParser rp{ctx}; 515 IPC::RequestParser rp{ctx};
365 struct Parameters { 516 struct Parameters {
366 PackedFunctionLevel function_level; 517 Core::IrSensor::PackedFunctionLevel function_level;
367 INSERT_PADDING_WORDS_NOINIT(1); 518 INSERT_PADDING_WORDS_NOINIT(1);
368 u64 applet_resource_user_id; 519 u64 applet_resource_user_id;
369 }; 520 };
@@ -378,7 +529,22 @@ void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) {
378 rb.Push(ResultSuccess); 529 rb.Push(ResultSuccess);
379} 530}
380 531
381IRS::~IRS() = default; 532Result IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const {
533 if (camera_handle.npad_id >
534 static_cast<u8>(NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) {
535 return InvalidIrCameraHandle;
536 }
537 if (camera_handle.npad_type != Core::HID::NpadStyleIndex::None) {
538 return InvalidIrCameraHandle;
539 }
540 return ResultSuccess;
541}
542
543Core::IrSensor::DeviceFormat& IRS::GetIrCameraSharedMemoryDeviceEntry(
544 const Core::IrSensor::IrCameraHandle& camera_handle) {
545 ASSERT_MSG(sizeof(StatusManager::device) > camera_handle.npad_id, "invalid npad_id");
546 return shared_memory->device[camera_handle.npad_id];
547}
382 548
383IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} { 549IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} {
384 // clang-format off 550 // clang-format off
@@ -395,4 +561,4 @@ IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} {
395 561
396IRS_SYS::~IRS_SYS() = default; 562IRS_SYS::~IRS_SYS() = default;
397 563
398} // namespace Service::HID 564} // namespace Service::IRS
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h
index 361dc2213..2e6115c73 100644
--- a/src/core/hle/service/hid/irs.h
+++ b/src/core/hle/service/hid/irs.h
@@ -4,13 +4,19 @@
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
13namespace Service::HID { 15namespace Core::HID {
16class EmulatedController;
17} // namespace Core::HID
18
19namespace Service::IRS {
14 20
15class IRS final : public ServiceFramework<IRS> { 21class IRS final : public ServiceFramework<IRS> {
16public: 22public:
@@ -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 Result 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> {
@@ -273,4 +114,4 @@ public:
273 ~IRS_SYS() override; 114 ~IRS_SYS() override;
274}; 115};
275 116
276} // namespace Service::HID 117} // namespace Service::IRS
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..6479af212
--- /dev/null
+++ b/src/core/hle/service/hid/irsensor/clustering_processor.cpp
@@ -0,0 +1,34 @@
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::IRS {
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}
13
14ClusteringProcessor::~ClusteringProcessor() = default;
15
16void ClusteringProcessor::StartProcessor() {}
17
18void ClusteringProcessor::SuspendProcessor() {}
19
20void ClusteringProcessor::StopProcessor() {}
21
22void ClusteringProcessor::SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config) {
23 current_config.camera_config.exposure_time = config.camera_config.exposure_time;
24 current_config.camera_config.gain = config.camera_config.gain;
25 current_config.camera_config.is_negative_used = config.camera_config.is_negative_used;
26 current_config.camera_config.light_target =
27 static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target);
28 current_config.pixel_count_min = config.pixel_count_min;
29 current_config.pixel_count_max = config.pixel_count_max;
30 current_config.is_external_light_filter_enabled = config.is_external_light_filter_enabled;
31 current_config.object_intensity_min = config.object_intensity_min;
32}
33
34} // namespace Service::IRS
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..6e2ba8846
--- /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::IRS {
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::IRS
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..98f0c579d
--- /dev/null
+++ b/src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
@@ -0,0 +1,150 @@
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::IRS {
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}
25
26ImageTransferProcessor::~ImageTransferProcessor() {
27 npad_device->DeleteCallback(callback_key);
28};
29
30void ImageTransferProcessor::StartProcessor() {
31 is_active = true;
32 device.camera_status = Core::IrSensor::IrCameraStatus::Available;
33 device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready;
34 processor_state.sampling_number = 0;
35 processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
36}
37
38void ImageTransferProcessor::SuspendProcessor() {}
39
40void ImageTransferProcessor::StopProcessor() {}
41
42void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) {
43 if (type != Core::HID::ControllerTriggerType::IrSensor) {
44 return;
45 }
46 if (!is_transfer_memory_set) {
47 return;
48 }
49
50 const auto camera_data = npad_device->GetCamera();
51
52 // This indicates how much ambient light is precent
53 processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
54 processor_state.sampling_number = camera_data.sample;
55
56 if (camera_data.format != current_config.origin_format) {
57 LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format,
58 current_config.origin_format);
59 memset(transfer_memory, 0, GetDataSize(current_config.trimming_format));
60 return;
61 }
62
63 if (current_config.origin_format > current_config.trimming_format) {
64 LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}",
65 current_config.origin_format, current_config.trimming_format);
66 memset(transfer_memory, 0, GetDataSize(current_config.trimming_format));
67 return;
68 }
69
70 std::vector<u8> window_data{};
71 const auto origin_width = GetDataWidth(current_config.origin_format);
72 const auto origin_height = GetDataHeight(current_config.origin_format);
73 const auto trimming_width = GetDataWidth(current_config.trimming_format);
74 const auto trimming_height = GetDataHeight(current_config.trimming_format);
75 window_data.resize(GetDataSize(current_config.trimming_format));
76
77 if (trimming_width + current_config.trimming_start_x > origin_width ||
78 trimming_height + current_config.trimming_start_y > origin_height) {
79 LOG_WARNING(Service_IRS,
80 "Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})",
81 current_config.trimming_start_x, current_config.trimming_start_y,
82 trimming_width, trimming_height, origin_width, origin_height);
83 memset(transfer_memory, 0, GetDataSize(current_config.trimming_format));
84 return;
85 }
86
87 for (std::size_t y = 0; y < trimming_height; y++) {
88 for (std::size_t x = 0; x < trimming_width; x++) {
89 const std::size_t window_index = (y * trimming_width) + x;
90 const std::size_t origin_index =
91 ((y + current_config.trimming_start_y) * origin_width) + x +
92 current_config.trimming_start_x;
93 window_data[window_index] = camera_data.data[origin_index];
94 }
95 }
96
97 memcpy(transfer_memory, window_data.data(), GetDataSize(current_config.trimming_format));
98
99 if (!IsProcessorActive()) {
100 StartProcessor();
101 }
102}
103
104void ImageTransferProcessor::SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config) {
105 current_config.camera_config.exposure_time = config.camera_config.exposure_time;
106 current_config.camera_config.gain = config.camera_config.gain;
107 current_config.camera_config.is_negative_used = config.camera_config.is_negative_used;
108 current_config.camera_config.light_target =
109 static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target);
110 current_config.origin_format =
111 static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format);
112 current_config.trimming_format =
113 static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format);
114 current_config.trimming_start_x = 0;
115 current_config.trimming_start_y = 0;
116
117 npad_device->SetCameraFormat(current_config.origin_format);
118}
119
120void ImageTransferProcessor::SetConfig(
121 Core::IrSensor::PackedImageTransferProcessorExConfig config) {
122 current_config.camera_config.exposure_time = config.camera_config.exposure_time;
123 current_config.camera_config.gain = config.camera_config.gain;
124 current_config.camera_config.is_negative_used = config.camera_config.is_negative_used;
125 current_config.camera_config.light_target =
126 static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target);
127 current_config.origin_format =
128 static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.origin_format);
129 current_config.trimming_format =
130 static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.trimming_format);
131 current_config.trimming_start_x = config.trimming_start_x;
132 current_config.trimming_start_y = config.trimming_start_y;
133
134 npad_device->SetCameraFormat(current_config.origin_format);
135}
136
137void ImageTransferProcessor::SetTransferMemoryPointer(u8* t_mem) {
138 is_transfer_memory_set = true;
139 transfer_memory = t_mem;
140}
141
142Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState(
143 std::vector<u8>& data) const {
144 const auto size = GetDataSize(current_config.trimming_format);
145 data.resize(size);
146 memcpy(data.data(), transfer_memory, size);
147 return processor_state;
148}
149
150} // namespace Service::IRS
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..393df492d
--- /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::IRS {
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::IRS
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..8e6dd99e4
--- /dev/null
+++ b/src/core/hle/service/hid/irsensor/ir_led_processor.cpp
@@ -0,0 +1,27 @@
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::IRS {
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}
13
14IrLedProcessor::~IrLedProcessor() = default;
15
16void IrLedProcessor::StartProcessor() {}
17
18void IrLedProcessor::SuspendProcessor() {}
19
20void IrLedProcessor::StopProcessor() {}
21
22void IrLedProcessor::SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config) {
23 current_config.light_target =
24 static_cast<Core::IrSensor::CameraLightTarget>(config.light_target);
25}
26
27} // namespace Service::IRS
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..c3d8693c9
--- /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::IRS {
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::IRS
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..dbaca420a
--- /dev/null
+++ b/src/core/hle/service/hid/irsensor/moment_processor.cpp
@@ -0,0 +1,34 @@
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::IRS {
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}
13
14MomentProcessor::~MomentProcessor() = default;
15
16void MomentProcessor::StartProcessor() {}
17
18void MomentProcessor::SuspendProcessor() {}
19
20void MomentProcessor::StopProcessor() {}
21
22void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) {
23 current_config.camera_config.exposure_time = config.camera_config.exposure_time;
24 current_config.camera_config.gain = config.camera_config.gain;
25 current_config.camera_config.is_negative_used = config.camera_config.is_negative_used;
26 current_config.camera_config.light_target =
27 static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target);
28 current_config.window_of_interest = config.window_of_interest;
29 current_config.preprocess =
30 static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess);
31 current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold;
32}
33
34} // namespace Service::IRS
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..d4bd22e0f
--- /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::IRS {
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::IRS
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..929f177fc
--- /dev/null
+++ b/src/core/hle/service/hid/irsensor/pointing_processor.cpp
@@ -0,0 +1,26 @@
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::IRS {
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}
13
14PointingProcessor::~PointingProcessor() = default;
15
16void PointingProcessor::StartProcessor() {}
17
18void PointingProcessor::SuspendProcessor() {}
19
20void PointingProcessor::StopProcessor() {}
21
22void PointingProcessor::SetConfig(Core::IrSensor::PackedPointingProcessorConfig config) {
23 current_config.window_of_interest = config.window_of_interest;
24}
25
26} // namespace Service::IRS
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..cf4930794
--- /dev/null
+++ b/src/core/hle/service/hid/irsensor/pointing_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/common_types.h"
7#include "core/hid/irs_types.h"
8#include "core/hle/service/hid/irsensor/processor_base.h"
9
10namespace Service::IRS {
11class PointingProcessor final : public ProcessorBase {
12public:
13 explicit PointingProcessor(Core::IrSensor::DeviceFormat& device_format);
14 ~PointingProcessor() 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::PackedPointingProcessorConfig config);
27
28private:
29 // This is nn::irsensor::PointingProcessorConfig
30 struct PointingProcessorConfig {
31 Core::IrSensor::IrsRect window_of_interest;
32 };
33 static_assert(sizeof(PointingProcessorConfig) == 0x8,
34 "PointingProcessorConfig is an invalid size");
35
36 struct PointingProcessorMarkerData {
37 u8 pointing_status;
38 INSERT_PADDING_BYTES(3);
39 u32 unknown;
40 float unkown_float1;
41 float position_x;
42 float position_y;
43 float unkown_float2;
44 Core::IrSensor::IrsRect window_of_interest;
45 };
46 static_assert(sizeof(PointingProcessorMarkerData) == 0x20,
47 "PointingProcessorMarkerData is an invalid size");
48
49 struct PointingProcessorMarkerState {
50 s64 sampling_number;
51 u64 timestamp;
52 std::array<PointingProcessorMarkerData, 0x3> data;
53 };
54 static_assert(sizeof(PointingProcessorMarkerState) == 0x70,
55 "PointingProcessorMarkerState is an invalid size");
56
57 PointingProcessorConfig current_config{};
58 Core::IrSensor::DeviceFormat& device;
59};
60
61} // namespace Service::IRS
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..4d43ca17a
--- /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::IRS {
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::IRS
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..bc0d2977b
--- /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::IRS {
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::IRS
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..e691c840a
--- /dev/null
+++ b/src/core/hle/service/hid/irsensor/tera_plugin_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/tera_plugin_processor.h"
5
6namespace Service::IRS {
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}
13
14TeraPluginProcessor::~TeraPluginProcessor() = default;
15
16void TeraPluginProcessor::StartProcessor() {}
17
18void TeraPluginProcessor::SuspendProcessor() {}
19
20void TeraPluginProcessor::StopProcessor() {}
21
22void TeraPluginProcessor::SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config) {
23 current_config.mode = config.mode;
24 current_config.unknown_1 = config.unknown_1;
25 current_config.unknown_2 = config.unknown_2;
26 current_config.unknown_3 = config.unknown_3;
27}
28
29} // namespace Service::IRS
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..bbea7ed0b
--- /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::IRS {
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::IRS