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 easy_switch;
22mod error;
23mod fn_lock;
24mod haptic;
25mod hires_wheel;
26mod lighting;
27mod litra;
28mod os_layout;
29mod pointer_scaling;
30mod report_rate;
31mod smartshift;
32
33pub use backlight::{get_backlight, get_backlight_on, update_backlight, update_backlight_on};
34pub use diagnostics::{
35 FeatureEntry, FirmwareEntity, FirmwareEntityInfo, ReprogControlEntry, dump_features,
36 dump_firmware_entities, dump_reprog_controls, read_battery_raw,
37};
38pub use dpi::{
39 Dpi, DpiCapabilities, DpiInfo, get_dpi, get_dpi_info, get_dpi_info_on, set_dpi, set_dpi_on,
40};
41pub use easy_switch::{
42 get_easy_switch_hosts, get_easy_switch_hosts_on, rename_easy_switch_host,
43 rename_easy_switch_host_on,
44};
45pub use error::{HidppFeatureErrorKind, HidppOperation, WriteError};
46pub use fn_lock::{get_fn_lock, get_fn_lock_on, set_fn_lock, set_fn_lock_on};
47pub use haptic::{ensure_haptics_armed_on, play_haptic, play_haptic_on};
48pub use hidpp::feature::haptic_feedback::HapticWaveform;
49pub use hidpp::feature::multi_platform::OsMask;
50pub use hires_wheel::{
51 ScrollReportingTarget, ScrollResolution, ScrollWheelMode, get_scroll_wheel_mode,
52 get_scroll_wheel_mode_on, set_scroll_inversion, set_scroll_inversion_on, set_scroll_resolution,
53 set_scroll_resolution_on, set_scroll_wheel_mode, set_scroll_wheel_mode_on,
54};
55pub use lighting::{
56 LightingMethod, LightingWrite, RgbControlLease, release_rgb_control, set_keyboard_color,
57 set_keyboard_color_on, set_keyboard_color_with, set_keyboard_color_with_on,
58};
59pub(crate) use litra::litra_capabilities;
60pub use litra::{
61 LITRA_BEAM_PRODUCT_ID, LITRA_GLOW_PRODUCT_ID, LightCommand, LitraDescriptor, LitraModel,
62 apply as apply_litra, encode_command as encode_litra_command, find_litra,
63 litra_model_for_route, matches_litra,
64};
65pub use openlogi_core::hid::{
66 EasySwitchHosts, EasySwitchSlot, HostConnection, HostOsInfo, HostOsKind,
67};
68pub use openlogi_core::hid::{ReportRate, ReportRateInfo};
69pub use os_layout::{HostOs, OsLayoutOutcome, OsVersion, keep_os_layout_on};
70pub use pointer_scaling::{PointerScaling, get_pointer_scaling, set_pointer_scaling};
71pub use report_rate::{
72 get_report_rate_info, get_report_rate_info_on, set_report_rate, set_report_rate_on,
73};
74pub use smartshift::{
75 get_smartshift_status, get_smartshift_status_on, set_smartshift, set_smartshift_on,
76 set_smartshift_sensitivity, toggle_smartshift, toggle_smartshift_on,
77};
78
79pub use openlogi_core::hid::light::commands_for_light_settings;
83
84pub(crate) use error::classify_hidpp_error;
85
86pub(crate) async fn open_feature<F: CreatableFeature + 'static>(
95 device: &mut Device,
96) -> Result<Arc<F>, WriteError> {
97 open_feature_with_version::<F>(device)
98 .await
99 .map(|(feature, _)| feature)
100}
101
102pub(crate) async fn open_feature_with_version<F: CreatableFeature + 'static>(
105 device: &mut Device,
106) -> Result<(Arc<F>, u8), WriteError> {
107 let info = device
108 .root()
109 .get_feature(F::ID)
110 .await
111 .map_err(|e| classify_hidpp_error(e, HidppOperation::ResolveFeature, F::ID))?
112 .ok_or(WriteError::FeatureUnsupported { feature_hex: F::ID })?;
113 Ok((device.add_feature::<F>(info.index), info.version))
114}
115
116pub(crate) async fn with_route<F, Fut, T>(
119 backend: &dyn HidBackend,
120 route: &DeviceRoute,
121 f: F,
122) -> Result<T, WriteError>
123where
124 F: FnOnce(Arc<HidppChannel>) -> Fut,
125 Fut: std::future::Future<Output = Result<T, WriteError>>,
126{
127 match open_route_channel(backend, route).await? {
128 Some(channel) => f(channel).await,
129 None => Err(WriteError::DeviceNotFound),
130 }
131}
132
133#[cfg(test)]
134mod tests;