Compare commits

..

1 Commits

Author SHA1 Message Date
Hamidreza Khorsand a43bbc0ed4 Merge branch 'main' into 'devel'
Add G614JU support

See merge request asus-linux/asusctl!239
2025-12-24 03:13:35 +03:30
14 changed files with 546 additions and 444 deletions
-3
View File
@@ -4,9 +4,6 @@
### Changed ### Changed
- Added support for TUF keyboard powerstate control - Added support for TUF keyboard powerstate control
- Improved AniMe Matrix support thanks to @Seom1177 !
- Fixed a bug with one-shot battery change, thanks @bitr8 !
## [6.2.0] ## [6.2.0]
Generated
+272 -279
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -44,7 +44,7 @@ smol = "^2.0"
mio = "0.8.11" mio = "0.8.11"
futures-util = "0.3.31" futures-util = "0.3.31"
zbus = "5.13.1" zbus = "5.5.0"
logind-zbus = { version = "5.2.0" } #, default-features = false, features = ["non_blocking"] } logind-zbus = { version = "5.2.0" } #, default-features = false, features = ["non_blocking"] }
serde = { version = "^1.0", features = ["serde_derive"] } serde = { version = "^1.0", features = ["serde_derive"] }
+1 -1
View File
@@ -1192,7 +1192,7 @@ fn print_firmware_attr(attr: &AsusArmouryProxyBlocking) -> Result<(), Box<dyn st
fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> { fn handle_armoury_command(cmd: &ArmouryCommand) -> Result<(), Box<dyn std::error::Error>> {
{ {
if cmd.free.is_empty() || (cmd.free.len() % 2 != 0) || cmd.help { if cmd.free.is_empty() || (cmd.free.len() % 2 != 0) || cmd.help {
const USAGE: &str = "Usage: asusctl armoury panel_overdrive 1 nv_dynamic_boost 5"; const USAGE: &str = "Usage: asusctl platform panel_overdrive 1 nv_dynamic_boost 5";
if cmd.free.len() % 2 != 0 { if cmd.free.len() % 2 != 0 {
println!( println!(
"Incorrect number of args, each attribute label must be paired with a setting:" "Incorrect number of args, each attribute label must be paired with a setting:"
+29 -43
View File
@@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use config_traits::StdConfig; use config_traits::StdConfig;
use log::{debug, error, info, warn}; use log::{debug, error, info};
use rog_platform::asus_armoury::{AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes}; use rog_platform::asus_armoury::{AttrValue, Attribute, FirmwareAttribute, FirmwareAttributes};
use rog_platform::platform::{PlatformProfile, RogPlatform}; use rog_platform::platform::{PlatformProfile, RogPlatform};
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
@@ -205,13 +205,7 @@ impl crate::Reloadable for AsusArmouryAttribute {
self.attr.base_path_exists(); self.attr.base_path_exists();
e e
})?; })?;
info!( info!("Set {} to {:?}", self.attr.name(), tune);
"Restored PPT armoury setting {} to {:?}",
self.attr.name(),
tune
);
} else {
info!("Ignored restoring PPT armoury setting {} as tuning group is disabled or no saved value", self.attr.name());
} }
} else { } else {
// Handle non-PPT attributes (boolean and other settings) // Handle non-PPT attributes (boolean and other settings)
@@ -219,10 +213,7 @@ impl crate::Reloadable for AsusArmouryAttribute {
self.attr self.attr
.set_current_value(&AttrValue::Integer(*saved_value)) .set_current_value(&AttrValue::Integer(*saved_value))
.map_err(|e| { .map_err(|e| {
error!( error!("Could not set {} value: {e:?}", self.attr.name());
"Error restoring armoury setting {}: {e:?}",
self.attr.name()
);
self.attr.base_path_exists(); self.attr.base_path_exists();
e e
})?; })?;
@@ -231,11 +222,6 @@ impl crate::Reloadable for AsusArmouryAttribute {
self.attr.name(), self.attr.name(),
saved_value saved_value
); );
} else {
info!(
"No saved armoury setting for {}: skipping restore",
self.attr.name()
);
} }
} }
@@ -411,44 +397,44 @@ impl AsusArmouryAttribute {
self.attr self.attr
.set_current_value(&AttrValue::Integer(value)) .set_current_value(&AttrValue::Integer(value))
.map_err(|e| { .map_err(|e| {
error!( error!("Could not set value: {e:?}");
"Could not set value to PPT property {}: {e:?}",
self.attr.name()
);
e e
})?; })?;
} else {
warn!(
"Tuning group is disabled: skipping setting value to PPT property {}",
self.attr.name()
);
} }
} else { } else {
self.attr self.attr
.set_current_value(&AttrValue::Integer(value)) .set_current_value(&AttrValue::Integer(value))
.map_err(|e| { .map_err(|e| {
error!( error!("Could not set value: {e:?}");
"Could not set value {value} to attribute {}: {e:?}",
self.attr.name()
);
e e
})?; })?;
let mut settings = self.config.lock().await; let has_attr = self
settings .config
.lock()
.await
.armoury_settings .armoury_settings
.entry(self.name()) .contains_key(&self.name());
.and_modify(|setting| { if has_attr {
debug!("Set config for {} = {value}", self.attr.name()); if let Some(setting) = self
*setting = value; .config
}) .lock()
.or_insert_with(|| { .await
debug!("Adding config for {} = {value}", self.attr.name()); .armoury_settings
value .get_mut(&self.name())
}); {
*setting = value
}
} else {
debug!("Adding config for {}", self.attr.name());
self.config
.lock()
.await
.armoury_settings
.insert(self.name(), value);
debug!("Set config for {} = {:?}", self.attr.name(), value);
}
} }
// write config after setting value
self.config.lock().await.write(); self.config.lock().await.write();
Ok(()) Ok(())
} }
+2 -11
View File
@@ -8,12 +8,6 @@ use serde::{Deserialize, Serialize};
const CONFIG_FILE: &str = "asusd.ron"; const CONFIG_FILE: &str = "asusd.ron";
/// Default value for base_charge_control_end_threshold when not present in config.
/// Returns 0 so restore_charge_limit() skips restoration for upgraded configs.
fn default_base_charge_limit() -> u8 {
0
}
#[derive(Default, Clone, Deserialize, Serialize, PartialEq)] #[derive(Default, Clone, Deserialize, Serialize, PartialEq)]
pub struct Tuning { pub struct Tuning {
pub enabled: bool, pub enabled: bool,
@@ -25,8 +19,8 @@ type Tunings = HashMap<PlatformProfile, Tuning>;
pub struct Config { pub struct Config {
// The current charge limit applied // The current charge limit applied
pub charge_control_end_threshold: u8, pub charge_control_end_threshold: u8,
/// Save charge limit for restoring after one-shot full charge /// Save charge limit for restoring
#[serde(default = "default_base_charge_limit")] #[serde(skip)]
pub base_charge_control_end_threshold: u8, pub base_charge_control_end_threshold: u8,
pub disable_nvidia_powerd_on_battery: bool, pub disable_nvidia_powerd_on_battery: bool,
/// An optional command/script to run when power is changed to AC /// An optional command/script to run when power is changed to AC
@@ -92,9 +86,6 @@ impl Default for Config {
fn default() -> Self { fn default() -> Self {
Self { Self {
charge_control_end_threshold: 100, charge_control_end_threshold: 100,
// NOTE: This is intentionally 100 (not 0 like the serde default).
// New installs get 100 (no limit). Upgraded configs missing this
// field get 0 via serde, which skips restore_charge_limit().
base_charge_control_end_threshold: 100, base_charge_control_end_threshold: 100,
disable_nvidia_powerd_on_battery: true, disable_nvidia_powerd_on_battery: true,
ac_command: Default::default(), ac_command: Default::default(),
+1 -1
View File
@@ -9,7 +9,7 @@ Environment=IS_SERVICE=1
# Reduce noisy span logs while keeping useful debug info for asusd and related crates. # Reduce noisy span logs while keeping useful debug info for asusd and related crates.
# Keep global level at info but allow debug for our crates; silence tracing::span (very noisy) # Keep global level at info but allow debug for our crates; silence tracing::span (very noisy)
# RUST_LOG format: <module>=<level>,... (levels: error,warn,info,debug,trace) # RUST_LOG format: <module>=<level>,... (levels: error,warn,info,debug,trace)
Environment=RUST_LOG="info,asusd=debug,rog_platform=debug,tracing::span=error,zbus::object_server=error,zbus::connection::handshake::common=error,zbus::connection::handshake::client=error" Environment=RUST_LOG="info,asusd=debug,rog_platform=debug,tracing::span=error"
# required to prevent init issues with hid_asus and MCU # required to prevent init issues with hid_asus and MCU
ExecStartPre=/bin/sleep 1 ExecStartPre=/bin/sleep 1
ExecStart=/usr/bin/asusd ExecStart=/usr/bin/asusd
+2 -20
View File
@@ -38,16 +38,7 @@
( (
device_name: "FA617NS", device_name: "FA617NS",
product_id: "", product_id: "",
layout_name: "fa507", layout_name: "fx505d",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard],
),
(
device_name: "FA617NT",
product_id: "",
layout_name: "fa507",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: r#None, advanced_type: r#None,
@@ -56,16 +47,7 @@
( (
device_name: "FA617XS", device_name: "FA617XS",
product_id: "", product_id: "",
layout_name: "fa507", layout_name: "fx505d",
basic_modes: [Static, Breathe, Pulse],
basic_zones: [],
advanced_type: r#None,
power_zones: [Keyboard],
),
(
device_name: "FA617XT",
product_id: "",
layout_name: "fa507",
basic_modes: [Static, Breathe, Pulse], basic_modes: [Static, Breathe, Pulse],
basic_zones: [], basic_zones: [],
advanced_type: r#None, advanced_type: r#None,
-6
View File
@@ -359,12 +359,6 @@ impl From<AuraEffect> for AuraModeNum {
} }
} }
#[cfg(feature = "dbus")]
impl zbus::zvariant::Basic for AuraModeNum {
const SIGNATURE_CHAR: char = 'u';
const SIGNATURE_STR: &'static str = "u";
}
/// Base effects have no zoning, while multizone is 1-4 /// Base effects have no zoning, while multizone is 1-4
#[cfg_attr( #[cfg_attr(
feature = "dbus", feature = "dbus",
+192 -4
View File
@@ -9,11 +9,15 @@ use std::process::Command;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
use futures_util::StreamExt;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use notify_rust::{Hint, Notification, Timeout}; use notify_rust::{Hint, Notification, Timeout, Urgency};
use rog_platform::platform::GpuMode;
use rog_platform::power::AsusPower; use rog_platform::power::AsusPower;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use supergfxctl::pci_device::GfxPower; use supergfxctl::actions::UserActionRequired as GfxUserAction;
use supergfxctl::pci_device::{GfxMode, GfxPower};
use supergfxctl::zbus_proxy::DaemonProxy as SuperProxy;
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
@@ -141,8 +145,12 @@ pub fn start_notifications(
} }
}); });
info!("Attempting to start plain dgpu status monitor"); let enabled_notifications_copy = config.clone();
start_dpu_status_mon(config.clone()); let no_supergfx = move |e: &zbus::Error| {
error!("zbus signal: receive_notify_gfx_status: {e}");
warn!("Attempting to start plain dgpu status monitor");
start_dpu_status_mon(enabled_notifications_copy.clone());
};
// GPU MUX Mode notif // GPU MUX Mode notif
// TODO: need to get armoury attrs and iter to find // TODO: need to get armoury attrs and iter to find
@@ -181,9 +189,95 @@ pub fn start_notifications(
// Ok::<(), zbus::Error>(()) // Ok::<(), zbus::Error>(())
// }); // });
let enabled_notifications_copy = config.clone();
// GPU Mode change/action notif
tokio::spawn(async move {
let conn = zbus::Connection::system().await.inspect_err(|e| {
no_supergfx(e);
})?;
let proxy = SuperProxy::builder(&conn).build().await.inspect_err(|e| {
no_supergfx(e);
})?;
let _ = proxy.mode().await.inspect_err(|e| {
no_supergfx(e);
})?;
let proxy_copy = proxy.clone();
let enabled_notifications_copy_action = enabled_notifications_copy.clone();
let mut p = proxy.receive_notify_action().await?;
tokio::spawn(async move {
info!("Started zbus signal thread: receive_notify_action");
while let Some(e) = p.next().await {
if let Ok(out) = e.args() {
// Respect user notification settings for gpu actions
if let Ok(cfg) = enabled_notifications_copy_action.lock() {
if !cfg.notifications.enabled || !cfg.notifications.receive_notify_gfx {
continue;
}
}
let action = out.action();
let mode = convert_gfx_mode(proxy.mode().await.unwrap_or_default());
match action {
supergfxctl::actions::UserActionRequired::Reboot => {
do_mux_notification("Graphics mode change requires reboot", &mode)
}
_ => do_gfx_action_notif(<&str>::from(action), *action, mode),
}
.map_err(|e| {
error!("zbus signal: do_gfx_action_notif: {e}");
e
})
.ok();
}
}
});
let mut p = proxy_copy.receive_notify_gfx_status().await?;
tokio::spawn(async move {
info!("Started zbus signal thread: receive_notify_gfx_status");
let mut last_status = GfxPower::Unknown;
while let Some(e) = p.next().await {
if let Ok(out) = e.args() {
let status = out.status;
if status != GfxPower::Unknown && status != last_status {
if let Ok(config) = enabled_notifications_copy.lock() {
if !config.notifications.receive_notify_gfx_status
|| !config.notifications.enabled
{
continue;
}
}
// Required check because status cycles through
// active/unknown/suspended
do_gpu_status_notif("dGPU status changed:", &status)
.show_async()
.await
.unwrap()
.on_close(|_| ());
}
last_status = status;
}
}
});
Ok::<(), zbus::Error>(())
});
Ok(vec![blocking]) Ok(vec![blocking])
} }
fn convert_gfx_mode(gfx: GfxMode) -> GpuMode {
match gfx {
GfxMode::Hybrid => GpuMode::Optimus,
GfxMode::Integrated => GpuMode::Integrated,
GfxMode::NvidiaNoModeset => GpuMode::Optimus,
GfxMode::Vfio => GpuMode::Vfio,
GfxMode::AsusEgpu => GpuMode::Egpu,
GfxMode::AsusMuxDgpu => GpuMode::Ultimate,
GfxMode::None => GpuMode::Error,
}
}
fn base_notification<T>(message: &str, data: &T) -> Notification fn base_notification<T>(message: &str, data: &T) -> Notification
where where
T: Display, T: Display,
@@ -209,3 +303,97 @@ fn do_gpu_status_notif(message: &str, data: &GfxPower) -> Notification {
notif.icon(icon); notif.icon(icon);
notif notif
} }
fn do_gfx_action_notif(message: &str, action: GfxUserAction, mode: GpuMode) -> Result<()> {
if matches!(action, GfxUserAction::Reboot) {
do_mux_notification("Graphics mode change requires reboot", &mode).ok();
return Ok(());
}
let mut notif = Notification::new();
notif
.appname(NOTIF_HEADER)
.summary(&format!("Changing to {mode}. {message}"))
//.hint(Hint::Resident(true))
.hint(Hint::Category("device".into()))
.urgency(Urgency::Critical)
// For user-action notifications keep them visible if they require interaction
// but for non-interactive actions we prefer they auto-hide like other notifs.
.timeout(Timeout::Milliseconds(6000))
.icon("dialog-warning")
.hint(Hint::Transient(true));
if matches!(action, GfxUserAction::Logout) {
notif.action("gfx-mode-session-action", "Logout");
let handle = notif.show()?;
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
if desktop.to_lowercase() == "gnome" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("gnome-session-quit");
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else if desktop.to_lowercase() == "kde" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("qdbus");
cmd.args([
"org.kde.ksmserver", "/KSMServer", "logout", "1", "0", "0",
]);
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else {
// todo: handle alternatives
}
}
} else {
notif.show()?;
}
Ok(())
}
/// Actual `GpuMode` unused as data is never correct until switched by reboot
fn do_mux_notification(message: &str, m: &GpuMode) -> Result<()> {
let mut notif = base_notification(message, &m.to_string());
notif
.action("gfx-mode-session-action", "Reboot")
.urgency(Urgency::Critical)
.icon("system-reboot-symbolic")
.hint(Hint::Transient(true));
let handle = notif.show()?;
std::thread::spawn(|| {
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
if desktop.to_lowercase() == "gnome" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("gnome-session-quit");
cmd.arg("--reboot");
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
} else if desktop.to_lowercase() == "kde" {
handle.wait_for_action(|id| {
if id == "gfx-mode-session-action" {
let mut cmd = Command::new("qdbus");
cmd.args([
"org.kde.ksmserver", "/KSMServer", "logout", "1", "1", "0",
]);
cmd.spawn().ok();
} else if id == "__closed" {
// TODO: cancel the switching
}
});
}
}
});
Ok(())
}
+1 -1
View File
@@ -170,7 +170,7 @@ pub fn init_tray(_supported_properties: Vec<Properties>, config: Arc<Mutex<Confi
// TODO: return an error to the UI // TODO: return an error to the UI
let mut tray; let mut tray;
match tray_init.disable_dbus_name(true).spawn().await { match tray_init.spawn_without_dbus_name().await {
Ok(t) => tray = t, Ok(t) => tray = t,
Err(e) => { Err(e) => {
log::error!( log::error!(
-6
View File
@@ -177,12 +177,6 @@ pub enum AuraMode {
DoubleFade = 14, DoubleFade = 14,
} }
#[cfg(feature = "dbus")]
impl zbus::zvariant::Basic for AuraMode {
const SIGNATURE_CHAR: char = 'u';
const SIGNATURE_STR: &'static str = "u";
}
impl AuraMode { impl AuraMode {
pub fn list() -> [String; 15] { pub fn list() -> [String; 15] {
[ [
+32 -47
View File
@@ -12,13 +12,12 @@ use crate::usb::{PROD_ID1, PROD_ID1_STR, PROD_ID2, PROD_ID2_STR};
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)] #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub enum SlashType { pub enum SlashType {
GA403_2024, GA403,
GA403_2025, GA403W,
GA605_2024, GA605,
GA605_2025, GU605,
GU605_2024, GU605C,
GU605_2025, G614F,
G614_2025,
#[default] #[default]
Unsupported, Unsupported,
} }
@@ -26,26 +25,24 @@ pub enum SlashType {
impl SlashType { impl SlashType {
pub const fn prod_id(&self) -> u16 { pub const fn prod_id(&self) -> u16 {
match self { match self {
SlashType::GA403_2025 => PROD_ID2, SlashType::GA403W => PROD_ID2,
SlashType::GA403_2024 => PROD_ID1, SlashType::GA403 => PROD_ID1,
SlashType::GA605_2025 => PROD_ID2, SlashType::GA605 => PROD_ID2,
SlashType::GA605_2024 => PROD_ID2, SlashType::GU605 => PROD_ID1,
SlashType::GU605_2025 => PROD_ID2, SlashType::GU605C => PROD_ID2,
SlashType::GU605_2024 => PROD_ID1, SlashType::G614F => PROD_ID2,
SlashType::G614_2025 => PROD_ID2,
SlashType::Unsupported => 0, SlashType::Unsupported => 0,
} }
} }
pub const fn prod_id_str(&self) -> &str { pub const fn prod_id_str(&self) -> &str {
match self { match self {
SlashType::GA403_2025 => PROD_ID2_STR, SlashType::GA403W => PROD_ID2_STR,
SlashType::GA403_2024 => PROD_ID1_STR, SlashType::GA403 => PROD_ID1_STR,
SlashType::GA605_2025 => PROD_ID2_STR, SlashType::GA605 => PROD_ID2_STR,
SlashType::GA605_2024 => PROD_ID2_STR, SlashType::GU605 => PROD_ID1_STR,
SlashType::GU605_2025 => PROD_ID2_STR, SlashType::GU605C => PROD_ID2_STR,
SlashType::GU605_2024 => PROD_ID1_STR, SlashType::G614F => PROD_ID2_STR,
SlashType::G614_2025 => PROD_ID2_STR,
SlashType::Unsupported => "", SlashType::Unsupported => "",
} }
} }
@@ -53,24 +50,17 @@ impl SlashType {
pub fn from_dmi() -> Self { pub fn from_dmi() -> Self {
let board_name = DMIID::new().unwrap_or_default().board_name.to_uppercase(); let board_name = DMIID::new().unwrap_or_default().board_name.to_uppercase();
if board_name.contains("G614F") { if board_name.contains("G614F") {
SlashType::G614_2025 SlashType::G614F
} else if [ } else if board_name.contains("GA403W") {
"GA403W", "GA403UH", "GA403UM", "GA403UP", SlashType::GA403W
]
.iter()
.any(|s| board_name.contains(s))
{
SlashType::GA403_2025
} else if board_name.contains("GA403") { } else if board_name.contains("GA403") {
SlashType::GA403_2024 SlashType::GA403
} else if board_name.contains("GA605K") {
SlashType::GA605_2025
} else if board_name.contains("GA605") { } else if board_name.contains("GA605") {
SlashType::GA605_2024 SlashType::GA605
} else if board_name.contains("GU605C") { } else if board_name.contains("GU605C") {
SlashType::GU605_2025 SlashType::GU605C
} else if board_name.contains("GU605") { } else if board_name.contains("GU605") {
SlashType::GU605_2024 SlashType::GU605
} else { } else {
SlashType::Unsupported SlashType::Unsupported
} }
@@ -82,13 +72,12 @@ impl FromStr for SlashType {
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
Ok(match s.to_uppercase().as_str() { Ok(match s.to_uppercase().as_str() {
"GA403_2025" => Self::GA403_2025, "GA403W" => Self::GA403W,
"GA403_2024" => Self::GA403_2024, "GA403" => Self::GA403,
"GA605_2025" => Self::GA605_2025, "GA605" => Self::GA605,
"GA605_2024" => Self::GA605_2024, "GU605C" => Self::GU605C,
"GU605_2025" => Self::GU605_2025, "GU605" => Self::GU605,
"GU605_2024" => Self::GU605_2024, "G614FR" => Self::G614F,
"G614_2025" => Self::G614_2025,
_ => Self::Unsupported, _ => Self::Unsupported,
}) })
} }
@@ -97,7 +86,6 @@ impl FromStr for SlashType {
#[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))] #[cfg_attr(feature = "dbus", derive(Type, Value, OwnedValue))]
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)] #[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
pub enum SlashMode { pub enum SlashMode {
Static = 0x06,
Bounce = 0x10, Bounce = 0x10,
Slash = 0x12, Slash = 0x12,
Loading = 0x13, Loading = 0x13,
@@ -121,7 +109,6 @@ impl FromStr for SlashMode {
fn from_str(s: &str) -> Result<Self, SlashError> { fn from_str(s: &str) -> Result<Self, SlashError> {
match s { match s {
"Static" => Ok(SlashMode::Static),
"Bounce" => Ok(SlashMode::Bounce), "Bounce" => Ok(SlashMode::Bounce),
"Slash" => Ok(SlashMode::Slash), "Slash" => Ok(SlashMode::Slash),
"Loading" => Ok(SlashMode::Loading), "Loading" => Ok(SlashMode::Loading),
@@ -145,7 +132,6 @@ impl FromStr for SlashMode {
impl Display for SlashMode { impl Display for SlashMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let str = match &self { let str = match &self {
SlashMode::Static => String::from("Static"),
SlashMode::Bounce => String::from("Bounce"), SlashMode::Bounce => String::from("Bounce"),
SlashMode::Slash => String::from("Slash"), SlashMode::Slash => String::from("Slash"),
SlashMode::Loading => String::from("Loading"), SlashMode::Loading => String::from("Loading"),
@@ -167,9 +153,8 @@ impl Display for SlashMode {
} }
impl SlashMode { impl SlashMode {
pub fn list() -> [String; 16] { pub fn list() -> [String; 15] {
[ [
SlashMode::Static.to_string(),
SlashMode::Bounce.to_string(), SlashMode::Bounce.to_string(),
SlashMode::Slash.to_string(), SlashMode::Slash.to_string(),
SlashMode::Loading.to_string(), SlashMode::Loading.to_string(),
+13 -21
View File
@@ -39,24 +39,17 @@ pub fn get_slash_type() -> SlashType {
.unwrap_or_default(); .unwrap_or_default();
let board_name = dmi.board_name.to_uppercase(); let board_name = dmi.board_name.to_uppercase();
if board_name.contains("G614F") { if board_name.contains("G614F") {
SlashType::G614_2025 SlashType::G614F
} else if [ } else if board_name.contains("GA403W") {
"GA403W", "GA403UH", "GA403UM", "GA403UP", SlashType::GA403W
]
.iter()
.any(|s| board_name.contains(s))
{
SlashType::GA403_2025
} else if board_name.contains("GA403") { } else if board_name.contains("GA403") {
SlashType::GA403_2024 SlashType::GA403
} else if board_name.contains("GA605K") {
SlashType::GA605_2025
} else if board_name.contains("GA605") { } else if board_name.contains("GA605") {
SlashType::GA605_2024 SlashType::GA605
} else if board_name.contains("GU605C") { } else if board_name.contains("GU605C") {
SlashType::GU605_2025 SlashType::GU605C
} else if board_name.contains("GU605") { } else if board_name.contains("GU605") {
SlashType::GU605_2024 SlashType::GU605
} else { } else {
SlashType::Unsupported SlashType::Unsupported
} }
@@ -64,13 +57,12 @@ pub fn get_slash_type() -> SlashType {
pub const fn report_id(slash_type: SlashType) -> u8 { pub const fn report_id(slash_type: SlashType) -> u8 {
match slash_type { match slash_type {
SlashType::GA403_2025 => REPORT_ID_19B6, SlashType::GA403W => REPORT_ID_19B6,
SlashType::GA403_2024 => REPORT_ID_193B, SlashType::GA403 => REPORT_ID_193B,
SlashType::GA605_2025 => REPORT_ID_19B6, SlashType::GA605 => REPORT_ID_19B6,
SlashType::GA605_2024 => REPORT_ID_19B6, SlashType::G614F => REPORT_ID_19B6,
SlashType::GU605_2025 => REPORT_ID_19B6, SlashType::GU605 => REPORT_ID_193B,
SlashType::GU605_2024 => REPORT_ID_193B, SlashType::GU605C => REPORT_ID_19B6,
SlashType::G614_2025 => REPORT_ID_19B6,
SlashType::Unsupported => REPORT_ID_19B6, SlashType::Unsupported => REPORT_ID_19B6,
} }
} }