diff options
Diffstat (limited to 'src/core/hle/service')
18 files changed, 1091 insertions, 308 deletions
| diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h index 46282f42e..4613a4e60 100644 --- a/src/core/hle/service/hid/errors.h +++ b/src/core/hle/service/hid/errors.h @@ -19,3 +19,10 @@ constexpr Result InvalidNpadId{ErrorModule::HID, 709};  constexpr Result NpadNotConnected{ErrorModule::HID, 710};  } // namespace Service::HID + +namespace Service::IRS { + +constexpr Result InvalidProcessorState{ErrorModule::Irsensor, 78}; +constexpr Result InvalidIrCameraHandle{ErrorModule::Irsensor, 204}; + +} // 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      std::make_shared<HidSys>(system)->InstallAsService(service_manager);      std::make_shared<HidTmp>(system)->InstallAsService(service_manager); -    std::make_shared<IRS>(system)->InstallAsService(service_manager); -    std::make_shared<IRS_SYS>(system)->InstallAsService(service_manager); +    std::make_shared<Service::IRS::IRS>(system)->InstallAsService(service_manager); +    std::make_shared<Service::IRS::IRS_SYS>(system)->InstallAsService(service_manager);      std::make_shared<XCD_SYS>(system)->InstallAsService(service_manager);  } 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 @@  // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later +#include <algorithm> +#include <random> +  #include "core/core.h"  #include "core/core_timing.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h"  #include "core/hle/ipc_helpers.h"  #include "core/hle/kernel/k_shared_memory.h"  #include "core/hle/kernel/k_transfer_memory.h"  #include "core/hle/kernel/kernel.h"  #include "core/hle/service/hid/errors.h"  #include "core/hle/service/hid/irs.h" +#include "core/hle/service/hid/irsensor/clustering_processor.h" +#include "core/hle/service/hid/irsensor/image_transfer_processor.h" +#include "core/hle/service/hid/irsensor/ir_led_processor.h" +#include "core/hle/service/hid/irsensor/moment_processor.h" +#include "core/hle/service/hid/irsensor/pointing_processor.h" +#include "core/hle/service/hid/irsensor/tera_plugin_processor.h" +#include "core/memory.h" -namespace Service::HID { +namespace Service::IRS {  IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} {      // clang-format off @@ -36,14 +48,19 @@ IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} {      };      // clang-format on +    u8* raw_shared_memory = system.Kernel().GetIrsSharedMem().GetPointer();      RegisterHandlers(functions); +    shared_memory = std::construct_at(reinterpret_cast<StatusManager*>(raw_shared_memory)); + +    npad_device = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);  } +IRS::~IRS() = default;  void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto applet_resource_user_id{rp.Pop<u64>()}; -    LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", +    LOG_WARNING(Service_IRS, "(STUBBED) called, applet_resource_user_id={}",                  applet_resource_user_id);      IPC::ResponseBuilder rb{ctx, 2}; @@ -54,7 +71,7 @@ void IRS::DeactivateIrsensor(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      const auto applet_resource_user_id{rp.Pop<u64>()}; -    LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", +    LOG_WARNING(Service_IRS, "(STUBBED) called, applet_resource_user_id={}",                  applet_resource_user_id);      IPC::ResponseBuilder rb{ctx, 2}; @@ -75,7 +92,7 @@ void IRS::GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx) {  void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      struct Parameters { -        IrCameraHandle camera_handle; +        Core::IrSensor::IrCameraHandle camera_handle;          INSERT_PADDING_WORDS_NOINIT(1);          u64 applet_resource_user_id;      }; @@ -88,17 +105,23 @@ void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) {                  parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,                  parameters.applet_resource_user_id); +    auto result = IsIrCameraHandleValid(parameters.camera_handle); +    if (result.IsSuccess()) { +        // TODO: Stop Image processor +        result = ResultSuccess; +    } +      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      struct Parameters { -        IrCameraHandle camera_handle; +        Core::IrSensor::IrCameraHandle camera_handle;          INSERT_PADDING_WORDS_NOINIT(1);          u64 applet_resource_user_id; -        PackedMomentProcessorConfig processor_config; +        Core::IrSensor::PackedMomentProcessorConfig processor_config;      };      static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size."); @@ -109,19 +132,28 @@ void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) {                  parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,                  parameters.applet_resource_user_id); +    const auto result = IsIrCameraHandleValid(parameters.camera_handle); + +    if (result.IsSuccess()) { +        auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); +        MakeProcessor<MomentProcessor>(parameters.camera_handle, device); +        auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle); +        image_transfer_processor.SetConfig(parameters.processor_config); +    } +      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      struct Parameters { -        IrCameraHandle camera_handle; +        Core::IrSensor::IrCameraHandle camera_handle;          INSERT_PADDING_WORDS_NOINIT(1);          u64 applet_resource_user_id; -        PackedClusteringProcessorConfig processor_config; +        Core::IrSensor::PackedClusteringProcessorConfig processor_config;      }; -    static_assert(sizeof(Parameters) == 0x40, "Parameters has incorrect size."); +    static_assert(sizeof(Parameters) == 0x38, "Parameters has incorrect size.");      const auto parameters{rp.PopRaw<Parameters>()}; @@ -130,17 +162,27 @@ void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) {                  parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,                  parameters.applet_resource_user_id); +    auto result = IsIrCameraHandleValid(parameters.camera_handle); + +    if (result.IsSuccess()) { +        auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); +        MakeProcessor<ClusteringProcessor>(parameters.camera_handle, device); +        auto& image_transfer_processor = +            GetProcessor<ClusteringProcessor>(parameters.camera_handle); +        image_transfer_processor.SetConfig(parameters.processor_config); +    } +      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      struct Parameters { -        IrCameraHandle camera_handle; +        Core::IrSensor::IrCameraHandle camera_handle;          INSERT_PADDING_WORDS_NOINIT(1);          u64 applet_resource_user_id; -        PackedImageTransferProcessorConfig processor_config; +        Core::IrSensor::PackedImageTransferProcessorConfig processor_config;          u32 transfer_memory_size;      };      static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size."); @@ -151,20 +193,42 @@ void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) {      auto t_mem =          system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); -    LOG_WARNING(Service_IRS, -                "(STUBBED) called, npad_type={}, npad_id={}, transfer_memory_size={}, " -                "applet_resource_user_id={}", -                parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, -                parameters.transfer_memory_size, parameters.applet_resource_user_id); +    if (t_mem.IsNull()) { +        LOG_ERROR(Service_IRS, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(ResultUnknown); +        return; +    } + +    ASSERT_MSG(t_mem->GetSize() == parameters.transfer_memory_size, "t_mem has incorrect size"); + +    u8* transfer_memory = system.Memory().GetPointer(t_mem->GetSourceAddress()); + +    LOG_INFO(Service_IRS, +             "called, npad_type={}, npad_id={}, transfer_memory_size={}, transfer_memory_size={}, " +             "applet_resource_user_id={}", +             parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, +             parameters.transfer_memory_size, t_mem->GetSize(), parameters.applet_resource_user_id); + +    const auto result = IsIrCameraHandleValid(parameters.camera_handle); + +    if (result.IsSuccess()) { +        auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); +        MakeProcessorWithCoreContext<ImageTransferProcessor>(parameters.camera_handle, device); +        auto& image_transfer_processor = +            GetProcessor<ImageTransferProcessor>(parameters.camera_handle); +        image_transfer_processor.SetConfig(parameters.processor_config); +        image_transfer_processor.SetTransferMemoryPointer(transfer_memory); +    }      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      struct Parameters { -        IrCameraHandle camera_handle; +        Core::IrSensor::IrCameraHandle camera_handle;          INSERT_PADDING_WORDS_NOINIT(1);          u64 applet_resource_user_id;      }; @@ -172,32 +236,68 @@ void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) {      const auto parameters{rp.PopRaw<Parameters>()}; -    LOG_WARNING(Service_IRS, -                "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", -                parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, -                parameters.applet_resource_user_id); +    LOG_DEBUG(Service_IRS, "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", +              parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, +              parameters.applet_resource_user_id); + +    const auto result = IsIrCameraHandleValid(parameters.camera_handle); +    if (result.IsError()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(result); +        return; +    } + +    const auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); + +    if (device.mode != Core::IrSensor::IrSensorMode::ImageTransferProcessor) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(InvalidProcessorState); +        return; +    } -    IPC::ResponseBuilder rb{ctx, 5}; +    std::vector<u8> data{}; +    const auto& image_transfer_processor = +        GetProcessor<ImageTransferProcessor>(parameters.camera_handle); +    const auto& state = image_transfer_processor.GetState(data); + +    ctx.WriteBuffer(data); +    IPC::ResponseBuilder rb{ctx, 6};      rb.Push(ResultSuccess); -    rb.PushRaw<u64>(system.CoreTiming().GetCPUTicks()); -    rb.PushRaw<u32>(0); +    rb.PushRaw(state);  }  void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx}; -    const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; -    const auto processor_config{rp.PopRaw<PackedTeraPluginProcessorConfig>()}; -    const auto applet_resource_user_id{rp.Pop<u64>()}; +    struct Parameters { +        Core::IrSensor::IrCameraHandle camera_handle; +        Core::IrSensor::PackedTeraPluginProcessorConfig processor_config; +        INSERT_PADDING_WORDS_NOINIT(1); +        u64 applet_resource_user_id; +    }; +    static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); -    LOG_WARNING(Service_IRS, -                "(STUBBED) called, npad_type={}, npad_id={}, mode={}, mcu_version={}.{}, " -                "applet_resource_user_id={}", -                camera_handle.npad_type, camera_handle.npad_id, processor_config.mode, -                processor_config.required_mcu_version.major, -                processor_config.required_mcu_version.minor, applet_resource_user_id); +    const auto parameters{rp.PopRaw<Parameters>()}; + +    LOG_WARNING( +        Service_IRS, +        "(STUBBED) called, npad_type={}, npad_id={}, mode={}, mcu_version={}.{}, " +        "applet_resource_user_id={}", +        parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, +        parameters.processor_config.mode, parameters.processor_config.required_mcu_version.major, +        parameters.processor_config.required_mcu_version.minor, parameters.applet_resource_user_id); + +    const auto result = IsIrCameraHandleValid(parameters.camera_handle); + +    if (result.IsSuccess()) { +        auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); +        MakeProcessor<TeraPluginProcessor>(parameters.camera_handle, device); +        auto& image_transfer_processor = +            GetProcessor<TeraPluginProcessor>(parameters.camera_handle); +        image_transfer_processor.SetConfig(parameters.processor_config); +    }      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) { @@ -207,17 +307,17 @@ void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) {      if (npad_id > Core::HID::NpadIdType::Player8 && npad_id != Core::HID::NpadIdType::Invalid &&          npad_id != Core::HID::NpadIdType::Handheld) {          IPC::ResponseBuilder rb{ctx, 2}; -        rb.Push(InvalidNpadId); +        rb.Push(Service::HID::InvalidNpadId);          return;      } -    IrCameraHandle camera_handle{ +    Core::IrSensor::IrCameraHandle camera_handle{          .npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)),          .npad_type = Core::HID::NpadStyleIndex::None,      }; -    LOG_WARNING(Service_IRS, "(STUBBED) called, npad_id={}, camera_npad_id={}, camera_npad_type={}", -                npad_id, camera_handle.npad_id, camera_handle.npad_type); +    LOG_INFO(Service_IRS, "called, npad_id={}, camera_npad_id={}, camera_npad_type={}", npad_id, +             camera_handle.npad_id, camera_handle.npad_type);      IPC::ResponseBuilder rb{ctx, 3};      rb.Push(ResultSuccess); @@ -226,8 +326,8 @@ void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) {  void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx}; -    const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; -    const auto processor_config{rp.PopRaw<PackedPointingProcessorConfig>()}; +    const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; +    const auto processor_config{rp.PopRaw<Core::IrSensor::PackedPointingProcessorConfig>()};      const auto applet_resource_user_id{rp.Pop<u64>()};      LOG_WARNING( @@ -236,14 +336,23 @@ void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) {          camera_handle.npad_type, camera_handle.npad_id, processor_config.required_mcu_version.major,          processor_config.required_mcu_version.minor, applet_resource_user_id); +    auto result = IsIrCameraHandleValid(camera_handle); + +    if (result.IsSuccess()) { +        auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle); +        MakeProcessor<PointingProcessor>(camera_handle, device); +        auto& image_transfer_processor = GetProcessor<PointingProcessor>(camera_handle); +        image_transfer_processor.SetConfig(processor_config); +    } +      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      struct Parameters { -        IrCameraHandle camera_handle; +        Core::IrSensor::IrCameraHandle camera_handle;          INSERT_PADDING_WORDS_NOINIT(1);          u64 applet_resource_user_id;      }; @@ -256,14 +365,20 @@ void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) {                  parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,                  parameters.applet_resource_user_id); +    auto result = IsIrCameraHandleValid(parameters.camera_handle); +    if (result.IsSuccess()) { +        // TODO: Suspend image processor +        result = ResultSuccess; +    } +      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx}; -    const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; -    const auto mcu_version{rp.PopRaw<PackedMcuVersion>()}; +    const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; +    const auto mcu_version{rp.PopRaw<Core::IrSensor::PackedMcuVersion>()};      const auto applet_resource_user_id{rp.Pop<u64>()};      LOG_WARNING( @@ -272,37 +387,45 @@ void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) {          camera_handle.npad_type, camera_handle.npad_id, applet_resource_user_id, mcu_version.major,          mcu_version.minor); +    auto result = IsIrCameraHandleValid(camera_handle); +    if (result.IsSuccess()) { +        // TODO: Check firmware version +        result = ResultSuccess; +    } +      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx}; -    struct Parameters { -        IrCameraHandle camera_handle; -        PackedFunctionLevel function_level; -        u64 applet_resource_user_id; -    }; -    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); - -    const auto parameters{rp.PopRaw<Parameters>()}; +    const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; +    const auto function_level{rp.PopRaw<Core::IrSensor::PackedFunctionLevel>()}; +    const auto applet_resource_user_id{rp.Pop<u64>()}; -    LOG_WARNING(Service_IRS, -                "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}", -                parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, -                parameters.applet_resource_user_id); +    LOG_WARNING( +        Service_IRS, +        "(STUBBED) called, npad_type={}, npad_id={}, function_level={}, applet_resource_user_id={}", +        camera_handle.npad_type, camera_handle.npad_id, function_level.function_level, +        applet_resource_user_id); + +    auto result = IsIrCameraHandleValid(camera_handle); +    if (result.IsSuccess()) { +        // TODO: Set Function level +        result = ResultSuccess; +    }      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      struct Parameters { -        IrCameraHandle camera_handle; +        Core::IrSensor::IrCameraHandle camera_handle;          INSERT_PADDING_WORDS_NOINIT(1);          u64 applet_resource_user_id; -        PackedImageTransferProcessorExConfig processor_config; +        Core::IrSensor::PackedImageTransferProcessorExConfig processor_config;          u64 transfer_memory_size;      };      static_assert(sizeof(Parameters) == 0x38, "Parameters has incorrect size."); @@ -313,20 +436,33 @@ void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) {      auto t_mem =          system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle); -    LOG_WARNING(Service_IRS, -                "(STUBBED) called, npad_type={}, npad_id={}, transfer_memory_size={}, " -                "applet_resource_user_id={}", -                parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, -                parameters.transfer_memory_size, parameters.applet_resource_user_id); +    u8* transfer_memory = system.Memory().GetPointer(t_mem->GetSourceAddress()); + +    LOG_INFO(Service_IRS, +             "called, npad_type={}, npad_id={}, transfer_memory_size={}, " +             "applet_resource_user_id={}", +             parameters.camera_handle.npad_type, parameters.camera_handle.npad_id, +             parameters.transfer_memory_size, parameters.applet_resource_user_id); + +    auto result = IsIrCameraHandleValid(parameters.camera_handle); + +    if (result.IsSuccess()) { +        auto& device = GetIrCameraSharedMemoryDeviceEntry(parameters.camera_handle); +        MakeProcessorWithCoreContext<ImageTransferProcessor>(parameters.camera_handle, device); +        auto& image_transfer_processor = +            GetProcessor<ImageTransferProcessor>(parameters.camera_handle); +        image_transfer_processor.SetConfig(parameters.processor_config); +        image_transfer_processor.SetTransferMemoryPointer(transfer_memory); +    }      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx}; -    const auto camera_handle{rp.PopRaw<IrCameraHandle>()}; -    const auto processor_config{rp.PopRaw<PackedIrLedProcessorConfig>()}; +    const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()}; +    const auto processor_config{rp.PopRaw<Core::IrSensor::PackedIrLedProcessorConfig>()};      const auto applet_resource_user_id{rp.Pop<u64>()};      LOG_WARNING(Service_IRS, @@ -336,14 +472,23 @@ void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) {                  processor_config.required_mcu_version.major,                  processor_config.required_mcu_version.minor, applet_resource_user_id); +    auto result = IsIrCameraHandleValid(camera_handle); + +    if (result.IsSuccess()) { +        auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle); +        MakeProcessor<IrLedProcessor>(camera_handle, device); +        auto& image_transfer_processor = GetProcessor<IrLedProcessor>(camera_handle); +        image_transfer_processor.SetConfig(processor_config); +    } +      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      struct Parameters { -        IrCameraHandle camera_handle; +        Core::IrSensor::IrCameraHandle camera_handle;          INSERT_PADDING_WORDS_NOINIT(1);          u64 applet_resource_user_id;      }; @@ -356,14 +501,20 @@ void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) {                  parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,                  parameters.applet_resource_user_id); +    auto result = IsIrCameraHandleValid(parameters.camera_handle); +    if (result.IsSuccess()) { +        // TODO: Stop image processor async +        result = ResultSuccess; +    } +      IPC::ResponseBuilder rb{ctx, 2}; -    rb.Push(ResultSuccess); +    rb.Push(result);  }  void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) {      IPC::RequestParser rp{ctx};      struct Parameters { -        PackedFunctionLevel function_level; +        Core::IrSensor::PackedFunctionLevel function_level;          INSERT_PADDING_WORDS_NOINIT(1);          u64 applet_resource_user_id;      }; @@ -378,7 +529,22 @@ void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) {      rb.Push(ResultSuccess);  } -IRS::~IRS() = default; +Result IRS::IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const { +    if (camera_handle.npad_id > +        static_cast<u8>(NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld))) { +        return InvalidIrCameraHandle; +    } +    if (camera_handle.npad_type != Core::HID::NpadStyleIndex::None) { +        return InvalidIrCameraHandle; +    } +    return ResultSuccess; +} + +Core::IrSensor::DeviceFormat& IRS::GetIrCameraSharedMemoryDeviceEntry( +    const Core::IrSensor::IrCameraHandle& camera_handle) { +    ASSERT_MSG(sizeof(StatusManager::device) > camera_handle.npad_id, "invalid npad_id"); +    return shared_memory->device[camera_handle.npad_id]; +}  IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} {      // clang-format off @@ -395,4 +561,4 @@ IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} {  IRS_SYS::~IRS_SYS() = default; -} // namespace Service::HID +} // 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 @@  #pragma once  #include "core/hid/hid_types.h" +#include "core/hid/irs_types.h" +#include "core/hle/service/hid/irsensor/processor_base.h"  #include "core/hle/service/service.h"  namespace Core {  class System;  } -namespace Service::HID { +namespace Core::HID { +class EmulatedController; +} // namespace Core::HID + +namespace Service::IRS {  class IRS final : public ServiceFramework<IRS> {  public: @@ -18,234 +24,19 @@ public:      ~IRS() override;  private: -    // This is nn::irsensor::IrCameraStatus -    enum IrCameraStatus : u32 { -        Available, -        Unsupported, -        Unconnected, -    }; - -    // This is nn::irsensor::IrCameraInternalStatus -    enum IrCameraInternalStatus : u32 { -        Stopped, -        FirmwareUpdateNeeded, -        Unkown2, -        Unkown3, -        Unkown4, -        FirmwareVersionRequested, -        FirmwareVersionIsInvalid, -        Ready, -        Setting, -    }; - -    // This is nn::irsensor::detail::StatusManager::IrSensorMode -    enum IrSensorMode : u64 { -        None, -        MomentProcessor, -        ClusteringProcessor, -        ImageTransferProcessor, -        PointingProcessorMarker, -        TeraPluginProcessor, -        IrLedProcessor, -    }; - -    // This is nn::irsensor::ImageProcessorStatus -    enum ImageProcessorStatus : u8 { -        stopped, -        running, -    }; - -    // This is nn::irsensor::ImageTransferProcessorFormat -    enum ImageTransferProcessorFormat : u8 { -        Size320x240, -        Size160x120, -        Size80x60, -        Size40x30, -        Size20x15, -    }; - -    // This is nn::irsensor::AdaptiveClusteringMode -    enum AdaptiveClusteringMode : u8 { -        StaticFov, -        DynamicFov, -    }; - -    // This is nn::irsensor::AdaptiveClusteringTargetDistance -    enum AdaptiveClusteringTargetDistance : u8 { -        Near, -        Middle, -        Far, -    }; - -    // This is nn::irsensor::IrsHandAnalysisMode -    enum IrsHandAnalysisMode : u8 { -        Silhouette, -        Image, -        SilhoueteAndImage, -        SilhuetteOnly, -    }; - -    // This is nn::irsensor::IrSensorFunctionLevel -    enum IrSensorFunctionLevel : u8 { -        unknown0, -        unknown1, -        unknown2, -        unknown3, -        unknown4, -    }; - -    // This is nn::irsensor::IrCameraHandle -    struct IrCameraHandle { -        u8 npad_id{}; -        Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None}; -        INSERT_PADDING_BYTES(2); -    }; -    static_assert(sizeof(IrCameraHandle) == 4, "IrCameraHandle is an invalid size"); - -    struct IrsRect { -        s16 x; -        s16 y; -        s16 width; -        s16 height; +    // This is nn::irsensor::detail::AruidFormat +    struct AruidFormat { +        u64 sensor_aruid; +        u64 sensor_aruid_status;      }; +    static_assert(sizeof(AruidFormat) == 0x10, "AruidFormat is an invalid size"); -    // This is nn::irsensor::PackedMcuVersion -    struct PackedMcuVersion { -        u16 major; -        u16 minor; +    // This is nn::irsensor::detail::StatusManager +    struct StatusManager { +        std::array<Core::IrSensor::DeviceFormat, 9> device; +        std::array<AruidFormat, 5> aruid;      }; -    static_assert(sizeof(PackedMcuVersion) == 4, "PackedMcuVersion is an invalid size"); - -    // This is nn::irsensor::MomentProcessorConfig -    struct MomentProcessorConfig { -        u64 exposire_time; -        u8 light_target; -        u8 gain; -        u8 is_negative_used; -        INSERT_PADDING_BYTES(7); -        IrsRect window_of_interest; -        u8 preprocess; -        u8 preprocess_intensity_threshold; -        INSERT_PADDING_BYTES(5); -    }; -    static_assert(sizeof(MomentProcessorConfig) == 0x28, -                  "MomentProcessorConfig is an invalid size"); - -    // This is nn::irsensor::PackedMomentProcessorConfig -    struct PackedMomentProcessorConfig { -        u64 exposire_time; -        u8 light_target; -        u8 gain; -        u8 is_negative_used; -        INSERT_PADDING_BYTES(5); -        IrsRect window_of_interest; -        PackedMcuVersion required_mcu_version; -        u8 preprocess; -        u8 preprocess_intensity_threshold; -        INSERT_PADDING_BYTES(2); -    }; -    static_assert(sizeof(PackedMomentProcessorConfig) == 0x20, -                  "PackedMomentProcessorConfig is an invalid size"); - -    // This is nn::irsensor::ClusteringProcessorConfig -    struct ClusteringProcessorConfig { -        u64 exposire_time; -        u32 light_target; -        u32 gain; -        u8 is_negative_used; -        INSERT_PADDING_BYTES(7); -        IrsRect window_of_interest; -        u32 pixel_count_min; -        u32 pixel_count_max; -        u32 object_intensity_min; -        u8 is_external_light_filter_enabled; -        INSERT_PADDING_BYTES(3); -    }; -    static_assert(sizeof(ClusteringProcessorConfig) == 0x30, -                  "ClusteringProcessorConfig is an invalid size"); - -    // This is nn::irsensor::PackedClusteringProcessorConfig -    struct PackedClusteringProcessorConfig { -        u64 exposire_time; -        u8 light_target; -        u8 gain; -        u8 is_negative_used; -        INSERT_PADDING_BYTES(5); -        IrsRect window_of_interest; -        PackedMcuVersion required_mcu_version; -        u32 pixel_count_min; -        u32 pixel_count_max; -        u32 object_intensity_min; -        u8 is_external_light_filter_enabled; -        INSERT_PADDING_BYTES(2); -    }; -    static_assert(sizeof(PackedClusteringProcessorConfig) == 0x30, -                  "PackedClusteringProcessorConfig is an invalid size"); - -    // This is nn::irsensor::PackedImageTransferProcessorConfig -    struct PackedImageTransferProcessorConfig { -        u64 exposire_time; -        u8 light_target; -        u8 gain; -        u8 is_negative_used; -        INSERT_PADDING_BYTES(5); -        PackedMcuVersion required_mcu_version; -        u8 format; -        INSERT_PADDING_BYTES(3); -    }; -    static_assert(sizeof(PackedImageTransferProcessorConfig) == 0x18, -                  "PackedImageTransferProcessorConfig is an invalid size"); - -    // This is nn::irsensor::PackedTeraPluginProcessorConfig -    struct PackedTeraPluginProcessorConfig { -        PackedMcuVersion required_mcu_version; -        u8 mode; -        INSERT_PADDING_BYTES(3); -    }; -    static_assert(sizeof(PackedTeraPluginProcessorConfig) == 0x8, -                  "PackedTeraPluginProcessorConfig is an invalid size"); - -    // This is nn::irsensor::PackedPointingProcessorConfig -    struct PackedPointingProcessorConfig { -        IrsRect window_of_interest; -        PackedMcuVersion required_mcu_version; -    }; -    static_assert(sizeof(PackedPointingProcessorConfig) == 0xC, -                  "PackedPointingProcessorConfig is an invalid size"); - -    // This is nn::irsensor::PackedFunctionLevel -    struct PackedFunctionLevel { -        IrSensorFunctionLevel function_level; -        INSERT_PADDING_BYTES(3); -    }; -    static_assert(sizeof(PackedFunctionLevel) == 0x4, "PackedFunctionLevel is an invalid size"); - -    // This is nn::irsensor::PackedImageTransferProcessorExConfig -    struct PackedImageTransferProcessorExConfig { -        u64 exposire_time; -        u8 light_target; -        u8 gain; -        u8 is_negative_used; -        INSERT_PADDING_BYTES(5); -        PackedMcuVersion required_mcu_version; -        ImageTransferProcessorFormat origin_format; -        ImageTransferProcessorFormat trimming_format; -        u16 trimming_start_x; -        u16 trimming_start_y; -        u8 is_external_light_filter_enabled; -        INSERT_PADDING_BYTES(3); -    }; -    static_assert(sizeof(PackedImageTransferProcessorExConfig) == 0x20, -                  "PackedImageTransferProcessorExConfig is an invalid size"); - -    // This is nn::irsensor::PackedIrLedProcessorConfig -    struct PackedIrLedProcessorConfig { -        PackedMcuVersion required_mcu_version; -        u8 light_target; -        INSERT_PADDING_BYTES(3); -    }; -    static_assert(sizeof(PackedIrLedProcessorConfig) == 0x8, -                  "PackedIrLedProcessorConfig is an invalid size"); +    static_assert(sizeof(StatusManager) == 0x8000, "StatusManager is an invalid size");      void ActivateIrsensor(Kernel::HLERequestContext& ctx);      void DeactivateIrsensor(Kernel::HLERequestContext& ctx); @@ -265,6 +56,56 @@ private:      void RunIrLedProcessor(Kernel::HLERequestContext& ctx);      void StopImageProcessorAsync(Kernel::HLERequestContext& ctx);      void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); + +    Result IsIrCameraHandleValid(const Core::IrSensor::IrCameraHandle& camera_handle) const; +    Core::IrSensor::DeviceFormat& GetIrCameraSharedMemoryDeviceEntry( +        const Core::IrSensor::IrCameraHandle& camera_handle); + +    template <typename T> +    void MakeProcessor(const Core::IrSensor::IrCameraHandle& handle, +                       Core::IrSensor::DeviceFormat& device_state) { +        const auto index = static_cast<std::size_t>(handle.npad_id); +        if (index > sizeof(processors)) { +            LOG_CRITICAL(Service_IRS, "Invalid index {}", index); +            return; +        } +        processors[index] = std::make_unique<T>(device_state); +    } + +    template <typename T> +    void MakeProcessorWithCoreContext(const Core::IrSensor::IrCameraHandle& handle, +                                      Core::IrSensor::DeviceFormat& device_state) { +        const auto index = static_cast<std::size_t>(handle.npad_id); +        if (index > sizeof(processors)) { +            LOG_CRITICAL(Service_IRS, "Invalid index {}", index); +            return; +        } +        processors[index] = std::make_unique<T>(system.HIDCore(), device_state, index); +    } + +    template <typename T> +    T& GetProcessor(const Core::IrSensor::IrCameraHandle& handle) { +        const auto index = static_cast<std::size_t>(handle.npad_id); +        if (index > sizeof(processors)) { +            LOG_CRITICAL(Service_IRS, "Invalid index {}", index); +            return static_cast<T&>(*processors[0]); +        } +        return static_cast<T&>(*processors[index]); +    } + +    template <typename T> +    const T& GetProcessor(const Core::IrSensor::IrCameraHandle& handle) const { +        const auto index = static_cast<std::size_t>(handle.npad_id); +        if (index > sizeof(processors)) { +            LOG_CRITICAL(Service_IRS, "Invalid index {}", index); +            return static_cast<T&>(*processors[0]); +        } +        return static_cast<T&>(*processors[index]); +    } + +    Core::HID::EmulatedController* npad_device = nullptr; +    StatusManager* shared_memory = nullptr; +    std::array<std::unique_ptr<ProcessorBase>, 9> processors{};  };  class IRS_SYS final : public ServiceFramework<IRS_SYS> { @@ -273,4 +114,4 @@ public:      ~IRS_SYS() override;  }; -} // namespace Service::HID +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/irsensor/clustering_processor.h" + +namespace Service::IRS { +ClusteringProcessor::ClusteringProcessor(Core::IrSensor::DeviceFormat& device_format) +    : device(device_format) { +    device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor; +    device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; +    device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; +} + +ClusteringProcessor::~ClusteringProcessor() = default; + +void ClusteringProcessor::StartProcessor() {} + +void ClusteringProcessor::SuspendProcessor() {} + +void ClusteringProcessor::StopProcessor() {} + +void ClusteringProcessor::SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config) { +    current_config.camera_config.exposure_time = config.camera_config.exposure_time; +    current_config.camera_config.gain = config.camera_config.gain; +    current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; +    current_config.camera_config.light_target = +        static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); +    current_config.pixel_count_min = config.pixel_count_min; +    current_config.pixel_count_max = config.pixel_count_max; +    current_config.is_external_light_filter_enabled = config.is_external_light_filter_enabled; +    current_config.object_intensity_min = config.object_intensity_min; +} + +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/irs_types.h" +#include "core/hle/service/hid/irsensor/processor_base.h" + +namespace Service::IRS { +class ClusteringProcessor final : public ProcessorBase { +public: +    explicit ClusteringProcessor(Core::IrSensor::DeviceFormat& device_format); +    ~ClusteringProcessor() override; + +    // Called when the processor is initialized +    void StartProcessor() override; + +    // Called when the processor is suspended +    void SuspendProcessor() override; + +    // Called when the processor is stopped +    void StopProcessor() override; + +    // Sets config parameters of the camera +    void SetConfig(Core::IrSensor::PackedClusteringProcessorConfig config); + +private: +    // This is nn::irsensor::ClusteringProcessorConfig +    struct ClusteringProcessorConfig { +        Core::IrSensor::CameraConfig camera_config; +        Core::IrSensor::IrsRect window_of_interest; +        u32 pixel_count_min; +        u32 pixel_count_max; +        u32 object_intensity_min; +        bool is_external_light_filter_enabled; +        INSERT_PADDING_BYTES(3); +    }; +    static_assert(sizeof(ClusteringProcessorConfig) == 0x30, +                  "ClusteringProcessorConfig is an invalid size"); + +    // This is nn::irsensor::AdaptiveClusteringProcessorConfig +    struct AdaptiveClusteringProcessorConfig { +        Core::IrSensor::AdaptiveClusteringMode mode; +        Core::IrSensor::AdaptiveClusteringTargetDistance target_distance; +    }; +    static_assert(sizeof(AdaptiveClusteringProcessorConfig) == 0x8, +                  "AdaptiveClusteringProcessorConfig is an invalid size"); + +    // This is nn::irsensor::ClusteringData +    struct ClusteringData { +        f32 average_intensity; +        Core::IrSensor::IrsCentroid centroid; +        u32 pixel_count; +        Core::IrSensor::IrsRect bound; +    }; +    static_assert(sizeof(ClusteringData) == 0x18, "ClusteringData is an invalid size"); + +    // This is nn::irsensor::ClusteringProcessorState +    struct ClusteringProcessorState { +        s64 sampling_number; +        u64 timestamp; +        u8 object_count; +        INSERT_PADDING_BYTES(3); +        Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; +        std::array<ClusteringData, 0x10> data; +    }; +    static_assert(sizeof(ClusteringProcessorState) == 0x198, +                  "ClusteringProcessorState is an invalid size"); + +    ClusteringProcessorConfig current_config{}; +    Core::IrSensor::DeviceFormat& device; +}; +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" +#include "core/hle/service/hid/irsensor/image_transfer_processor.h" + +namespace Service::IRS { +ImageTransferProcessor::ImageTransferProcessor(Core::HID::HIDCore& hid_core_, +                                               Core::IrSensor::DeviceFormat& device_format, +                                               std::size_t npad_index) +    : device{device_format} { +    npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index); + +    Core::HID::ControllerUpdateCallback engine_callback{ +        .on_change = [this](Core::HID::ControllerTriggerType type) { OnControllerUpdate(type); }, +        .is_npad_service = true, +    }; +    callback_key = npad_device->SetCallback(engine_callback); + +    device.mode = Core::IrSensor::IrSensorMode::ImageTransferProcessor; +    device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; +    device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; +} + +ImageTransferProcessor::~ImageTransferProcessor() { +    npad_device->DeleteCallback(callback_key); +}; + +void ImageTransferProcessor::StartProcessor() { +    is_active = true; +    device.camera_status = Core::IrSensor::IrCameraStatus::Available; +    device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Ready; +    processor_state.sampling_number = 0; +    processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; +} + +void ImageTransferProcessor::SuspendProcessor() {} + +void ImageTransferProcessor::StopProcessor() {} + +void ImageTransferProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) { +    if (type != Core::HID::ControllerTriggerType::IrSensor) { +        return; +    } +    if (!is_transfer_memory_set) { +        return; +    } + +    const auto camera_data = npad_device->GetCamera(); + +    // This indicates how much ambient light is precent +    processor_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; +    processor_state.sampling_number = camera_data.sample; + +    if (camera_data.format != current_config.origin_format) { +        LOG_WARNING(Service_IRS, "Wrong Input format {} expected {}", camera_data.format, +                    current_config.origin_format); +        memset(transfer_memory, 0, GetDataSize(current_config.trimming_format)); +        return; +    } + +    if (current_config.origin_format > current_config.trimming_format) { +        LOG_WARNING(Service_IRS, "Origin format {} is smaller than trimming format {}", +                    current_config.origin_format, current_config.trimming_format); +        memset(transfer_memory, 0, GetDataSize(current_config.trimming_format)); +        return; +    } + +    std::vector<u8> window_data{}; +    const auto origin_width = GetDataWidth(current_config.origin_format); +    const auto origin_height = GetDataHeight(current_config.origin_format); +    const auto trimming_width = GetDataWidth(current_config.trimming_format); +    const auto trimming_height = GetDataHeight(current_config.trimming_format); +    window_data.resize(GetDataSize(current_config.trimming_format)); + +    if (trimming_width + current_config.trimming_start_x > origin_width || +        trimming_height + current_config.trimming_start_y > origin_height) { +        LOG_WARNING(Service_IRS, +                    "Trimming area ({}, {}, {}, {}) is outside of origin area ({}, {})", +                    current_config.trimming_start_x, current_config.trimming_start_y, +                    trimming_width, trimming_height, origin_width, origin_height); +        memset(transfer_memory, 0, GetDataSize(current_config.trimming_format)); +        return; +    } + +    for (std::size_t y = 0; y < trimming_height; y++) { +        for (std::size_t x = 0; x < trimming_width; x++) { +            const std::size_t window_index = (y * trimming_width) + x; +            const std::size_t origin_index = +                ((y + current_config.trimming_start_y) * origin_width) + x + +                current_config.trimming_start_x; +            window_data[window_index] = camera_data.data[origin_index]; +        } +    } + +    memcpy(transfer_memory, window_data.data(), GetDataSize(current_config.trimming_format)); + +    if (!IsProcessorActive()) { +        StartProcessor(); +    } +} + +void ImageTransferProcessor::SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config) { +    current_config.camera_config.exposure_time = config.camera_config.exposure_time; +    current_config.camera_config.gain = config.camera_config.gain; +    current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; +    current_config.camera_config.light_target = +        static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); +    current_config.origin_format = +        static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format); +    current_config.trimming_format = +        static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.format); +    current_config.trimming_start_x = 0; +    current_config.trimming_start_y = 0; + +    npad_device->SetCameraFormat(current_config.origin_format); +} + +void ImageTransferProcessor::SetConfig( +    Core::IrSensor::PackedImageTransferProcessorExConfig config) { +    current_config.camera_config.exposure_time = config.camera_config.exposure_time; +    current_config.camera_config.gain = config.camera_config.gain; +    current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; +    current_config.camera_config.light_target = +        static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); +    current_config.origin_format = +        static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.origin_format); +    current_config.trimming_format = +        static_cast<Core::IrSensor::ImageTransferProcessorFormat>(config.trimming_format); +    current_config.trimming_start_x = config.trimming_start_x; +    current_config.trimming_start_y = config.trimming_start_y; + +    npad_device->SetCameraFormat(current_config.origin_format); +} + +void ImageTransferProcessor::SetTransferMemoryPointer(u8* t_mem) { +    is_transfer_memory_set = true; +    transfer_memory = t_mem; +} + +Core::IrSensor::ImageTransferProcessorState ImageTransferProcessor::GetState( +    std::vector<u8>& data) const { +    const auto size = GetDataSize(current_config.trimming_format); +    data.resize(size); +    memcpy(data.data(), transfer_memory, size); +    return processor_state; +} + +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/irs_types.h" +#include "core/hle/service/hid/irsensor/processor_base.h" + +namespace Core::HID { +class EmulatedController; +} // namespace Core::HID + +namespace Service::IRS { +class ImageTransferProcessor final : public ProcessorBase { +public: +    explicit ImageTransferProcessor(Core::HID::HIDCore& hid_core_, +                                    Core::IrSensor::DeviceFormat& device_format, +                                    std::size_t npad_index); +    ~ImageTransferProcessor() override; + +    // Called when the processor is initialized +    void StartProcessor() override; + +    // Called when the processor is suspended +    void SuspendProcessor() override; + +    // Called when the processor is stopped +    void StopProcessor() override; + +    // Sets config parameters of the camera +    void SetConfig(Core::IrSensor::PackedImageTransferProcessorConfig config); +    void SetConfig(Core::IrSensor::PackedImageTransferProcessorExConfig config); + +    // Transfer memory where the image data will be stored +    void SetTransferMemoryPointer(u8* t_mem); + +    Core::IrSensor::ImageTransferProcessorState GetState(std::vector<u8>& data) const; + +private: +    // This is nn::irsensor::ImageTransferProcessorConfig +    struct ImageTransferProcessorConfig { +        Core::IrSensor::CameraConfig camera_config; +        Core::IrSensor::ImageTransferProcessorFormat format; +    }; +    static_assert(sizeof(ImageTransferProcessorConfig) == 0x20, +                  "ImageTransferProcessorConfig is an invalid size"); + +    // This is nn::irsensor::ImageTransferProcessorExConfig +    struct ImageTransferProcessorExConfig { +        Core::IrSensor::CameraConfig camera_config; +        Core::IrSensor::ImageTransferProcessorFormat origin_format; +        Core::IrSensor::ImageTransferProcessorFormat trimming_format; +        u16 trimming_start_x; +        u16 trimming_start_y; +        bool is_external_light_filter_enabled; +        INSERT_PADDING_BYTES(3); +    }; +    static_assert(sizeof(ImageTransferProcessorExConfig) == 0x28, +                  "ImageTransferProcessorExConfig is an invalid size"); + +    void OnControllerUpdate(Core::HID::ControllerTriggerType type); + +    ImageTransferProcessorExConfig current_config{}; +    Core::IrSensor::ImageTransferProcessorState processor_state{}; +    Core::IrSensor::DeviceFormat& device; +    Core::HID::EmulatedController* npad_device; +    int callback_key{}; + +    u8* transfer_memory = nullptr; +    bool is_transfer_memory_set = false; +}; +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/irsensor/ir_led_processor.h" + +namespace Service::IRS { +IrLedProcessor::IrLedProcessor(Core::IrSensor::DeviceFormat& device_format) +    : device(device_format) { +    device.mode = Core::IrSensor::IrSensorMode::IrLedProcessor; +    device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; +    device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; +} + +IrLedProcessor::~IrLedProcessor() = default; + +void IrLedProcessor::StartProcessor() {} + +void IrLedProcessor::SuspendProcessor() {} + +void IrLedProcessor::StopProcessor() {} + +void IrLedProcessor::SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config) { +    current_config.light_target = +        static_cast<Core::IrSensor::CameraLightTarget>(config.light_target); +} + +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/bit_field.h" +#include "common/common_types.h" +#include "core/hid/irs_types.h" +#include "core/hle/service/hid/irsensor/processor_base.h" + +namespace Service::IRS { +class IrLedProcessor final : public ProcessorBase { +public: +    explicit IrLedProcessor(Core::IrSensor::DeviceFormat& device_format); +    ~IrLedProcessor() override; + +    // Called when the processor is initialized +    void StartProcessor() override; + +    // Called when the processor is suspended +    void SuspendProcessor() override; + +    // Called when the processor is stopped +    void StopProcessor() override; + +    // Sets config parameters of the camera +    void SetConfig(Core::IrSensor::PackedIrLedProcessorConfig config); + +private: +    // This is nn::irsensor::IrLedProcessorConfig +    struct IrLedProcessorConfig { +        Core::IrSensor::CameraLightTarget light_target; +    }; +    static_assert(sizeof(IrLedProcessorConfig) == 0x4, "IrLedProcessorConfig is an invalid size"); + +    struct IrLedProcessorState { +        s64 sampling_number; +        u64 timestamp; +        std::array<u8, 0x8> data; +    }; +    static_assert(sizeof(IrLedProcessorState) == 0x18, "IrLedProcessorState is an invalid size"); + +    IrLedProcessorConfig current_config{}; +    Core::IrSensor::DeviceFormat& device; +}; + +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/irsensor/moment_processor.h" + +namespace Service::IRS { +MomentProcessor::MomentProcessor(Core::IrSensor::DeviceFormat& device_format) +    : device(device_format) { +    device.mode = Core::IrSensor::IrSensorMode::MomentProcessor; +    device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; +    device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; +} + +MomentProcessor::~MomentProcessor() = default; + +void MomentProcessor::StartProcessor() {} + +void MomentProcessor::SuspendProcessor() {} + +void MomentProcessor::StopProcessor() {} + +void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig config) { +    current_config.camera_config.exposure_time = config.camera_config.exposure_time; +    current_config.camera_config.gain = config.camera_config.gain; +    current_config.camera_config.is_negative_used = config.camera_config.is_negative_used; +    current_config.camera_config.light_target = +        static_cast<Core::IrSensor::CameraLightTarget>(config.camera_config.light_target); +    current_config.window_of_interest = config.window_of_interest; +    current_config.preprocess = +        static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess); +    current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold; +} + +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/bit_field.h" +#include "common/common_types.h" +#include "core/hid/irs_types.h" +#include "core/hle/service/hid/irsensor/processor_base.h" + +namespace Service::IRS { +class MomentProcessor final : public ProcessorBase { +public: +    explicit MomentProcessor(Core::IrSensor::DeviceFormat& device_format); +    ~MomentProcessor() override; + +    // Called when the processor is initialized +    void StartProcessor() override; + +    // Called when the processor is suspended +    void SuspendProcessor() override; + +    // Called when the processor is stopped +    void StopProcessor() override; + +    // Sets config parameters of the camera +    void SetConfig(Core::IrSensor::PackedMomentProcessorConfig config); + +private: +    // This is nn::irsensor::MomentProcessorConfig +    struct MomentProcessorConfig { +        Core::IrSensor::CameraConfig camera_config; +        Core::IrSensor::IrsRect window_of_interest; +        Core::IrSensor::MomentProcessorPreprocess preprocess; +        u32 preprocess_intensity_threshold; +    }; +    static_assert(sizeof(MomentProcessorConfig) == 0x28, +                  "MomentProcessorConfig is an invalid size"); + +    // This is nn::irsensor::MomentStatistic +    struct MomentStatistic { +        f32 average_intensity; +        Core::IrSensor::IrsCentroid centroid; +    }; +    static_assert(sizeof(MomentStatistic) == 0xC, "MomentStatistic is an invalid size"); + +    // This is nn::irsensor::MomentProcessorState +    struct MomentProcessorState { +        s64 sampling_number; +        u64 timestamp; +        Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; +        INSERT_PADDING_BYTES(4); +        std::array<MomentStatistic, 0x30> stadistic; +    }; +    static_assert(sizeof(MomentProcessorState) == 0x258, "MomentProcessorState is an invalid size"); + +    MomentProcessorConfig current_config{}; +    Core::IrSensor::DeviceFormat& device; +}; + +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/irsensor/pointing_processor.h" + +namespace Service::IRS { +PointingProcessor::PointingProcessor(Core::IrSensor::DeviceFormat& device_format) +    : device(device_format) { +    device.mode = Core::IrSensor::IrSensorMode::PointingProcessorMarker; +    device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; +    device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; +} + +PointingProcessor::~PointingProcessor() = default; + +void PointingProcessor::StartProcessor() {} + +void PointingProcessor::SuspendProcessor() {} + +void PointingProcessor::StopProcessor() {} + +void PointingProcessor::SetConfig(Core::IrSensor::PackedPointingProcessorConfig config) { +    current_config.window_of_interest = config.window_of_interest; +} + +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/irs_types.h" +#include "core/hle/service/hid/irsensor/processor_base.h" + +namespace Service::IRS { +class PointingProcessor final : public ProcessorBase { +public: +    explicit PointingProcessor(Core::IrSensor::DeviceFormat& device_format); +    ~PointingProcessor() override; + +    // Called when the processor is initialized +    void StartProcessor() override; + +    // Called when the processor is suspended +    void SuspendProcessor() override; + +    // Called when the processor is stopped +    void StopProcessor() override; + +    // Sets config parameters of the camera +    void SetConfig(Core::IrSensor::PackedPointingProcessorConfig config); + +private: +    // This is nn::irsensor::PointingProcessorConfig +    struct PointingProcessorConfig { +        Core::IrSensor::IrsRect window_of_interest; +    }; +    static_assert(sizeof(PointingProcessorConfig) == 0x8, +                  "PointingProcessorConfig is an invalid size"); + +    struct PointingProcessorMarkerData { +        u8 pointing_status; +        INSERT_PADDING_BYTES(3); +        u32 unknown; +        float unkown_float1; +        float position_x; +        float position_y; +        float unkown_float2; +        Core::IrSensor::IrsRect window_of_interest; +    }; +    static_assert(sizeof(PointingProcessorMarkerData) == 0x20, +                  "PointingProcessorMarkerData is an invalid size"); + +    struct PointingProcessorMarkerState { +        s64 sampling_number; +        u64 timestamp; +        std::array<PointingProcessorMarkerData, 0x3> data; +    }; +    static_assert(sizeof(PointingProcessorMarkerState) == 0x70, +                  "PointingProcessorMarkerState is an invalid size"); + +    PointingProcessorConfig current_config{}; +    Core::IrSensor::DeviceFormat& device; +}; + +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/irsensor/processor_base.h" + +namespace Service::IRS { + +ProcessorBase::ProcessorBase() {} +ProcessorBase::~ProcessorBase() = default; + +bool ProcessorBase::IsProcessorActive() const { +    return is_active; +} + +std::size_t ProcessorBase::GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const { +    switch (format) { +    case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: +        return 320 * 240; +    case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: +        return 160 * 120; +    case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: +        return 80 * 60; +    case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: +        return 40 * 30; +    case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: +        return 20 * 15; +    default: +        return 0; +    } +} + +std::size_t ProcessorBase::GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const { +    switch (format) { +    case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: +        return 320; +    case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: +        return 160; +    case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: +        return 80; +    case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: +        return 40; +    case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: +        return 20; +    default: +        return 0; +    } +} + +std::size_t ProcessorBase::GetDataHeight( +    Core::IrSensor::ImageTransferProcessorFormat format) const { +    switch (format) { +    case Core::IrSensor::ImageTransferProcessorFormat::Size320x240: +        return 240; +    case Core::IrSensor::ImageTransferProcessorFormat::Size160x120: +        return 120; +    case Core::IrSensor::ImageTransferProcessorFormat::Size80x60: +        return 60; +    case Core::IrSensor::ImageTransferProcessorFormat::Size40x30: +        return 30; +    case Core::IrSensor::ImageTransferProcessorFormat::Size20x15: +        return 15; +    default: +        return 0; +    } +} + +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/common_types.h" +#include "core/hid/irs_types.h" + +namespace Service::IRS { +class ProcessorBase { +public: +    explicit ProcessorBase(); +    virtual ~ProcessorBase(); + +    virtual void StartProcessor() = 0; +    virtual void SuspendProcessor() = 0; +    virtual void StopProcessor() = 0; + +    bool IsProcessorActive() const; + +protected: +    /// Returns the number of bytes the image uses +    std::size_t GetDataSize(Core::IrSensor::ImageTransferProcessorFormat format) const; + +    /// Returns the width of the image +    std::size_t GetDataWidth(Core::IrSensor::ImageTransferProcessorFormat format) const; + +    /// Returns the height of the image +    std::size_t GetDataHeight(Core::IrSensor::ImageTransferProcessorFormat format) const; + +    bool is_active{false}; +}; +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "core/hle/service/hid/irsensor/tera_plugin_processor.h" + +namespace Service::IRS { +TeraPluginProcessor::TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format) +    : device(device_format) { +    device.mode = Core::IrSensor::IrSensorMode::TeraPluginProcessor; +    device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; +    device.camera_internal_status = Core::IrSensor::IrCameraInternalStatus::Stopped; +} + +TeraPluginProcessor::~TeraPluginProcessor() = default; + +void TeraPluginProcessor::StartProcessor() {} + +void TeraPluginProcessor::SuspendProcessor() {} + +void TeraPluginProcessor::StopProcessor() {} + +void TeraPluginProcessor::SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config) { +    current_config.mode = config.mode; +    current_config.unknown_1 = config.unknown_1; +    current_config.unknown_2 = config.unknown_2; +    current_config.unknown_3 = config.unknown_3; +} + +} // 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 @@ +// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/bit_field.h" +#include "common/common_types.h" +#include "core/hid/irs_types.h" +#include "core/hle/service/hid/irsensor/processor_base.h" + +namespace Service::IRS { +class TeraPluginProcessor final : public ProcessorBase { +public: +    explicit TeraPluginProcessor(Core::IrSensor::DeviceFormat& device_format); +    ~TeraPluginProcessor() override; + +    // Called when the processor is initialized +    void StartProcessor() override; + +    // Called when the processor is suspended +    void SuspendProcessor() override; + +    // Called when the processor is stopped +    void StopProcessor() override; + +    // Sets config parameters of the camera +    void SetConfig(Core::IrSensor::PackedTeraPluginProcessorConfig config); + +private: +    // This is nn::irsensor::TeraPluginProcessorConfig +    struct TeraPluginProcessorConfig { +        u8 mode; +        u8 unknown_1; +        u8 unknown_2; +        u8 unknown_3; +    }; +    static_assert(sizeof(TeraPluginProcessorConfig) == 0x4, +                  "TeraPluginProcessorConfig is an invalid size"); + +    struct TeraPluginProcessorState { +        s64 sampling_number; +        u64 timestamp; +        Core::IrSensor::CameraAmbientNoiseLevel ambient_noise_level; +        std::array<u8, 0x12c> data; +    }; +    static_assert(sizeof(TeraPluginProcessorState) == 0x140, +                  "TeraPluginProcessorState is an invalid size"); + +    TeraPluginProcessorConfig current_config{}; +    Core::IrSensor::DeviceFormat& device; +}; + +} // namespace Service::IRS | 
