Buttplug sex toy control library
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 uuid::{Uuid, uuid};
9
10use crate::device::{
11 hardware::{HardwareCommand, HardwareWriteCmd},
12 protocol::{ProtocolHandler, ProtocolKeepaliveStrategy, generic_protocol_setup},
13};
14use buttplug_core::errors::ButtplugDeviceError;
15use buttplug_server_device_config::Endpoint;
16use std::sync::atomic::{AtomicU8, Ordering};
17generic_protocol_setup!(SvakomV5, "svakom-v5");
18
19const SVAKOM_V5_VIBRATOR_UUID: Uuid = uuid!("d19af460-3d81-483b-a87f-b2781d972bac");
20
21#[derive(Default)]
22pub struct SvakomV5 {
23 last_vibrator_speeds: [AtomicU8; 2],
24}
25
26impl ProtocolHandler for SvakomV5 {
27 fn keepalive_strategy(&self) -> ProtocolKeepaliveStrategy {
28 ProtocolKeepaliveStrategy::HardwareRequiredRepeatLastPacketStrategy
29 }
30
31 fn handle_output_vibrate_cmd(
32 &self,
33 feature_index: u32,
34 _feature_id: uuid::Uuid,
35 speed: u32,
36 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
37 self.last_vibrator_speeds[feature_index as usize].store(speed as u8, Ordering::Relaxed);
38 let vibe1 = self.last_vibrator_speeds[0].load(Ordering::Relaxed);
39 let vibe2 = self.last_vibrator_speeds[1].load(Ordering::Relaxed);
40 Ok(vec![
41 HardwareWriteCmd::new(
42 &[SVAKOM_V5_VIBRATOR_UUID],
43 Endpoint::Tx,
44 [
45 0x55,
46 0x03,
47 if (vibe1 > 0 && vibe2 > 0) || vibe1 == vibe2 {
48 0x00
49 } else if vibe1 > 0 {
50 0x01
51 } else {
52 0x02
53 },
54 0x00,
55 if vibe1 == vibe2 && vibe1 == 0 {
56 0x00
57 } else {
58 0x01
59 },
60 { vibe1.max(vibe2) },
61 ]
62 .to_vec(),
63 false,
64 )
65 .into(),
66 ])
67 }
68
69 fn handle_output_oscillate_cmd(
70 &self,
71 _feature_index: u32,
72 feature_id: uuid::Uuid,
73 speed: u32,
74 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
75 Ok(vec![
76 HardwareWriteCmd::new(
77 &[feature_id],
78 Endpoint::Tx,
79 [0x55, 0x09, 0x00, 0x00, speed as u8, 0x00].to_vec(),
80 false,
81 )
82 .into(),
83 ])
84 }
85}