service: irs: Split processors and implement ImageTransferProcessor
This commit is contained in:
parent
57311b2c8b
commit
4539700595
18 changed files with 1090 additions and 290 deletions
|
@ -478,6 +478,20 @@ add_library(core STATIC
|
||||||
hle/service/hid/hidbus/starlink.h
|
hle/service/hid/hidbus/starlink.h
|
||||||
hle/service/hid/hidbus/stubbed.cpp
|
hle/service/hid/hidbus/stubbed.cpp
|
||||||
hle/service/hid/hidbus/stubbed.h
|
hle/service/hid/hidbus/stubbed.h
|
||||||
|
hle/service/hid/irsensor/clustering_processor.cpp
|
||||||
|
hle/service/hid/irsensor/clustering_processor.h
|
||||||
|
hle/service/hid/irsensor/image_transfer_processor.cpp
|
||||||
|
hle/service/hid/irsensor/image_transfer_processor.h
|
||||||
|
hle/service/hid/irsensor/ir_led_processor.cpp
|
||||||
|
hle/service/hid/irsensor/ir_led_processor.h
|
||||||
|
hle/service/hid/irsensor/moment_processor.cpp
|
||||||
|
hle/service/hid/irsensor/moment_processor.h
|
||||||
|
hle/service/hid/irsensor/pointing_processor.cpp
|
||||||
|
hle/service/hid/irsensor/pointing_processor.h
|
||||||
|
hle/service/hid/irsensor/processor_base.cpp
|
||||||
|
hle/service/hid/irsensor/processor_base.h
|
||||||
|
hle/service/hid/irsensor/tera_plugin_processor.cpp
|
||||||
|
hle/service/hid/irsensor/tera_plugin_processor.h
|
||||||
hle/service/jit/jit_context.cpp
|
hle/service/jit/jit_context.cpp
|
||||||
hle/service/jit/jit_context.h
|
hle/service/jit/jit_context.h
|
||||||
hle/service/jit/jit.cpp
|
hle/service/jit/jit.cpp
|
||||||
|
|
|
@ -18,4 +18,7 @@ constexpr Result NpadIsSameType{ErrorModule::HID, 602};
|
||||||
constexpr Result InvalidNpadId{ErrorModule::HID, 709};
|
constexpr Result InvalidNpadId{ErrorModule::HID, 709};
|
||||||
constexpr Result NpadNotConnected{ErrorModule::HID, 710};
|
constexpr Result NpadNotConnected{ErrorModule::HID, 710};
|
||||||
|
|
||||||
|
constexpr ResultCode InvalidProcessorState{ErrorModule::Irsensor, 78};
|
||||||
|
constexpr ResultCode InvalidIrCameraHandle{ErrorModule::Irsensor, 204};
|
||||||
|
|
||||||
} // namespace Service::HID
|
} // namespace Service::HID
|
||||||
|
|
|
@ -1,14 +1,26 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.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/ipc_helpers.h"
|
||||||
#include "core/hle/kernel/k_shared_memory.h"
|
#include "core/hle/kernel/k_shared_memory.h"
|
||||||
#include "core/hle/kernel/k_transfer_memory.h"
|
#include "core/hle/kernel/k_transfer_memory.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/service/hid/errors.h"
|
#include "core/hle/service/hid/errors.h"
|
||||||
#include "core/hle/service/hid/irs.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::HID {
|
||||||
|
|
||||||
|
@ -36,8 +48,13 @@ IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} {
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
u8* raw_shared_memory = system.Kernel().GetIrsSharedMem().GetPointer();
|
||||||
RegisterHandlers(functions);
|
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) {
|
void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
@ -75,7 +92,7 @@ void IRS::GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
|
||||||
void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) {
|
void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
IrCameraHandle camera_handle;
|
Core::IrSensor::IrCameraHandle camera_handle;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
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.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
||||||
parameters.applet_resource_user_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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) {
|
void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
IrCameraHandle camera_handle;
|
Core::IrSensor::IrCameraHandle camera_handle;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
u64 applet_resource_user_id;
|
||||||
PackedMomentProcessorConfig processor_config;
|
Core::IrSensor::PackedMomentProcessorConfig processor_config;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size.");
|
static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size.");
|
||||||
|
|
||||||
|
@ -109,17 +132,26 @@ void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
||||||
parameters.applet_resource_user_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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) {
|
void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
IrCameraHandle camera_handle;
|
Core::IrSensor::IrCameraHandle camera_handle;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
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) == 0x40, "Parameters has incorrect size.");
|
||||||
|
|
||||||
|
@ -130,17 +162,27 @@ void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
||||||
parameters.applet_resource_user_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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) {
|
void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
IrCameraHandle camera_handle;
|
Core::IrSensor::IrCameraHandle camera_handle;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
u64 applet_resource_user_id;
|
||||||
PackedImageTransferProcessorConfig processor_config;
|
Core::IrSensor::PackedImageTransferProcessorConfig processor_config;
|
||||||
u32 transfer_memory_size;
|
u32 transfer_memory_size;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size.");
|
static_assert(sizeof(Parameters) == 0x30, "Parameters has incorrect size.");
|
||||||
|
@ -151,20 +193,42 @@ void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
auto t_mem =
|
auto t_mem =
|
||||||
system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle);
|
system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle);
|
||||||
|
|
||||||
LOG_WARNING(Service_IRS,
|
if (t_mem.IsNull()) {
|
||||||
"(STUBBED) called, npad_type={}, npad_id={}, transfer_memory_size={}, "
|
LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle);
|
||||||
"applet_resource_user_id={}",
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
rb.Push(ResultUnknown);
|
||||||
parameters.transfer_memory_size, parameters.applet_resource_user_id);
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) {
|
void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
IrCameraHandle camera_handle;
|
Core::IrSensor::IrCameraHandle camera_handle;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
u64 applet_resource_user_id;
|
||||||
};
|
};
|
||||||
|
@ -172,21 +236,40 @@ void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
const auto parameters{rp.PopRaw<Parameters>()};
|
const auto parameters{rp.PopRaw<Parameters>()};
|
||||||
|
|
||||||
LOG_WARNING(Service_IRS,
|
LOG_DEBUG(Service_IRS, "(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
|
||||||
"(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
|
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
||||||
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
parameters.applet_resource_user_id);
|
||||||
parameters.applet_resource_user_id);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 5};
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.Push(ResultSuccess);
|
||||||
rb.PushRaw<u64>(system.CoreTiming().GetCPUTicks());
|
rb.PushRaw(state);
|
||||||
rb.PushRaw<u32>(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) {
|
void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto camera_handle{rp.PopRaw<IrCameraHandle>()};
|
const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
|
||||||
const auto processor_config{rp.PopRaw<PackedTeraPluginProcessorConfig>()};
|
const auto processor_config{rp.PopRaw<Core::IrSensor::PackedTeraPluginProcessorConfig>()};
|
||||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||||
|
|
||||||
LOG_WARNING(Service_IRS,
|
LOG_WARNING(Service_IRS,
|
||||||
|
@ -196,8 +279,17 @@ void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
processor_config.required_mcu_version.major,
|
processor_config.required_mcu_version.major,
|
||||||
processor_config.required_mcu_version.minor, applet_resource_user_id);
|
processor_config.required_mcu_version.minor, applet_resource_user_id);
|
||||||
|
|
||||||
|
const auto result = IsIrCameraHandleValid(camera_handle);
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
auto& device = GetIrCameraSharedMemoryDeviceEntry(camera_handle);
|
||||||
|
MakeProcessor<TeraPluginProcessor>(camera_handle, device);
|
||||||
|
auto& image_transfer_processor = GetProcessor<TeraPluginProcessor>(camera_handle);
|
||||||
|
image_transfer_processor.SetConfig(processor_config);
|
||||||
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) {
|
void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -211,13 +303,13 @@ void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IrCameraHandle camera_handle{
|
Core::IrSensor::IrCameraHandle camera_handle{
|
||||||
.npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)),
|
.npad_id = static_cast<u8>(NpadIdTypeToIndex(npad_id)),
|
||||||
.npad_type = Core::HID::NpadStyleIndex::None,
|
.npad_type = Core::HID::NpadStyleIndex::None,
|
||||||
};
|
};
|
||||||
|
|
||||||
LOG_WARNING(Service_IRS, "(STUBBED) called, npad_id={}, camera_npad_id={}, camera_npad_type={}",
|
LOG_INFO(Service_IRS, "called, npad_id={}, camera_npad_id={}, camera_npad_type={}", npad_id,
|
||||||
npad_id, camera_handle.npad_id, camera_handle.npad_type);
|
camera_handle.npad_id, camera_handle.npad_type);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -226,8 +318,8 @@ void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) {
|
||||||
|
|
||||||
void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) {
|
void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto camera_handle{rp.PopRaw<IrCameraHandle>()};
|
const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
|
||||||
const auto processor_config{rp.PopRaw<PackedPointingProcessorConfig>()};
|
const auto processor_config{rp.PopRaw<Core::IrSensor::PackedPointingProcessorConfig>()};
|
||||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||||
|
|
||||||
LOG_WARNING(
|
LOG_WARNING(
|
||||||
|
@ -236,14 +328,23 @@ void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
camera_handle.npad_type, camera_handle.npad_id, processor_config.required_mcu_version.major,
|
camera_handle.npad_type, camera_handle.npad_id, processor_config.required_mcu_version.major,
|
||||||
processor_config.required_mcu_version.minor, applet_resource_user_id);
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) {
|
void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
IrCameraHandle camera_handle;
|
Core::IrSensor::IrCameraHandle camera_handle;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
u64 applet_resource_user_id;
|
||||||
};
|
};
|
||||||
|
@ -256,14 +357,20 @@ void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
||||||
parameters.applet_resource_user_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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) {
|
void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto camera_handle{rp.PopRaw<IrCameraHandle>()};
|
const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
|
||||||
const auto mcu_version{rp.PopRaw<PackedMcuVersion>()};
|
const auto mcu_version{rp.PopRaw<Core::IrSensor::PackedMcuVersion>()};
|
||||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||||
|
|
||||||
LOG_WARNING(
|
LOG_WARNING(
|
||||||
|
@ -272,37 +379,45 @@ void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) {
|
||||||
camera_handle.npad_type, camera_handle.npad_id, applet_resource_user_id, mcu_version.major,
|
camera_handle.npad_type, camera_handle.npad_id, applet_resource_user_id, mcu_version.major,
|
||||||
mcu_version.minor);
|
mcu_version.minor);
|
||||||
|
|
||||||
|
auto result = IsIrCameraHandleValid(camera_handle);
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
// TODO: Check firmware version
|
||||||
|
result = ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) {
|
void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
struct Parameters {
|
const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
|
||||||
IrCameraHandle camera_handle;
|
const auto function_level{rp.PopRaw<Core::IrSensor::PackedFunctionLevel>()};
|
||||||
PackedFunctionLevel function_level;
|
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||||
u64 applet_resource_user_id;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
|
|
||||||
|
|
||||||
const auto parameters{rp.PopRaw<Parameters>()};
|
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);
|
||||||
|
|
||||||
LOG_WARNING(Service_IRS,
|
auto result = IsIrCameraHandleValid(camera_handle);
|
||||||
"(STUBBED) called, npad_type={}, npad_id={}, applet_resource_user_id={}",
|
if (result.IsSuccess()) {
|
||||||
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
// TODO: Set Function level
|
||||||
parameters.applet_resource_user_id);
|
result = ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) {
|
void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
IrCameraHandle camera_handle;
|
Core::IrSensor::IrCameraHandle camera_handle;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
u64 applet_resource_user_id;
|
||||||
PackedImageTransferProcessorExConfig processor_config;
|
Core::IrSensor::PackedImageTransferProcessorExConfig processor_config;
|
||||||
u64 transfer_memory_size;
|
u64 transfer_memory_size;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Parameters) == 0x38, "Parameters has incorrect size.");
|
static_assert(sizeof(Parameters) == 0x38, "Parameters has incorrect size.");
|
||||||
|
@ -313,20 +428,33 @@ void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
auto t_mem =
|
auto t_mem =
|
||||||
system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle);
|
system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(t_mem_handle);
|
||||||
|
|
||||||
LOG_WARNING(Service_IRS,
|
u8* transfer_memory = system.Memory().GetPointer(t_mem->GetSourceAddress());
|
||||||
"(STUBBED) called, npad_type={}, npad_id={}, transfer_memory_size={}, "
|
|
||||||
"applet_resource_user_id={}",
|
LOG_INFO(Service_IRS,
|
||||||
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
"called, npad_type={}, npad_id={}, transfer_memory_size={}, "
|
||||||
parameters.transfer_memory_size, parameters.applet_resource_user_id);
|
"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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) {
|
void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto camera_handle{rp.PopRaw<IrCameraHandle>()};
|
const auto camera_handle{rp.PopRaw<Core::IrSensor::IrCameraHandle>()};
|
||||||
const auto processor_config{rp.PopRaw<PackedIrLedProcessorConfig>()};
|
const auto processor_config{rp.PopRaw<Core::IrSensor::PackedIrLedProcessorConfig>()};
|
||||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||||
|
|
||||||
LOG_WARNING(Service_IRS,
|
LOG_WARNING(Service_IRS,
|
||||||
|
@ -336,14 +464,23 @@ void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) {
|
||||||
processor_config.required_mcu_version.major,
|
processor_config.required_mcu_version.major,
|
||||||
processor_config.required_mcu_version.minor, applet_resource_user_id);
|
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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) {
|
void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
IrCameraHandle camera_handle;
|
Core::IrSensor::IrCameraHandle camera_handle;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
u64 applet_resource_user_id;
|
||||||
};
|
};
|
||||||
|
@ -356,14 +493,20 @@ void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) {
|
||||||
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
parameters.camera_handle.npad_type, parameters.camera_handle.npad_id,
|
||||||
parameters.applet_resource_user_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};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) {
|
void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
PackedFunctionLevel function_level;
|
Core::IrSensor::PackedFunctionLevel function_level;
|
||||||
INSERT_PADDING_WORDS_NOINIT(1);
|
INSERT_PADDING_WORDS_NOINIT(1);
|
||||||
u64 applet_resource_user_id;
|
u64 applet_resource_user_id;
|
||||||
};
|
};
|
||||||
|
@ -378,7 +521,22 @@ void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) {
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
IRS::~IRS() = default;
|
ResultCode 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"} {
|
IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
|
@ -4,12 +4,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hid/hid_types.h"
|
#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"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Core::HID {
|
||||||
|
class EmulatedController;
|
||||||
|
} // namespace Core::HID
|
||||||
|
|
||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
|
|
||||||
class IRS final : public ServiceFramework<IRS> {
|
class IRS final : public ServiceFramework<IRS> {
|
||||||
|
@ -18,234 +24,19 @@ public:
|
||||||
~IRS() override;
|
~IRS() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This is nn::irsensor::IrCameraStatus
|
// This is nn::irsensor::detail::AruidFormat
|
||||||
enum IrCameraStatus : u32 {
|
struct AruidFormat {
|
||||||
Available,
|
u64 sensor_aruid;
|
||||||
Unsupported,
|
u64 sensor_aruid_status;
|
||||||
Unconnected,
|
|
||||||
};
|
};
|
||||||
|
static_assert(sizeof(AruidFormat) == 0x10, "AruidFormat is an invalid size");
|
||||||
|
|
||||||
// This is nn::irsensor::IrCameraInternalStatus
|
// This is nn::irsensor::detail::StatusManager
|
||||||
enum IrCameraInternalStatus : u32 {
|
struct StatusManager {
|
||||||
Stopped,
|
std::array<Core::IrSensor::DeviceFormat, 9> device;
|
||||||
FirmwareUpdateNeeded,
|
std::array<AruidFormat, 5> aruid;
|
||||||
Unkown2,
|
|
||||||
Unkown3,
|
|
||||||
Unkown4,
|
|
||||||
FirmwareVersionRequested,
|
|
||||||
FirmwareVersionIsInvalid,
|
|
||||||
Ready,
|
|
||||||
Setting,
|
|
||||||
};
|
};
|
||||||
|
static_assert(sizeof(StatusManager) == 0x8000, "StatusManager is an invalid size");
|
||||||
// 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::PackedMcuVersion
|
|
||||||
struct PackedMcuVersion {
|
|
||||||
u16 major;
|
|
||||||
u16 minor;
|
|
||||||
};
|
|
||||||
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");
|
|
||||||
|
|
||||||
void ActivateIrsensor(Kernel::HLERequestContext& ctx);
|
void ActivateIrsensor(Kernel::HLERequestContext& ctx);
|
||||||
void DeactivateIrsensor(Kernel::HLERequestContext& ctx);
|
void DeactivateIrsensor(Kernel::HLERequestContext& ctx);
|
||||||
|
@ -265,6 +56,56 @@ private:
|
||||||
void RunIrLedProcessor(Kernel::HLERequestContext& ctx);
|
void RunIrLedProcessor(Kernel::HLERequestContext& ctx);
|
||||||
void StopImageProcessorAsync(Kernel::HLERequestContext& ctx);
|
void StopImageProcessorAsync(Kernel::HLERequestContext& ctx);
|
||||||
void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx);
|
void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
ResultCode 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> {
|
class IRS_SYS final : public ServiceFramework<IRS_SYS> {
|
||||||
|
|
36
src/core/hle/service/hid/irsensor/clustering_processor.cpp
Normal file
36
src/core/hle/service/hid/irsensor/clustering_processor.cpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// 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::HID {
|
||||||
|
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;
|
||||||
|
device.state.start = 0;
|
||||||
|
device.state.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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::HID
|
74
src/core/hle/service/hid/irsensor/clustering_processor.h
Normal file
74
src/core/hle/service/hid/irsensor/clustering_processor.h
Normal file
|
@ -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::HID {
|
||||||
|
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::HID
|
154
src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
Normal file
154
src/core/hle/service/hid/irsensor/image_transfer_processor.cpp
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
// 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::HID {
|
||||||
|
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;
|
||||||
|
device.state.start = 0;
|
||||||
|
device.state.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
device.state.start = 0;
|
||||||
|
device.state.count = 1;
|
||||||
|
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::HID
|
73
src/core/hle/service/hid/irsensor/image_transfer_processor.h
Normal file
73
src/core/hle/service/hid/irsensor/image_transfer_processor.h
Normal file
|
@ -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::HID {
|
||||||
|
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::HID
|
29
src/core/hle/service/hid/irsensor/ir_led_processor.cpp
Normal file
29
src/core/hle/service/hid/irsensor/ir_led_processor.cpp
Normal file
|
@ -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/ir_led_processor.h"
|
||||||
|
|
||||||
|
namespace Service::HID {
|
||||||
|
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;
|
||||||
|
device.state.start = 0;
|
||||||
|
device.state.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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::HID
|
47
src/core/hle/service/hid/irsensor/ir_led_processor.h
Normal file
47
src/core/hle/service/hid/irsensor/ir_led_processor.h
Normal file
|
@ -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::HID {
|
||||||
|
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::HID
|
36
src/core/hle/service/hid/irsensor/moment_processor.cpp
Normal file
36
src/core/hle/service/hid/irsensor/moment_processor.cpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// 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::HID {
|
||||||
|
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;
|
||||||
|
device.state.start = 0;
|
||||||
|
device.state.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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::HID
|
61
src/core/hle/service/hid/irsensor/moment_processor.h
Normal file
61
src/core/hle/service/hid/irsensor/moment_processor.h
Normal file
|
@ -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::HID {
|
||||||
|
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::HID
|
28
src/core/hle/service/hid/irsensor/pointing_processor.cpp
Normal file
28
src/core/hle/service/hid/irsensor/pointing_processor.cpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// 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::HID {
|
||||||
|
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;
|
||||||
|
device.state.start = 0;
|
||||||
|
device.state.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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::HID
|
62
src/core/hle/service/hid/irsensor/pointing_processor.h
Normal file
62
src/core/hle/service/hid/irsensor/pointing_processor.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// 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::HID {
|
||||||
|
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::HID
|
67
src/core/hle/service/hid/irsensor/processor_base.cpp
Normal file
67
src/core/hle/service/hid/irsensor/processor_base.cpp
Normal file
|
@ -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::HID {
|
||||||
|
|
||||||
|
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::HID
|
33
src/core/hle/service/hid/irsensor/processor_base.h
Normal file
33
src/core/hle/service/hid/irsensor/processor_base.h
Normal file
|
@ -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::HID {
|
||||||
|
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::HID
|
31
src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp
Normal file
31
src/core/hle/service/hid/irsensor/tera_plugin_processor.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// 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::HID {
|
||||||
|
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;
|
||||||
|
device.state.start = 0;
|
||||||
|
device.state.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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::HID
|
53
src/core/hle/service/hid/irsensor/tera_plugin_processor.h
Normal file
53
src/core/hle/service/hid/irsensor/tera_plugin_processor.h
Normal file
|
@ -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::HID {
|
||||||
|
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::HID
|
Loading…
Reference in a new issue