buttplug/server/device/protocol/
svakom_iker.rs1use crate::{
9 core::{
10 errors::ButtplugDeviceError,
11 message::{ActuatorType, Endpoint},
12 },
13 server::device::{
14 configuration::{ProtocolCommunicationSpecifier, UserDeviceDefinition, UserDeviceIdentifier},
15 hardware::{Hardware, HardwareCommand, HardwareWriteCmd},
16 protocol::{
17 generic_protocol_initializer_setup,
18 ProtocolHandler,
19 ProtocolIdentifier,
20 ProtocolInitializer,
21 },
22 },
23};
24use async_trait::async_trait;
25use std::sync::atomic::{AtomicU8, Ordering};
26use std::sync::Arc;
27
28generic_protocol_initializer_setup!(SvakomIker, "svakom-iker");
29
30#[derive(Default)]
31pub struct SvakomIkerInitializer {}
32
33#[async_trait]
34impl ProtocolInitializer for SvakomIkerInitializer {
35 async fn initialize(
36 &mut self,
37 _: Arc<Hardware>,
38 _: &UserDeviceDefinition,
39 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> {
40 Ok(Arc::new(SvakomIker::new()))
41 }
42}
43
44#[derive(Default)]
45pub struct SvakomIker {
46 last_speeds: Arc<Vec<AtomicU8>>,
47}
48
49impl SvakomIker {
50 fn new() -> Self {
51 let last_speeds = Arc::new((0..2).map(|_| AtomicU8::new(0)).collect::<Vec<AtomicU8>>());
52
53 Self { last_speeds }
54 }
55}
56
57impl ProtocolHandler for SvakomIker {
58 fn keepalive_strategy(&self) -> super::ProtocolKeepaliveStrategy {
59 super::ProtocolKeepaliveStrategy::RepeatLastPacketStrategy
60 }
61
62 fn handle_scalar_cmd(
63 &self,
64 cmds: &[Option<(ActuatorType, u32)>],
65 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
66 let mut vibe_off = false;
67 let mut msg_vec = vec![];
68 if let Some((_, speed)) = cmds[0] {
69 self.last_speeds[0].store(speed as u8, Ordering::SeqCst);
70 if speed == 0 {
71 vibe_off = true;
72 }
73 msg_vec.push(
74 HardwareWriteCmd::new(
75 Endpoint::Tx,
76 [0x55, 0x03, 0x03, 0x00, 0x01, speed as u8].to_vec(),
77 false,
78 )
79 .into(),
80 );
81 }
82 if cmds.len() > 1 {
83 if let Some((_, speed)) = cmds[1] {
84 self.last_speeds[1].store(speed as u8, Ordering::SeqCst);
85 msg_vec.push(
86 HardwareWriteCmd::new(
87 Endpoint::Tx,
88 [0x55, 0x07, 0x00, 0x00, speed as u8, 0x00].to_vec(),
89 false,
90 )
91 .into(),
92 );
93 } else if vibe_off && self.last_speeds[1].load(Ordering::SeqCst) != 0 {
94 msg_vec.push(
95 HardwareWriteCmd::new(
96 Endpoint::Tx,
97 [
98 0x55,
99 0x07,
100 0x00,
101 0x00,
102 self.last_speeds[1].load(Ordering::SeqCst),
103 0x00,
104 ]
105 .to_vec(),
106 false,
107 )
108 .into(),
109 );
110 }
111 }
112 Ok(msg_vec)
113 }
114}