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 JOYHUB_PROTOCOL_UUID: Uuid = uuid!("c0f6785a-0056-4a2a-a2a9-dc7ca4ae2a0d");
20
21generic_protocol_setup!(JoyHub, "joyhub");
22
23#[derive(Default)]
24pub struct JoyHub {
25 last_cmds: [AtomicU8; 3],
26}
27
28impl JoyHub {
29 fn form_hardware_command(
30 &self,
31 index: u32,
32 speed: u32,
33 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
34 self.last_cmds[index as usize].store(speed as u8, Ordering::Relaxed);
35 Ok(vec![
36 HardwareWriteCmd::new(
37 &[JOYHUB_PROTOCOL_UUID],
38 Endpoint::Tx,
39 vec![
40 0xa0,
41 0x03,
42 self.last_cmds[0].load(Ordering::Relaxed),
43 self.last_cmds[2].load(Ordering::Relaxed),
44 self.last_cmds[1].load(Ordering::Relaxed),
45 0x00,
46 0xaa,
47 ],
48 false,
49 )
50 .into(),
51 ])
52 }
53}
54
55impl ProtocolHandler for JoyHub {
56 fn handle_output_vibrate_cmd(
57 &self,
58 feature_index: u32,
59 _feature_id: Uuid,
60 speed: u32,
61 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
62 self.form_hardware_command(feature_index, speed)
63 }
64
65 fn handle_output_rotate_cmd(
66 &self,
67 feature_index: u32,
68 _feature_id: Uuid,
69 speed: i32,
70 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
71 self.form_hardware_command(feature_index, speed as u32)
72 }
73
74 fn handle_output_oscillate_cmd(
75 &self,
76 feature_index: u32,
77 _feature_id: Uuid,
78 speed: u32,
79 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
80 self.form_hardware_command(feature_index, speed)
81 }
82
83 fn handle_output_constrict_cmd(
84 &self,
85 _feature_index: u32,
86 feature_id: Uuid,
87 level: u32,
88 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
89 Ok(vec![
90 HardwareWriteCmd::new(
91 &[feature_id],
92 Endpoint::Tx,
93 vec![
94 0xa0,
95 0x07,
96 if level == 0 { 0x00 } else { 0x01 },
97 0x00,
98 level as u8,
99 0xff,
100 ],
101 false,
102 )
103 .into(),
104 ])
105 }
106}