Buttplug sex toy control library
at dev 115 lines 2.9 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 crate::device::{ 9 hardware::{Hardware, HardwareCommand, HardwareWriteCmd}, 10 protocol::{ 11 ProtocolHandler, 12 ProtocolIdentifier, 13 ProtocolInitializer, 14 ProtocolKeepaliveStrategy, 15 generic_protocol_initializer_setup, 16 }, 17}; 18use async_trait::async_trait; 19use buttplug_core::errors::ButtplugDeviceError; 20use buttplug_server_device_config::Endpoint; 21use buttplug_server_device_config::{ 22 ProtocolCommunicationSpecifier, 23 ServerDeviceDefinition, 24 UserDeviceIdentifier, 25}; 26use std::{ 27 sync::{ 28 Arc, 29 atomic::{AtomicU8, Ordering}, 30 }, 31 time::Duration, 32}; 33use uuid::{Uuid, uuid}; 34 35generic_protocol_initializer_setup!(MysteryVibe, "mysteryvibe"); 36 37const MYSTERYVIBE_PROTOCOL_UUID: Uuid = uuid!("53bca658-2efe-4388-8ced-333789bac20b"); 38 39#[derive(Default)] 40pub struct MysteryVibeInitializer {} 41 42#[async_trait] 43impl ProtocolInitializer for MysteryVibeInitializer { 44 async fn initialize( 45 &mut self, 46 hardware: Arc<Hardware>, 47 def: &ServerDeviceDefinition, 48 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> { 49 let msg = HardwareWriteCmd::new( 50 &[MYSTERYVIBE_PROTOCOL_UUID], 51 Endpoint::TxMode, 52 vec![0x43u8, 0x02u8, 0x00u8], 53 true, 54 ); 55 hardware.write_value(&msg).await?; 56 let vibrator_count = def 57 .features() 58 .iter() 59 .filter(|x| x.output().is_some()) 60 .count(); 61 Ok(Arc::new(MysteryVibe::new(vibrator_count as u8))) 62 } 63} 64 65// Time between Mysteryvibe update commands, in milliseconds. This is basically 66// a best guess derived from watching packet timing a few years ago. 67// 68// Thelemic vibrator. Neat. 69// 70const MYSTERYVIBE_COMMAND_DELAY_MS: u64 = 93; 71 72#[derive(Default)] 73pub struct MysteryVibe { 74 speeds: Vec<AtomicU8>, 75} 76 77impl MysteryVibe { 78 pub fn new(vibrator_count: u8) -> Self { 79 Self { 80 speeds: std::iter::repeat_with(AtomicU8::default) 81 .take(vibrator_count as usize) 82 .collect(), 83 } 84 } 85} 86 87impl ProtocolHandler for MysteryVibe { 88 fn keepalive_strategy(&self) -> ProtocolKeepaliveStrategy { 89 ProtocolKeepaliveStrategy::RepeatLastPacketStrategyWithTiming(Duration::from_millis( 90 MYSTERYVIBE_COMMAND_DELAY_MS, 91 )) 92 } 93 94 fn handle_output_vibrate_cmd( 95 &self, 96 feature_index: u32, 97 _feature_id: Uuid, 98 speed: u32, 99 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 100 self.speeds[feature_index as usize].store(speed as u8, Ordering::Relaxed); 101 Ok(vec![ 102 HardwareWriteCmd::new( 103 &[MYSTERYVIBE_PROTOCOL_UUID], 104 Endpoint::TxVibrate, 105 self 106 .speeds 107 .iter() 108 .map(|x| x.load(Ordering::Relaxed)) 109 .collect(), 110 false, 111 ) 112 .into(), 113 ]) 114 } 115}