diff options
Diffstat (limited to 'src/core')
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 | ||
| 867 | void 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 | |||
| 854 | bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { | 886 | bool 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 | ||
| 963 | bool 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 | |||
| 931 | void EmulatedController::SetLedPattern() { | 980 | void 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 | ||
| 1215 | CameraValues EmulatedController::GetCameraValues() const { | ||
| 1216 | std::scoped_lock lock{mutex}; | ||
| 1217 | return controller.camera_values; | ||
| 1218 | } | ||
| 1219 | |||
| 1166 | HomeButtonState EmulatedController::GetHomeButtons() const { | 1220 | HomeButtonState 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 | ||
| 1308 | const CameraState& EmulatedController::GetCamera() const { | ||
| 1309 | std::scoped_lock lock{mutex}; | ||
| 1310 | return controller.camera_state; | ||
| 1311 | } | ||
| 1312 | |||
| 1254 | void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) { | 1313 | void 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 | ||
| 20 | namespace Core::HID { | 21 | namespace Core::HID { |
| 21 | const std::size_t max_emulated_controllers = 2; | 22 | const std::size_t max_emulated_controllers = 2; |
| 23 | const std::size_t output_devices = 3; | ||
| 22 | struct ControllerMotionInfo { | 24 | struct 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>; |
| 35 | using BatteryDevices = | 37 | using 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>; |
| 37 | using OutputDevices = | 39 | using CameraDevices = std::unique_ptr<Common::Input::InputDevice>; |
| 38 | std::array<std::unique_ptr<Common::Input::OutputDevice>, max_emulated_controllers>; | 40 | using OutputDevices = std::array<std::unique_ptr<Common::Input::OutputDevice>, output_devices>; |
| 39 | 41 | ||
| 40 | using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>; | 42 | using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>; |
| 41 | using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>; | 43 | using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>; |
| 42 | using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>; | 44 | using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>; |
| 43 | using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>; | 45 | using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>; |
| 44 | using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>; | 46 | using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>; |
| 45 | using OutputParams = std::array<Common::ParamPackage, max_emulated_controllers>; | 47 | using CameraParams = Common::ParamPackage; |
| 48 | using OutputParams = std::array<Common::ParamPackage, output_devices>; | ||
| 46 | 49 | ||
| 47 | using ButtonValues = std::array<Common::Input::ButtonStatus, Settings::NativeButton::NumButtons>; | 50 | using ButtonValues = std::array<Common::Input::ButtonStatus, Settings::NativeButton::NumButtons>; |
| 48 | using SticksValues = std::array<Common::Input::StickStatus, Settings::NativeAnalog::NumAnalogs>; | 51 | using SticksValues = std::array<Common::Input::StickStatus, Settings::NativeAnalog::NumAnalogs>; |
| @@ -51,6 +54,7 @@ using TriggerValues = | |||
| 51 | using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>; | 54 | using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::NativeMotion::NumMotions>; |
| 52 | using ColorValues = std::array<Common::Input::BodyColorStatus, max_emulated_controllers>; | 55 | using ColorValues = std::array<Common::Input::BodyColorStatus, max_emulated_controllers>; |
| 53 | using BatteryValues = std::array<Common::Input::BatteryStatus, max_emulated_controllers>; | 56 | using BatteryValues = std::array<Common::Input::BatteryStatus, max_emulated_controllers>; |
| 57 | using CameraValues = Common::Input::CameraStatus; | ||
| 54 | using VibrationValues = std::array<Common::Input::VibrationStatus, max_emulated_controllers>; | 58 | using VibrationValues = std::array<Common::Input::VibrationStatus, max_emulated_controllers>; |
| 55 | 59 | ||
| 56 | struct AnalogSticks { | 60 | struct AnalogSticks { |
| @@ -70,6 +74,12 @@ struct BatteryLevelState { | |||
| 70 | NpadPowerInfo right{}; | 74 | NpadPowerInfo right{}; |
| 71 | }; | 75 | }; |
| 72 | 76 | ||
| 77 | struct CameraState { | ||
| 78 | Core::IrSensor::ImageTransferProcessorFormat format{}; | ||
| 79 | std::vector<u8> data{}; | ||
| 80 | std::size_t sample{}; | ||
| 81 | }; | ||
| 82 | |||
| 73 | struct ControllerMotion { | 83 | struct 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 | ||
| 112 | enum class ControllerTriggerType { | 124 | enum 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 | ||
| 273 | Common::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 | |||
| 273 | void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) { | 287 | void 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 | |||
| 77 | Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback); | 77 | Common::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 | */ | ||
| 85 | Common::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 | |||
| 10 | namespace Core::IrSensor { | ||
| 11 | |||
| 12 | // This is nn::irsensor::CameraAmbientNoiseLevel | ||
| 13 | enum 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 | ||
| 21 | enum class CameraLightTarget : u32 { | ||
| 22 | AllLeds, | ||
| 23 | BrightLeds, | ||
| 24 | DimLeds, | ||
| 25 | None, | ||
| 26 | }; | ||
| 27 | |||
| 28 | // This is nn::irsensor::PackedCameraLightTarget | ||
| 29 | enum class PackedCameraLightTarget : u8 { | ||
| 30 | AllLeds, | ||
| 31 | BrightLeds, | ||
| 32 | DimLeds, | ||
| 33 | None, | ||
| 34 | }; | ||
| 35 | |||
| 36 | // This is nn::irsensor::AdaptiveClusteringMode | ||
| 37 | enum class AdaptiveClusteringMode : u32 { | ||
| 38 | StaticFov, | ||
| 39 | DynamicFov, | ||
| 40 | }; | ||
| 41 | |||
| 42 | // This is nn::irsensor::AdaptiveClusteringTargetDistance | ||
| 43 | enum class AdaptiveClusteringTargetDistance : u32 { | ||
| 44 | Near, | ||
| 45 | Middle, | ||
| 46 | Far, | ||
| 47 | }; | ||
| 48 | |||
| 49 | // This is nn::irsensor::ImageTransferProcessorFormat | ||
| 50 | enum class ImageTransferProcessorFormat : u32 { | ||
| 51 | Size320x240, | ||
| 52 | Size160x120, | ||
| 53 | Size80x60, | ||
| 54 | Size40x30, | ||
| 55 | Size20x15, | ||
| 56 | }; | ||
| 57 | |||
| 58 | // This is nn::irsensor::PackedImageTransferProcessorFormat | ||
| 59 | enum class PackedImageTransferProcessorFormat : u8 { | ||
| 60 | Size320x240, | ||
| 61 | Size160x120, | ||
| 62 | Size80x60, | ||
| 63 | Size40x30, | ||
| 64 | Size20x15, | ||
| 65 | }; | ||
| 66 | |||
| 67 | // This is nn::irsensor::IrCameraStatus | ||
| 68 | enum class IrCameraStatus : u32 { | ||
| 69 | Available, | ||
| 70 | Unsupported, | ||
| 71 | Unconnected, | ||
| 72 | }; | ||
| 73 | |||
| 74 | // This is nn::irsensor::IrCameraInternalStatus | ||
| 75 | enum 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 | ||
| 88 | enum 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 | ||
| 99 | enum ImageProcessorStatus : u32 { | ||
| 100 | Stopped, | ||
| 101 | Running, | ||
| 102 | }; | ||
| 103 | |||
| 104 | // This is nn::irsensor::HandAnalysisMode | ||
| 105 | enum class HandAnalysisMode : u32 { | ||
| 106 | None, | ||
| 107 | Silhouette, | ||
| 108 | Image, | ||
| 109 | SilhoueteAndImage, | ||
| 110 | SilhuetteOnly, | ||
| 111 | }; | ||
| 112 | |||
| 113 | // This is nn::irsensor::IrSensorFunctionLevel | ||
| 114 | enum class IrSensorFunctionLevel : u8 { | ||
| 115 | unknown0, | ||
| 116 | unknown1, | ||
| 117 | unknown2, | ||
| 118 | unknown3, | ||
| 119 | unknown4, | ||
| 120 | }; | ||
| 121 | |||
| 122 | // This is nn::irsensor::MomentProcessorPreprocess | ||
| 123 | enum class MomentProcessorPreprocess : u32 { | ||
| 124 | Unkown0, | ||
| 125 | Unkown1, | ||
| 126 | }; | ||
| 127 | |||
| 128 | // This is nn::irsensor::PackedMomentProcessorPreprocess | ||
| 129 | enum class PackedMomentProcessorPreprocess : u8 { | ||
| 130 | Unkown0, | ||
| 131 | Unkown1, | ||
| 132 | }; | ||
| 133 | |||
| 134 | // This is nn::irsensor::PointingStatus | ||
| 135 | enum class PointingStatus : u32 { | ||
| 136 | Unkown0, | ||
| 137 | Unkown1, | ||
| 138 | }; | ||
| 139 | |||
| 140 | struct IrsRect { | ||
| 141 | s16 x; | ||
| 142 | s16 y; | ||
| 143 | s16 width; | ||
| 144 | s16 height; | ||
| 145 | }; | ||
| 146 | |||
| 147 | struct IrsCentroid { | ||
| 148 | f32 x; | ||
| 149 | f32 y; | ||
| 150 | }; | ||
| 151 | |||
| 152 | struct CameraConfig { | ||
| 153 | u64 exposure_time; | ||
| 154 | CameraLightTarget light_target; | ||
| 155 | u32 gain; | ||
| 156 | bool is_negative_used; | ||
| 157 | INSERT_PADDING_BYTES(7); | ||
| 158 | }; | ||
| 159 | static_assert(sizeof(CameraConfig) == 0x18, "CameraConfig is an invalid size"); | ||
| 160 | |||
| 161 | struct PackedCameraConfig { | ||
| 162 | u64 exposure_time; | ||
| 163 | PackedCameraLightTarget light_target; | ||
| 164 | u8 gain; | ||
| 165 | bool is_negative_used; | ||
| 166 | INSERT_PADDING_BYTES(5); | ||
| 167 | }; | ||
| 168 | static_assert(sizeof(PackedCameraConfig) == 0x10, "PackedCameraConfig is an invalid size"); | ||
| 169 | |||
| 170 | // This is nn::irsensor::IrCameraHandle | ||
| 171 | struct IrCameraHandle { | ||
| 172 | u8 npad_id{}; | ||
| 173 | Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None}; | ||
| 174 | INSERT_PADDING_BYTES(2); | ||
| 175 | }; | ||
| 176 | static_assert(sizeof(IrCameraHandle) == 4, "IrCameraHandle is an invalid size"); | ||
| 177 | |||
| 178 | // This is nn::irsensor::PackedMcuVersion | ||
| 179 | struct PackedMcuVersion { | ||
| 180 | u16 major; | ||
| 181 | u16 minor; | ||
| 182 | }; | ||
| 183 | static_assert(sizeof(PackedMcuVersion) == 4, "PackedMcuVersion is an invalid size"); | ||
| 184 | |||
| 185 | // This is nn::irsensor::PackedMomentProcessorConfig | ||
| 186 | struct 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 | }; | ||
| 194 | static_assert(sizeof(PackedMomentProcessorConfig) == 0x20, | ||
| 195 | "PackedMomentProcessorConfig is an invalid size"); | ||
| 196 | |||
| 197 | // This is nn::irsensor::PackedClusteringProcessorConfig | ||
| 198 | struct 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 | }; | ||
| 208 | static_assert(sizeof(PackedClusteringProcessorConfig) == 0x28, | ||
| 209 | "PackedClusteringProcessorConfig is an invalid size"); | ||
| 210 | |||
| 211 | // This is nn::irsensor::PackedImageTransferProcessorConfig | ||
| 212 | struct PackedImageTransferProcessorConfig { | ||
| 213 | PackedCameraConfig camera_config; | ||
| 214 | PackedMcuVersion required_mcu_version; | ||
| 215 | PackedImageTransferProcessorFormat format; | ||
| 216 | INSERT_PADDING_BYTES(3); | ||
| 217 | }; | ||
| 218 | static_assert(sizeof(PackedImageTransferProcessorConfig) == 0x18, | ||
| 219 | "PackedImageTransferProcessorConfig is an invalid size"); | ||
| 220 | |||
| 221 | // This is nn::irsensor::PackedTeraPluginProcessorConfig | ||
| 222 | struct PackedTeraPluginProcessorConfig { | ||
| 223 | PackedMcuVersion required_mcu_version; | ||
| 224 | u8 mode; | ||
| 225 | u8 unknown_1; | ||
| 226 | u8 unknown_2; | ||
| 227 | u8 unknown_3; | ||
| 228 | }; | ||
| 229 | static_assert(sizeof(PackedTeraPluginProcessorConfig) == 0x8, | ||
| 230 | "PackedTeraPluginProcessorConfig is an invalid size"); | ||
| 231 | |||
| 232 | // This is nn::irsensor::PackedPointingProcessorConfig | ||
| 233 | struct PackedPointingProcessorConfig { | ||
| 234 | IrsRect window_of_interest; | ||
| 235 | PackedMcuVersion required_mcu_version; | ||
| 236 | }; | ||
| 237 | static_assert(sizeof(PackedPointingProcessorConfig) == 0xC, | ||
| 238 | "PackedPointingProcessorConfig is an invalid size"); | ||
| 239 | |||
| 240 | // This is nn::irsensor::PackedFunctionLevel | ||
| 241 | struct PackedFunctionLevel { | ||
| 242 | IrSensorFunctionLevel function_level; | ||
| 243 | INSERT_PADDING_BYTES(3); | ||
| 244 | }; | ||
| 245 | static_assert(sizeof(PackedFunctionLevel) == 0x4, "PackedFunctionLevel is an invalid size"); | ||
| 246 | |||
| 247 | // This is nn::irsensor::PackedImageTransferProcessorExConfig | ||
| 248 | struct 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 | }; | ||
| 258 | static_assert(sizeof(PackedImageTransferProcessorExConfig) == 0x20, | ||
| 259 | "PackedImageTransferProcessorExConfig is an invalid size"); | ||
| 260 | |||
| 261 | // This is nn::irsensor::PackedIrLedProcessorConfig | ||
| 262 | struct PackedIrLedProcessorConfig { | ||
| 263 | PackedMcuVersion required_mcu_version; | ||
| 264 | u8 light_target; | ||
| 265 | INSERT_PADDING_BYTES(3); | ||
| 266 | }; | ||
| 267 | static_assert(sizeof(PackedIrLedProcessorConfig) == 0x8, | ||
| 268 | "PackedIrLedProcessorConfig is an invalid size"); | ||
| 269 | |||
| 270 | // This is nn::irsensor::HandAnalysisConfig | ||
| 271 | struct HandAnalysisConfig { | ||
| 272 | HandAnalysisMode mode; | ||
| 273 | }; | ||
| 274 | static_assert(sizeof(HandAnalysisConfig) == 0x4, "HandAnalysisConfig is an invalid size"); | ||
| 275 | |||
| 276 | // This is nn::irsensor::detail::ProcessorState contents are different for each processor | ||
| 277 | struct ProcessorState { | ||
| 278 | std::array<u8, 0xE20> processor_raw_data{}; | ||
| 279 | }; | ||
| 280 | static_assert(sizeof(ProcessorState) == 0xE20, "ProcessorState is an invalid size"); | ||
| 281 | |||
| 282 | // This is nn::irsensor::detail::DeviceFormat | ||
| 283 | struct 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 | }; | ||
| 290 | static_assert(sizeof(DeviceFormat) == 0xE30, "DeviceFormat is an invalid size"); | ||
| 291 | |||
| 292 | // This is nn::irsensor::ImageTransferProcessorState | ||
| 293 | struct ImageTransferProcessorState { | ||
| 294 | u64 sampling_number; | ||
| 295 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 296 | INSERT_PADDING_BYTES(4); | ||
| 297 | }; | ||
| 298 | static_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}; | |||
| 19 | constexpr Result NpadNotConnected{ErrorModule::HID, 710}; | 19 | constexpr Result NpadNotConnected{ErrorModule::HID, 710}; |
| 20 | 20 | ||
| 21 | } // namespace Service::HID | 21 | } // namespace Service::HID |
| 22 | |||
| 23 | namespace Service::IRS { | ||
| 24 | |||
| 25 | constexpr Result InvalidProcessorState{ErrorModule::Irsensor, 78}; | ||
| 26 | constexpr 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 | ||
| 13 | namespace Service::HID { | 25 | namespace Service::IRS { |
| 14 | 26 | ||
| 15 | IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} { | 27 | IRS::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 | } |
| 57 | IRS::~IRS() = default; | ||
| 41 | 58 | ||
| 42 | void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) { | 59 | void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) { |
| 43 | IPC::RequestParser rp{ctx}; | 60 | IPC::RequestParser rp{ctx}; |
| 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) { | |||
| 75 | void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { | 92 | void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { |
| 76 | IPC::RequestParser rp{ctx}; | 93 | IPC::RequestParser rp{ctx}; |
| 77 | struct Parameters { | 94 | struct Parameters { |
| 78 | IrCameraHandle camera_handle; | 95 | Core::IrSensor::IrCameraHandle camera_handle; |
| 79 | INSERT_PADDING_WORDS_NOINIT(1); | 96 | INSERT_PADDING_WORDS_NOINIT(1); |
| 80 | u64 applet_resource_user_id; | 97 | u64 applet_resource_user_id; |
| 81 | }; | 98 | }; |
| @@ -88,17 +105,23 @@ void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { | |||
| 88 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, | 105 | parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, |
| 89 | parameters.applet_resource_user_id); | 106 | parameters.applet_resource_user_id); |
| 90 | 107 | ||
| 108 | auto result = IsIrCameraHandleValid(parameters.camera_handle); | ||
| 109 | if (result.IsSuccess()) { | ||
| 110 | // TODO: Stop Image processor | ||
| 111 | result = ResultSuccess; | ||
| 112 | } | ||
| 113 | |||
| 91 | IPC::ResponseBuilder rb{ctx, 2}; | 114 | IPC::ResponseBuilder rb{ctx, 2}; |
| 92 | rb.Push(ResultSuccess); | 115 | rb.Push(result); |
| 93 | } | 116 | } |
| 94 | 117 | ||
| 95 | void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) { | 118 | void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) { |
| 96 | IPC::RequestParser rp{ctx}; | 119 | IPC::RequestParser rp{ctx}; |
| 97 | struct Parameters { | 120 | struct Parameters { |
| 98 | IrCameraHandle camera_handle; | 121 | Core::IrSensor::IrCameraHandle camera_handle; |
| 99 | INSERT_PADDING_WORDS_NOINIT(1); | 122 | INSERT_PADDING_WORDS_NOINIT(1); |
| 100 | u64 applet_resource_user_id; | 123 | u64 applet_resource_user_id; |
| 101 | PackedMomentProcessorConfig processor_config; | 124 | Core::IrSensor::PackedMomentProcessorConfig processor_config; |
| 102 | }; | 125 | }; |
| 103 | static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size."); | 126 | static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size."); |
| 104 | 127 | ||
| @@ -109,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 | ||
| 116 | void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { | 148 | void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { |
| 117 | IPC::RequestParser rp{ctx}; | 149 | IPC::RequestParser rp{ctx}; |
| 118 | struct Parameters { | 150 | struct Parameters { |
| 119 | IrCameraHandle camera_handle; | 151 | Core::IrSensor::IrCameraHandle camera_handle; |
| 120 | INSERT_PADDING_WORDS_NOINIT(1); | 152 | INSERT_PADDING_WORDS_NOINIT(1); |
| 121 | u64 applet_resource_user_id; | 153 | u64 applet_resource_user_id; |
| 122 | PackedClusteringProcessorConfig processor_config; | 154 | Core::IrSensor::PackedClusteringProcessorConfig processor_config; |
| 123 | }; | 155 | }; |
| 124 | static_assert(sizeof(Parameters) == 0x40, "Parameters has incorrect size."); | 156 | static_assert(sizeof(Parameters) == 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 | ||
| 137 | void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { | 179 | void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { |
| 138 | IPC::RequestParser rp{ctx}; | 180 | IPC::RequestParser rp{ctx}; |
| 139 | struct Parameters { | 181 | struct Parameters { |
| 140 | IrCameraHandle camera_handle; | 182 | Core::IrSensor::IrCameraHandle camera_handle; |
| 141 | INSERT_PADDING_WORDS_NOINIT(1); | 183 | INSERT_PADDING_WORDS_NOINIT(1); |
| 142 | u64 applet_resource_user_id; | 184 | u64 applet_resource_user_id; |
| 143 | PackedImageTransferProcessorConfig processor_config; | 185 | Core::IrSensor::PackedImageTransferProcessorConfig processor_config; |
| 144 | u32 transfer_memory_size; | 186 | u32 transfer_memory_size; |
| 145 | }; | 187 | }; |
| 146 | static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size."); | 188 | static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size."); |
| @@ -151,20 +193,42 @@ void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { | |||
| 151 | auto t_mem = | 193 | auto t_mem = |
| 152 | system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); | 194 | system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); |
| 153 | 195 | ||
| 154 | LOG_WARNING(Service_IRS, | 196 | if (t_mem.IsNull()) { |
| 155 | "(STUBBED) called, npad_type={}, npad_id={}, transfer_memory_size={}, " | 197 | LOG_ERROR(Service_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 | ||
| 164 | void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) { | 228 | void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) { |
| 165 | IPC::RequestParser rp{ctx}; | 229 | IPC::RequestParser rp{ctx}; |
| 166 | struct Parameters { | 230 | struct Parameters { |
| 167 | IrCameraHandle camera_handle; | 231 | Core::IrSensor::IrCameraHandle camera_handle; |
| 168 | INSERT_PADDING_WORDS_NOINIT(1); | 232 | INSERT_PADDING_WORDS_NOINIT(1); |
| 169 | u64 applet_resource_user_id; | 233 | u64 applet_resource_user_id; |
| 170 | }; | 234 | }; |
| @@ -172,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 | ||
| 186 | void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) { | 269 | void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) { |
| 187 | IPC::RequestParser rp{ctx}; | 270 | IPC::RequestParser rp{ctx}; |
| 188 | const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; | 271 | 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 | ||
| 203 | void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) { | 303 | void 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 | ||
| 227 | void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) { | 327 | void 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 | ||
| 243 | void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) { | 352 | void 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 | ||
| 263 | void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) { | 378 | void 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 | ||
| 279 | void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) { | 400 | void 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 | ||
| 299 | void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { | 422 | void 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 | ||
| 326 | void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) { | 462 | void 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 | ||
| 343 | void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { | 488 | void 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 | ||
| 363 | void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) { | 514 | void 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 | ||
| 381 | IRS::~IRS() = default; | 532 | Result 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 | |||
| 543 | Core::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 | ||
| 383 | IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} { | 549 | IRS_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 | ||
| 396 | IRS_SYS::~IRS_SYS() = default; | 562 | IRS_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 | ||
| 9 | namespace Core { | 11 | namespace Core { |
| 10 | class System; | 12 | class System; |
| 11 | } | 13 | } |
| 12 | 14 | ||
| 13 | namespace Service::HID { | 15 | namespace Core::HID { |
| 16 | class EmulatedController; | ||
| 17 | } // namespace Core::HID | ||
| 18 | |||
| 19 | namespace Service::IRS { | ||
| 14 | 20 | ||
| 15 | class IRS final : public ServiceFramework<IRS> { | 21 | class IRS final : public ServiceFramework<IRS> { |
| 16 | public: | 22 | public: |
| @@ -18,234 +24,19 @@ public: | |||
| 18 | ~IRS() override; | 24 | ~IRS() override; |
| 19 | 25 | ||
| 20 | private: | 26 | private: |
| 21 | // This is nn::irsensor::IrCameraStatus | 27 | // This is nn::irsensor::detail::AruidFormat |
| 22 | enum IrCameraStatus : u32 { | 28 | struct AruidFormat { |
| 23 | Available, | 29 | u64 sensor_aruid; |
| 24 | Unsupported, | 30 | u64 sensor_aruid_status; |
| 25 | Unconnected, | ||
| 26 | }; | ||
| 27 | |||
| 28 | // This is nn::irsensor::IrCameraInternalStatus | ||
| 29 | enum IrCameraInternalStatus : u32 { | ||
| 30 | Stopped, | ||
| 31 | FirmwareUpdateNeeded, | ||
| 32 | Unkown2, | ||
| 33 | Unkown3, | ||
| 34 | Unkown4, | ||
| 35 | FirmwareVersionRequested, | ||
| 36 | FirmwareVersionIsInvalid, | ||
| 37 | Ready, | ||
| 38 | Setting, | ||
| 39 | }; | ||
| 40 | |||
| 41 | // This is nn::irsensor::detail::StatusManager::IrSensorMode | ||
| 42 | enum IrSensorMode : u64 { | ||
| 43 | None, | ||
| 44 | MomentProcessor, | ||
| 45 | ClusteringProcessor, | ||
| 46 | ImageTransferProcessor, | ||
| 47 | PointingProcessorMarker, | ||
| 48 | TeraPluginProcessor, | ||
| 49 | IrLedProcessor, | ||
| 50 | }; | ||
| 51 | |||
| 52 | // This is nn::irsensor::ImageProcessorStatus | ||
| 53 | enum ImageProcessorStatus : u8 { | ||
| 54 | stopped, | ||
| 55 | running, | ||
| 56 | }; | ||
| 57 | |||
| 58 | // This is nn::irsensor::ImageTransferProcessorFormat | ||
| 59 | enum ImageTransferProcessorFormat : u8 { | ||
| 60 | Size320x240, | ||
| 61 | Size160x120, | ||
| 62 | Size80x60, | ||
| 63 | Size40x30, | ||
| 64 | Size20x15, | ||
| 65 | }; | ||
| 66 | |||
| 67 | // This is nn::irsensor::AdaptiveClusteringMode | ||
| 68 | enum AdaptiveClusteringMode : u8 { | ||
| 69 | StaticFov, | ||
| 70 | DynamicFov, | ||
| 71 | }; | ||
| 72 | |||
| 73 | // This is nn::irsensor::AdaptiveClusteringTargetDistance | ||
| 74 | enum AdaptiveClusteringTargetDistance : u8 { | ||
| 75 | Near, | ||
| 76 | Middle, | ||
| 77 | Far, | ||
| 78 | }; | ||
| 79 | |||
| 80 | // This is nn::irsensor::IrsHandAnalysisMode | ||
| 81 | enum IrsHandAnalysisMode : u8 { | ||
| 82 | Silhouette, | ||
| 83 | Image, | ||
| 84 | SilhoueteAndImage, | ||
| 85 | SilhuetteOnly, | ||
| 86 | }; | ||
| 87 | |||
| 88 | // This is nn::irsensor::IrSensorFunctionLevel | ||
| 89 | enum IrSensorFunctionLevel : u8 { | ||
| 90 | unknown0, | ||
| 91 | unknown1, | ||
| 92 | unknown2, | ||
| 93 | unknown3, | ||
| 94 | unknown4, | ||
| 95 | }; | ||
| 96 | |||
| 97 | // This is nn::irsensor::IrCameraHandle | ||
| 98 | struct IrCameraHandle { | ||
| 99 | u8 npad_id{}; | ||
| 100 | Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None}; | ||
| 101 | INSERT_PADDING_BYTES(2); | ||
| 102 | }; | ||
| 103 | static_assert(sizeof(IrCameraHandle) == 4, "IrCameraHandle is an invalid size"); | ||
| 104 | |||
| 105 | struct IrsRect { | ||
| 106 | s16 x; | ||
| 107 | s16 y; | ||
| 108 | s16 width; | ||
| 109 | s16 height; | ||
| 110 | }; | 31 | }; |
| 32 | static_assert(sizeof(AruidFormat) == 0x10, "AruidFormat is an invalid size"); | ||
| 111 | 33 | ||
| 112 | // This is nn::irsensor::PackedMcuVersion | 34 | // This is nn::irsensor::detail::StatusManager |
| 113 | struct PackedMcuVersion { | 35 | struct StatusManager { |
| 114 | u16 major; | 36 | std::array<Core::IrSensor::DeviceFormat, 9> device; |
| 115 | u16 minor; | 37 | std::array<AruidFormat, 5> aruid; |
| 116 | }; | 38 | }; |
| 117 | static_assert(sizeof(PackedMcuVersion) == 4, "PackedMcuVersion is an invalid size"); | 39 | static_assert(sizeof(StatusManager) == 0x8000, "StatusManager is an invalid size"); |
| 118 | |||
| 119 | // This is nn::irsensor::MomentProcessorConfig | ||
| 120 | struct MomentProcessorConfig { | ||
| 121 | u64 exposire_time; | ||
| 122 | u8 light_target; | ||
| 123 | u8 gain; | ||
| 124 | u8 is_negative_used; | ||
| 125 | INSERT_PADDING_BYTES(7); | ||
| 126 | IrsRect window_of_interest; | ||
| 127 | u8 preprocess; | ||
| 128 | u8 preprocess_intensity_threshold; | ||
| 129 | INSERT_PADDING_BYTES(5); | ||
| 130 | }; | ||
| 131 | static_assert(sizeof(MomentProcessorConfig) == 0x28, | ||
| 132 | "MomentProcessorConfig is an invalid size"); | ||
| 133 | |||
| 134 | // This is nn::irsensor::PackedMomentProcessorConfig | ||
| 135 | struct PackedMomentProcessorConfig { | ||
| 136 | u64 exposire_time; | ||
| 137 | u8 light_target; | ||
| 138 | u8 gain; | ||
| 139 | u8 is_negative_used; | ||
| 140 | INSERT_PADDING_BYTES(5); | ||
| 141 | IrsRect window_of_interest; | ||
| 142 | PackedMcuVersion required_mcu_version; | ||
| 143 | u8 preprocess; | ||
| 144 | u8 preprocess_intensity_threshold; | ||
| 145 | INSERT_PADDING_BYTES(2); | ||
| 146 | }; | ||
| 147 | static_assert(sizeof(PackedMomentProcessorConfig) == 0x20, | ||
| 148 | "PackedMomentProcessorConfig is an invalid size"); | ||
| 149 | |||
| 150 | // This is nn::irsensor::ClusteringProcessorConfig | ||
| 151 | struct ClusteringProcessorConfig { | ||
| 152 | u64 exposire_time; | ||
| 153 | u32 light_target; | ||
| 154 | u32 gain; | ||
| 155 | u8 is_negative_used; | ||
| 156 | INSERT_PADDING_BYTES(7); | ||
| 157 | IrsRect window_of_interest; | ||
| 158 | u32 pixel_count_min; | ||
| 159 | u32 pixel_count_max; | ||
| 160 | u32 object_intensity_min; | ||
| 161 | u8 is_external_light_filter_enabled; | ||
| 162 | INSERT_PADDING_BYTES(3); | ||
| 163 | }; | ||
| 164 | static_assert(sizeof(ClusteringProcessorConfig) == 0x30, | ||
| 165 | "ClusteringProcessorConfig is an invalid size"); | ||
| 166 | |||
| 167 | // This is nn::irsensor::PackedClusteringProcessorConfig | ||
| 168 | struct PackedClusteringProcessorConfig { | ||
| 169 | u64 exposire_time; | ||
| 170 | u8 light_target; | ||
| 171 | u8 gain; | ||
| 172 | u8 is_negative_used; | ||
| 173 | INSERT_PADDING_BYTES(5); | ||
| 174 | IrsRect window_of_interest; | ||
| 175 | PackedMcuVersion required_mcu_version; | ||
| 176 | u32 pixel_count_min; | ||
| 177 | u32 pixel_count_max; | ||
| 178 | u32 object_intensity_min; | ||
| 179 | u8 is_external_light_filter_enabled; | ||
| 180 | INSERT_PADDING_BYTES(2); | ||
| 181 | }; | ||
| 182 | static_assert(sizeof(PackedClusteringProcessorConfig) == 0x30, | ||
| 183 | "PackedClusteringProcessorConfig is an invalid size"); | ||
| 184 | |||
| 185 | // This is nn::irsensor::PackedImageTransferProcessorConfig | ||
| 186 | struct PackedImageTransferProcessorConfig { | ||
| 187 | u64 exposire_time; | ||
| 188 | u8 light_target; | ||
| 189 | u8 gain; | ||
| 190 | u8 is_negative_used; | ||
| 191 | INSERT_PADDING_BYTES(5); | ||
| 192 | PackedMcuVersion required_mcu_version; | ||
| 193 | u8 format; | ||
| 194 | INSERT_PADDING_BYTES(3); | ||
| 195 | }; | ||
| 196 | static_assert(sizeof(PackedImageTransferProcessorConfig) == 0x18, | ||
| 197 | "PackedImageTransferProcessorConfig is an invalid size"); | ||
| 198 | |||
| 199 | // This is nn::irsensor::PackedTeraPluginProcessorConfig | ||
| 200 | struct PackedTeraPluginProcessorConfig { | ||
| 201 | PackedMcuVersion required_mcu_version; | ||
| 202 | u8 mode; | ||
| 203 | INSERT_PADDING_BYTES(3); | ||
| 204 | }; | ||
| 205 | static_assert(sizeof(PackedTeraPluginProcessorConfig) == 0x8, | ||
| 206 | "PackedTeraPluginProcessorConfig is an invalid size"); | ||
| 207 | |||
| 208 | // This is nn::irsensor::PackedPointingProcessorConfig | ||
| 209 | struct PackedPointingProcessorConfig { | ||
| 210 | IrsRect window_of_interest; | ||
| 211 | PackedMcuVersion required_mcu_version; | ||
| 212 | }; | ||
| 213 | static_assert(sizeof(PackedPointingProcessorConfig) == 0xC, | ||
| 214 | "PackedPointingProcessorConfig is an invalid size"); | ||
| 215 | |||
| 216 | // This is nn::irsensor::PackedFunctionLevel | ||
| 217 | struct PackedFunctionLevel { | ||
| 218 | IrSensorFunctionLevel function_level; | ||
| 219 | INSERT_PADDING_BYTES(3); | ||
| 220 | }; | ||
| 221 | static_assert(sizeof(PackedFunctionLevel) == 0x4, "PackedFunctionLevel is an invalid size"); | ||
| 222 | |||
| 223 | // This is nn::irsensor::PackedImageTransferProcessorExConfig | ||
| 224 | struct PackedImageTransferProcessorExConfig { | ||
| 225 | u64 exposire_time; | ||
| 226 | u8 light_target; | ||
| 227 | u8 gain; | ||
| 228 | u8 is_negative_used; | ||
| 229 | INSERT_PADDING_BYTES(5); | ||
| 230 | PackedMcuVersion required_mcu_version; | ||
| 231 | ImageTransferProcessorFormat origin_format; | ||
| 232 | ImageTransferProcessorFormat trimming_format; | ||
| 233 | u16 trimming_start_x; | ||
| 234 | u16 trimming_start_y; | ||
| 235 | u8 is_external_light_filter_enabled; | ||
| 236 | INSERT_PADDING_BYTES(3); | ||
| 237 | }; | ||
| 238 | static_assert(sizeof(PackedImageTransferProcessorExConfig) == 0x20, | ||
| 239 | "PackedImageTransferProcessorExConfig is an invalid size"); | ||
| 240 | |||
| 241 | // This is nn::irsensor::PackedIrLedProcessorConfig | ||
| 242 | struct PackedIrLedProcessorConfig { | ||
| 243 | PackedMcuVersion required_mcu_version; | ||
| 244 | u8 light_target; | ||
| 245 | INSERT_PADDING_BYTES(3); | ||
| 246 | }; | ||
| 247 | static_assert(sizeof(PackedIrLedProcessorConfig) == 0x8, | ||
| 248 | "PackedIrLedProcessorConfig is an invalid size"); | ||
| 249 | 40 | ||
| 250 | void ActivateIrsensor(Kernel::HLERequestContext& ctx); | 41 | void ActivateIrsensor(Kernel::HLERequestContext& ctx); |
| 251 | void DeactivateIrsensor(Kernel::HLERequestContext& ctx); | 42 | void DeactivateIrsensor(Kernel::HLERequestContext& ctx); |
| @@ -265,6 +56,56 @@ private: | |||
| 265 | void RunIrLedProcessor(Kernel::HLERequestContext& ctx); | 56 | void RunIrLedProcessor(Kernel::HLERequestContext& ctx); |
| 266 | void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); | 57 | void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); |
| 267 | void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); | 58 | void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); |
| 59 | |||
| 60 | 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 | ||
| 270 | class IRS_SYS final : public ServiceFramework<IRS_SYS> { | 111 | class 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 | |||
| 6 | namespace Service::IRS { | ||
| 7 | ClusteringProcessor::ClusteringProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | } | ||
| 13 | |||
| 14 | ClusteringProcessor::~ClusteringProcessor() = default; | ||
| 15 | |||
| 16 | void ClusteringProcessor::StartProcessor() {} | ||
| 17 | |||
| 18 | void ClusteringProcessor::SuspendProcessor() {} | ||
| 19 | |||
| 20 | void ClusteringProcessor::StopProcessor() {} | ||
| 21 | |||
| 22 | void 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 | |||
| 10 | namespace Service::IRS { | ||
| 11 | class ClusteringProcessor final : public ProcessorBase { | ||
| 12 | public: | ||
| 13 | explicit ClusteringProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 14 | ~ClusteringProcessor() override; | ||
| 15 | |||
| 16 | // Called when the processor is initialized | ||
| 17 | void StartProcessor() override; | ||
| 18 | |||
| 19 | // Called when the processor is suspended | ||
| 20 | void SuspendProcessor() override; | ||
| 21 | |||
| 22 | // Called when the processor is stopped | ||
| 23 | void StopProcessor() override; | ||
| 24 | |||
| 25 | // Sets config parameters of the camera | ||
| 26 | void SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config); | ||
| 27 | |||
| 28 | private: | ||
| 29 | // This is nn::irsensor::ClusteringProcessorConfig | ||
| 30 | struct ClusteringProcessorConfig { | ||
| 31 | Core::IrSensor::CameraConfig camera_config; | ||
| 32 | Core::IrSensor::IrsRect window_of_interest; | ||
| 33 | u32 pixel_count_min; | ||
| 34 | u32 pixel_count_max; | ||
| 35 | u32 object_intensity_min; | ||
| 36 | bool is_external_light_filter_enabled; | ||
| 37 | INSERT_PADDING_BYTES(3); | ||
| 38 | }; | ||
| 39 | static_assert(sizeof(ClusteringProcessorConfig) == 0x30, | ||
| 40 | "ClusteringProcessorConfig is an invalid size"); | ||
| 41 | |||
| 42 | // This is nn::irsensor::AdaptiveClusteringProcessorConfig | ||
| 43 | struct AdaptiveClusteringProcessorConfig { | ||
| 44 | Core::IrSensor::AdaptiveClusteringMode mode; | ||
| 45 | Core::IrSensor::AdaptiveClusteringTargetDistance target_distance; | ||
| 46 | }; | ||
| 47 | static_assert(sizeof(AdaptiveClusteringProcessorConfig) == 0x8, | ||
| 48 | "AdaptiveClusteringProcessorConfig is an invalid size"); | ||
| 49 | |||
| 50 | // This is nn::irsensor::ClusteringData | ||
| 51 | struct ClusteringData { | ||
| 52 | f32 average_intensity; | ||
| 53 | Core::IrSensor::IrsCentroid centroid; | ||
| 54 | u32 pixel_count; | ||
| 55 | Core::IrSensor::IrsRect bound; | ||
| 56 | }; | ||
| 57 | static_assert(sizeof(ClusteringData) == 0x18, "ClusteringData is an invalid size"); | ||
| 58 | |||
| 59 | // This is nn::irsensor::ClusteringProcessorState | ||
| 60 | struct ClusteringProcessorState { | ||
| 61 | s64 sampling_number; | ||
| 62 | u64 timestamp; | ||
| 63 | u8 object_count; | ||
| 64 | INSERT_PADDING_BYTES(3); | ||
| 65 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 66 | std::array<ClusteringData, 0x10> data; | ||
| 67 | }; | ||
| 68 | static_assert(sizeof(ClusteringProcessorState) == 0x198, | ||
| 69 | "ClusteringProcessorState is an invalid size"); | ||
| 70 | |||
| 71 | ClusteringProcessorConfig current_config{}; | ||
| 72 | Core::IrSensor::DeviceFormat& device; | ||
| 73 | }; | ||
| 74 | } // namespace Service::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 | |||
| 8 | namespace Service::IRS { | ||
| 9 | ImageTransferProcessor::ImageTransferProcessor(Core::HID::HIDCore& hid_core_, | ||
| 10 | Core::IrSensor::DeviceFormat& device_format, | ||
| 11 | std::size_t npad_index) | ||
| 12 | : device{device_format} { | ||
| 13 | npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index); | ||
| 14 | |||
| 15 | Core::HID::ControllerUpdateCallback engine_callback{ | ||
| 16 | .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, | ||
| 17 | .is_npad_service = true, | ||
| 18 | }; | ||
| 19 | callback_key = npad_device->SetCallback(engine_callback); | ||
| 20 | |||
| 21 | device.mode = Core::IrSensor::IrSensorMode::ImageTransferProcessor; | ||
| 22 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 23 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 24 | } | ||
| 25 | |||
| 26 | ImageTransferProcessor::~ImageTransferProcessor() { | ||
| 27 | npad_device->DeleteCallback(callback_key); | ||
| 28 | }; | ||
| 29 | |||
| 30 | void 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 | |||
| 38 | void ImageTransferProcessor::SuspendProcessor() {} | ||
| 39 | |||
| 40 | void ImageTransferProcessor::StopProcessor() {} | ||
| 41 | |||
| 42 | void 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 | |||
| 104 | void 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 | |||
| 120 | void 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 | |||
| 137 | void ImageTransferProcessor::SetTransferMemoryPointer(u8* t_mem) { | ||
| 138 | is_transfer_memory_set = true; | ||
| 139 | transfer_memory = t_mem; | ||
| 140 | } | ||
| 141 | |||
| 142 | Core::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 | |||
| 10 | namespace Core::HID { | ||
| 11 | class EmulatedController; | ||
| 12 | } // namespace Core::HID | ||
| 13 | |||
| 14 | namespace Service::IRS { | ||
| 15 | class ImageTransferProcessor final : public ProcessorBase { | ||
| 16 | public: | ||
| 17 | explicit ImageTransferProcessor(Core::HID::HIDCore& hid_core_, | ||
| 18 | Core::IrSensor::DeviceFormat& device_format, | ||
| 19 | std::size_t npad_index); | ||
| 20 | ~ImageTransferProcessor() override; | ||
| 21 | |||
| 22 | // Called when the processor is initialized | ||
| 23 | void StartProcessor() override; | ||
| 24 | |||
| 25 | // Called when the processor is suspended | ||
| 26 | void SuspendProcessor() override; | ||
| 27 | |||
| 28 | // Called when the processor is stopped | ||
| 29 | void StopProcessor() override; | ||
| 30 | |||
| 31 | // Sets config parameters of the camera | ||
| 32 | void SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config); | ||
| 33 | void SetConfig(Core::IrSensor::PackedImageTransferProcessorExConfig config); | ||
| 34 | |||
| 35 | // Transfer memory where the image data will be stored | ||
| 36 | void SetTransferMemoryPointer(u8* t_mem); | ||
| 37 | |||
| 38 | Core::IrSensor::ImageTransferProcessorState GetState(std::vector<u8>& data) const; | ||
| 39 | |||
| 40 | private: | ||
| 41 | // This is nn::irsensor::ImageTransferProcessorConfig | ||
| 42 | struct ImageTransferProcessorConfig { | ||
| 43 | Core::IrSensor::CameraConfig camera_config; | ||
| 44 | Core::IrSensor::ImageTransferProcessorFormat format; | ||
| 45 | }; | ||
| 46 | static_assert(sizeof(ImageTransferProcessorConfig) == 0x20, | ||
| 47 | "ImageTransferProcessorConfig is an invalid size"); | ||
| 48 | |||
| 49 | // This is nn::irsensor::ImageTransferProcessorExConfig | ||
| 50 | struct ImageTransferProcessorExConfig { | ||
| 51 | Core::IrSensor::CameraConfig camera_config; | ||
| 52 | Core::IrSensor::ImageTransferProcessorFormat origin_format; | ||
| 53 | Core::IrSensor::ImageTransferProcessorFormat trimming_format; | ||
| 54 | u16 trimming_start_x; | ||
| 55 | u16 trimming_start_y; | ||
| 56 | bool is_external_light_filter_enabled; | ||
| 57 | INSERT_PADDING_BYTES(3); | ||
| 58 | }; | ||
| 59 | static_assert(sizeof(ImageTransferProcessorExConfig) == 0x28, | ||
| 60 | "ImageTransferProcessorExConfig is an invalid size"); | ||
| 61 | |||
| 62 | void OnControllerUpdate(Core::HID::ControllerTriggerType type); | ||
| 63 | |||
| 64 | ImageTransferProcessorExConfig current_config{}; | ||
| 65 | Core::IrSensor::ImageTransferProcessorState processor_state{}; | ||
| 66 | Core::IrSensor::DeviceFormat& device; | ||
| 67 | Core::HID::EmulatedController* npad_device; | ||
| 68 | int callback_key{}; | ||
| 69 | |||
| 70 | u8* transfer_memory = nullptr; | ||
| 71 | bool is_transfer_memory_set = false; | ||
| 72 | }; | ||
| 73 | } // namespace Service::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 | |||
| 6 | namespace Service::IRS { | ||
| 7 | IrLedProcessor::IrLedProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::IrLedProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | } | ||
| 13 | |||
| 14 | IrLedProcessor::~IrLedProcessor() = default; | ||
| 15 | |||
| 16 | void IrLedProcessor::StartProcessor() {} | ||
| 17 | |||
| 18 | void IrLedProcessor::SuspendProcessor() {} | ||
| 19 | |||
| 20 | void IrLedProcessor::StopProcessor() {} | ||
| 21 | |||
| 22 | void 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 | |||
| 11 | namespace Service::IRS { | ||
| 12 | class IrLedProcessor final : public ProcessorBase { | ||
| 13 | public: | ||
| 14 | explicit IrLedProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 15 | ~IrLedProcessor() override; | ||
| 16 | |||
| 17 | // Called when the processor is initialized | ||
| 18 | void StartProcessor() override; | ||
| 19 | |||
| 20 | // Called when the processor is suspended | ||
| 21 | void SuspendProcessor() override; | ||
| 22 | |||
| 23 | // Called when the processor is stopped | ||
| 24 | void StopProcessor() override; | ||
| 25 | |||
| 26 | // Sets config parameters of the camera | ||
| 27 | void SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config); | ||
| 28 | |||
| 29 | private: | ||
| 30 | // This is nn::irsensor::IrLedProcessorConfig | ||
| 31 | struct IrLedProcessorConfig { | ||
| 32 | Core::IrSensor::CameraLightTarget light_target; | ||
| 33 | }; | ||
| 34 | static_assert(sizeof(IrLedProcessorConfig) == 0x4, "IrLedProcessorConfig is an invalid size"); | ||
| 35 | |||
| 36 | struct IrLedProcessorState { | ||
| 37 | s64 sampling_number; | ||
| 38 | u64 timestamp; | ||
| 39 | std::array<u8, 0x8> data; | ||
| 40 | }; | ||
| 41 | static_assert(sizeof(IrLedProcessorState) == 0x18, "IrLedProcessorState is an invalid size"); | ||
| 42 | |||
| 43 | IrLedProcessorConfig current_config{}; | ||
| 44 | Core::IrSensor::DeviceFormat& device; | ||
| 45 | }; | ||
| 46 | |||
| 47 | } // namespace Service::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 | |||
| 6 | namespace Service::IRS { | ||
| 7 | MomentProcessor::MomentProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::MomentProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | } | ||
| 13 | |||
| 14 | MomentProcessor::~MomentProcessor() = default; | ||
| 15 | |||
| 16 | void MomentProcessor::StartProcessor() {} | ||
| 17 | |||
| 18 | void MomentProcessor::SuspendProcessor() {} | ||
| 19 | |||
| 20 | void MomentProcessor::StopProcessor() {} | ||
| 21 | |||
| 22 | void 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 | |||
| 11 | namespace Service::IRS { | ||
| 12 | class MomentProcessor final : public ProcessorBase { | ||
| 13 | public: | ||
| 14 | explicit MomentProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 15 | ~MomentProcessor() override; | ||
| 16 | |||
| 17 | // Called when the processor is initialized | ||
| 18 | void StartProcessor() override; | ||
| 19 | |||
| 20 | // Called when the processor is suspended | ||
| 21 | void SuspendProcessor() override; | ||
| 22 | |||
| 23 | // Called when the processor is stopped | ||
| 24 | void StopProcessor() override; | ||
| 25 | |||
| 26 | // Sets config parameters of the camera | ||
| 27 | void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config); | ||
| 28 | |||
| 29 | private: | ||
| 30 | // This is nn::irsensor::MomentProcessorConfig | ||
| 31 | struct MomentProcessorConfig { | ||
| 32 | Core::IrSensor::CameraConfig camera_config; | ||
| 33 | Core::IrSensor::IrsRect window_of_interest; | ||
| 34 | Core::IrSensor::MomentProcessorPreprocess preprocess; | ||
| 35 | u32 preprocess_intensity_threshold; | ||
| 36 | }; | ||
| 37 | static_assert(sizeof(MomentProcessorConfig) == 0x28, | ||
| 38 | "MomentProcessorConfig is an invalid size"); | ||
| 39 | |||
| 40 | // This is nn::irsensor::MomentStatistic | ||
| 41 | struct MomentStatistic { | ||
| 42 | f32 average_intensity; | ||
| 43 | Core::IrSensor::IrsCentroid centroid; | ||
| 44 | }; | ||
| 45 | static_assert(sizeof(MomentStatistic) == 0xC, "MomentStatistic is an invalid size"); | ||
| 46 | |||
| 47 | // This is nn::irsensor::MomentProcessorState | ||
| 48 | struct MomentProcessorState { | ||
| 49 | s64 sampling_number; | ||
| 50 | u64 timestamp; | ||
| 51 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 52 | INSERT_PADDING_BYTES(4); | ||
| 53 | std::array<MomentStatistic, 0x30> stadistic; | ||
| 54 | }; | ||
| 55 | static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size"); | ||
| 56 | |||
| 57 | MomentProcessorConfig current_config{}; | ||
| 58 | Core::IrSensor::DeviceFormat& device; | ||
| 59 | }; | ||
| 60 | |||
| 61 | } // namespace Service::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 | |||
| 6 | namespace Service::IRS { | ||
| 7 | PointingProcessor::PointingProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::PointingProcessorMarker; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | } | ||
| 13 | |||
| 14 | PointingProcessor::~PointingProcessor() = default; | ||
| 15 | |||
| 16 | void PointingProcessor::StartProcessor() {} | ||
| 17 | |||
| 18 | void PointingProcessor::SuspendProcessor() {} | ||
| 19 | |||
| 20 | void PointingProcessor::StopProcessor() {} | ||
| 21 | |||
| 22 | void 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 | |||
| 10 | namespace Service::IRS { | ||
| 11 | class PointingProcessor final : public ProcessorBase { | ||
| 12 | public: | ||
| 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 | |||
| 28 | private: | ||
| 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 | |||
| 6 | namespace Service::IRS { | ||
| 7 | |||
| 8 | ProcessorBase::ProcessorBase() {} | ||
| 9 | ProcessorBase::~ProcessorBase() = default; | ||
| 10 | |||
| 11 | bool ProcessorBase::IsProcessorActive() const { | ||
| 12 | return is_active; | ||
| 13 | } | ||
| 14 | |||
| 15 | std::size_t ProcessorBase::GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 16 | switch (format) { | ||
| 17 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 18 | return 320 * 240; | ||
| 19 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 20 | return 160 * 120; | ||
| 21 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 22 | return 80 * 60; | ||
| 23 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 24 | return 40 * 30; | ||
| 25 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 26 | return 20 * 15; | ||
| 27 | default: | ||
| 28 | return 0; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | std::size_t ProcessorBase::GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 33 | switch (format) { | ||
| 34 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 35 | return 320; | ||
| 36 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 37 | return 160; | ||
| 38 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 39 | return 80; | ||
| 40 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 41 | return 40; | ||
| 42 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 43 | return 20; | ||
| 44 | default: | ||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | std::size_t ProcessorBase::GetDataHeight( | ||
| 50 | Core::IrSensor::ImageTransferProcessorFormat format) const { | ||
| 51 | switch (format) { | ||
| 52 | case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: | ||
| 53 | return 240; | ||
| 54 | case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: | ||
| 55 | return 120; | ||
| 56 | case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: | ||
| 57 | return 60; | ||
| 58 | case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: | ||
| 59 | return 30; | ||
| 60 | case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: | ||
| 61 | return 15; | ||
| 62 | default: | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | } // namespace Service::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 | |||
| 9 | namespace Service::IRS { | ||
| 10 | class ProcessorBase { | ||
| 11 | public: | ||
| 12 | explicit ProcessorBase(); | ||
| 13 | virtual ~ProcessorBase(); | ||
| 14 | |||
| 15 | virtual void StartProcessor() = 0; | ||
| 16 | virtual void SuspendProcessor() = 0; | ||
| 17 | virtual void StopProcessor() = 0; | ||
| 18 | |||
| 19 | bool IsProcessorActive() const; | ||
| 20 | |||
| 21 | protected: | ||
| 22 | /// Returns the number of bytes the image uses | ||
| 23 | std::size_t GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 24 | |||
| 25 | /// Returns the width of the image | ||
| 26 | std::size_t GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 27 | |||
| 28 | /// Returns the height of the image | ||
| 29 | std::size_t GetDataHeight(Core::IrSensor::ImageTransferProcessorFormat format) const; | ||
| 30 | |||
| 31 | bool is_active{false}; | ||
| 32 | }; | ||
| 33 | } // namespace Service::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 | |||
| 6 | namespace Service::IRS { | ||
| 7 | TeraPluginProcessor::TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format) | ||
| 8 | : device(device_format) { | ||
| 9 | device.mode = Core::IrSensor::IrSensorMode::TeraPluginProcessor; | ||
| 10 | device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; | ||
| 11 | device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; | ||
| 12 | } | ||
| 13 | |||
| 14 | TeraPluginProcessor::~TeraPluginProcessor() = default; | ||
| 15 | |||
| 16 | void TeraPluginProcessor::StartProcessor() {} | ||
| 17 | |||
| 18 | void TeraPluginProcessor::SuspendProcessor() {} | ||
| 19 | |||
| 20 | void TeraPluginProcessor::StopProcessor() {} | ||
| 21 | |||
| 22 | void 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 | |||
| 11 | namespace Service::IRS { | ||
| 12 | class TeraPluginProcessor final : public ProcessorBase { | ||
| 13 | public: | ||
| 14 | explicit TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format); | ||
| 15 | ~TeraPluginProcessor() override; | ||
| 16 | |||
| 17 | // Called when the processor is initialized | ||
| 18 | void StartProcessor() override; | ||
| 19 | |||
| 20 | // Called when the processor is suspended | ||
| 21 | void SuspendProcessor() override; | ||
| 22 | |||
| 23 | // Called when the processor is stopped | ||
| 24 | void StopProcessor() override; | ||
| 25 | |||
| 26 | // Sets config parameters of the camera | ||
| 27 | void SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config); | ||
| 28 | |||
| 29 | private: | ||
| 30 | // This is nn::irsensor::TeraPluginProcessorConfig | ||
| 31 | struct TeraPluginProcessorConfig { | ||
| 32 | u8 mode; | ||
| 33 | u8 unknown_1; | ||
| 34 | u8 unknown_2; | ||
| 35 | u8 unknown_3; | ||
| 36 | }; | ||
| 37 | static_assert(sizeof(TeraPluginProcessorConfig) == 0x4, | ||
| 38 | "TeraPluginProcessorConfig is an invalid size"); | ||
| 39 | |||
| 40 | struct TeraPluginProcessorState { | ||
| 41 | s64 sampling_number; | ||
| 42 | u64 timestamp; | ||
| 43 | Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; | ||
| 44 | std::array<u8, 0x12c> data; | ||
| 45 | }; | ||
| 46 | static_assert(sizeof(TeraPluginProcessorState) == 0x140, | ||
| 47 | "TeraPluginProcessorState is an invalid size"); | ||
| 48 | |||
| 49 | TeraPluginProcessorConfig current_config{}; | ||
| 50 | Core::IrSensor::DeviceFormat& device; | ||
| 51 | }; | ||
| 52 | |||
| 53 | } // namespace Service::IRS | ||