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