Buttplug sex toy control library
at master 132 lines 3.5 kB view raw
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}