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_V2_PROTOCOL_UUID: Uuid = uuid!("3144b936-99c8-47f3-b85d-defa5fac9e6d");
20generic_protocol_setup!(JoyHubV2, "joyhub-v2");
21
22#[derive(Default)]
23pub struct JoyHubV2 {
24 last_cmds: [AtomicU8; 3],
25}
26
27impl JoyHubV2 {
28 fn form_hardware_command(
29 &self,
30 index: u32,
31 speed: u32,
32 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
33 info!("GOT JOYHUB COMMAND");
34 self.last_cmds[index as usize].store(speed as u8, Ordering::Relaxed);
35 Ok(vec![
36 HardwareWriteCmd::new(
37 &[JOYHUB_V2_PROTOCOL_UUID],
38 Endpoint::Tx,
39 vec![
40 0xa0,
41 0x03,
42 self.last_cmds[0].load(Ordering::Relaxed),
43 self.last_cmds[1].load(Ordering::Relaxed),
44 self.last_cmds[2].load(Ordering::Relaxed),
45 0x00,
46 0xaa,
47 ],
48 false,
49 )
50 .into(),
51 ])
52 }
53}
54
55impl ProtocolHandler for JoyHubV2 {
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![0xa0, 0x0d, 0x00, 0x00, level as u8, 0xff],
94 false,
95 )
96 .into(),
97 ])
98 }
99}