-
Notifications
You must be signed in to change notification settings - Fork 21
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
Conversation
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.
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. |
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// 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. |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Create a new [IioDevice] associated with the given device and | |
/// Create a new [LedDevice] associated with the given device and |
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(()) | ||
} | ||
} |
There was a problem hiding this comment.
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.
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 {} |
- group: led | ||
led: | ||
name: ASUS ROG Ally Config |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
#[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()) | ||
} | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
let multi_index_strings = contents | ||
.split_whitespace() | ||
.into_iter() | ||
.map(|str| String::from(str)) | ||
.collect::<Vec<String>>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make clippy happy:
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>>(); |
enum IndexType { | ||
RGB, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make clippy happy:
enum IndexType { | |
RGB, | |
} | |
enum IndexType { | |
Rgb, | |
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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>, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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)))?, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To fix clippy warnings:
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(()) |
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(()) | ||
} |
There was a problem hiding this comment.
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.
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(()) | |
} |
There was a problem hiding this comment.
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>, |
There was a problem hiding this comment.
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.
#[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()) | ||
} | ||
} |
There was a problem hiding this comment.
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>), |
There was a problem hiding this comment.
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>, |
There was a problem hiding this comment.
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.
Continued in #297 |
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.