use std::sync::Arc;
use crate::{
channel::HidppChannel,
feature::{CreatableFeature, Feature, FeatureEndpoint},
protocol::v20::Hidpp20Error,
};
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct ChangeHostCapabilities: u8 {
const ENHANCED_HOST_SWITCH = 1 << 0;
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[non_exhaustive]
pub struct ChangeHostInfo {
pub host_count: u8,
pub current_host: u8,
pub capabilities: ChangeHostCapabilities,
}
#[derive(Clone)]
pub struct ChangeHostFeature {
endpoint: FeatureEndpoint,
}
impl CreatableFeature for ChangeHostFeature {
const ID: u16 = 0x1814;
const STARTING_VERSION: u8 = 0;
fn new(chan: Arc<HidppChannel>, device_index: u8, feature_index: u8) -> Self {
Self {
endpoint: FeatureEndpoint::new(chan, device_index, feature_index),
}
}
}
impl Feature for ChangeHostFeature {}
impl ChangeHostFeature {
pub async fn get_host_info(&self) -> Result<ChangeHostInfo, Hidpp20Error> {
let payload = self.endpoint.call(0, [0; 3]).await?.extend_payload();
Ok(ChangeHostInfo {
host_count: payload[0],
current_host: payload[1],
capabilities: ChangeHostCapabilities::from_bits_retain(payload[2]),
})
}
pub async fn set_current_host(&self, host: u8) -> Result<(), Hidpp20Error> {
self.endpoint.notify(1, [host, 0, 0]).await
}
pub async fn get_cookies(&self, host_count: u8) -> Result<Vec<u8>, Hidpp20Error> {
let count = usize::from(host_count);
let payload = self.endpoint.call(2, [0; 3]).await?.extend_payload();
if count > payload.len() {
return Err(Hidpp20Error::UnsupportedResponse);
}
Ok(payload[..count].to_vec())
}
pub async fn set_cookie(&self, host: u8, cookie: u8) -> Result<(), Hidpp20Error> {
self.endpoint.call(3, [host, cookie, 0]).await?;
Ok(())
}
}