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 std::sync::atomic::{AtomicU8, Ordering};
9
10use uuid::{Uuid, uuid};
11
12use crate::device::{
13 hardware::{HardwareCommand, HardwareWriteCmd},
14 protocol::{ProtocolHandler, generic_protocol_setup},
15};
16use buttplug_core::errors::ButtplugDeviceError;
17use buttplug_server_device_config::Endpoint;
18
19const JEJOUE_PROTOCOL_UUID: Uuid = uuid!("d3dd2bf5-b029-4bc1-9466-39f82c2e3258");
20generic_protocol_setup!(JeJoue, "jejoue");
21
22pub struct JeJoue {
23 speeds: [AtomicU8; 2],
24}
25
26impl Default for JeJoue {
27 fn default() -> Self {
28 Self {
29 speeds: [AtomicU8::new(0), AtomicU8::new(0)],
30 }
31 }
32}
33
34impl ProtocolHandler for JeJoue {
35 fn handle_output_vibrate_cmd(
36 &self,
37 feature_index: u32,
38 _feature_id: Uuid,
39 speed: u32,
40 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
41 self.speeds[feature_index as usize].store(speed as u8, Ordering::Relaxed);
42
43 // Default to both vibes
44 let mut pattern: u8 = 1;
45
46 // Use vibe 1 as speed
47 let mut speed = self.speeds[0].load(Ordering::Relaxed);
48 let vibe1_running = speed > 0;
49 let mut vibe2_running = false;
50 // Unless it's zero, then give vibe 2 a chance
51 if !vibe1_running {
52 speed = self.speeds[1].load(Ordering::Relaxed);
53
54 // If we've vibing on 2 only, then change the pattern
55 if speed != 0 {
56 vibe2_running = true;
57 pattern = 3;
58 }
59 }
60
61 // If we've vibing on 1 only, then change the pattern
62 if pattern == 1 && speed != 0 && !vibe2_running {
63 pattern = 2;
64 }
65
66 Ok(vec![
67 HardwareWriteCmd::new(
68 &[JEJOUE_PROTOCOL_UUID],
69 Endpoint::Tx,
70 vec![pattern, speed],
71 false,
72 )
73 .into(),
74 ])
75 }
76}