mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	Merge pull request #9492 from german77/joycon_release
Input_common: Implement custom joycon driver v2
This commit is contained in:
		@@ -2,6 +2,7 @@
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <common/scope_exit.h>
 | 
			
		||||
 | 
			
		||||
#include "common/polyfill_ranges.h"
 | 
			
		||||
#include "common/thread.h"
 | 
			
		||||
@@ -94,6 +95,7 @@ void EmulatedController::ReloadFromSettings() {
 | 
			
		||||
        motion_params[index] = Common::ParamPackage(player.motions[index]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    controller.color_values = {};
 | 
			
		||||
    controller.colors_state.fullkey = {
 | 
			
		||||
        .body = GetNpadColor(player.body_color_left),
 | 
			
		||||
        .button = GetNpadColor(player.button_color_left),
 | 
			
		||||
@@ -107,6 +109,8 @@ void EmulatedController::ReloadFromSettings() {
 | 
			
		||||
        .button = GetNpadColor(player.button_color_right),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ring_params[0] = Common::ParamPackage(Settings::values.ringcon_analogs);
 | 
			
		||||
 | 
			
		||||
    // Other or debug controller should always be a pro controller
 | 
			
		||||
    if (npad_id_type != NpadIdType::Other) {
 | 
			
		||||
        SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type));
 | 
			
		||||
@@ -133,18 +137,28 @@ void EmulatedController::LoadDevices() {
 | 
			
		||||
    trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL];
 | 
			
		||||
    trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR];
 | 
			
		||||
 | 
			
		||||
    color_params[LeftIndex] = left_joycon;
 | 
			
		||||
    color_params[RightIndex] = right_joycon;
 | 
			
		||||
    color_params[LeftIndex].Set("color", true);
 | 
			
		||||
    color_params[RightIndex].Set("color", true);
 | 
			
		||||
 | 
			
		||||
    battery_params[LeftIndex] = left_joycon;
 | 
			
		||||
    battery_params[RightIndex] = right_joycon;
 | 
			
		||||
    battery_params[LeftIndex].Set("battery", true);
 | 
			
		||||
    battery_params[RightIndex].Set("battery", true);
 | 
			
		||||
 | 
			
		||||
    camera_params = Common::ParamPackage{"engine:camera,camera:1"};
 | 
			
		||||
    nfc_params = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"};
 | 
			
		||||
    camera_params[0] = right_joycon;
 | 
			
		||||
    camera_params[0].Set("camera", true);
 | 
			
		||||
    camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"};
 | 
			
		||||
    ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"};
 | 
			
		||||
    nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"};
 | 
			
		||||
    nfc_params[1] = right_joycon;
 | 
			
		||||
    nfc_params[1].Set("nfc", true);
 | 
			
		||||
 | 
			
		||||
    output_params[LeftIndex] = left_joycon;
 | 
			
		||||
    output_params[RightIndex] = right_joycon;
 | 
			
		||||
    output_params[2] = camera_params;
 | 
			
		||||
    output_params[3] = nfc_params;
 | 
			
		||||
    output_params[2] = camera_params[1];
 | 
			
		||||
    output_params[3] = nfc_params[0];
 | 
			
		||||
    output_params[LeftIndex].Set("output", true);
 | 
			
		||||
    output_params[RightIndex].Set("output", true);
 | 
			
		||||
    output_params[2].Set("output", true);
 | 
			
		||||
@@ -160,8 +174,11 @@ void EmulatedController::LoadDevices() {
 | 
			
		||||
                           Common::Input::CreateInputDevice);
 | 
			
		||||
    std::ranges::transform(battery_params, battery_devices.begin(),
 | 
			
		||||
                           Common::Input::CreateInputDevice);
 | 
			
		||||
    camera_devices = Common::Input::CreateInputDevice(camera_params);
 | 
			
		||||
    nfc_devices = Common::Input::CreateInputDevice(nfc_params);
 | 
			
		||||
    std::ranges::transform(color_params, color_devices.begin(), Common::Input::CreateInputDevice);
 | 
			
		||||
    std::ranges::transform(camera_params, camera_devices.begin(), Common::Input::CreateInputDevice);
 | 
			
		||||
    std::ranges::transform(ring_params, ring_analog_devices.begin(),
 | 
			
		||||
                           Common::Input::CreateInputDevice);
 | 
			
		||||
    std::ranges::transform(nfc_params, nfc_devices.begin(), Common::Input::CreateInputDevice);
 | 
			
		||||
    std::ranges::transform(output_params, output_devices.begin(),
 | 
			
		||||
                           Common::Input::CreateOutputDevice);
 | 
			
		||||
 | 
			
		||||
@@ -323,6 +340,19 @@ void EmulatedController::ReloadInput() {
 | 
			
		||||
        battery_devices[index]->ForceUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (std::size_t index = 0; index < color_devices.size(); ++index) {
 | 
			
		||||
        if (!color_devices[index]) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        color_devices[index]->SetCallback({
 | 
			
		||||
            .on_change =
 | 
			
		||||
                [this, index](const Common::Input::CallbackStatus& callback) {
 | 
			
		||||
                    SetColors(callback, index);
 | 
			
		||||
                },
 | 
			
		||||
        });
 | 
			
		||||
        color_devices[index]->ForceUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (std::size_t index = 0; index < motion_devices.size(); ++index) {
 | 
			
		||||
        if (!motion_devices[index]) {
 | 
			
		||||
            continue;
 | 
			
		||||
@@ -336,22 +366,37 @@ void EmulatedController::ReloadInput() {
 | 
			
		||||
        motion_devices[index]->ForceUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (camera_devices) {
 | 
			
		||||
        camera_devices->SetCallback({
 | 
			
		||||
    for (std::size_t index = 0; index < camera_devices.size(); ++index) {
 | 
			
		||||
        if (!camera_devices[index]) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        camera_devices[index]->SetCallback({
 | 
			
		||||
            .on_change =
 | 
			
		||||
                [this](const Common::Input::CallbackStatus& callback) { SetCamera(callback); },
 | 
			
		||||
        });
 | 
			
		||||
        camera_devices->ForceUpdate();
 | 
			
		||||
        camera_devices[index]->ForceUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (nfc_devices) {
 | 
			
		||||
        if (npad_id_type == NpadIdType::Handheld || npad_id_type == NpadIdType::Player1) {
 | 
			
		||||
            nfc_devices->SetCallback({
 | 
			
		||||
                .on_change =
 | 
			
		||||
                    [this](const Common::Input::CallbackStatus& callback) { SetNfc(callback); },
 | 
			
		||||
            });
 | 
			
		||||
            nfc_devices->ForceUpdate();
 | 
			
		||||
    for (std::size_t index = 0; index < ring_analog_devices.size(); ++index) {
 | 
			
		||||
        if (!ring_analog_devices[index]) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        ring_analog_devices[index]->SetCallback({
 | 
			
		||||
            .on_change =
 | 
			
		||||
                [this](const Common::Input::CallbackStatus& callback) { SetRingAnalog(callback); },
 | 
			
		||||
        });
 | 
			
		||||
        ring_analog_devices[index]->ForceUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (std::size_t index = 0; index < nfc_devices.size(); ++index) {
 | 
			
		||||
        if (!nfc_devices[index]) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        nfc_devices[index]->SetCallback({
 | 
			
		||||
            .on_change =
 | 
			
		||||
                [this](const Common::Input::CallbackStatus& callback) { SetNfc(callback); },
 | 
			
		||||
        });
 | 
			
		||||
        nfc_devices[index]->ForceUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Register TAS devices. No need to force update
 | 
			
		||||
@@ -421,6 +466,9 @@ void EmulatedController::UnloadInput() {
 | 
			
		||||
    for (auto& battery : battery_devices) {
 | 
			
		||||
        battery.reset();
 | 
			
		||||
    }
 | 
			
		||||
    for (auto& color : color_devices) {
 | 
			
		||||
        color.reset();
 | 
			
		||||
    }
 | 
			
		||||
    for (auto& output : output_devices) {
 | 
			
		||||
        output.reset();
 | 
			
		||||
    }
 | 
			
		||||
@@ -436,8 +484,15 @@ void EmulatedController::UnloadInput() {
 | 
			
		||||
    for (auto& stick : virtual_stick_devices) {
 | 
			
		||||
        stick.reset();
 | 
			
		||||
    }
 | 
			
		||||
    camera_devices.reset();
 | 
			
		||||
    nfc_devices.reset();
 | 
			
		||||
    for (auto& camera : camera_devices) {
 | 
			
		||||
        camera.reset();
 | 
			
		||||
    }
 | 
			
		||||
    for (auto& ring : ring_analog_devices) {
 | 
			
		||||
        ring.reset();
 | 
			
		||||
    }
 | 
			
		||||
    for (auto& nfc : nfc_devices) {
 | 
			
		||||
        nfc.reset();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedController::EnableConfiguration() {
 | 
			
		||||
@@ -449,6 +504,11 @@ void EmulatedController::EnableConfiguration() {
 | 
			
		||||
void EmulatedController::DisableConfiguration() {
 | 
			
		||||
    is_configuring = false;
 | 
			
		||||
 | 
			
		||||
    // Get Joycon colors before turning on the controller
 | 
			
		||||
    for (const auto& color_device : color_devices) {
 | 
			
		||||
        color_device->ForceUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Apply temporary npad type to the real controller
 | 
			
		||||
    if (tmp_npad_type != npad_type) {
 | 
			
		||||
        if (is_connected) {
 | 
			
		||||
@@ -502,6 +562,9 @@ void EmulatedController::SaveCurrentConfig() {
 | 
			
		||||
    for (std::size_t index = 0; index < player.motions.size(); ++index) {
 | 
			
		||||
        player.motions[index] = motion_params[index].Serialize();
 | 
			
		||||
    }
 | 
			
		||||
    if (npad_id_type == NpadIdType::Player1) {
 | 
			
		||||
        Settings::values.ringcon_analogs = ring_params[0].Serialize();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedController::RestoreConfig() {
 | 
			
		||||
@@ -773,17 +836,21 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
 | 
			
		||||
    if (index >= controller.stick_values.size()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    std::unique_lock lock{mutex};
 | 
			
		||||
    auto trigger_guard =
 | 
			
		||||
        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Stick, !is_configuring); });
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    const auto stick_value = TransformToStick(callback);
 | 
			
		||||
 | 
			
		||||
    // Only read stick values that have the same uuid or are over the threshold to avoid flapping
 | 
			
		||||
    if (controller.stick_values[index].uuid != uuid) {
 | 
			
		||||
        const bool is_tas = uuid == TAS_UUID;
 | 
			
		||||
        if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) {
 | 
			
		||||
            trigger_guard.Cancel();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left &&
 | 
			
		||||
            !stick_value.right) {
 | 
			
		||||
            trigger_guard.Cancel();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -794,8 +861,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        controller.analog_stick_state.left = {};
 | 
			
		||||
        controller.analog_stick_state.right = {};
 | 
			
		||||
        lock.unlock();
 | 
			
		||||
        TriggerOnChange(ControllerTriggerType::Stick, false);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -827,9 +892,6 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback,
 | 
			
		||||
        controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lock.unlock();
 | 
			
		||||
    TriggerOnChange(ControllerTriggerType::Stick, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callback,
 | 
			
		||||
@@ -837,7 +899,9 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
 | 
			
		||||
    if (index >= controller.trigger_values.size()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    std::unique_lock lock{mutex};
 | 
			
		||||
    auto trigger_guard =
 | 
			
		||||
        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Trigger, !is_configuring); });
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    const auto trigger_value = TransformToTrigger(callback);
 | 
			
		||||
 | 
			
		||||
    // Only read trigger values that have the same uuid or are pressed once
 | 
			
		||||
@@ -853,13 +917,12 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        controller.gc_trigger_state.left = 0;
 | 
			
		||||
        controller.gc_trigger_state.right = 0;
 | 
			
		||||
        lock.unlock();
 | 
			
		||||
        TriggerOnChange(ControllerTriggerType::Trigger, false);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Only GC controllers have analog triggers
 | 
			
		||||
    if (npad_type != NpadStyleIndex::GameCube) {
 | 
			
		||||
        trigger_guard.Cancel();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -876,9 +939,6 @@ void EmulatedController::SetTrigger(const Common::Input::CallbackStatus& callbac
 | 
			
		||||
        controller.npad_button_state.zr.Assign(trigger.pressed.value);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lock.unlock();
 | 
			
		||||
    TriggerOnChange(ControllerTriggerType::Trigger, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback,
 | 
			
		||||
@@ -886,7 +946,8 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
 | 
			
		||||
    if (index >= controller.motion_values.size()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    std::unique_lock lock{mutex};
 | 
			
		||||
    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Motion, !is_configuring); });
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    auto& raw_status = controller.motion_values[index].raw_status;
 | 
			
		||||
    auto& emulated = controller.motion_values[index].emulated;
 | 
			
		||||
 | 
			
		||||
@@ -907,8 +968,6 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
 | 
			
		||||
    force_update_motion = raw_status.force_update;
 | 
			
		||||
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        lock.unlock();
 | 
			
		||||
        TriggerOnChange(ControllerTriggerType::Motion, false);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -918,9 +977,56 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
 | 
			
		||||
    motion.rotation = emulated.GetRotations();
 | 
			
		||||
    motion.orientation = emulated.GetOrientation();
 | 
			
		||||
    motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    lock.unlock();
 | 
			
		||||
    TriggerOnChange(ControllerTriggerType::Motion, true);
 | 
			
		||||
void EmulatedController::SetColors(const Common::Input::CallbackStatus& callback,
 | 
			
		||||
                                   std::size_t index) {
 | 
			
		||||
    if (index >= controller.color_values.size()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    auto trigger_guard =
 | 
			
		||||
        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Color, !is_configuring); });
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    controller.color_values[index] = TransformToColor(callback);
 | 
			
		||||
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (controller.color_values[index].body == 0) {
 | 
			
		||||
        trigger_guard.Cancel();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    controller.colors_state.fullkey = {
 | 
			
		||||
        .body = GetNpadColor(controller.color_values[index].body),
 | 
			
		||||
        .button = GetNpadColor(controller.color_values[index].buttons),
 | 
			
		||||
    };
 | 
			
		||||
    if (npad_type == NpadStyleIndex::ProController) {
 | 
			
		||||
        controller.colors_state.left = {
 | 
			
		||||
            .body = GetNpadColor(controller.color_values[index].left_grip),
 | 
			
		||||
            .button = GetNpadColor(controller.color_values[index].buttons),
 | 
			
		||||
        };
 | 
			
		||||
        controller.colors_state.right = {
 | 
			
		||||
            .body = GetNpadColor(controller.color_values[index].right_grip),
 | 
			
		||||
            .button = GetNpadColor(controller.color_values[index].buttons),
 | 
			
		||||
        };
 | 
			
		||||
    } else {
 | 
			
		||||
        switch (index) {
 | 
			
		||||
        case LeftIndex:
 | 
			
		||||
            controller.colors_state.left = {
 | 
			
		||||
                .body = GetNpadColor(controller.color_values[index].body),
 | 
			
		||||
                .button = GetNpadColor(controller.color_values[index].buttons),
 | 
			
		||||
            };
 | 
			
		||||
            break;
 | 
			
		||||
        case RightIndex:
 | 
			
		||||
            controller.colors_state.right = {
 | 
			
		||||
                .body = GetNpadColor(controller.color_values[index].body),
 | 
			
		||||
                .button = GetNpadColor(controller.color_values[index].buttons),
 | 
			
		||||
            };
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callback,
 | 
			
		||||
@@ -928,12 +1034,11 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
 | 
			
		||||
    if (index >= controller.battery_values.size()) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    std::unique_lock lock{mutex};
 | 
			
		||||
    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Battery, !is_configuring); });
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    controller.battery_values[index] = TransformToBattery(callback);
 | 
			
		||||
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        lock.unlock();
 | 
			
		||||
        TriggerOnChange(ControllerTriggerType::Battery, false);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -989,18 +1094,14 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
 | 
			
		||||
        };
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    lock.unlock();
 | 
			
		||||
    TriggerOnChange(ControllerTriggerType::Battery, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback) {
 | 
			
		||||
    std::unique_lock lock{mutex};
 | 
			
		||||
    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::IrSensor, !is_configuring); });
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    controller.camera_values = TransformToCamera(callback);
 | 
			
		||||
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        lock.unlock();
 | 
			
		||||
        TriggerOnChange(ControllerTriggerType::IrSensor, false);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1008,18 +1109,28 @@ void EmulatedController::SetCamera(const Common::Input::CallbackStatus& callback
 | 
			
		||||
    controller.camera_state.format =
 | 
			
		||||
        static_cast<Core::IrSensor::ImageTransferProcessorFormat>(controller.camera_values.format);
 | 
			
		||||
    controller.camera_state.data = controller.camera_values.data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    lock.unlock();
 | 
			
		||||
    TriggerOnChange(ControllerTriggerType::IrSensor, true);
 | 
			
		||||
void EmulatedController::SetRingAnalog(const Common::Input::CallbackStatus& callback) {
 | 
			
		||||
    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::RingController, !is_configuring); });
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    const auto force_value = TransformToStick(callback);
 | 
			
		||||
 | 
			
		||||
    controller.ring_analog_value = force_value.x;
 | 
			
		||||
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    controller.ring_analog_state.force = force_value.x.value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
 | 
			
		||||
    std::unique_lock lock{mutex};
 | 
			
		||||
    SCOPE_EXIT({ TriggerOnChange(ControllerTriggerType::Nfc, !is_configuring); });
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    controller.nfc_values = TransformToNfc(callback);
 | 
			
		||||
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        lock.unlock();
 | 
			
		||||
        TriggerOnChange(ControllerTriggerType::Nfc, false);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1027,9 +1138,6 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
 | 
			
		||||
        controller.nfc_values.state,
 | 
			
		||||
        controller.nfc_values.data,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    lock.unlock();
 | 
			
		||||
    TriggerOnChange(ControllerTriggerType::Nfc, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
 | 
			
		||||
@@ -1061,7 +1169,7 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
 | 
			
		||||
        .type = type,
 | 
			
		||||
    };
 | 
			
		||||
    return output_devices[device_index]->SetVibration(status) ==
 | 
			
		||||
           Common::Input::VibrationError::None;
 | 
			
		||||
           Common::Input::DriverResult::Success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
 | 
			
		||||
@@ -1083,16 +1191,32 @@ bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
 | 
			
		||||
    return output_devices[device_index]->IsVibrationEnabled();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) {
 | 
			
		||||
    LOG_INFO(Service_HID, "Set polling mode {}", polling_mode);
 | 
			
		||||
    auto& output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
 | 
			
		||||
Common::Input::DriverResult EmulatedController::SetPollingMode(
 | 
			
		||||
    EmulatedDeviceIndex device_index, Common::Input::PollingMode polling_mode) {
 | 
			
		||||
    LOG_INFO(Service_HID, "Set polling mode {}, device_index={}", polling_mode, device_index);
 | 
			
		||||
 | 
			
		||||
    auto& left_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Left)];
 | 
			
		||||
    auto& right_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
 | 
			
		||||
    auto& nfc_output_device = output_devices[3];
 | 
			
		||||
 | 
			
		||||
    const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode);
 | 
			
		||||
    const auto mapped_nfc_result = output_device->SetPollingMode(polling_mode);
 | 
			
		||||
    if (device_index == EmulatedDeviceIndex::LeftIndex) {
 | 
			
		||||
        return left_output_device->SetPollingMode(polling_mode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return virtual_nfc_result == Common::Input::PollingError::None ||
 | 
			
		||||
           mapped_nfc_result == Common::Input::PollingError::None;
 | 
			
		||||
    if (device_index == EmulatedDeviceIndex::RightIndex) {
 | 
			
		||||
        const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode);
 | 
			
		||||
        const auto mapped_nfc_result = right_output_device->SetPollingMode(polling_mode);
 | 
			
		||||
 | 
			
		||||
        if (virtual_nfc_result == Common::Input::DriverResult::Success) {
 | 
			
		||||
            return virtual_nfc_result;
 | 
			
		||||
        }
 | 
			
		||||
        return mapped_nfc_result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    left_output_device->SetPollingMode(polling_mode);
 | 
			
		||||
    right_output_device->SetPollingMode(polling_mode);
 | 
			
		||||
    nfc_output_device->SetPollingMode(polling_mode);
 | 
			
		||||
    return Common::Input::DriverResult::Success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool EmulatedController::SetCameraFormat(
 | 
			
		||||
@@ -1103,13 +1227,22 @@ bool EmulatedController::SetCameraFormat(
 | 
			
		||||
    auto& camera_output_device = output_devices[2];
 | 
			
		||||
 | 
			
		||||
    if (right_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>(
 | 
			
		||||
            camera_format)) == Common::Input::CameraError::None) {
 | 
			
		||||
            camera_format)) == Common::Input::DriverResult::Success) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Fallback to Qt camera if native device doesn't have support
 | 
			
		||||
    return camera_output_device->SetCameraFormat(static_cast<Common::Input::CameraFormat>(
 | 
			
		||||
               camera_format)) == Common::Input::CameraError::None;
 | 
			
		||||
               camera_format)) == Common::Input::DriverResult::Success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Common::ParamPackage EmulatedController::GetRingParam() const {
 | 
			
		||||
    return ring_params[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedController::SetRingParam(Common::ParamPackage param) {
 | 
			
		||||
    ring_params[0] = std::move(param);
 | 
			
		||||
    ReloadInput();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool EmulatedController::HasNfc() const {
 | 
			
		||||
@@ -1263,39 +1396,35 @@ void EmulatedController::Connect(bool use_temporary_value) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unique_lock lock{mutex};
 | 
			
		||||
    auto trigger_guard =
 | 
			
		||||
        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Connected, !is_configuring); });
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        tmp_is_connected = true;
 | 
			
		||||
        lock.unlock();
 | 
			
		||||
        TriggerOnChange(ControllerTriggerType::Connected, false);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (is_connected) {
 | 
			
		||||
        trigger_guard.Cancel();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    is_connected = true;
 | 
			
		||||
 | 
			
		||||
    lock.unlock();
 | 
			
		||||
    TriggerOnChange(ControllerTriggerType::Connected, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedController::Disconnect() {
 | 
			
		||||
    std::unique_lock lock{mutex};
 | 
			
		||||
    auto trigger_guard =
 | 
			
		||||
        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Disconnected, !is_configuring); });
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        tmp_is_connected = false;
 | 
			
		||||
        lock.unlock();
 | 
			
		||||
        TriggerOnChange(ControllerTriggerType::Disconnected, false);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!is_connected) {
 | 
			
		||||
        trigger_guard.Cancel();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    is_connected = false;
 | 
			
		||||
 | 
			
		||||
    lock.unlock();
 | 
			
		||||
    TriggerOnChange(ControllerTriggerType::Disconnected, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool EmulatedController::IsConnected(bool get_temporary_value) const {
 | 
			
		||||
@@ -1320,19 +1449,21 @@ NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
 | 
			
		||||
    std::unique_lock lock{mutex};
 | 
			
		||||
    auto trigger_guard =
 | 
			
		||||
        SCOPE_GUARD({ TriggerOnChange(ControllerTriggerType::Type, !is_configuring); });
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        if (tmp_npad_type == npad_type_) {
 | 
			
		||||
            trigger_guard.Cancel();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        tmp_npad_type = npad_type_;
 | 
			
		||||
        lock.unlock();
 | 
			
		||||
        TriggerOnChange(ControllerTriggerType::Type, false);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (npad_type == npad_type_) {
 | 
			
		||||
        trigger_guard.Cancel();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (is_connected) {
 | 
			
		||||
@@ -1340,9 +1471,6 @@ void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
 | 
			
		||||
                    NpadIdTypeToIndex(npad_id_type));
 | 
			
		||||
    }
 | 
			
		||||
    npad_type = npad_type_;
 | 
			
		||||
 | 
			
		||||
    lock.unlock();
 | 
			
		||||
    TriggerOnChange(ControllerTriggerType::Type, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LedPattern EmulatedController::GetLedPattern() const {
 | 
			
		||||
@@ -1403,6 +1531,10 @@ CameraValues EmulatedController::GetCameraValues() const {
 | 
			
		||||
    return controller.camera_values;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RingAnalogValue EmulatedController::GetRingSensorValues() const {
 | 
			
		||||
    return controller.ring_analog_value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HomeButtonState EmulatedController::GetHomeButtons() const {
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
@@ -1436,7 +1568,7 @@ DebugPadButton EmulatedController::GetDebugPadButtons() const {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AnalogSticks EmulatedController::GetSticks() const {
 | 
			
		||||
    std::unique_lock lock{mutex};
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        return {};
 | 
			
		||||
@@ -1486,6 +1618,10 @@ const CameraState& EmulatedController::GetCamera() const {
 | 
			
		||||
    return controller.camera_state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RingSensorForce EmulatedController::GetRingSensorForce() const {
 | 
			
		||||
    return controller.ring_analog_state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const NfcState& EmulatedController::GetNfc() const {
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    return controller.nfc_state;
 | 
			
		||||
 
 | 
			
		||||
@@ -35,19 +35,27 @@ using ControllerMotionDevices =
 | 
			
		||||
    std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeMotion::NumMotions>;
 | 
			
		||||
using TriggerDevices =
 | 
			
		||||
    std::array<std::unique_ptr<Common::Input::InputDevice>, Settings::NativeTrigger::NumTriggers>;
 | 
			
		||||
using ColorDevices =
 | 
			
		||||
    std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>;
 | 
			
		||||
using BatteryDevices =
 | 
			
		||||
    std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>;
 | 
			
		||||
using CameraDevices = std::unique_ptr<Common::Input::InputDevice>;
 | 
			
		||||
using NfcDevices = std::unique_ptr<Common::Input::InputDevice>;
 | 
			
		||||
using CameraDevices =
 | 
			
		||||
    std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>;
 | 
			
		||||
using RingAnalogDevices =
 | 
			
		||||
    std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>;
 | 
			
		||||
using NfcDevices =
 | 
			
		||||
    std::array<std::unique_ptr<Common::Input::InputDevice>, max_emulated_controllers>;
 | 
			
		||||
using OutputDevices = std::array<std::unique_ptr<Common::Input::OutputDevice>, output_devices_size>;
 | 
			
		||||
 | 
			
		||||
using ButtonParams = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
 | 
			
		||||
using StickParams = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
 | 
			
		||||
using ControllerMotionParams = std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions>;
 | 
			
		||||
using TriggerParams = std::array<Common::ParamPackage, Settings::NativeTrigger::NumTriggers>;
 | 
			
		||||
using ColorParams = std::array<Common::ParamPackage, max_emulated_controllers>;
 | 
			
		||||
using BatteryParams = std::array<Common::ParamPackage, max_emulated_controllers>;
 | 
			
		||||
using CameraParams = Common::ParamPackage;
 | 
			
		||||
using NfcParams = Common::ParamPackage;
 | 
			
		||||
using CameraParams = std::array<Common::ParamPackage, max_emulated_controllers>;
 | 
			
		||||
using RingAnalogParams = std::array<Common::ParamPackage, max_emulated_controllers>;
 | 
			
		||||
using NfcParams = std::array<Common::ParamPackage, max_emulated_controllers>;
 | 
			
		||||
using OutputParams = std::array<Common::ParamPackage, output_devices_size>;
 | 
			
		||||
 | 
			
		||||
using ButtonValues = std::array<Common::Input::ButtonStatus, Settings::NativeButton::NumButtons>;
 | 
			
		||||
@@ -58,6 +66,7 @@ using ControllerMotionValues = std::array<ControllerMotionInfo, Settings::Native
 | 
			
		||||
using ColorValues = std::array<Common::Input::BodyColorStatus, max_emulated_controllers>;
 | 
			
		||||
using BatteryValues = std::array<Common::Input::BatteryStatus, max_emulated_controllers>;
 | 
			
		||||
using CameraValues = Common::Input::CameraStatus;
 | 
			
		||||
using RingAnalogValue = Common::Input::AnalogStatus;
 | 
			
		||||
using NfcValues = Common::Input::NfcStatus;
 | 
			
		||||
using VibrationValues = std::array<Common::Input::VibrationStatus, max_emulated_controllers>;
 | 
			
		||||
 | 
			
		||||
@@ -84,6 +93,10 @@ struct CameraState {
 | 
			
		||||
    std::size_t sample{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct RingSensorForce {
 | 
			
		||||
    f32 force;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct NfcState {
 | 
			
		||||
    Common::Input::NfcState state{};
 | 
			
		||||
    std::vector<u8> data{};
 | 
			
		||||
@@ -116,6 +129,7 @@ struct ControllerStatus {
 | 
			
		||||
    BatteryValues battery_values{};
 | 
			
		||||
    VibrationValues vibration_values{};
 | 
			
		||||
    CameraValues camera_values{};
 | 
			
		||||
    RingAnalogValue ring_analog_value{};
 | 
			
		||||
    NfcValues nfc_values{};
 | 
			
		||||
 | 
			
		||||
    // Data for HID serices
 | 
			
		||||
@@ -129,6 +143,7 @@ struct ControllerStatus {
 | 
			
		||||
    ControllerColors colors_state{};
 | 
			
		||||
    BatteryLevelState battery_state{};
 | 
			
		||||
    CameraState camera_state{};
 | 
			
		||||
    RingSensorForce ring_analog_state{};
 | 
			
		||||
    NfcState nfc_state{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -141,6 +156,7 @@ enum class ControllerTriggerType {
 | 
			
		||||
    Battery,
 | 
			
		||||
    Vibration,
 | 
			
		||||
    IrSensor,
 | 
			
		||||
    RingController,
 | 
			
		||||
    Nfc,
 | 
			
		||||
    Connected,
 | 
			
		||||
    Disconnected,
 | 
			
		||||
@@ -294,6 +310,9 @@ public:
 | 
			
		||||
    /// Returns the latest camera status from the controller with parameters
 | 
			
		||||
    CameraValues GetCameraValues() const;
 | 
			
		||||
 | 
			
		||||
    /// Returns the latest status of analog input from the ring sensor with parameters
 | 
			
		||||
    RingAnalogValue GetRingSensorValues() const;
 | 
			
		||||
 | 
			
		||||
    /// Returns the latest status of button input for the hid::HomeButton service
 | 
			
		||||
    HomeButtonState GetHomeButtons() const;
 | 
			
		||||
 | 
			
		||||
@@ -324,6 +343,9 @@ public:
 | 
			
		||||
    /// Returns the latest camera status from the controller
 | 
			
		||||
    const CameraState& GetCamera() const;
 | 
			
		||||
 | 
			
		||||
    /// Returns the latest ringcon force sensor value
 | 
			
		||||
    RingSensorForce GetRingSensorForce() const;
 | 
			
		||||
 | 
			
		||||
    /// Returns the latest ntag status from the controller
 | 
			
		||||
    const NfcState& GetNfc() const;
 | 
			
		||||
 | 
			
		||||
@@ -341,10 +363,12 @@ public:
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the desired data to be polled from a controller
 | 
			
		||||
     * @param device_index index of the controller to set the polling mode
 | 
			
		||||
     * @param polling_mode type of input desired buttons, gyro, nfc, ir, etc.
 | 
			
		||||
     * @return true if SetPollingMode was successfull
 | 
			
		||||
     * @return driver result from this command
 | 
			
		||||
     */
 | 
			
		||||
    bool SetPollingMode(Common::Input::PollingMode polling_mode);
 | 
			
		||||
    Common::Input::DriverResult SetPollingMode(EmulatedDeviceIndex device_index,
 | 
			
		||||
                                               Common::Input::PollingMode polling_mode);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the desired camera format to be polled from a controller
 | 
			
		||||
@@ -353,6 +377,15 @@ public:
 | 
			
		||||
     */
 | 
			
		||||
    bool SetCameraFormat(Core::IrSensor::ImageTransferProcessorFormat camera_format);
 | 
			
		||||
 | 
			
		||||
    // Returns the current mapped ring device
 | 
			
		||||
    Common::ParamPackage GetRingParam() const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the current mapped ring device
 | 
			
		||||
     * @param param ParamPackage with ring sensor data to be mapped
 | 
			
		||||
     */
 | 
			
		||||
    void SetRingParam(Common::ParamPackage param);
 | 
			
		||||
 | 
			
		||||
    /// Returns true if the device has nfc support
 | 
			
		||||
    bool HasNfc() const;
 | 
			
		||||
 | 
			
		||||
@@ -432,10 +465,17 @@ private:
 | 
			
		||||
     */
 | 
			
		||||
    void SetMotion(const Common::Input::CallbackStatus& callback, std::size_t index);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the color status of the controller
 | 
			
		||||
     * @param callback A CallbackStatus containing the color status
 | 
			
		||||
     * @param index color ID of the to be updated
 | 
			
		||||
     */
 | 
			
		||||
    void SetColors(const Common::Input::CallbackStatus& callback, std::size_t index);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the battery status of the controller
 | 
			
		||||
     * @param callback A CallbackStatus containing the battery status
 | 
			
		||||
     * @param index Button ID of the to be updated
 | 
			
		||||
     * @param index battery ID of the to be updated
 | 
			
		||||
     */
 | 
			
		||||
    void SetBattery(const Common::Input::CallbackStatus& callback, std::size_t index);
 | 
			
		||||
 | 
			
		||||
@@ -445,6 +485,12 @@ private:
 | 
			
		||||
     */
 | 
			
		||||
    void SetCamera(const Common::Input::CallbackStatus& callback);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the ring analog sensor status of the ring controller
 | 
			
		||||
     * @param callback A CallbackStatus containing the force status
 | 
			
		||||
     */
 | 
			
		||||
    void SetRingAnalog(const Common::Input::CallbackStatus& callback);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the nfc status of the controller
 | 
			
		||||
     * @param callback A CallbackStatus containing the nfc status
 | 
			
		||||
@@ -484,7 +530,9 @@ private:
 | 
			
		||||
    ControllerMotionParams motion_params;
 | 
			
		||||
    TriggerParams trigger_params;
 | 
			
		||||
    BatteryParams battery_params;
 | 
			
		||||
    ColorParams color_params;
 | 
			
		||||
    CameraParams camera_params;
 | 
			
		||||
    RingAnalogParams ring_params;
 | 
			
		||||
    NfcParams nfc_params;
 | 
			
		||||
    OutputParams output_params;
 | 
			
		||||
 | 
			
		||||
@@ -493,7 +541,9 @@ private:
 | 
			
		||||
    ControllerMotionDevices motion_devices;
 | 
			
		||||
    TriggerDevices trigger_devices;
 | 
			
		||||
    BatteryDevices battery_devices;
 | 
			
		||||
    ColorDevices color_devices;
 | 
			
		||||
    CameraDevices camera_devices;
 | 
			
		||||
    RingAnalogDevices ring_analog_devices;
 | 
			
		||||
    NfcDevices nfc_devices;
 | 
			
		||||
    OutputDevices output_devices;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@ EmulatedDevices::EmulatedDevices() = default;
 | 
			
		||||
EmulatedDevices::~EmulatedDevices() = default;
 | 
			
		||||
 | 
			
		||||
void EmulatedDevices::ReloadFromSettings() {
 | 
			
		||||
    ring_params = Common::ParamPackage(Settings::values.ringcon_analogs);
 | 
			
		||||
    ReloadInput();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -66,8 +65,6 @@ void EmulatedDevices::ReloadInput() {
 | 
			
		||||
        key_index++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ring_analog_device = Common::Input::CreateInputDevice(ring_params);
 | 
			
		||||
 | 
			
		||||
    for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) {
 | 
			
		||||
        if (!mouse_button_devices[index]) {
 | 
			
		||||
            continue;
 | 
			
		||||
@@ -122,13 +119,6 @@ void EmulatedDevices::ReloadInput() {
 | 
			
		||||
                },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ring_analog_device) {
 | 
			
		||||
        ring_analog_device->SetCallback({
 | 
			
		||||
            .on_change =
 | 
			
		||||
                [this](const Common::Input::CallbackStatus& callback) { SetRingAnalog(callback); },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedDevices::UnloadInput() {
 | 
			
		||||
@@ -145,7 +135,6 @@ void EmulatedDevices::UnloadInput() {
 | 
			
		||||
    for (auto& button : keyboard_modifier_devices) {
 | 
			
		||||
        button.reset();
 | 
			
		||||
    }
 | 
			
		||||
    ring_analog_device.reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedDevices::EnableConfiguration() {
 | 
			
		||||
@@ -165,7 +154,6 @@ void EmulatedDevices::SaveCurrentConfig() {
 | 
			
		||||
    if (!is_configuring) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    Settings::values.ringcon_analogs = ring_params.Serialize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedDevices::RestoreConfig() {
 | 
			
		||||
@@ -175,15 +163,6 @@ void EmulatedDevices::RestoreConfig() {
 | 
			
		||||
    ReloadFromSettings();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Common::ParamPackage EmulatedDevices::GetRingParam() const {
 | 
			
		||||
    return ring_params;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedDevices::SetRingParam(Common::ParamPackage param) {
 | 
			
		||||
    ring_params = std::move(param);
 | 
			
		||||
    ReloadInput();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedDevices::SetKeyboardButton(const Common::Input::CallbackStatus& callback,
 | 
			
		||||
                                        std::size_t index) {
 | 
			
		||||
    if (index >= device_status.keyboard_values.size()) {
 | 
			
		||||
@@ -430,23 +409,6 @@ void EmulatedDevices::SetMouseStick(const Common::Input::CallbackStatus& callbac
 | 
			
		||||
    TriggerOnChange(DeviceTriggerType::Mouse);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedDevices::SetRingAnalog(const Common::Input::CallbackStatus& callback) {
 | 
			
		||||
    std::lock_guard lock{mutex};
 | 
			
		||||
    const auto force_value = TransformToStick(callback);
 | 
			
		||||
 | 
			
		||||
    device_status.ring_analog_value = force_value.x;
 | 
			
		||||
 | 
			
		||||
    if (is_configuring) {
 | 
			
		||||
        device_status.ring_analog_value = {};
 | 
			
		||||
        TriggerOnChange(DeviceTriggerType::RingController);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    device_status.ring_analog_state.force = force_value.x.value;
 | 
			
		||||
 | 
			
		||||
    TriggerOnChange(DeviceTriggerType::RingController);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
KeyboardValues EmulatedDevices::GetKeyboardValues() const {
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    return device_status.keyboard_values;
 | 
			
		||||
@@ -462,10 +424,6 @@ MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const {
 | 
			
		||||
    return device_status.mouse_button_values;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RingAnalogValue EmulatedDevices::GetRingSensorValues() const {
 | 
			
		||||
    return device_status.ring_analog_value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
KeyboardKey EmulatedDevices::GetKeyboard() const {
 | 
			
		||||
    std::scoped_lock lock{mutex};
 | 
			
		||||
    return device_status.keyboard_state;
 | 
			
		||||
@@ -491,10 +449,6 @@ AnalogStickState EmulatedDevices::GetMouseWheel() const {
 | 
			
		||||
    return device_status.mouse_wheel_state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RingSensorForce EmulatedDevices::GetRingSensorForce() const {
 | 
			
		||||
    return device_status.ring_analog_state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) {
 | 
			
		||||
    std::scoped_lock lock{callback_mutex};
 | 
			
		||||
    for (const auto& poller_pair : callback_list) {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,11 +26,9 @@ using MouseButtonDevices = std::array<std::unique_ptr<Common::Input::InputDevice
 | 
			
		||||
using MouseAnalogDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
 | 
			
		||||
                                      Settings::NativeMouseWheel::NumMouseWheels>;
 | 
			
		||||
using MouseStickDevice = std::unique_ptr<Common::Input::InputDevice>;
 | 
			
		||||
using RingAnalogDevice = std::unique_ptr<Common::Input::InputDevice>;
 | 
			
		||||
 | 
			
		||||
using MouseButtonParams =
 | 
			
		||||
    std::array<Common::ParamPackage, Settings::NativeMouseButton::NumMouseButtons>;
 | 
			
		||||
using RingAnalogParams = Common::ParamPackage;
 | 
			
		||||
 | 
			
		||||
using KeyboardValues =
 | 
			
		||||
    std::array<Common::Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardKeys>;
 | 
			
		||||
@@ -41,17 +39,12 @@ using MouseButtonValues =
 | 
			
		||||
using MouseAnalogValues =
 | 
			
		||||
    std::array<Common::Input::AnalogStatus, Settings::NativeMouseWheel::NumMouseWheels>;
 | 
			
		||||
using MouseStickValue = Common::Input::TouchStatus;
 | 
			
		||||
using RingAnalogValue = Common::Input::AnalogStatus;
 | 
			
		||||
 | 
			
		||||
struct MousePosition {
 | 
			
		||||
    f32 x;
 | 
			
		||||
    f32 y;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct RingSensorForce {
 | 
			
		||||
    f32 force;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct DeviceStatus {
 | 
			
		||||
    // Data from input_common
 | 
			
		||||
    KeyboardValues keyboard_values{};
 | 
			
		||||
@@ -59,7 +52,6 @@ struct DeviceStatus {
 | 
			
		||||
    MouseButtonValues mouse_button_values{};
 | 
			
		||||
    MouseAnalogValues mouse_analog_values{};
 | 
			
		||||
    MouseStickValue mouse_stick_value{};
 | 
			
		||||
    RingAnalogValue ring_analog_value{};
 | 
			
		||||
 | 
			
		||||
    // Data for HID serices
 | 
			
		||||
    KeyboardKey keyboard_state{};
 | 
			
		||||
@@ -67,7 +59,6 @@ struct DeviceStatus {
 | 
			
		||||
    MouseButton mouse_button_state{};
 | 
			
		||||
    MousePosition mouse_position_state{};
 | 
			
		||||
    AnalogStickState mouse_wheel_state{};
 | 
			
		||||
    RingSensorForce ring_analog_state{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class DeviceTriggerType {
 | 
			
		||||
@@ -138,9 +129,6 @@ public:
 | 
			
		||||
    /// Returns the latest status of button input from the mouse with parameters
 | 
			
		||||
    MouseButtonValues GetMouseButtonsValues() const;
 | 
			
		||||
 | 
			
		||||
    /// Returns the latest status of analog input from the ring sensor with parameters
 | 
			
		||||
    RingAnalogValue GetRingSensorValues() const;
 | 
			
		||||
 | 
			
		||||
    /// Returns the latest status of button input from the keyboard
 | 
			
		||||
    KeyboardKey GetKeyboard() const;
 | 
			
		||||
 | 
			
		||||
@@ -156,9 +144,6 @@ public:
 | 
			
		||||
    /// Returns the latest mouse wheel change
 | 
			
		||||
    AnalogStickState GetMouseWheel() const;
 | 
			
		||||
 | 
			
		||||
    /// Returns the latest ringcon force sensor value
 | 
			
		||||
    RingSensorForce GetRingSensorForce() const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a callback to the list of events
 | 
			
		||||
     * @param update_callback InterfaceUpdateCallback that will be triggered
 | 
			
		||||
@@ -224,14 +209,11 @@ private:
 | 
			
		||||
 | 
			
		||||
    bool is_configuring{false};
 | 
			
		||||
 | 
			
		||||
    RingAnalogParams ring_params;
 | 
			
		||||
 | 
			
		||||
    KeyboardDevices keyboard_devices;
 | 
			
		||||
    KeyboardModifierDevices keyboard_modifier_devices;
 | 
			
		||||
    MouseButtonDevices mouse_button_devices;
 | 
			
		||||
    MouseAnalogDevices mouse_analog_devices;
 | 
			
		||||
    MouseStickDevice mouse_stick_device;
 | 
			
		||||
    RingAnalogDevice ring_analog_device;
 | 
			
		||||
 | 
			
		||||
    mutable std::mutex mutex;
 | 
			
		||||
    mutable std::mutex callback_mutex;
 | 
			
		||||
 
 | 
			
		||||
@@ -304,6 +304,18 @@ Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& cal
 | 
			
		||||
    return nfc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Common::Input::BodyColorStatus TransformToColor(const Common::Input::CallbackStatus& callback) {
 | 
			
		||||
    switch (callback.type) {
 | 
			
		||||
    case Common::Input::InputType::Color:
 | 
			
		||||
        return callback.color_status;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        LOG_ERROR(Input, "Conversion from type {} to color not implemented", callback.type);
 | 
			
		||||
        return {};
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value) {
 | 
			
		||||
    const auto& properties = analog.properties;
 | 
			
		||||
    float& raw_value = analog.raw_value;
 | 
			
		||||
 
 | 
			
		||||
@@ -88,10 +88,18 @@ Common::Input::CameraStatus TransformToCamera(const Common::Input::CallbackStatu
 | 
			
		||||
 * Converts raw input data into a valid nfc status.
 | 
			
		||||
 *
 | 
			
		||||
 * @param callback Supported callbacks: Nfc.
 | 
			
		||||
 * @return A valid CameraObject object.
 | 
			
		||||
 * @return A valid data tag vector.
 | 
			
		||||
 */
 | 
			
		||||
Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& callback);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Converts raw input data into a valid color status.
 | 
			
		||||
 *
 | 
			
		||||
 * @param callback Supported callbacks: Color.
 | 
			
		||||
 * @return A valid Color object.
 | 
			
		||||
 */
 | 
			
		||||
Common::Input::BodyColorStatus TransformToColor(const Common::Input::CallbackStatus& callback);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Converts raw analog data into a valid analog value
 | 
			
		||||
 * @param analog An analog object containing raw data and properties
 | 
			
		||||
 
 | 
			
		||||
@@ -272,6 +272,8 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconLeft:
 | 
			
		||||
        shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
 | 
			
		||||
        shared_memory->fullkey_color.fullkey = body_colors.left;
 | 
			
		||||
        shared_memory->joycon_color.attribute = ColorAttribute::Ok;
 | 
			
		||||
        shared_memory->joycon_color.left = body_colors.left;
 | 
			
		||||
        shared_memory->battery_level_dual = battery_level.left.battery_level;
 | 
			
		||||
@@ -285,6 +287,8 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
        shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1);
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
 | 
			
		||||
        shared_memory->fullkey_color.fullkey = body_colors.right;
 | 
			
		||||
        shared_memory->joycon_color.attribute = ColorAttribute::Ok;
 | 
			
		||||
        shared_memory->joycon_color.right = body_colors.right;
 | 
			
		||||
        shared_memory->battery_level_right = battery_level.right.battery_level;
 | 
			
		||||
@@ -332,6 +336,20 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
 | 
			
		||||
    controller.is_connected = true;
 | 
			
		||||
    controller.device->Connect();
 | 
			
		||||
    controller.device->SetLedPattern();
 | 
			
		||||
    if (controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
 | 
			
		||||
        if (controller.is_dual_left_connected) {
 | 
			
		||||
            controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::LeftIndex,
 | 
			
		||||
                                              Common::Input::PollingMode::Active);
 | 
			
		||||
        }
 | 
			
		||||
        if (controller.is_dual_right_connected) {
 | 
			
		||||
            controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                              Common::Input::PollingMode::Active);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices,
 | 
			
		||||
                                          Common::Input::PollingMode::Active);
 | 
			
		||||
    }
 | 
			
		||||
    SignalStyleSetChangedEvent(npad_id);
 | 
			
		||||
    WriteEmptyEntry(controller.shared_memory);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -297,13 +297,13 @@ void HidBus::EnableExternalDevice(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
 | 
			
		||||
    const auto parameters{rp.PopRaw<Parameters>()};
 | 
			
		||||
 | 
			
		||||
    LOG_INFO(Service_HID,
 | 
			
		||||
             "called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, "
 | 
			
		||||
             "player_number={}, is_valid={}, inval={}, applet_resource_user_id{}",
 | 
			
		||||
             parameters.enable, parameters.bus_handle.abstracted_pad_id,
 | 
			
		||||
             parameters.bus_handle.bus_type, parameters.bus_handle.internal_index,
 | 
			
		||||
             parameters.bus_handle.player_number, parameters.bus_handle.is_valid, parameters.inval,
 | 
			
		||||
             parameters.applet_resource_user_id);
 | 
			
		||||
    LOG_DEBUG(Service_HID,
 | 
			
		||||
              "called, enable={}, abstracted_pad_id={}, bus_type={}, internal_index={}, "
 | 
			
		||||
              "player_number={}, is_valid={}, inval={}, applet_resource_user_id{}",
 | 
			
		||||
              parameters.enable, parameters.bus_handle.abstracted_pad_id,
 | 
			
		||||
              parameters.bus_handle.bus_type, parameters.bus_handle.internal_index,
 | 
			
		||||
              parameters.bus_handle.player_number, parameters.bus_handle.is_valid, parameters.inval,
 | 
			
		||||
              parameters.applet_resource_user_id);
 | 
			
		||||
 | 
			
		||||
    const auto device_index = GetDeviceIndexFromHandle(parameters.bus_handle);
 | 
			
		||||
 | 
			
		||||
@@ -326,11 +326,11 @@ void HidBus::GetExternalDeviceId(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto bus_handle_{rp.PopRaw<BusHandle>()};
 | 
			
		||||
 | 
			
		||||
    LOG_INFO(Service_HID,
 | 
			
		||||
             "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
 | 
			
		||||
             "is_valid={}",
 | 
			
		||||
             bus_handle_.abstracted_pad_id, bus_handle_.bus_type, bus_handle_.internal_index,
 | 
			
		||||
             bus_handle_.player_number, bus_handle_.is_valid);
 | 
			
		||||
    LOG_DEBUG(Service_HID,
 | 
			
		||||
              "called, abstracted_pad_id={}, bus_type={}, internal_index={}, player_number={}, "
 | 
			
		||||
              "is_valid={}",
 | 
			
		||||
              bus_handle_.abstracted_pad_id, bus_handle_.bus_type, bus_handle_.internal_index,
 | 
			
		||||
              bus_handle_.player_number, bus_handle_.is_valid);
 | 
			
		||||
 | 
			
		||||
    const auto device_index = GetDeviceIndexFromHandle(bus_handle_);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
 | 
			
		||||
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
			
		||||
 | 
			
		||||
#include "core/hid/emulated_devices.h"
 | 
			
		||||
#include "core/hid/emulated_controller.h"
 | 
			
		||||
#include "core/hid/hid_core.h"
 | 
			
		||||
#include "core/hle/kernel/k_event.h"
 | 
			
		||||
#include "core/hle/kernel/k_readable_event.h"
 | 
			
		||||
@@ -12,16 +12,20 @@ namespace Service::HID {
 | 
			
		||||
RingController::RingController(Core::HID::HIDCore& hid_core_,
 | 
			
		||||
                               KernelHelpers::ServiceContext& service_context_)
 | 
			
		||||
    : HidbusBase(service_context_) {
 | 
			
		||||
    input = hid_core_.GetEmulatedDevices();
 | 
			
		||||
    input = hid_core_.GetEmulatedController(Core::HID::NpadIdType::Player1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RingController::~RingController() = default;
 | 
			
		||||
 | 
			
		||||
void RingController::OnInit() {
 | 
			
		||||
    input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                          Common::Input::PollingMode::Ring);
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RingController::OnRelease() {
 | 
			
		||||
    input->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                          Common::Input::PollingMode::Active);
 | 
			
		||||
    return;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
#include "core/hle/service/hid/hidbus/hidbus_base.h"
 | 
			
		||||
 | 
			
		||||
namespace Core::HID {
 | 
			
		||||
class EmulatedDevices;
 | 
			
		||||
class EmulatedController;
 | 
			
		||||
} // namespace Core::HID
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
@@ -248,6 +248,6 @@ private:
 | 
			
		||||
        .zero = {.value = idle_value, .crc = 225},
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Core::HID::EmulatedDevices* input;
 | 
			
		||||
    Core::HID::EmulatedController* input;
 | 
			
		||||
};
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -108,6 +108,8 @@ void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    auto result = IsIrCameraHandleValid(parameters.camera_handle);
 | 
			
		||||
    if (result.IsSuccess()) {
 | 
			
		||||
        // TODO: Stop Image processor
 | 
			
		||||
        npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                    Common::Input::PollingMode::Active);
 | 
			
		||||
        result = ResultSuccess;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -139,6 +141,8 @@ void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        MakeProcessor<MomentProcessor>(parameters.camera_handle, device);
 | 
			
		||||
        auto& image_transfer_processor = GetProcessor<MomentProcessor>(parameters.camera_handle);
 | 
			
		||||
        image_transfer_processor.SetConfig(parameters.processor_config);
 | 
			
		||||
        npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                    Common::Input::PollingMode::IR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
@@ -170,6 +174,8 @@ void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        auto& image_transfer_processor =
 | 
			
		||||
            GetProcessor<ClusteringProcessor>(parameters.camera_handle);
 | 
			
		||||
        image_transfer_processor.SetConfig(parameters.processor_config);
 | 
			
		||||
        npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                    Common::Input::PollingMode::IR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
@@ -219,6 +225,8 @@ void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
            GetProcessor<ImageTransferProcessor>(parameters.camera_handle);
 | 
			
		||||
        image_transfer_processor.SetConfig(parameters.processor_config);
 | 
			
		||||
        image_transfer_processor.SetTransferMemoryPointer(transfer_memory);
 | 
			
		||||
        npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                    Common::Input::PollingMode::IR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
@@ -294,6 +302,8 @@ void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        auto& image_transfer_processor =
 | 
			
		||||
            GetProcessor<TeraPluginProcessor>(parameters.camera_handle);
 | 
			
		||||
        image_transfer_processor.SetConfig(parameters.processor_config);
 | 
			
		||||
        npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                    Common::Input::PollingMode::IR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
@@ -343,6 +353,8 @@ void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        MakeProcessor<PointingProcessor>(camera_handle, device);
 | 
			
		||||
        auto& image_transfer_processor = GetProcessor<PointingProcessor>(camera_handle);
 | 
			
		||||
        image_transfer_processor.SetConfig(processor_config);
 | 
			
		||||
        npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                    Common::Input::PollingMode::IR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
@@ -453,6 +465,8 @@ void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
            GetProcessor<ImageTransferProcessor>(parameters.camera_handle);
 | 
			
		||||
        image_transfer_processor.SetConfig(parameters.processor_config);
 | 
			
		||||
        image_transfer_processor.SetTransferMemoryPointer(transfer_memory);
 | 
			
		||||
        npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                    Common::Input::PollingMode::IR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
@@ -479,6 +493,8 @@ void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        MakeProcessor<IrLedProcessor>(camera_handle, device);
 | 
			
		||||
        auto& image_transfer_processor = GetProcessor<IrLedProcessor>(camera_handle);
 | 
			
		||||
        image_transfer_processor.SetConfig(processor_config);
 | 
			
		||||
        npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                    Common::Input::PollingMode::IR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
@@ -504,6 +520,8 @@ void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    auto result = IsIrCameraHandleValid(parameters.camera_handle);
 | 
			
		||||
    if (result.IsSuccess()) {
 | 
			
		||||
        // TODO: Stop image processor async
 | 
			
		||||
        npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                    Common::Input::PollingMode::Active);
 | 
			
		||||
        result = ResultSuccess;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -130,7 +130,9 @@ Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) {
 | 
			
		||||
        return WrongDeviceState;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!npad_device->SetPollingMode(Common::Input::PollingMode::NFC)) {
 | 
			
		||||
    if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                    Common::Input::PollingMode::NFC) !=
 | 
			
		||||
        Common::Input::DriverResult::Success) {
 | 
			
		||||
        LOG_ERROR(Service_NFC, "Nfc not supported");
 | 
			
		||||
        return NfcDisabled;
 | 
			
		||||
    }
 | 
			
		||||
@@ -141,7 +143,8 @@ Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result NfcDevice::StopDetection() {
 | 
			
		||||
    npad_device->SetPollingMode(Common::Input::PollingMode::Active);
 | 
			
		||||
    npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                Common::Input::PollingMode::Active);
 | 
			
		||||
 | 
			
		||||
    if (device_state == NFP::DeviceState::Initialized) {
 | 
			
		||||
        return ResultSuccess;
 | 
			
		||||
 
 | 
			
		||||
@@ -152,7 +152,9 @@ Result NfpDevice::StartDetection(TagProtocol allowed_protocol) {
 | 
			
		||||
        return WrongDeviceState;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!npad_device->SetPollingMode(Common::Input::PollingMode::NFC)) {
 | 
			
		||||
    if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                    Common::Input::PollingMode::NFC) !=
 | 
			
		||||
        Common::Input::DriverResult::Success) {
 | 
			
		||||
        LOG_ERROR(Service_NFP, "Nfc not supported");
 | 
			
		||||
        return NfcDisabled;
 | 
			
		||||
    }
 | 
			
		||||
@@ -163,7 +165,8 @@ Result NfpDevice::StartDetection(TagProtocol allowed_protocol) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Result NfpDevice::StopDetection() {
 | 
			
		||||
    npad_device->SetPollingMode(Common::Input::PollingMode::Active);
 | 
			
		||||
    npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
 | 
			
		||||
                                Common::Input::PollingMode::Active);
 | 
			
		||||
 | 
			
		||||
    if (device_state == DeviceState::Initialized) {
 | 
			
		||||
        return ResultSuccess;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user