Skip to content
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

Implement LEDs devices #268

Closed
wants to merge 3 commits into from
Closed

Conversation

NeroReflex
Copy link
Contributor

This is an initial implementation of LEDs devices: as of now only a static color (defined in the configuration) can be set when the device is acquired.

Implement Led configuration support with a fixed color.

Cleanup wasteful clone() calls in various lookup methods.
Enable acquisition of LED devices and setting of a fixed color if specified in the configuration.
@pastaq
Copy link
Contributor

pastaq commented Jan 28, 2025

Does this replace #246 ?

@NeroReflex
Copy link
Contributor Author

Does this replace #246 ?

Mostly. That other PR still has an improvement (that has a problem) that will be a future PR after this PR knce I will have fixed it.

@pastaq
Copy link
Contributor

pastaq commented Jan 29, 2025

I would say close that one and make that PR independently. We don't need to track it as open since we won't be merging it.

true
}

/// Returns true if a given iio device is within a list of iio configs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Returns true if a given iio device is within a list of iio configs.
/// Returns true if a given led device is within a list of led configs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again? Something has gone wrong since I fixed this already

}

impl LedDevice {
/// Create a new [IioDevice] associated with the given device and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Create a new [IioDevice] associated with the given device and
/// Create a new [LedDevice] associated with the given device and

Comment on lines +128 to +167
impl SourceOutputDevice for MultiColorChassis {
fn write_event(
&mut self,
event: crate::input::output_event::OutputEvent,
) -> Result<(), crate::input::source::OutputError> {
//log::trace!("Received output event: {event:?}");
let _ = event;
Ok(())
}

fn upload_effect(
&mut self,
effect: evdev::FFEffectData,
) -> Result<i16, crate::input::source::OutputError> {
//log::trace!("Received upload effect: {effect:?}");
let _ = effect;
Ok(-1)
}

fn update_effect(
&mut self,
effect_id: i16,
effect: evdev::FFEffectData,
) -> Result<(), crate::input::source::OutputError> {
//log::trace!("Received update effect: {effect_id:?} {effect:?}");
let _ = effect;
let _ = effect_id;
Ok(())
}

fn erase_effect(&mut self, effect_id: i16) -> Result<(), crate::input::source::OutputError> {
//log::trace!("Received erase effect: {effect_id:?}");
let _ = effect_id;
Ok(())
}

fn stop(&mut self) -> Result<(), crate::input::source::OutputError> {
Ok(())
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can omit these methods if they are not implemented since a default implementation already exists, but I presume we'll want to handle output events; notably DualSense output events that change LED color.

Suggested change
impl SourceOutputDevice for MultiColorChassis {
fn write_event(
&mut self,
event: crate::input::output_event::OutputEvent,
) -> Result<(), crate::input::source::OutputError> {
//log::trace!("Received output event: {event:?}");
let _ = event;
Ok(())
}
fn upload_effect(
&mut self,
effect: evdev::FFEffectData,
) -> Result<i16, crate::input::source::OutputError> {
//log::trace!("Received upload effect: {effect:?}");
let _ = effect;
Ok(-1)
}
fn update_effect(
&mut self,
effect_id: i16,
effect: evdev::FFEffectData,
) -> Result<(), crate::input::source::OutputError> {
//log::trace!("Received update effect: {effect_id:?} {effect:?}");
let _ = effect;
let _ = effect_id;
Ok(())
}
fn erase_effect(&mut self, effect_id: i16) -> Result<(), crate::input::source::OutputError> {
//log::trace!("Received erase effect: {effect_id:?}");
let _ = effect_id;
Ok(())
}
fn stop(&mut self) -> Result<(), crate::input::source::OutputError> {
Ok(())
}
}
impl SourceOutputDevice for MultiColorChassis {}

Comment on lines +56 to +58
- group: led
led:
name: ASUS ROG Ally Config
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also add these to the rootfs/usr/share/inputplumber/schema/composite_device_v1.json schema file.

Also, is "ASUS ROG Ally Config" the actual name returned by the driver?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's the name luke gave it

Comment on lines +40 to +47
#[interface(name = "org.shadowblip.Input.Source.LEDDevice")]
impl SourceLedInterface {
/// Returns the human readable name of the device (e.g. XBox 360 Pad)
#[zbus(property)]
fn id(&self) -> fdo::Result<String> {
Ok(self.device.sysname())
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do this in a follow-up PR, but we should probably make an interface to allow users to change LED colors using DBus.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. Since I could not figure out how to make colors change via dualsense emulation and dbus I just implemented the basic to have leds change colors once.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also add a dbus bool property to permit or block source devices from adjusting the RGB color in the follow on PR. That will ensure targets like the DS5 don't change the RGB if the user prefers they not be changed.

Comment on lines +53 to +57
let multi_index_strings = contents
.split_whitespace()
.into_iter()
.map(|str| String::from(str))
.collect::<Vec<String>>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make clippy happy:

Suggested change
let multi_index_strings = contents
.split_whitespace()
.into_iter()
.map(|str| String::from(str))
.collect::<Vec<String>>();
let multi_index_strings = contents
.split_whitespace()
.map(String::from)
.collect::<Vec<String>>();

Comment on lines +24 to +26
enum IndexType {
RGB,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make clippy happy:

Suggested change
enum IndexType {
RGB,
}
enum IndexType {
Rgb,
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh no my eyes! Noooo not this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also do an #allow here to make clippy ignore it since it's an acronym

pub struct MultiColorChassis {
multi_intensity_path: PathBuf,
multi_index_map: Vec<IndexType>,
fixed_color: Option<LedFixedColor>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we ever use fixed_color outside initialization? Maybe we can remove this and just set the color in the constructor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to set it back after a resume or keep track of it I left it just for good measure, but yeah not very usefult.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we not storing the last setting otherwise? We could call this current_color and report it in dbus.

Comment on lines +87 to +103
let contents = (self
.multi_index_map
.iter()
.zip(contents.split_whitespace().into_iter())
.map(|(index_type, index_value)| match index_type {
IndexType::RGB => {
(((r as u32) << 16u32) | ((g as u32) << 8u32) | ((b as u32) << 0u32))
.to_string()
}
_ => String::from(index_value),
})
.collect::<Vec<String>>())
.join(" ");
Ok(
std::fs::write(self.multi_intensity_path.as_path(), contents)
.map_err(|err| Box::new(MultiColorChassisError::MultiIntensityUpdateError(err)))?,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To fix clippy warnings:

Suggested change
let contents = (self
.multi_index_map
.iter()
.zip(contents.split_whitespace().into_iter())
.map(|(index_type, index_value)| match index_type {
IndexType::RGB => {
(((r as u32) << 16u32) | ((g as u32) << 8u32) | ((b as u32) << 0u32))
.to_string()
}
_ => String::from(index_value),
})
.collect::<Vec<String>>())
.join(" ");
Ok(
std::fs::write(self.multi_intensity_path.as_path(), contents)
.map_err(|err| Box::new(MultiColorChassisError::MultiIntensityUpdateError(err)))?,
)
let values = self
.multi_index_map
.iter()
.zip(contents.split_whitespace())
.map(|(index_type, _index_value)| match index_type {
IndexType::Rgb => {
(((r as u32) << 16u32) | ((g as u32) << 8u32) | (b as u32)).to_string()
}
})
.collect::<Vec<String>>();
let contents = values.join(" ");
std::fs::write(self.multi_intensity_path.as_path(), contents)
.map_err(|err| Box::new(MultiColorChassisError::MultiIntensityUpdateError(err)))?;
Ok(())

Comment on lines +129 to +136
fn write_event(
&mut self,
event: crate::input::output_event::OutputEvent,
) -> Result<(), crate::input::source::OutputError> {
//log::trace!("Received output event: {event:?}");
let _ = event;
Ok(())
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably handle output events so LEDs can be controlled. Or we can handle this in a follow-up PR.

Suggested change
fn write_event(
&mut self,
event: crate::input::output_event::OutputEvent,
) -> Result<(), crate::input::source::OutputError> {
//log::trace!("Received output event: {event:?}");
let _ = event;
Ok(())
}
fn write_event(&mut self, event: OutputEvent) -> Result<(), crate::input::source::OutputError> {
//log::trace!("Received output event: {event:?}");
match event {
OutputEvent::DualSense(report) => {
if !report.allow_led_color {
return Ok(());
}
// Handle DualSense LED events...
}
_ => {
return Ok(());
}
}
Ok(())
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was unable to figure out why so I left it alone for this PR, but I will look into getting it in a follow-up commit in this PR

pub struct Led {
pub id: Option<String>,
pub name: Option<String>,
pub led_fixed_color: Option<LedFixedColor>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really see a case where we would ever specify a device start up with a specific color as this is entirely user preference. A simple dbus interface should be sufficient to expose and test this feature.

Comment on lines +40 to +47
#[interface(name = "org.shadowblip.Input.Source.LEDDevice")]
impl SourceLedInterface {
/// Returns the human readable name of the device (e.g. XBox 360 Pad)
#[zbus(property)]
fn id(&self) -> fdo::Result<String> {
Ok(self.device.sysname())
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also add a dbus bool property to permit or block source devices from adjusting the RGB color in the follow on PR. That will ensure targets like the DS5 don't change the RGB if the user prefers they not be changed.

/// [LedDevice] represents an input device using the leds subsystem.
#[derive(Debug)]
pub enum LedDevice {
MultiColorChassis(SourceDriver<MultiColorChassis>),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might consider changing this class name fro MultiColorChassis to JoystickRing since that's what the new asus driver calls them and I'll be changing ayn/ayaneo-platform drivers to do the same.

pub struct MultiColorChassis {
multi_intensity_path: PathBuf,
multi_index_map: Vec<IndexType>,
fixed_color: Option<LedFixedColor>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we not storing the last setting otherwise? We could call this current_color and report it in dbus.

@pastaq
Copy link
Contributor

pastaq commented Feb 23, 2025

Continued in #297

@pastaq pastaq closed this Feb 23, 2025
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