Skip to main content

openlogi_hid/write/
shared.rs

1use std::sync::Arc;
2
3use hidpp::channel::HidppChannel;
4
5use crate::route::DeviceRoute;
6use crate::smartshift::SmartShiftMode;
7use crate::smartshift::SmartShiftStatus;
8
9use super::WriteError;
10use super::dpi::{DpiInfo, get_dpi_info_on_channel, set_dpi_on_channel};
11use super::fn_lock::set_fn_lock_on_channel;
12use super::lighting::{LightingMethod, set_keyboard_color_with_on_channel};
13use super::smartshift::{
14    get_smartshift_status_on_channel, set_smartshift_on_channel, toggle_smartshift_on_channel,
15};
16
17/// An open HID++ channel to a device, shared so route-addressed reads and writes
18/// can reuse an inventory- or capture-owned connection instead of
19/// re-enumerating and opening a fresh channel each time (which costs ~100ms+).
20///
21/// Cheap to clone (an `Arc` plus the [`DeviceRoute`] it points at). Built by
22/// the inventory registry or a standalone capture session.
23#[derive(Clone)]
24pub struct SharedChannel {
25    channel: Arc<HidppChannel>,
26    route: DeviceRoute,
27}
28
29impl SharedChannel {
30    /// Wrap an open channel that reaches `route`.
31    #[must_use]
32    pub(crate) fn new(channel: Arc<HidppChannel>, route: DeviceRoute) -> Self {
33        Self { channel, route }
34    }
35
36    /// Whether this channel reaches `route` — so the write path only reuses it
37    /// for the device it actually points at.
38    #[must_use]
39    pub fn matches(&self, route: &DeviceRoute) -> bool {
40        self.route == *route
41    }
42
43    pub(crate) fn channel(&self) -> &Arc<HidppChannel> {
44        &self.channel
45    }
46
47    pub(crate) fn device_index(&self) -> u8 {
48        self.route.device_index()
49    }
50}
51
52/// Write DPI on an already-open [`SharedChannel`] — the fast path that skips
53/// enumeration and channel setup.
54pub async fn set_dpi_on(shared: &SharedChannel, dpi: u16) -> Result<(), WriteError> {
55    set_dpi_on_channel(&shared.channel, shared.route.device_index(), dpi).await
56}
57
58/// Read current DPI and supported values on an already-open [`SharedChannel`].
59pub async fn get_dpi_info_on(shared: &SharedChannel) -> Result<DpiInfo, WriteError> {
60    get_dpi_info_on_channel(&shared.channel, shared.route.device_index()).await
61}
62
63/// Toggle SmartShift on an already-open [`SharedChannel`].
64pub async fn toggle_smartshift_on(shared: &SharedChannel) -> Result<SmartShiftMode, WriteError> {
65    toggle_smartshift_on_channel(&shared.channel, shared.route.device_index()).await
66}
67
68/// Read SmartShift mode and sensitivity on an already-open [`SharedChannel`].
69pub async fn get_smartshift_status_on(
70    shared: &SharedChannel,
71) -> Result<SmartShiftStatus, WriteError> {
72    get_smartshift_status_on_channel(&shared.channel, shared.route.device_index()).await
73}
74
75/// Write keyboard Fn-lock on an already-open [`SharedChannel`] — the fast
76/// path that skips enumeration and channel setup.
77pub async fn set_fn_lock_on(shared: &SharedChannel, on: bool) -> Result<(), WriteError> {
78    set_fn_lock_on_channel(&shared.channel, shared.route.device_index(), on).await
79}
80
81/// Write a full SmartShift configuration on an already-open [`SharedChannel`]
82/// — the fast path that skips enumeration and channel setup.
83pub async fn set_smartshift_on(
84    shared: &SharedChannel,
85    mode: SmartShiftMode,
86    auto_disengage: u8,
87    tunable_torque: u8,
88) -> Result<(), WriteError> {
89    set_smartshift_on_channel(
90        &shared.channel,
91        shared.route.device_index(),
92        mode,
93        auto_disengage,
94        tunable_torque,
95    )
96    .await
97}
98
99/// Set a solid keyboard colour on an already-open [`SharedChannel`], using
100/// [`LightingMethod::Auto`].
101pub async fn set_keyboard_color_on(
102    shared: &SharedChannel,
103    r: u8,
104    g: u8,
105    b: u8,
106) -> Result<(), WriteError> {
107    set_keyboard_color_with_on(shared, LightingMethod::Auto, r, g, b).await
108}
109
110/// Set a solid keyboard colour on an already-open [`SharedChannel`] with an
111/// explicit lighting method.
112pub async fn set_keyboard_color_with_on(
113    shared: &SharedChannel,
114    method: LightingMethod,
115    r: u8,
116    g: u8,
117    b: u8,
118) -> Result<(), WriteError> {
119    set_keyboard_color_with_on_channel(
120        &shared.channel,
121        shared.route.device_index(),
122        method,
123        r,
124        g,
125        b,
126    )
127    .await
128}