fork
Configure Feed
Select the types of activity you want to include in your feed.
Buttplug sex toy control library
fork
Configure Feed
Select the types of activity you want to include in your feed.
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::{
9 Arc,
10 atomic::{AtomicU8, Ordering},
11};
12
13use async_trait::async_trait;
14use uuid::{Uuid, uuid};
15
16use crate::device::{
17 hardware::{Hardware, HardwareCommand, HardwareWriteCmd},
18 protocol::{
19 ProtocolHandler,
20 ProtocolIdentifier,
21 ProtocolInitializer,
22 generic_protocol_initializer_setup,
23 },
24};
25use buttplug_core::errors::ButtplugDeviceError;
26use buttplug_server_device_config::Endpoint;
27use buttplug_server_device_config::{
28 ProtocolCommunicationSpecifier,
29 ServerDeviceDefinition,
30 UserDeviceIdentifier,
31};
32const LOVEHONEY_DESIRE_PROTOCOL_UUID: Uuid = uuid!("5dcd8487-4814-44cb-a768-13bf81d545c0");
33const LOVEHONEY_DESIRE_VIBE2_PROTOCOL_UUID: Uuid = uuid!("d44a99fe-903b-4fff-bee7-1141767c9cca");
34
35generic_protocol_initializer_setup!(LovehoneyDesire, "lovehoney-desire");
36
37#[derive(Default)]
38pub struct LovehoneyDesireInitializer {}
39
40#[async_trait]
41impl ProtocolInitializer for LovehoneyDesireInitializer {
42 async fn initialize(
43 &mut self,
44 _: Arc<Hardware>,
45 def: &ServerDeviceDefinition,
46 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> {
47 Ok(Arc::new(LovehoneyDesire::new(
48 def
49 .features()
50 .iter()
51 .filter(|x| x.output().is_some())
52 .count() as u8,
53 )))
54 }
55}
56
57pub struct LovehoneyDesire {
58 current_commands: Vec<AtomicU8>,
59}
60
61impl LovehoneyDesire {
62 fn new(num_vibrators: u8) -> Self {
63 Self {
64 current_commands: std::iter::repeat_with(AtomicU8::default)
65 .take(num_vibrators as usize)
66 .collect(),
67 }
68 }
69}
70
71impl ProtocolHandler for LovehoneyDesire {
72 fn handle_output_vibrate_cmd(
73 &self,
74 feature_index: u32,
75 _feature_id: Uuid,
76 speed: u32,
77 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
78 // The Lovehoney Desire has 2 types of commands
79 //
80 // - Set both motors with one command
81 // - Set each motor separately
82 //
83 // We'll need to check what we got back and write our
84 // commands accordingly.
85 if self.current_commands.len() == 1 {
86 Ok(vec![
87 HardwareWriteCmd::new(
88 &[LOVEHONEY_DESIRE_PROTOCOL_UUID],
89 Endpoint::Tx,
90 vec![0xF3, 0, speed as u8],
91 true,
92 )
93 .into(),
94 ])
95 } else {
96 self.current_commands[feature_index as usize].store(speed as u8, Ordering::Relaxed);
97 let speed0 = self.current_commands[0].load(Ordering::Relaxed);
98 let speed1 = self.current_commands[1].load(Ordering::Relaxed);
99 if speed0 == speed1 {
100 Ok(vec![
101 HardwareWriteCmd::new(
102 &[
103 LOVEHONEY_DESIRE_PROTOCOL_UUID,
104 LOVEHONEY_DESIRE_VIBE2_PROTOCOL_UUID,
105 ],
106 Endpoint::Tx,
107 vec![0xF3, 0, speed0],
108 true,
109 )
110 .into(),
111 ])
112 } else {
113 Ok(vec![
114 HardwareWriteCmd::new(
115 &[LOVEHONEY_DESIRE_PROTOCOL_UUID],
116 Endpoint::Tx,
117 vec![0xF3, 1, speed0],
118 true,
119 )
120 .into(),
121 HardwareWriteCmd::new(
122 &[LOVEHONEY_DESIRE_VIBE2_PROTOCOL_UUID],
123 Endpoint::Tx,
124 vec![0xF3, 2, speed1],
125 true,
126 )
127 .into(),
128 ])
129 }
130 }
131 }
132}