summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt15
-rw-r--r--src/core/hid/emulated_controller.cpp59
-rw-r--r--src/core/hid/emulated_controller.h40
-rw-r--r--src/core/hid/input_converter.cpp14
-rw-r--r--src/core/hid/input_converter.h8
-rw-r--r--src/core/hid/irs_types.h301
-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
24 files changed, 1525 insertions, 311 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 11d554bad..32cc2f392 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -158,6 +158,7 @@ add_library(core STATIC
158 hid/input_converter.h 158 hid/input_converter.h
159 hid/input_interpreter.cpp 159 hid/input_interpreter.cpp
160 hid/input_interpreter.h 160 hid/input_interpreter.h
161 hid/irs_types.h
161 hid/motion_input.cpp 162 hid/motion_input.cpp
162 hid/motion_input.h 163 hid/motion_input.h
163 hle/api_version.h 164 hle/api_version.h
@@ -477,6 +478,20 @@ add_library(core STATIC
477 hle/service/hid/hidbus/starlink.h 478 hle/service/hid/hidbus/starlink.h
478 hle/service/hid/hidbus/stubbed.cpp 479 hle/service/hid/hidbus/stubbed.cpp
479 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
480 hle/service/jit/jit_context.cpp 495 hle/service/jit/jit_context.cpp
481 hle/service/jit/jit_context.h 496 hle/service/jit/jit_context.h
482 hle/service/jit/jit.cpp 497 hle/service/jit/jit.cpp
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index bd2384515..8c3895937 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -126,10 +126,14 @@ void EmulatedController::LoadDevices() {
126 battery_params[LeftIndex].Set("battery", true); 126 battery_params[LeftIndex].Set("battery", true);
127 battery_params[RightIndex].Set("battery", true); 127 battery_params[RightIndex].Set("battery", true);
128 128
129 camera_params = Common::ParamPackage{"engine:camera,camera:1"};
130
129 output_params[LeftIndex] = left_joycon; 131 output_params[LeftIndex] = left_joycon;
130 output_params[RightIndex] = right_joycon; 132 output_params[RightIndex] = right_joycon;
133 output_params[2] = camera_params;
131 output_params[LeftIndex].Set("output", true); 134 output_params[LeftIndex].Set("output", true);
132 output_params[RightIndex].Set("output", true); 135 output_params[RightIndex].Set("output", true);
136 output_params[2].Set("output", true);
133 137
134 LoadTASParams(); 138 LoadTASParams();
135 139
@@ -146,6 +150,7 @@ void EmulatedController::LoadDevices() {
146 Common::Input::CreateDevice<Common::Input::InputDevice>); 150 Common::Input::CreateDevice<Common::Input::InputDevice>);
147 std::transform(battery_params.begin(), battery_params.end(), battery_devices.begin(), 151 std::transform(battery_params.begin(), battery_params.end(), battery_devices.begin(),
148 Common::Input::CreateDevice<Common::Input::InputDevice>); 152 Common::Input::CreateDevice<Common::Input::InputDevice>);
153 camera_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(camera_params);
149 std::transform(output_params.begin(), output_params.end(), output_devices.begin(), 154 std::transform(output_params.begin(), output_params.end(), output_devices.begin(),
150 Common::Input::CreateDevice<Common::Input::OutputDevice>); 155 Common::Input::CreateDevice<Common::Input::OutputDevice>);
151 156
@@ -267,6 +272,14 @@ void EmulatedController::ReloadInput() {
267 motion_devices[index]->ForceUpdate(); 272 motion_devices[index]->ForceUpdate();
268 } 273 }
269 274
275 if (camera_devices) {
276 camera_devices->SetCallback({
277 .on_change =
278 [this](const Common::Input::CallbackStatus& callback) { SetCamera(callback); },
279 });
280 camera_devices->ForceUpdate();
281 }
282
270 // Use a common UUID for TAS 283 // Use a common UUID for TAS
271 static constexpr Common::UUID TAS_UUID = Common::UUID{ 284 static constexpr Common::UUID TAS_UUID = Common::UUID{
272 {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 285 {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
@@ -851,6 +864,25 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
851 TriggerOnChange(ControllerTriggerType::Battery, true); 864 TriggerOnChange(ControllerTriggerType::Battery, true);
852} 865}
853 866
867void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) {
868 std::unique_lock lock{mutex};
869 controller.camera_values = TransformToCamera(callback);
870
871 if (is_configuring) {
872 lock.unlock();
873 TriggerOnChange(ControllerTriggerType::IrSensor, false);
874 return;
875 }
876
877 controller.camera_state.sample++;
878 controller.camera_state.format =
879 static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format);
880 controller.camera_state.data = controller.camera_values.data;
881
882 lock.unlock();
883 TriggerOnChange(ControllerTriggerType::IrSensor, true);
884}
885
854bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { 886bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
855 if (device_index >= output_devices.size()) { 887 if (device_index >= output_devices.size()) {
856 return false; 888 return false;
@@ -928,6 +960,23 @@ bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode)
928 return output_device->SetPollingMode(polling_mode) == Common::Input::PollingError::None; 960 return output_device->SetPollingMode(polling_mode) == Common::Input::PollingError::None;
929} 961}
930 962
963bool EmulatedController::SetCameraFormat(
964 Core::IrSensor::ImageTransferProcessorFormat camera_format) {
965 LOG_INFO(Service_HID, "Set camera format {}", camera_format);
966
967 auto& right_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
968 auto& camera_output_device = output_devices[2];
969
970 if (right_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>(
971 camera_format)) == Common::Input::CameraError::None) {
972 return true;
973 }
974
975 // Fallback to Qt camera if native device doesn't have support
976 return camera_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>(
977 camera_format)) == Common::Input::CameraError::None;
978}
979
931void EmulatedController::SetLedPattern() { 980void EmulatedController::SetLedPattern() {
932 for (auto& device : output_devices) { 981 for (auto& device : output_devices) {
933 if (!device) { 982 if (!device) {
@@ -1163,6 +1212,11 @@ BatteryValues EmulatedController::GetBatteryValues() const {
1163 return controller.battery_values; 1212 return controller.battery_values;
1164} 1213}
1165 1214
1215CameraValues EmulatedController::GetCameraValues() const {
1216 std::scoped_lock lock{mutex};
1217 return controller.camera_values;
1218}
1219
1166HomeButtonState EmulatedController::GetHomeButtons() const { 1220HomeButtonState EmulatedController::GetHomeButtons() const {
1167 std::scoped_lock lock{mutex}; 1221 std::scoped_lock lock{mutex};
1168 if (is_configuring) { 1222 if (is_configuring) {
@@ -1251,6 +1305,11 @@ BatteryLevelState EmulatedController::GetBattery() const {
1251 return controller.battery_state; 1305 return controller.battery_state;
1252} 1306}
1253 1307
1308const CameraState& EmulatedController::GetCamera() const {
1309 std::scoped_lock lock{mutex};
1310 return controller.camera_state;
1311}
1312
1254void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) { 1313void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) {
1255 std::scoped_lock lock{callback_mutex}; 1314 std::scoped_lock lock{callback_mutex};
1256 for (const auto& poller_pair : callback_list) { 1315 for (const auto& poller_pair : callback_list) {
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 3f02ed3c0..823c1700c 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -15,10 +15,12 @@
15#include "common/settings.h" 15#include "common/settings.h"
16#include "common/vector_math.h" 16#include "common/vector_math.h"
17#include "core/hid/hid_types.h" 17#include "core/hid/hid_types.h"
18#include "core/hid/irs_types.h"
18#include "core/hid/motion_input.h" 19#include "core/hid/motion_input.h"
19 20
20namespace Core::HID { 21namespace Core::HID {
21const std::size_t max_emulated_controllers = 2; 22const std::size_t max_emulated_controllers = 2;
23const std::size_t output_devices = 3;
22struct ControllerMotionInfo { 24struct ControllerMotionInfo {
23 Common::Input::MotionStatus raw_status{}; 25 Common::Input::MotionStatus raw_status{};
24 MotionInput emulated{}; 26 MotionInput emulated{};
@@ -34,15 +36,16 @@ using TriggerDevices =
34 std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeTrigger::NumTriggers>; 36 std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
35using BatteryDevices = 37using BatteryDevices =
36 std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>; 38 std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>;
37using OutputDevices = 39using CameraDevices = std::unique_ptr<Common::Input::InputDevice>;
38 std::array<std::unique_ptr<Common::Input::OutputDevice>, max_emulated_controllers>; 40using OutputDevices = std::array<std::unique_ptr<Common::Input::OutputDevice>, output_devices>;
39 41
40using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>; 42using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
41using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>; 43using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
42using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>; 44using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>;
43using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>; 45using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>;
44using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>; 46using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>;
45using OutputParams = std::array<Common::ParamPackage, max_emulated_controllers>; 47using CameraParams = Common::ParamPackage;
48using OutputParams = std::array<Common::ParamPackage, output_devices>;
46 49
47using ButtonValues = std::array<Common::Input::ButtonStatus, Settings::NativeButton::NumButtons>; 50using ButtonValues = std::array<Common::Input::ButtonStatus, Settings::NativeButton::NumButtons>;
48using SticksValues = std::array<Common::Input::StickStatus, Settings::NativeAnalog::NumAnalogs>; 51using SticksValues = std::array<Common::Input::StickStatus, Settings::NativeAnalog::NumAnalogs>;
@@ -51,6 +54,7 @@ using TriggerValues =
51using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>; 54using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>;
52using ColorValues = std::array<Common::Input::BodyColorStatus, max_emulated_controllers>; 55using ColorValues = std::array<Common::Input::BodyColorStatus, max_emulated_controllers>;
53using BatteryValues = std::array<Common::Input::BatteryStatus, max_emulated_controllers>; 56using BatteryValues = std::array<Common::Input::BatteryStatus, max_emulated_controllers>;
57using CameraValues = Common::Input::CameraStatus;
54using VibrationValues = std::array<Common::Input::VibrationStatus, max_emulated_controllers>; 58using VibrationValues = std::array<Common::Input::VibrationStatus, max_emulated_controllers>;
55 59
56struct AnalogSticks { 60struct AnalogSticks {
@@ -70,6 +74,12 @@ struct BatteryLevelState {
70 NpadPowerInfo right{}; 74 NpadPowerInfo right{};
71}; 75};
72 76
77struct CameraState {
78 Core::IrSensor::ImageTransferProcessorFormat format{};
79 std::vector<u8> data{};
80 std::size_t sample{};
81};
82
73struct ControllerMotion { 83struct ControllerMotion {
74 Common::Vec3f accel{}; 84 Common::Vec3f accel{};
75 Common::Vec3f gyro{}; 85 Common::Vec3f gyro{};
@@ -96,6 +106,7 @@ struct ControllerStatus {
96 ColorValues color_values{}; 106 ColorValues color_values{};
97 BatteryValues battery_values{}; 107 BatteryValues battery_values{};
98 VibrationValues vibration_values{}; 108 VibrationValues vibration_values{};
109 CameraValues camera_values{};
99 110
100 // Data for HID serices 111 // Data for HID serices
101 HomeButtonState home_button_state{}; 112 HomeButtonState home_button_state{};
@@ -107,6 +118,7 @@ struct ControllerStatus {
107 NpadGcTriggerState gc_trigger_state{}; 118 NpadGcTriggerState gc_trigger_state{};
108 ControllerColors colors_state{}; 119 ControllerColors colors_state{};
109 BatteryLevelState battery_state{}; 120 BatteryLevelState battery_state{};
121 CameraState camera_state{};
110}; 122};
111 123
112enum class ControllerTriggerType { 124enum class ControllerTriggerType {
@@ -117,6 +129,7 @@ enum class ControllerTriggerType {
117 Color, 129 Color,
118 Battery, 130 Battery,
119 Vibration, 131 Vibration,
132 IrSensor,
120 Connected, 133 Connected,
121 Disconnected, 134 Disconnected,
122 Type, 135 Type,
@@ -269,6 +282,9 @@ public:
269 /// Returns the latest battery status from the controller with parameters 282 /// Returns the latest battery status from the controller with parameters
270 BatteryValues GetBatteryValues() const; 283 BatteryValues GetBatteryValues() const;
271 284
285 /// Returns the latest camera status from the controller with parameters
286 CameraValues GetCameraValues() const;
287
272 /// Returns the latest status of button input for the hid::HomeButton service 288 /// Returns the latest status of button input for the hid::HomeButton service
273 HomeButtonState GetHomeButtons() const; 289 HomeButtonState GetHomeButtons() const;
274 290
@@ -296,6 +312,9 @@ public:
296 /// Returns the latest battery status from the controller 312 /// Returns the latest battery status from the controller
297 BatteryLevelState GetBattery() const; 313 BatteryLevelState GetBattery() const;
298 314
315 /// Returns the latest camera status from the controller
316 const CameraState& GetCamera() const;
317
299 /** 318 /**
300 * Sends a specific vibration to the output device 319 * Sends a specific vibration to the output device
301 * @return true if vibration had no errors 320 * @return true if vibration had no errors
@@ -315,6 +334,13 @@ public:
315 */ 334 */
316 bool SetPollingMode(Common::Input::PollingMode polling_mode); 335 bool SetPollingMode(Common::Input::PollingMode polling_mode);
317 336
337 /**
338 * Sets the desired camera format to be polled from a controller
339 * @param camera_format size of each frame
340 * @return true if SetCameraFormat was successfull
341 */
342 bool SetCameraFormat(Core::IrSensor::ImageTransferProcessorFormat camera_format);
343
318 /// Returns the led pattern corresponding to this emulated controller 344 /// Returns the led pattern corresponding to this emulated controller
319 LedPattern GetLedPattern() const; 345 LedPattern GetLedPattern() const;
320 346
@@ -393,6 +419,12 @@ private:
393 void SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index); 419 void SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index);
394 420
395 /** 421 /**
422 * Updates the camera status of the controller
423 * @param callback A CallbackStatus containing the camera status
424 */
425 void SetCamera(const Common::Input::CallbackStatus& callback);
426
427 /**
396 * Triggers a callback that something has changed on the controller status 428 * Triggers a callback that something has changed on the controller status
397 * @param type Input type of the event to trigger 429 * @param type Input type of the event to trigger
398 * @param is_service_update indicates if this event should only be sent to HID services 430 * @param is_service_update indicates if this event should only be sent to HID services
@@ -417,6 +449,7 @@ private:
417 ControllerMotionParams motion_params; 449 ControllerMotionParams motion_params;
418 TriggerParams trigger_params; 450 TriggerParams trigger_params;
419 BatteryParams battery_params; 451 BatteryParams battery_params;
452 CameraParams camera_params;
420 OutputParams output_params; 453 OutputParams output_params;
421 454
422 ButtonDevices button_devices; 455 ButtonDevices button_devices;
@@ -424,6 +457,7 @@ private:
424 ControllerMotionDevices motion_devices; 457 ControllerMotionDevices motion_devices;
425 TriggerDevices trigger_devices; 458 TriggerDevices trigger_devices;
426 BatteryDevices battery_devices; 459 BatteryDevices battery_devices;
460 CameraDevices camera_devices;
427 OutputDevices output_devices; 461 OutputDevices output_devices;
428 462
429 // TAS related variables 463 // TAS related variables
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index 18d9f042d..68d143a01 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -270,6 +270,20 @@ Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatu
270 return status; 270 return status;
271} 271}
272 272
273Common::Input::CameraStatus TransformToCamera(const Common::Input::CallbackStatus& callback) {
274 Common::Input::CameraStatus camera{};
275 switch (callback.type) {
276 case Common::Input::InputType::IrSensor:
277 camera = callback.camera_status;
278 break;
279 default:
280 LOG_ERROR(Input, "Conversion from type {} to camera not implemented", callback.type);
281 break;
282 }
283
284 return camera;
285}
286
273void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) { 287void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) {
274 const auto& properties = analog.properties; 288 const auto& properties = analog.properties;
275 float& raw_value = analog.raw_value; 289 float& raw_value = analog.raw_value;
diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h
index 2be36889f..143c50cc0 100644
--- a/src/core/hid/input_converter.h
+++ b/src/core/hid/input_converter.h
@@ -77,6 +77,14 @@ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackSta
77Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback); 77Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback);
78 78
79/** 79/**
80 * Converts raw input data into a valid camera status.
81 *
82 * @param callback Supported callbacks: Camera.
83 * @return A valid CameraObject object.
84 */
85Common::Input::CameraStatus TransformToCamera(const Common::Input::CallbackStatus& callback);
86
87/**
80 * Converts raw analog data into a valid analog value 88 * Converts raw analog data into a valid analog value
81 * @param analog An analog object containing raw data and properties 89 * @param analog An analog object containing raw data and properties
82 * @param clamp_value determines if the value needs to be clamped between -1.0f and 1.0f. 90 * @param clamp_value determines if the value needs to be clamped between -1.0f and 1.0f.
diff --git a/src/core/hid/irs_types.h b/src/core/hid/irs_types.h
new file mode 100644
index 000000000..88c5b016d
--- /dev/null
+++ b/src/core/hid/irs_types.h
@@ -0,0 +1,301 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include "common/common_funcs.h"
7#include "common/common_types.h"
8#include "core/hid/hid_types.h"
9
10namespace Core::IrSensor {
11
12// This is nn::irsensor::CameraAmbientNoiseLevel
13enum class CameraAmbientNoiseLevel : u32 {
14 Low,
15 Medium,
16 High,
17 Unkown3, // This level can't be reached
18};
19
20// This is nn::irsensor::CameraLightTarget
21enum class CameraLightTarget : u32 {
22 AllLeds,
23 BrightLeds,
24 DimLeds,
25 None,
26};
27
28// This is nn::irsensor::PackedCameraLightTarget
29enum class PackedCameraLightTarget : u8 {
30 AllLeds,
31 BrightLeds,
32 DimLeds,
33 None,
34};
35
36// This is nn::irsensor::AdaptiveClusteringMode
37enum class AdaptiveClusteringMode : u32 {
38 StaticFov,
39 DynamicFov,
40};
41
42// This is nn::irsensor::AdaptiveClusteringTargetDistance
43enum class AdaptiveClusteringTargetDistance : u32 {
44 Near,
45 Middle,
46 Far,
47};
48
49// This is nn::irsensor::ImageTransferProcessorFormat
50enum class ImageTransferProcessorFormat : u32 {
51 Size320x240,
52 Size160x120,
53 Size80x60,
54 Size40x30,
55 Size20x15,
56};
57
58// This is nn::irsensor::PackedImageTransferProcessorFormat
59enum class PackedImageTransferProcessorFormat : u8 {
60 Size320x240,
61 Size160x120,
62 Size80x60,
63 Size40x30,
64 Size20x15,
65};
66
67// This is nn::irsensor::IrCameraStatus
68enum class IrCameraStatus : u32 {
69 Available,
70 Unsupported,
71 Unconnected,
72};
73
74// This is nn::irsensor::IrCameraInternalStatus
75enum class IrCameraInternalStatus : u32 {
76 Stopped,
77 FirmwareUpdateNeeded,
78 Unkown2,
79 Unkown3,
80 Unkown4,
81 FirmwareVersionRequested,
82 FirmwareVersionIsInvalid,
83 Ready,
84 Setting,
85};
86
87// This is nn::irsensor::detail::StatusManager::IrSensorMode
88enum class IrSensorMode : u64 {
89 None,
90 MomentProcessor,
91 ClusteringProcessor,
92 ImageTransferProcessor,
93 PointingProcessorMarker,
94 TeraPluginProcessor,
95 IrLedProcessor,
96};
97
98// This is nn::irsensor::ImageProcessorStatus
99enum ImageProcessorStatus : u32 {
100 Stopped,
101 Running,
102};
103
104// This is nn::irsensor::HandAnalysisMode
105enum class HandAnalysisMode : u32 {
106 None,
107 Silhouette,
108 Image,
109 SilhoueteAndImage,
110 SilhuetteOnly,
111};
112
113// This is nn::irsensor::IrSensorFunctionLevel
114enum class IrSensorFunctionLevel : u8 {
115 unknown0,
116 unknown1,
117 unknown2,
118 unknown3,
119 unknown4,
120};
121
122// This is nn::irsensor::MomentProcessorPreprocess
123enum class MomentProcessorPreprocess : u32 {
124 Unkown0,
125 Unkown1,
126};
127
128// This is nn::irsensor::PackedMomentProcessorPreprocess
129enum class PackedMomentProcessorPreprocess : u8 {
130 Unkown0,
131 Unkown1,
132};
133
134// This is nn::irsensor::PointingStatus
135enum class PointingStatus : u32 {
136 Unkown0,
137 Unkown1,
138};
139
140struct IrsRect {
141 s16 x;
142 s16 y;
143 s16 width;
144 s16 height;
145};
146
147struct IrsCentroid {
148 f32 x;
149 f32 y;
150};
151
152struct CameraConfig {
153 u64 exposure_time;
154 CameraLightTarget light_target;
155 u32 gain;
156 bool is_negative_used;
157 INSERT_PADDING_BYTES(7);
158};
159static_assert(sizeof(CameraConfig) == 0x18, "CameraConfig is an invalid size");
160
161struct PackedCameraConfig {
162 u64 exposure_time;
163 PackedCameraLightTarget light_target;
164 u8 gain;
165 bool is_negative_used;
166 INSERT_PADDING_BYTES(5);
167};
168static_assert(sizeof(PackedCameraConfig) == 0x10, "PackedCameraConfig is an invalid size");
169
170// This is nn::irsensor::IrCameraHandle
171struct IrCameraHandle {
172 u8 npad_id{};
173 Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None};
174 INSERT_PADDING_BYTES(2);
175};
176static_assert(sizeof(IrCameraHandle) == 4, "IrCameraHandle is an invalid size");
177
178// This is nn::irsensor::PackedMcuVersion
179struct PackedMcuVersion {
180 u16 major;
181 u16 minor;
182};
183static_assert(sizeof(PackedMcuVersion) == 4, "PackedMcuVersion is an invalid size");
184
185// This is nn::irsensor::PackedMomentProcessorConfig
186struct PackedMomentProcessorConfig {
187 PackedCameraConfig camera_config;
188 IrsRect window_of_interest;
189 PackedMcuVersion required_mcu_version;
190 PackedMomentProcessorPreprocess preprocess;
191 u8 preprocess_intensity_threshold;
192 INSERT_PADDING_BYTES(2);
193};
194static_assert(sizeof(PackedMomentProcessorConfig) == 0x20,
195 "PackedMomentProcessorConfig is an invalid size");
196
197// This is nn::irsensor::PackedClusteringProcessorConfig
198struct PackedClusteringProcessorConfig {
199 PackedCameraConfig camera_config;
200 IrsRect window_of_interest;
201 PackedMcuVersion required_mcu_version;
202 u32 pixel_count_min;
203 u32 pixel_count_max;
204 u8 object_intensity_min;
205 bool is_external_light_filter_enabled;
206 INSERT_PADDING_BYTES(2);
207};
208static_assert(sizeof(PackedClusteringProcessorConfig) == 0x28,
209 "PackedClusteringProcessorConfig is an invalid size");
210
211// This is nn::irsensor::PackedImageTransferProcessorConfig
212struct PackedImageTransferProcessorConfig {
213 PackedCameraConfig camera_config;
214 PackedMcuVersion required_mcu_version;
215 PackedImageTransferProcessorFormat format;
216 INSERT_PADDING_BYTES(3);
217};
218static_assert(sizeof(PackedImageTransferProcessorConfig) == 0x18,
219 "PackedImageTransferProcessorConfig is an invalid size");
220
221// This is nn::irsensor::PackedTeraPluginProcessorConfig
222struct PackedTeraPluginProcessorConfig {
223 PackedMcuVersion required_mcu_version;
224 u8 mode;
225 u8 unknown_1;
226 u8 unknown_2;
227 u8 unknown_3;
228};
229static_assert(sizeof(PackedTeraPluginProcessorConfig) == 0x8,
230 "PackedTeraPluginProcessorConfig is an invalid size");
231
232// This is nn::irsensor::PackedPointingProcessorConfig
233struct PackedPointingProcessorConfig {
234 IrsRect window_of_interest;
235 PackedMcuVersion required_mcu_version;
236};
237static_assert(sizeof(PackedPointingProcessorConfig) == 0xC,
238 "PackedPointingProcessorConfig is an invalid size");
239
240// This is nn::irsensor::PackedFunctionLevel
241struct PackedFunctionLevel {
242 IrSensorFunctionLevel function_level;
243 INSERT_PADDING_BYTES(3);
244};
245static_assert(sizeof(PackedFunctionLevel) == 0x4, "PackedFunctionLevel is an invalid size");
246
247// This is nn::irsensor::PackedImageTransferProcessorExConfig
248struct PackedImageTransferProcessorExConfig {
249 PackedCameraConfig camera_config;
250 PackedMcuVersion required_mcu_version;
251 PackedImageTransferProcessorFormat origin_format;
252 PackedImageTransferProcessorFormat trimming_format;
253 u16 trimming_start_x;
254 u16 trimming_start_y;
255 bool is_external_light_filter_enabled;
256 INSERT_PADDING_BYTES(5);
257};
258static_assert(sizeof(PackedImageTransferProcessorExConfig) == 0x20,
259 "PackedImageTransferProcessorExConfig is an invalid size");
260
261// This is nn::irsensor::PackedIrLedProcessorConfig
262struct PackedIrLedProcessorConfig {
263 PackedMcuVersion required_mcu_version;
264 u8 light_target;
265 INSERT_PADDING_BYTES(3);
266};
267static_assert(sizeof(PackedIrLedProcessorConfig) == 0x8,
268 "PackedIrLedProcessorConfig is an invalid size");
269
270// This is nn::irsensor::HandAnalysisConfig
271struct HandAnalysisConfig {
272 HandAnalysisMode mode;
273};
274static_assert(sizeof(HandAnalysisConfig) == 0x4, "HandAnalysisConfig is an invalid size");
275
276// This is nn::irsensor::detail::ProcessorState contents are different for each processor
277struct ProcessorState {
278 std::array<u8, 0xE20> processor_raw_data{};
279};
280static_assert(sizeof(ProcessorState) == 0xE20, "ProcessorState is an invalid size");
281
282// This is nn::irsensor::detail::DeviceFormat
283struct DeviceFormat {
284 Core::IrSensor::IrCameraStatus camera_status{Core::IrSensor::IrCameraStatus::Unconnected};
285 Core::IrSensor::IrCameraInternalStatus camera_internal_status{
286 Core::IrSensor::IrCameraInternalStatus::Ready};
287 Core::IrSensor::IrSensorMode mode{Core::IrSensor::IrSensorMode::None};
288 ProcessorState state{};
289};
290static_assert(sizeof(DeviceFormat) == 0xE30, "DeviceFormat is an invalid size");
291
292// This is nn::irsensor::ImageTransferProcessorState
293struct ImageTransferProcessorState {
294 u64 sampling_number;
295 Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level;
296 INSERT_PADDING_BYTES(4);
297};
298static_assert(sizeof(ImageTransferProcessorState) == 0x10,
299 "ImageTransferProcessorState is an invalid size");
300
301} // namespace Core::IrSensor
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