1use std::sync::Arc;
12
13use hidpp::{channel::HidppChannel, device::Device, feature::CreatableFeature};
14
15use crate::backend::HidBackend;
16use crate::channel::route::{DeviceRoute, open_route_channel};
17
18mod backlight;
19mod diagnostics;
20mod dpi;
21mod error;
22mod fn_lock;
23mod haptic;
24mod hires_wheel;
25mod lighting;
26mod litra;
27mod smartshift;
28
29pub use backlight::{get_backlight, set_backlight_enabled};
30pub use diagnostics::{
31 FeatureEntry, FirmwareEntity, FirmwareEntityInfo, ReprogControlEntry, dump_features,
32 dump_firmware_entities, dump_reprog_controls, read_battery_raw,
33};
34pub use dpi::{
35 Dpi, DpiCapabilities, DpiInfo, get_dpi, get_dpi_info, get_dpi_info_on, set_dpi, set_dpi_on,
36};
37pub use error::{HidppFeatureErrorKind, HidppOperation, WriteError};
38pub use fn_lock::{set_fn_lock, set_fn_lock_on};
39pub use haptic::{ensure_haptics_armed_on, play_haptic, play_haptic_on};
40pub use hidpp::feature::haptic_feedback::HapticWaveform;
41pub use hires_wheel::{
42 ScrollReportingTarget, ScrollResolution, ScrollWheelMode, get_scroll_wheel_mode,
43 get_scroll_wheel_mode_on, set_scroll_inversion, set_scroll_inversion_on, set_scroll_resolution,
44 set_scroll_resolution_on, set_scroll_wheel_mode, set_scroll_wheel_mode_on,
45};
46pub use lighting::{
47 LightingMethod, set_keyboard_color, set_keyboard_color_on, set_keyboard_color_with,
48 set_keyboard_color_with_on,
49};
50pub(crate) use litra::litra_capabilities;
51pub use litra::{
52 LITRA_BEAM_PRODUCT_ID, LITRA_GLOW_PRODUCT_ID, LightCommand, LitraDescriptor, LitraModel,
53 apply as apply_litra, encode_command as encode_litra_command, find_litra,
54 litra_model_for_route, matches_litra,
55};
56pub use smartshift::{
57 get_smartshift_status, get_smartshift_status_on, set_smartshift, set_smartshift_on,
58 set_smartshift_sensitivity, toggle_smartshift, toggle_smartshift_on,
59};
60
61pub use openlogi_core::hid::light::commands_for_light_settings;
65
66pub(crate) use error::classify_hidpp_error;
67
68pub(crate) async fn open_feature<F: CreatableFeature + 'static>(
77 device: &mut Device,
78) -> Result<Arc<F>, WriteError> {
79 let info = device
80 .root()
81 .get_feature(F::ID)
82 .await
83 .map_err(|e| classify_hidpp_error(e, HidppOperation::ResolveFeature, F::ID))?
84 .ok_or(WriteError::FeatureUnsupported { feature_hex: F::ID })?;
85 Ok(device.add_feature::<F>(info.index))
86}
87
88pub(crate) async fn with_route<F, Fut, T>(
91 backend: &dyn HidBackend,
92 route: &DeviceRoute,
93 f: F,
94) -> Result<T, WriteError>
95where
96 F: FnOnce(Arc<HidppChannel>) -> Fut,
97 Fut: std::future::Future<Output = Result<T, WriteError>>,
98{
99 match open_route_channel(backend, route).await? {
100 Some(channel) => f(channel).await,
101 None => Err(WriteError::DeviceNotFound),
102 }
103}
104
105#[cfg(test)]
106mod tests;