buttplug/server/device/protocol/
hgod.rs1use crate::server::device::configuration::ProtocolCommunicationSpecifier;
9use crate::{
10 core::{
11 errors::ButtplugDeviceError,
12 message::{ActuatorType, Endpoint},
13 },
14 server::device::{
15 configuration::{UserDeviceDefinition, UserDeviceIdentifier},
16 hardware::{Hardware, HardwareCommand, HardwareWriteCmd},
17 protocol::{
18 generic_protocol_initializer_setup,
19 ProtocolHandler,
20 ProtocolIdentifier,
21 ProtocolInitializer,
22 },
23 },
24 util::{async_manager, sleep},
25};
26use async_trait::async_trait;
27use std::{
28 sync::{
29 atomic::{AtomicU8, Ordering},
30 Arc,
31 },
32 time::Duration,
33};
34
35const HGOD_COMMAND_DELAY_MS: u64 = 100;
37
38generic_protocol_initializer_setup!(Hgod, "hgod");
39
40#[derive(Default)]
41pub struct HgodInitializer {}
42
43#[async_trait]
44impl ProtocolInitializer for HgodInitializer {
45 async fn initialize(
46 &mut self,
47 hardware: Arc<Hardware>,
48 _: &UserDeviceDefinition,
49 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> {
50 Ok(Arc::new(Hgod::new(hardware)))
51 }
52}
53
54pub struct Hgod {
55 last_command: Arc<AtomicU8>,
56}
57
58impl Hgod {
59 fn new(hardware: Arc<Hardware>) -> Self {
60 let last_command = Arc::new(AtomicU8::new(0));
61
62 let last_command_clone = last_command.clone();
63 async_manager::spawn(async move {
64 send_hgod_updates(hardware, last_command_clone).await;
65 });
66
67 Self { last_command }
68 }
69}
70
71async fn send_hgod_updates(device: Arc<Hardware>, data: Arc<AtomicU8>) {
73 loop {
74 let speed = data.load(Ordering::SeqCst);
75 let command = vec![0x55, 0x04, 0, 0, 0, speed];
76 if speed > 0 {
77 if let Err(e) = device
78 .write_value(&HardwareWriteCmd::new(Endpoint::Tx, command, false))
79 .await
80 {
81 error!(
82 "Got an error from a hgod device, exiting control loop: {:?}",
83 e
84 );
85 break;
86 }
87 }
88 sleep(Duration::from_millis(HGOD_COMMAND_DELAY_MS)).await;
89 }
90}
91
92impl ProtocolHandler for Hgod {
93 fn handle_scalar_cmd(
94 &self,
95 commands: &[Option<(ActuatorType, u32)>],
96 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
97 if let Some(cmd) = commands[0] {
98 self.last_command.store(cmd.1 as u8, Ordering::SeqCst);
99 }
100 Ok(vec![])
101 }
102}