buttplug/server/device/protocol/
svakom_iker.rs

1// Buttplug Rust Source Code File - See https://buttplug.io for more info.
2//
3// Copyright 2016-2024 Nonpolynomial Labs LLC. All rights reserved.
4//
5// Licensed under the BSD 3-Clause license. See LICENSE file in the project root
6// for full license information.
7
8use 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}