mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
unsafe pointery stuff
This commit is contained in:
444
src/core.rs
444
src/core.rs
@@ -42,9 +42,6 @@ static FAN_TYPE_2_PATH: &str = "/sys/devices/platform/asus-nb-wmi/fan_boost_mode
|
|||||||
/// - `LED_INIT4`
|
/// - `LED_INIT4`
|
||||||
pub(crate) struct RogCore {
|
pub(crate) struct RogCore {
|
||||||
handle: DeviceHandle<rusb::GlobalContext>,
|
handle: DeviceHandle<rusb::GlobalContext>,
|
||||||
initialised: bool,
|
|
||||||
led_endpoint: u8,
|
|
||||||
config: Config,
|
|
||||||
virt_keys: VirtKeys,
|
virt_keys: VirtKeys,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,22 +76,19 @@ impl RogCore {
|
|||||||
|
|
||||||
Ok(RogCore {
|
Ok(RogCore {
|
||||||
handle: dev_handle,
|
handle: dev_handle,
|
||||||
initialised: false,
|
|
||||||
led_endpoint,
|
|
||||||
config: Config::default().read(),
|
|
||||||
virt_keys: VirtKeys::new(),
|
virt_keys: VirtKeys::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn reload(&mut self) -> Result<(), Box<dyn Error>> {
|
pub(crate) async fn reload(&mut self, config: &mut Config) -> Result<(), Box<dyn Error>> {
|
||||||
let mode_curr = self.config.current_mode[3];
|
// let mode_curr = self.config.current_mode[3];
|
||||||
let mode = self
|
// let mode = self
|
||||||
.config
|
// .config
|
||||||
.builtin_modes
|
// .builtin_modes
|
||||||
.get_field_from(BuiltInModeByte::from(mode_curr).into())
|
// .get_field_from(BuiltInModeByte::from(mode_curr).into())
|
||||||
.unwrap()
|
// .unwrap()
|
||||||
.to_owned();
|
// .to_owned();
|
||||||
self.aura_write_messages(&[&mode])?;
|
// self.aura_write_messages(&[&mode])?;
|
||||||
|
|
||||||
let path = if Path::new(FAN_TYPE_1_PATH).exists() {
|
let path = if Path::new(FAN_TYPE_1_PATH).exists() {
|
||||||
FAN_TYPE_1_PATH
|
FAN_TYPE_1_PATH
|
||||||
@@ -105,8 +99,8 @@ impl RogCore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut file = OpenOptions::new().write(true).open(path)?;
|
let mut file = OpenOptions::new().write(true).open(path)?;
|
||||||
file.write_all(format!("{:?}\n", self.config.fan_mode).as_bytes())?;
|
file.write_all(format!("{:?}\n", config.fan_mode).as_bytes())?;
|
||||||
self.set_pstate_for_fan_mode(FanLevel::from(self.config.fan_mode))?;
|
self.set_pstate_for_fan_mode(FanLevel::from(config.fan_mode))?;
|
||||||
info!("Reloaded last saved settings");
|
info!("Reloaded last saved settings");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -128,174 +122,7 @@ impl RogCore {
|
|||||||
Err(AuraError::UsbError(rusb::Error::NoDevice))
|
Err(AuraError::UsbError(rusb::Error::NoDevice))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aura_write(&mut self, message: &[u8]) -> Result<(), AuraError> {
|
pub(crate) fn fan_mode_step(&mut self, config: &mut Config) -> Result<(), Box<dyn Error>> {
|
||||||
match self
|
|
||||||
.handle
|
|
||||||
.write_interrupt(self.led_endpoint, message, Duration::from_millis(2))
|
|
||||||
{
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => match err {
|
|
||||||
rusb::Error::Timeout => {}
|
|
||||||
_ => error!("Failed to read keyboard interrupt: {:?}", err),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn aura_write_messages(&mut self, messages: &[&[u8]]) -> Result<(), AuraError> {
|
|
||||||
if !self.initialised {
|
|
||||||
self.aura_write(&LED_INIT1)?;
|
|
||||||
self.aura_write(LED_INIT2.as_bytes())?;
|
|
||||||
self.aura_write(&LED_INIT3)?;
|
|
||||||
self.aura_write(LED_INIT4.as_bytes())?;
|
|
||||||
self.aura_write(&LED_INIT5)?;
|
|
||||||
self.initialised = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for message in messages {
|
|
||||||
self.aura_write(*message)?;
|
|
||||||
self.aura_write(&LED_SET)?;
|
|
||||||
}
|
|
||||||
// Changes won't persist unless apply is set
|
|
||||||
self.aura_write(&LED_APPLY)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write an effect block
|
|
||||||
///
|
|
||||||
/// `aura_effect_init` must be called any effect routine, and called only once.
|
|
||||||
pub fn aura_write_effect(&mut self, effect: Vec<Vec<u8>>) -> Result<(), AuraError> {
|
|
||||||
for row in effect.iter() {
|
|
||||||
self.aura_write(row)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write an effect block
|
|
||||||
///
|
|
||||||
/// `aura_effect_init` must be called any effect routine, and called only once.
|
|
||||||
pub async fn async_write_effect(
|
|
||||||
handle: &DeviceHandle<rusb::GlobalContext>,
|
|
||||||
endpoint: u8,
|
|
||||||
effect: Vec<Vec<u8>>,
|
|
||||||
) -> Result<(), AuraError> {
|
|
||||||
for row in effect.iter() {
|
|
||||||
match handle.write_interrupt(endpoint, row, Duration::from_millis(2)) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => match err {
|
|
||||||
rusb::Error::Timeout => {}
|
|
||||||
_ => error!("Failed to write LED interrupt: {:?}", err),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn aura_set_and_save(
|
|
||||||
&mut self,
|
|
||||||
supported_modes: &[BuiltInModeByte],
|
|
||||||
bytes: &[u8],
|
|
||||||
) -> Result<(), AuraError> {
|
|
||||||
let mode = BuiltInModeByte::from(bytes[3]);
|
|
||||||
if bytes[1] == 0xbc {
|
|
||||||
self.aura_write(bytes)?;
|
|
||||||
return Ok(());
|
|
||||||
} else if supported_modes.contains(&mode) || bytes[1] == 0xba {
|
|
||||||
let messages = [bytes];
|
|
||||||
self.aura_write_messages(&messages)?;
|
|
||||||
self.config.set_field_from(bytes);
|
|
||||||
self.config.write();
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
warn!("{:?} not supported", mode);
|
|
||||||
Err(AuraError::NotSupported)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn aura_bright_inc(
|
|
||||||
&mut self,
|
|
||||||
supported_modes: &[BuiltInModeByte],
|
|
||||||
max_bright: u8,
|
|
||||||
) -> Result<(), AuraError> {
|
|
||||||
let mut bright = self.config.brightness;
|
|
||||||
if bright < max_bright {
|
|
||||||
bright += 1;
|
|
||||||
self.config.brightness = bright;
|
|
||||||
let bytes = aura_brightness_bytes(bright);
|
|
||||||
self.aura_set_and_save(supported_modes, &bytes)?;
|
|
||||||
info!("Increased LED brightness to {:#?}", bright);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn aura_bright_dec(
|
|
||||||
&mut self,
|
|
||||||
supported_modes: &[BuiltInModeByte],
|
|
||||||
min_bright: u8,
|
|
||||||
) -> Result<(), AuraError> {
|
|
||||||
let mut bright = self.config.brightness;
|
|
||||||
if bright > min_bright {
|
|
||||||
bright -= 1;
|
|
||||||
self.config.brightness = bright;
|
|
||||||
let bytes = aura_brightness_bytes(bright);
|
|
||||||
self.aura_set_and_save(supported_modes, &bytes)?;
|
|
||||||
info!("Decreased LED brightness to {:#?}", bright);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Select next Aura effect
|
|
||||||
///
|
|
||||||
/// If the current effect is the last one then the effect selected wraps around to the first.
|
|
||||||
pub(crate) fn aura_mode_next(
|
|
||||||
&mut self,
|
|
||||||
supported_modes: &[BuiltInModeByte],
|
|
||||||
) -> Result<(), AuraError> {
|
|
||||||
// TODO: different path for multi-zone (byte 2 controlled, non-zero)
|
|
||||||
let mode_curr = self.config.current_mode[3];
|
|
||||||
let idx = supported_modes.binary_search(&mode_curr.into()).unwrap();
|
|
||||||
let idx_next = if idx < supported_modes.len() - 1 {
|
|
||||||
idx + 1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
let mode_next = self
|
|
||||||
.config
|
|
||||||
.builtin_modes
|
|
||||||
.get_field_from(supported_modes[idx_next].into())
|
|
||||||
.unwrap()
|
|
||||||
.to_owned();
|
|
||||||
self.aura_set_and_save(supported_modes, &mode_next)?;
|
|
||||||
info!("Switched LED mode to {:#?}", supported_modes[idx_next]);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Select previous Aura effect
|
|
||||||
///
|
|
||||||
/// If the current effect is the first one then the effect selected wraps around to the last.
|
|
||||||
pub(crate) fn aura_mode_prev(
|
|
||||||
&mut self,
|
|
||||||
supported_modes: &[BuiltInModeByte],
|
|
||||||
) -> Result<(), AuraError> {
|
|
||||||
// TODO: different path for multi-zone (byte 2 controlled, non-zero)
|
|
||||||
let mode_curr = self.config.current_mode[3];
|
|
||||||
let idx = supported_modes.binary_search(&mode_curr.into()).unwrap();
|
|
||||||
let idx_next = if idx > 0 {
|
|
||||||
idx - 1
|
|
||||||
} else {
|
|
||||||
supported_modes.len() - 1
|
|
||||||
};
|
|
||||||
let mode_next = self
|
|
||||||
.config
|
|
||||||
.builtin_modes
|
|
||||||
.get_field_from(supported_modes[idx_next].into())
|
|
||||||
.unwrap()
|
|
||||||
.to_owned();
|
|
||||||
self.aura_set_and_save(supported_modes, &mode_next)?;
|
|
||||||
info!("Switched LED mode to {:#?}", supported_modes[idx_next]);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn fan_mode_step(&mut self) -> Result<(), Box<dyn Error>> {
|
|
||||||
let path = if Path::new(FAN_TYPE_1_PATH).exists() {
|
let path = if Path::new(FAN_TYPE_1_PATH).exists() {
|
||||||
FAN_TYPE_1_PATH
|
FAN_TYPE_1_PATH
|
||||||
} else if Path::new(FAN_TYPE_2_PATH).exists() {
|
} else if Path::new(FAN_TYPE_2_PATH).exists() {
|
||||||
@@ -319,8 +146,8 @@ impl RogCore {
|
|||||||
info!("Fan mode stepped to: {:#?}", FanLevel::from(n));
|
info!("Fan mode stepped to: {:#?}", FanLevel::from(n));
|
||||||
fan_ctrl.write_all(format!("{:?}\n", n).as_bytes())?;
|
fan_ctrl.write_all(format!("{:?}\n", n).as_bytes())?;
|
||||||
self.set_pstate_for_fan_mode(FanLevel::from(n))?;
|
self.set_pstate_for_fan_mode(FanLevel::from(n))?;
|
||||||
self.config.fan_mode = n;
|
config.fan_mode = n;
|
||||||
self.config.write();
|
config.write();
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -435,60 +262,197 @@ impl RogCore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// use sysfs_class::{Brightness, SysClass};
|
/// UNSAFE: because we're holding a pointer to something that *may* go out of scope while the
|
||||||
// pub(crate) struct Backlight {
|
/// pointer is held. We're relying on access to struct to be behind a Mutex, and for behaviour
|
||||||
// backlight: sysfs_class::Backlight,
|
/// that may cause invalididated pointer to cause the program to panic rather than continue.
|
||||||
// step: u64,
|
pub(crate) struct LedWriter {
|
||||||
// max: u64,
|
handle: *mut DeviceHandle<rusb::GlobalContext>,
|
||||||
// }
|
led_endpoint: u8,
|
||||||
|
initialised: bool,
|
||||||
|
}
|
||||||
|
|
||||||
// impl Backlight {
|
/// UNSAFE
|
||||||
// pub(crate) fn new(id: &str) -> Result<Backlight, std::io::Error> {
|
unsafe impl Send for LedWriter {}
|
||||||
// for bl in sysfs_class::Backlight::iter() {
|
unsafe impl Sync for LedWriter {}
|
||||||
// let bl = bl?;
|
|
||||||
// if bl.id() == id {
|
impl LedWriter {
|
||||||
// let max = bl.max_brightness()?;
|
pub fn new(device_handle: *mut DeviceHandle<rusb::GlobalContext>, led_endpoint: u8) -> Self {
|
||||||
// let step = max / 50;
|
LedWriter {
|
||||||
// return Ok(Backlight {
|
handle: device_handle,
|
||||||
// backlight: bl,
|
led_endpoint,
|
||||||
// step,
|
initialised: false,
|
||||||
// max,
|
}
|
||||||
// });
|
}
|
||||||
// }
|
|
||||||
// }
|
pub fn aura_write(&mut self, message: &[u8]) -> Result<(), AuraError> {
|
||||||
// panic!("Backlight not found")
|
let handle = unsafe { &*self.handle };
|
||||||
// }
|
match handle.write_interrupt(self.led_endpoint, message, Duration::from_millis(2)) {
|
||||||
// pub(crate) fn step_up(&self) {
|
Ok(_) => {}
|
||||||
// let brightness = self
|
Err(err) => match err {
|
||||||
// .backlight
|
rusb::Error::Timeout => {}
|
||||||
// .brightness()
|
_ => error!("Failed to read keyboard interrupt: {:?}", err),
|
||||||
// .map_err(|err| warn!("Failed to fetch backlight level: {}", err))
|
},
|
||||||
// .unwrap();
|
}
|
||||||
// if brightness + self.step <= self.max {
|
Ok(())
|
||||||
// self.backlight
|
}
|
||||||
// .set_brightness(brightness + self.step)
|
|
||||||
// .map_or_else(
|
fn aura_write_messages(&mut self, messages: &[&[u8]]) -> Result<(), AuraError> {
|
||||||
// |err| warn!("Failed to increment backlight level: {}", err),
|
if !self.initialised {
|
||||||
// |_| {},
|
self.aura_write(&LED_INIT1)?;
|
||||||
// );
|
self.aura_write(LED_INIT2.as_bytes())?;
|
||||||
// }
|
self.aura_write(&LED_INIT3)?;
|
||||||
// }
|
self.aura_write(LED_INIT4.as_bytes())?;
|
||||||
// pub(crate) fn step_down(&self) {
|
self.aura_write(&LED_INIT5)?;
|
||||||
// let brightness = self
|
self.initialised = true;
|
||||||
// .backlight
|
}
|
||||||
// .brightness()
|
|
||||||
// .map_err(|err| warn!("Failed to fetch backlight level: {}", err))
|
for message in messages {
|
||||||
// .unwrap();
|
self.aura_write(*message)?;
|
||||||
// if brightness > self.step {
|
self.aura_write(&LED_SET)?;
|
||||||
// self.backlight
|
}
|
||||||
// .set_brightness(brightness - self.step)
|
// Changes won't persist unless apply is set
|
||||||
// .map_or_else(
|
self.aura_write(&LED_APPLY)?;
|
||||||
// |err| warn!("Failed to increment backlight level: {}", err),
|
Ok(())
|
||||||
// |_| {},
|
}
|
||||||
// );
|
|
||||||
// }
|
/// Write an effect block
|
||||||
// }
|
///
|
||||||
// }
|
/// `aura_effect_init` must be called any effect routine, and called only once.
|
||||||
|
pub fn aura_write_effect(&mut self, effect: Vec<Vec<u8>>) -> Result<(), AuraError> {
|
||||||
|
for row in effect.iter() {
|
||||||
|
self.aura_write(row)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write an effect block
|
||||||
|
///
|
||||||
|
/// `aura_effect_init` must be called any effect routine, and called only once.
|
||||||
|
pub async fn async_write_effect(
|
||||||
|
&self,
|
||||||
|
endpoint: u8,
|
||||||
|
effect: Vec<Vec<u8>>,
|
||||||
|
) -> Result<(), AuraError> {
|
||||||
|
let handle = unsafe { &*self.handle };
|
||||||
|
for row in effect.iter() {
|
||||||
|
match handle.write_interrupt(endpoint, row, Duration::from_millis(2)) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(err) => match err {
|
||||||
|
rusb::Error::Timeout => {}
|
||||||
|
_ => error!("Failed to write LED interrupt: {:?}", err),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn aura_set_and_save(
|
||||||
|
&mut self,
|
||||||
|
supported_modes: &[BuiltInModeByte],
|
||||||
|
bytes: &[u8],
|
||||||
|
config: &mut Config,
|
||||||
|
) -> Result<(), AuraError> {
|
||||||
|
let mode = BuiltInModeByte::from(bytes[3]);
|
||||||
|
if bytes[1] == 0xbc {
|
||||||
|
self.aura_write(bytes)?;
|
||||||
|
return Ok(());
|
||||||
|
} else if supported_modes.contains(&mode) || bytes[1] == 0xba {
|
||||||
|
let messages = [bytes];
|
||||||
|
self.aura_write_messages(&messages)?;
|
||||||
|
config.set_field_from(bytes);
|
||||||
|
config.write();
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
warn!("{:?} not supported", mode);
|
||||||
|
Err(AuraError::NotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn aura_bright_inc(
|
||||||
|
&mut self,
|
||||||
|
supported_modes: &[BuiltInModeByte],
|
||||||
|
max_bright: u8,
|
||||||
|
config: &mut Config,
|
||||||
|
) -> Result<(), AuraError> {
|
||||||
|
let mut bright = config.brightness;
|
||||||
|
if bright < max_bright {
|
||||||
|
bright += 1;
|
||||||
|
config.brightness = bright;
|
||||||
|
let bytes = aura_brightness_bytes(bright);
|
||||||
|
self.aura_set_and_save(supported_modes, &bytes, config)?;
|
||||||
|
info!("Increased LED brightness to {:#?}", bright);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn aura_bright_dec(
|
||||||
|
&mut self,
|
||||||
|
supported_modes: &[BuiltInModeByte],
|
||||||
|
min_bright: u8,
|
||||||
|
config: &mut Config,
|
||||||
|
) -> Result<(), AuraError> {
|
||||||
|
let mut bright = config.brightness;
|
||||||
|
if bright > min_bright {
|
||||||
|
bright -= 1;
|
||||||
|
config.brightness = bright;
|
||||||
|
let bytes = aura_brightness_bytes(bright);
|
||||||
|
self.aura_set_and_save(supported_modes, &bytes, config)?;
|
||||||
|
info!("Decreased LED brightness to {:#?}", bright);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Select next Aura effect
|
||||||
|
///
|
||||||
|
/// If the current effect is the last one then the effect selected wraps around to the first.
|
||||||
|
pub(crate) fn aura_mode_next(
|
||||||
|
&mut self,
|
||||||
|
supported_modes: &[BuiltInModeByte],
|
||||||
|
config: &mut Config,
|
||||||
|
) -> Result<(), AuraError> {
|
||||||
|
// TODO: different path for multi-zone (byte 2 controlled, non-zero)
|
||||||
|
let mode_curr = config.current_mode[3];
|
||||||
|
let idx = supported_modes.binary_search(&mode_curr.into()).unwrap();
|
||||||
|
let idx_next = if idx < supported_modes.len() - 1 {
|
||||||
|
idx + 1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
let mode_next = config
|
||||||
|
.builtin_modes
|
||||||
|
.get_field_from(supported_modes[idx_next].into())
|
||||||
|
.unwrap()
|
||||||
|
.to_owned();
|
||||||
|
self.aura_set_and_save(supported_modes, &mode_next, config)?;
|
||||||
|
info!("Switched LED mode to {:#?}", supported_modes[idx_next]);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Select previous Aura effect
|
||||||
|
///
|
||||||
|
/// If the current effect is the first one then the effect selected wraps around to the last.
|
||||||
|
pub(crate) fn aura_mode_prev(
|
||||||
|
&mut self,
|
||||||
|
supported_modes: &[BuiltInModeByte],
|
||||||
|
config: &mut Config,
|
||||||
|
) -> Result<(), AuraError> {
|
||||||
|
// TODO: different path for multi-zone (byte 2 controlled, non-zero)
|
||||||
|
let mode_curr = config.current_mode[3];
|
||||||
|
let idx = supported_modes.binary_search(&mode_curr.into()).unwrap();
|
||||||
|
let idx_next = if idx > 0 {
|
||||||
|
idx - 1
|
||||||
|
} else {
|
||||||
|
supported_modes.len() - 1
|
||||||
|
};
|
||||||
|
let mode_next = config
|
||||||
|
.builtin_modes
|
||||||
|
.get_field_from(supported_modes[idx_next].into())
|
||||||
|
.unwrap()
|
||||||
|
.to_owned();
|
||||||
|
self.aura_set_and_save(supported_modes, &mode_next, config)?;
|
||||||
|
info!("Switched LED mode to {:#?}", supported_modes[idx_next]);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Options)]
|
#[derive(Debug, Options)]
|
||||||
pub struct LedBrightness {
|
pub struct LedBrightness {
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ pub static DBUS_NAME: &'static str = "org.rogcore.Daemon";
|
|||||||
pub static DBUS_PATH: &'static str = "/org/rogcore/Daemon";
|
pub static DBUS_PATH: &'static str = "/org/rogcore/Daemon";
|
||||||
pub static DBUS_IFACE: &'static str = "org.rogcore.Daemon";
|
pub static DBUS_IFACE: &'static str = "org.rogcore.Daemon";
|
||||||
|
|
||||||
use crate::{
|
use crate::{config::Config, core::*, laptops::match_laptop};
|
||||||
core::RogCore,
|
|
||||||
laptops::{match_laptop, Laptop},
|
|
||||||
};
|
|
||||||
use dbus::{
|
use dbus::{
|
||||||
nonblock::Process,
|
nonblock::Process,
|
||||||
tree::{Factory, MTSync, Method, MethodErr, Tree},
|
tree::{Factory, MTSync, Method, MethodErr, Tree},
|
||||||
@@ -16,9 +13,10 @@ use log::{error, info};
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
type LedMsgType = Arc<tokio::sync::Mutex<Option<Vec<u8>>>>;
|
type LedMsgType = Arc<Mutex<Option<Vec<u8>>>>;
|
||||||
type EffectType = Arc<tokio::sync::Mutex<Option<Vec<Vec<u8>>>>>;
|
type EffectType = Arc<Mutex<Option<Vec<Vec<u8>>>>>;
|
||||||
|
|
||||||
// Timing is such that:
|
// Timing is such that:
|
||||||
// - interrupt write is minimum 1ms (sometimes lower)
|
// - interrupt write is minimum 1ms (sometimes lower)
|
||||||
@@ -31,6 +29,8 @@ type EffectType = Arc<tokio::sync::Mutex<Option<Vec<Vec<u8>>>>>;
|
|||||||
// DBUS processing takes 6ms if not tokiod
|
// DBUS processing takes 6ms if not tokiod
|
||||||
pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
||||||
let laptop = match_laptop();
|
let laptop = match_laptop();
|
||||||
|
let mut config = Config::default().read();
|
||||||
|
|
||||||
let mut rogcore = RogCore::new(
|
let mut rogcore = RogCore::new(
|
||||||
laptop.usb_vendor(),
|
laptop.usb_vendor(),
|
||||||
laptop.usb_product(),
|
laptop.usb_product(),
|
||||||
@@ -47,9 +47,16 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
// Reload settings
|
// Reload settings
|
||||||
rogcore.reload().await?;
|
rogcore.reload(&mut config).await?;
|
||||||
let usb_dev_handle = unsafe { &*(rogcore.get_raw_device_handle()) };
|
let usb_dev_handle = unsafe { &*(rogcore.get_raw_device_handle()) };
|
||||||
let rogcore = Arc::new(tokio::sync::Mutex::new(Box::pin(rogcore)));
|
|
||||||
|
// Set up the mutexes
|
||||||
|
let led_writer = Arc::new(Mutex::new(LedWriter::new(
|
||||||
|
rogcore.get_raw_device_handle(),
|
||||||
|
laptop.led_endpoint(),
|
||||||
|
)));
|
||||||
|
let config = Arc::new(Mutex::new(config));
|
||||||
|
let rogcore = Arc::new(Mutex::new(Box::pin(rogcore)));
|
||||||
|
|
||||||
let (resource, connection) = connection::new_system_sync()?;
|
let (resource, connection) = connection::new_system_sync()?;
|
||||||
tokio::spawn(async {
|
tokio::spawn(async {
|
||||||
@@ -73,6 +80,8 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
let report_filter_bytes = laptop.key_filter().to_owned();
|
let report_filter_bytes = laptop.key_filter().to_owned();
|
||||||
// This is *not* safe
|
// This is *not* safe
|
||||||
let rogcore = rogcore.clone();
|
let rogcore = rogcore.clone();
|
||||||
|
let led_writer = led_writer.clone();
|
||||||
|
let config = config.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
let data =
|
let data =
|
||||||
@@ -80,7 +89,7 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
.await;
|
.await;
|
||||||
if let Some(bytes) = data {
|
if let Some(bytes) = data {
|
||||||
let mut rogcore = rogcore.lock().await;
|
let mut rogcore = rogcore.lock().await;
|
||||||
match laptop.run(&mut rogcore, bytes) {
|
match laptop.run(&mut rogcore, &led_writer, &config, bytes).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("{:?}", err);
|
error!("{:?}", err);
|
||||||
@@ -96,10 +105,12 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
loop {
|
loop {
|
||||||
connection.process_all();
|
connection.process_all();
|
||||||
|
|
||||||
|
let led_writer = led_writer.clone();
|
||||||
if let Ok(mut lock) = input.try_lock() {
|
if let Ok(mut lock) = input.try_lock() {
|
||||||
if let Some(bytes) = lock.take() {
|
if let Some(bytes) = lock.take() {
|
||||||
let mut rogcore = rogcore.lock().await;
|
let mut led_writer = led_writer.lock().await;
|
||||||
rogcore.aura_set_and_save(&supported, &bytes)?;
|
let mut config = config.lock().await;
|
||||||
|
led_writer.aura_set_and_save(&supported, &bytes, &mut config)?;
|
||||||
time_mark = Instant::now();
|
time_mark = Instant::now();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,7 +121,9 @@ pub async fn start_daemon() -> Result<(), Box<dyn Error>> {
|
|||||||
// Spawn a writer
|
// Spawn a writer
|
||||||
if let Some(stuff) = lock.take() {
|
if let Some(stuff) = lock.take() {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
RogCore::async_write_effect(usb_dev_handle, led_endpoint, stuff)
|
let led_writer = led_writer.lock().await;
|
||||||
|
led_writer
|
||||||
|
.async_write_effect(led_endpoint, stuff)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
@@ -196,8 +209,8 @@ fn dbus_create_ledeffect_method(effect: EffectType) -> Method<MTSync, ()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn dbus_create_tree() -> (Tree<MTSync, ()>, LedMsgType, EffectType) {
|
fn dbus_create_tree() -> (Tree<MTSync, ()>, LedMsgType, EffectType) {
|
||||||
let input: LedMsgType = Arc::new(tokio::sync::Mutex::new(None));
|
let input: LedMsgType = Arc::new(Mutex::new(None));
|
||||||
let effect: EffectType = Arc::new(tokio::sync::Mutex::new(None));
|
let effect: EffectType = Arc::new(Mutex::new(None));
|
||||||
|
|
||||||
let factory = Factory::new_sync::<()>();
|
let factory = Factory::new_sync::<()>();
|
||||||
let tree = factory.tree(()).add(
|
let tree = factory.tree(()).add(
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::aura::BuiltInModeByte;
|
use crate::aura::BuiltInModeByte;
|
||||||
use crate::core::RogCore;
|
use crate::config::Config;
|
||||||
|
use crate::core::{LedWriter, RogCore};
|
||||||
use crate::error::AuraError;
|
use crate::error::AuraError;
|
||||||
//use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState};
|
//use keycode::{KeyMap, KeyMappingId, KeyState, KeyboardState};
|
||||||
use crate::virt_device::ConsumerKeys;
|
use crate::virt_device::ConsumerKeys;
|
||||||
@@ -66,29 +67,6 @@ pub(crate) fn match_laptop() -> LaptopBase {
|
|||||||
panic!("could not match laptop");
|
panic!("could not match laptop");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All laptop models should implement this trait. The role of a `Laptop` is to
|
|
||||||
/// "drive" the `RogCore`.
|
|
||||||
///
|
|
||||||
/// `do_hotkey_action` is passed the byte that a hotkey emits, and is expected to
|
|
||||||
/// perform whichever action matches that. For now the only key bytes passed in are
|
|
||||||
/// the ones which match `byte[0] == hotkey_group_byte`. On the GX502GW the keyboard
|
|
||||||
/// has 3 explicit groups: main, vol+media, and the ones that the Linux kernel doesn't
|
|
||||||
/// map.
|
|
||||||
///
|
|
||||||
/// If using the `keycode` crate to build keyboard input, the report must be prefixed
|
|
||||||
/// with the report ID (usually `0x01` for the virtual keyboard).
|
|
||||||
pub(crate) trait Laptop {
|
|
||||||
fn run(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError>;
|
|
||||||
fn led_endpoint(&self) -> u8;
|
|
||||||
fn key_endpoint(&self) -> u8;
|
|
||||||
fn key_filter(&self) -> &[u8];
|
|
||||||
fn usb_vendor(&self) -> u16;
|
|
||||||
fn usb_product(&self) -> u16;
|
|
||||||
// required for profiles which match more than one laptop
|
|
||||||
fn set_usb_product(&mut self, product: u16);
|
|
||||||
fn supported_modes(&self) -> &[BuiltInModeByte];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) type LaptopRunner = dyn Fn(&mut RogCore, [u8; 32]) -> Result<(), AuraError>;
|
pub(crate) type LaptopRunner = dyn Fn(&mut RogCore, [u8; 32]) -> Result<(), AuraError>;
|
||||||
|
|
||||||
pub(super) struct LaptopBase {
|
pub(super) struct LaptopBase {
|
||||||
@@ -103,53 +81,84 @@ pub(super) struct LaptopBase {
|
|||||||
//backlight: Backlight,
|
//backlight: Backlight,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Laptop for LaptopBase {
|
use tokio::sync::Mutex;
|
||||||
fn run(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> {
|
|
||||||
|
impl LaptopBase {
|
||||||
|
/// Pass in LedWriter as Mutex so it is only locked when required
|
||||||
|
pub(super) async fn run(
|
||||||
|
&self,
|
||||||
|
rogcore: &mut RogCore,
|
||||||
|
led_writer: &Mutex<LedWriter>,
|
||||||
|
config: &Mutex<Config>,
|
||||||
|
key_buf: [u8; 32],
|
||||||
|
) -> Result<(), AuraError> {
|
||||||
match self.usb_product {
|
match self.usb_product {
|
||||||
0x1869 | 0x1866 => self.gx502_runner(rogcore, key_buf),
|
0x1869 | 0x1866 => {
|
||||||
0x1854 => self.gl753_runner(rogcore, key_buf),
|
self.gx502_runner(rogcore, led_writer, config, key_buf)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
0x1854 => {
|
||||||
|
self.gl753_runner(rogcore, led_writer, config, key_buf)
|
||||||
|
.await
|
||||||
|
}
|
||||||
_ => panic!("No runner available for this device"),
|
_ => panic!("No runner available for this device"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn led_endpoint(&self) -> u8 {
|
pub(super) fn led_endpoint(&self) -> u8 {
|
||||||
self.led_endpoint
|
self.led_endpoint
|
||||||
}
|
}
|
||||||
fn key_endpoint(&self) -> u8 {
|
pub(super) fn key_endpoint(&self) -> u8 {
|
||||||
self.key_endpoint
|
self.key_endpoint
|
||||||
}
|
}
|
||||||
fn key_filter(&self) -> &[u8] {
|
pub(super) fn key_filter(&self) -> &[u8] {
|
||||||
&self.report_filter_bytes
|
&self.report_filter_bytes
|
||||||
}
|
}
|
||||||
fn usb_vendor(&self) -> u16 {
|
pub(super) fn usb_vendor(&self) -> u16 {
|
||||||
self.usb_vendor
|
self.usb_vendor
|
||||||
}
|
}
|
||||||
fn usb_product(&self) -> u16 {
|
pub(super) fn usb_product(&self) -> u16 {
|
||||||
self.usb_product
|
self.usb_product
|
||||||
}
|
}
|
||||||
fn set_usb_product(&mut self, product: u16) {
|
pub(super) fn set_usb_product(&mut self, product: u16) {
|
||||||
self.usb_product = product;
|
self.usb_product = product;
|
||||||
}
|
}
|
||||||
fn supported_modes(&self) -> &[BuiltInModeByte] {
|
pub(super) fn supported_modes(&self) -> &[BuiltInModeByte] {
|
||||||
&self.supported_modes
|
&self.supported_modes
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl LaptopBase {
|
|
||||||
// 0x1866, per-key LEDs, media-keys split from vendor specific
|
// 0x1866, per-key LEDs, media-keys split from vendor specific
|
||||||
fn gx502_runner(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> {
|
async fn gx502_runner(
|
||||||
|
&self,
|
||||||
|
rogcore: &mut RogCore,
|
||||||
|
led_writer: &Mutex<LedWriter>,
|
||||||
|
config: &Mutex<Config>,
|
||||||
|
key_buf: [u8; 32],
|
||||||
|
) -> Result<(), AuraError> {
|
||||||
let max_led_bright = self.max_led_bright;
|
let max_led_bright = self.max_led_bright;
|
||||||
let min_led_bright = self.min_led_bright;
|
let min_led_bright = self.min_led_bright;
|
||||||
let supported_modes = self.supported_modes.to_owned();
|
let supported_modes = self.supported_modes.to_owned();
|
||||||
match GX502Keys::from(key_buf[1]) {
|
match GX502Keys::from(key_buf[1]) {
|
||||||
GX502Keys::LedBrightUp => {
|
GX502Keys::LedBrightUp => {
|
||||||
rogcore.aura_bright_inc(&supported_modes, max_led_bright)?;
|
let mut led_writer = led_writer.lock().await;
|
||||||
|
let mut config = config.lock().await;
|
||||||
|
led_writer.aura_bright_inc(&supported_modes, max_led_bright, &mut config)?;
|
||||||
}
|
}
|
||||||
GX502Keys::LedBrightDown => {
|
GX502Keys::LedBrightDown => {
|
||||||
rogcore.aura_bright_dec(&supported_modes, min_led_bright)?;
|
let mut led_writer = led_writer.lock().await;
|
||||||
|
let mut config = config.lock().await;
|
||||||
|
led_writer.aura_bright_dec(&supported_modes, min_led_bright, &mut config)?;
|
||||||
|
}
|
||||||
|
GX502Keys::AuraNext => {
|
||||||
|
let mut led_writer = led_writer.lock().await;
|
||||||
|
let mut config = config.lock().await;
|
||||||
|
led_writer.aura_mode_next(&supported_modes, &mut config)?;
|
||||||
|
}
|
||||||
|
GX502Keys::AuraPrevious => {
|
||||||
|
let mut led_writer = led_writer.lock().await;
|
||||||
|
let mut config = config.lock().await;
|
||||||
|
led_writer.aura_mode_prev(&supported_modes, &mut config)?;
|
||||||
}
|
}
|
||||||
GX502Keys::AuraNext => rogcore.aura_mode_next(&supported_modes)?,
|
|
||||||
GX502Keys::AuraPrevious => rogcore.aura_mode_prev(&supported_modes)?,
|
|
||||||
GX502Keys::ScreenBrightUp => {
|
GX502Keys::ScreenBrightUp => {
|
||||||
rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into())
|
rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into())
|
||||||
} //self.backlight.step_up(),
|
} //self.backlight.step_up(),
|
||||||
@@ -160,7 +169,8 @@ impl LaptopBase {
|
|||||||
GX502Keys::AirplaneMode => rogcore.toggle_airplane_mode(),
|
GX502Keys::AirplaneMode => rogcore.toggle_airplane_mode(),
|
||||||
GX502Keys::MicToggle => {}
|
GX502Keys::MicToggle => {}
|
||||||
GX502Keys::Fan => {
|
GX502Keys::Fan => {
|
||||||
rogcore.fan_mode_step().unwrap_or_else(|err| {
|
let mut config = config.lock().await;
|
||||||
|
rogcore.fan_mode_step(&mut config).unwrap_or_else(|err| {
|
||||||
warn!("Couldn't toggle fan mode: {:?}", err);
|
warn!("Couldn't toggle fan mode: {:?}", err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -192,16 +202,26 @@ impl LaptopBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GL753VE == 0x1854, 4 zone keyboard
|
// GL753VE == 0x1854, 4 zone keyboard
|
||||||
fn gl753_runner(&self, rogcore: &mut RogCore, key_buf: [u8; 32]) -> Result<(), AuraError> {
|
async fn gl753_runner(
|
||||||
|
&self,
|
||||||
|
rogcore: &mut RogCore,
|
||||||
|
led_writer: &Mutex<LedWriter>,
|
||||||
|
config: &Mutex<Config>,
|
||||||
|
key_buf: [u8; 32],
|
||||||
|
) -> Result<(), AuraError> {
|
||||||
let max_led_bright = self.max_led_bright;
|
let max_led_bright = self.max_led_bright;
|
||||||
let min_led_bright = self.min_led_bright;
|
let min_led_bright = self.min_led_bright;
|
||||||
let supported_modes = self.supported_modes.to_owned();
|
let supported_modes = self.supported_modes.to_owned();
|
||||||
match GL753Keys::from(key_buf[1]) {
|
match GL753Keys::from(key_buf[1]) {
|
||||||
GL753Keys::LedBrightUp => {
|
GL753Keys::LedBrightUp => {
|
||||||
rogcore.aura_bright_inc(&supported_modes, max_led_bright)?;
|
let mut led_writer = led_writer.lock().await;
|
||||||
|
let mut config = config.lock().await;
|
||||||
|
led_writer.aura_bright_inc(&supported_modes, max_led_bright, &mut config)?;
|
||||||
}
|
}
|
||||||
GL753Keys::LedBrightDown => {
|
GL753Keys::LedBrightDown => {
|
||||||
rogcore.aura_bright_dec(&supported_modes, min_led_bright)?;
|
let mut led_writer = led_writer.lock().await;
|
||||||
|
let mut config = config.lock().await;
|
||||||
|
led_writer.aura_bright_dec(&supported_modes, min_led_bright, &mut config)?;
|
||||||
}
|
}
|
||||||
GL753Keys::ScreenBrightUp => {
|
GL753Keys::ScreenBrightUp => {
|
||||||
rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into())
|
rogcore.virt_keys().press(ConsumerKeys::BacklightInc.into())
|
||||||
|
|||||||
Reference in New Issue
Block a user