Buttplug sex toy control library
at dev 2.8 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::ServerDeviceDefinition; 28use buttplug_server_device_config::{ProtocolCommunicationSpecifier, UserDeviceIdentifier}; 29const MAGICMOTIONV4_PROTOCOL_UUID: Uuid = uuid!("d4d62d09-c3e1-44c9-8eba-caa15de5b2a7"); 30 31generic_protocol_initializer_setup!(MagicMotionV4, "magic-motion-4"); 32 33#[derive(Default)] 34pub struct MagicMotionV4Initializer {} 35 36#[async_trait] 37impl ProtocolInitializer for MagicMotionV4Initializer { 38 async fn initialize( 39 &mut self, 40 _: Arc<Hardware>, 41 def: &ServerDeviceDefinition, 42 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> { 43 Ok(Arc::new(MagicMotionV4::new( 44 def 45 .features() 46 .iter() 47 .filter(|x| x.output().is_some()) 48 .count() as u8, 49 ))) 50 } 51} 52 53pub struct MagicMotionV4 { 54 current_commands: Vec<AtomicU8>, 55} 56 57impl MagicMotionV4 { 58 fn new(num_vibrators: u8) -> Self { 59 Self { 60 current_commands: std::iter::repeat_with(AtomicU8::default) 61 .take(num_vibrators as usize) 62 .collect(), 63 } 64 } 65} 66 67impl ProtocolHandler for MagicMotionV4 { 68 fn handle_output_vibrate_cmd( 69 &self, 70 feature_index: u32, 71 _feature_id: Uuid, 72 speed: u32, 73 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 74 let data = if self.current_commands.len() == 1 { 75 vec![ 76 0x10, 77 0xff, 78 0x04, 79 0x0a, 80 0x32, 81 0x32, 82 0x00, 83 0x04, 84 0x08, 85 speed as u8, 86 0x64, 87 0x00, 88 0x04, 89 0x08, 90 speed as u8, 91 0x64, 92 0x01, 93 ] 94 } else { 95 self.current_commands[feature_index as usize].store(speed as u8, Ordering::Relaxed); 96 let speed0 = self.current_commands[0].load(Ordering::Relaxed); 97 let speed1 = self.current_commands[1].load(Ordering::Relaxed); 98 vec![ 99 0x10, 0xff, 0x04, 0x0a, 0x32, 0x32, 0x00, 0x04, 0x08, speed0, 0x64, 0x00, 0x04, 0x08, 100 speed1, 0x64, 0x01, 101 ] 102 }; 103 Ok(vec![ 104 HardwareWriteCmd::new(&[MAGICMOTIONV4_PROTOCOL_UUID], Endpoint::Tx, data, true).into(), 105 ]) 106 } 107}