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;
7
8use super::WriteError;
9use super::dpi::set_dpi_on_channel;
10use super::smartshift::{set_smartshift_on_channel, toggle_smartshift_on_channel};
11
12/// An open HID++ channel to a device, shared so DPI / SmartShift writes can
13/// reuse the capture session's connection instead of re-enumerating and
14/// opening a fresh channel each time (which costs ~100ms+).
15///
16/// Cheap to clone (an `Arc` plus the [`DeviceRoute`] it points at). Built by
17/// the capture session via `SharedChannel::new` and stashed in a slot the
18/// GUI's write path consults.
19#[derive(Clone)]
20pub struct SharedChannel {
21    channel: Arc<HidppChannel>,
22    route: DeviceRoute,
23}
24
25impl SharedChannel {
26    /// Wrap an open channel that reaches `route`.
27    #[must_use]
28    pub(crate) fn new(channel: Arc<HidppChannel>, route: DeviceRoute) -> Self {
29        Self { channel, route }
30    }
31
32    /// Whether this channel reaches `route` — so the write path only reuses it
33    /// for the device it actually points at.
34    #[must_use]
35    pub fn matches(&self, route: &DeviceRoute) -> bool {
36        self.route == *route
37    }
38
39    pub(crate) fn channel(&self) -> &Arc<HidppChannel> {
40        &self.channel
41    }
42
43    pub(crate) fn device_index(&self) -> u8 {
44        self.route.device_index()
45    }
46}
47
48/// Write DPI on an already-open [`SharedChannel`] — the fast path that skips
49/// enumeration and channel setup.
50pub async fn set_dpi_on(shared: &SharedChannel, dpi: u16) -> Result<(), WriteError> {
51    set_dpi_on_channel(&shared.channel, shared.route.device_index(), dpi).await
52}
53
54/// Toggle SmartShift on an already-open [`SharedChannel`].
55pub async fn toggle_smartshift_on(shared: &SharedChannel) -> Result<SmartShiftMode, WriteError> {
56    toggle_smartshift_on_channel(&shared.channel, shared.route.device_index()).await
57}
58
59/// Write a full SmartShift configuration on an already-open [`SharedChannel`]
60/// — the fast path that skips enumeration and channel setup.
61pub async fn set_smartshift_on(
62    shared: &SharedChannel,
63    mode: SmartShiftMode,
64    auto_disengage: u8,
65    tunable_torque: u8,
66) -> Result<(), WriteError> {
67    set_smartshift_on_channel(
68        &shared.channel,
69        shared.route.device_index(),
70        mode,
71        auto_disengage,
72        tunable_torque,
73    )
74    .await
75}