use std::{hash::Hash, sync::Arc};
use num_enum::{IntoPrimitive, TryFromPrimitive};
use crate::{
channel::HidppChannel,
feature::{CreatableFeature, Feature},
nibble::U4,
protocol::v20::{self, Hidpp20Error},
};
pub struct SmartShiftFeatureV0 {
chan: Arc<HidppChannel>,
device_index: u8,
feature_index: u8,
}
impl CreatableFeature for SmartShiftFeatureV0 {
const ID: u16 = 0x2110;
const STARTING_VERSION: u8 = 0;
fn new(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> Self {
Self {
chan,
device_index,
feature_index,
}
}
}
impl Feature for SmartShiftFeatureV0 {
}
impl SmartShiftFeatureV0 {
pub async fn get_ratchet_control_mode(&self) -> Result<RatchetControlMode, Hidpp20Error> {
let response = self
.chan
.send_v20(v20::Message::Short(
v20::MessageHeader {
device_index: self.device_index,
feature_index: self.feature_index,
function_id: U4::from_lo(0),
software_id: self.chan.get_sw_id(),
},
[0x00, 0x00, 0x00],
))
.await?;
let payload = response.extend_payload();
Ok(RatchetControlMode {
wheel_mode: WheelMode::try_from(payload[0])
.map_err(|_| Hidpp20Error::UnsupportedResponse)?,
auto_disengage: payload[1],
auto_disengage_default: payload[2],
})
}
pub async fn set_ratchet_control_mode(
&self,
wheel_mode: Option<WheelMode>,
auto_disengage: Option<u8>,
auto_disengage_default: Option<u8>,
) -> Result<(), Hidpp20Error> {
self.chan
.send_v20(v20::Message::Short(
v20::MessageHeader {
device_index: self.device_index,
feature_index: self.feature_index,
function_id: U4::from_lo(1),
software_id: self.chan.get_sw_id(),
},
[
wheel_mode.map_or(0, u8::from),
auto_disengage.unwrap_or(0),
auto_disengage_default.unwrap_or(0),
],
))
.await?;
Ok(())
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct RatchetControlMode {
pub wheel_mode: WheelMode,
pub auto_disengage: u8,
pub auto_disengage_default: u8,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, IntoPrimitive, TryFromPrimitive)]
#[non_exhaustive]
#[repr(u8)]
pub enum WheelMode {
Freespin = 1,
Ratchet = 2,
}