Skip to content

Fluke/zotac zone dials #339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

flukejones
Copy link
Contributor

No description provided.

@flukejones flukejones marked this pull request as draft April 18, 2025 11:51
@flukejones
Copy link
Contributor Author

WIP. Needs help

@flukejones flukejones force-pushed the fluke/zotac-zone-dials branch 2 times, most recently from 49036c0 to b9776ed Compare April 19, 2025 08:08
@flukejones flukejones force-pushed the fluke/zotac-zone-dials branch 2 times, most recently from a7829a8 to 5b0af67 Compare April 19, 2025 10:56
@flukejones
Copy link
Contributor Author

I'm at a loss as to why I'm getting a dual event:

[src/input/composite_device/mod.rs:329:25] &device_id = "evdev://event11"
[src/input/composite_device/mod.rs:329:25] &event = Native(
    NativeEvent {
        capability: Gamepad(
            Dial(
                RightStickDial,
            ),
        ),
        source_capability: None,
        value: Vector2 {
            x: Some(
                -1.0,
            ),
            y: None,
        },
    },
)
[src/input/event/value.rs:1009:17] direction.as_str() = "counter-clockwise"
[src/input/event/value.rs:1009:17] direction.as_str() = "clockwise"
[2025-04-19T10:53:53Z DEBUG inputplumber::input::composite_device] Checking single intercept event.
[2025-04-19T10:53:53Z DEBUG inputplumber::input::composite_device] Checking single intercept event.
[src/input/composite_device/mod.rs:329:25] &device_id = "evdev://event11"
[src/input/composite_device/mod.rs:329:25] &event = Native(
    NativeEvent {
        capability: Gamepad(
            Dial(
                RightStickDial,
            ),
        ),
        source_capability: None,
        value: Vector2 {
            x: Some(
                -1.0,
            ),
            y: None,
        },
    },
)
[src/input/event/value.rs:1009:17] direction.as_str() = "counter-clockwise"
[src/input/event/value.rs:1009:17] direction.as_str() = "clockwise"
[2025-04-19T10:53:53Z DEBUG inputplumber::input::composite_device] Checking single intercept event.
[2025-04-19T10:53:53Z DEBUG inputplumber::input::composite_device] Checking single intercept event.

Doesn't make sense at all. Kernel driver ouputs a single event.

@pastaq
Copy link
Contributor

pastaq commented Apr 19, 2025

Are you mapping the evdev and the hidraw?

@pastaq
Copy link
Contributor

pastaq commented Apr 19, 2025

You have the x axis of the dial mapped to two events, so it will trigger on both. You should translate the InputValue for that capability to clockwise/counterclockwise based on the axis value being > 0 / < 0 instead.

@flukejones
Copy link
Contributor Author

@pastaq can you walk me through this please? There is just too much repetitive code for me to follow around here.

@flukejones
Copy link
Contributor Author

Hmm no I think I understand now.

@flukejones flukejones force-pushed the fluke/zotac-zone-dials branch 2 times, most recently from 61ce07d to 28163d3 Compare April 19, 2025 12:23
@flukejones
Copy link
Contributor Author

Alright so everything works now except for this particular problem:

The driver emits and re-emits either 1 or -1. These events are seen fine for the raw event handling. But when it gets to event/value.rs translate() it falls over.

I'm not really all that sure how best to handle translate_dial_to_button(). What happens is that due to the above a release event is never seen, and when you turn the dial the opposite way we then get a 0 due to changed direction and value. If I change translate_dial_to_button() to:

return match direction.as_str() {
    "clockwise" => {
        if let Some(x) = x {
            if x > 0.0 {
                Ok(InputValue::Bool(true))
            } else {
                Ok(InputValue::None)
            }
        } else {
            Ok(InputValue::None)
        }
    }
    "counter-clockwise" => {
        if let Some(x) = x {
            if x < 0.0 {
                Ok(InputValue::Bool(true))
            } else {
                Ok(InputValue::None)
            }
        } else {
            Ok(InputValue::None)
        }
    }

I never get another event from IP on these. They are stuck on true. So i assume the values get cached? At the very least I think REL_WHEEL and such need to ignore that there is no 0 event.

@ShadowApex
Copy link
Contributor

ShadowApex commented Apr 19, 2025

Looking at this more, since these events do not have a "button up" state, you'll need to emulate that yourself when encountering a dial -> button translation. It seems like what you want to do is send a "button down" + "button up" event for each "tick" of the dial. So we'll need to translate that single dial event into "button down" + "button up" events.

There may be a more elegant way to do this, but what first comes to mind is you could handle this in the translate_event() function in composite_device/mod.rs. In that function, you can check to see if this is a dial -> button translation and create the button up/down events to emit there.

E.g.

                // Translate the event into the defined target event(s)
                for target_event in mapping.target_events.iter() {
                    // TODO: We can cache this conversion for faster translation
                    let target_cap: Capability = target_event.clone().into();
                    let result = event.get_value().translate(
                        &source_cap,
                        &mapping.source_event,
                        &target_cap,
                        target_event,
                    );
                    let value = match result {
                        Ok(v) => v,
                        ...
                    };
                    if matches!(value, InputValue::None) {
                        continue;
                    }

                    // If the the event translation should result in a button pulse, return the
                    // translated pulse events.
                    if source_cap.is_button_pulse_translation(target_cap) {
                        let event = NativeEvent::new_translated(source_cap.clone(), target_cap, InputValue::Bool(true));
                        events.push(event);
                        let event = NativeEvent::new_translated(source_cap.clone(), target_cap, InputValue::Bool(false));
                        events.push(event);
                        continue;
                    }

                    let event = NativeEvent::new_translated(source_cap.clone(), target_cap, value);
                    events.push(event);
                }
  ...

@flukejones flukejones force-pushed the fluke/zotac-zone-dials branch 2 times, most recently from 650e614 to 3300b3d Compare April 22, 2025 08:16
@flukejones
Copy link
Contributor Author

Alright, this is working now. So cleanup is required.

Full support for the driver to enable the majority of use-cases.
Does not include proper support of dial/wheels or touchpads.

Signed-off-by: Luke Jones <[email protected]>
@flukejones flukejones force-pushed the fluke/zotac-zone-dials branch 5 times, most recently from a295973 to e1b0222 Compare April 22, 2025 09:06
@flukejones flukejones force-pushed the fluke/zotac-zone-dials branch from e1b0222 to 7810744 Compare April 22, 2025 09:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants