Buttplug sex toy control library
at dev 2.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 super::fleshlight_launch_helper::calculate_speed; 9use crate::device::{ 10 hardware::{Hardware, HardwareCommand, HardwareWriteCmd}, 11 protocol::{ 12 ProtocolHandler, 13 ProtocolIdentifier, 14 ProtocolInitializer, 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::sync::{ 27 Arc, 28 atomic::{AtomicU8, Ordering}, 29}; 30use uuid::{Uuid, uuid}; 31 32const KIIROO_V2_PROTOCOL_UUID: Uuid = uuid!("05ab9d57-5e65-47b2-add4-5bad3e8663e5"); 33generic_protocol_initializer_setup!(KiirooV2, "kiiroo-v2"); 34 35#[derive(Default)] 36pub struct KiirooV2Initializer {} 37 38#[async_trait] 39impl ProtocolInitializer for KiirooV2Initializer { 40 async fn initialize( 41 &mut self, 42 hardware: Arc<Hardware>, 43 _: &ServerDeviceDefinition, 44 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> { 45 let msg = HardwareWriteCmd::new( 46 &[KIIROO_V2_PROTOCOL_UUID], 47 Endpoint::Firmware, 48 vec![0x0u8], 49 true, 50 ); 51 hardware.write_value(&msg).await?; 52 Ok(Arc::new(KiirooV2::default())) 53 } 54} 55 56#[derive(Default)] 57pub struct KiirooV2 { 58 previous_position: Arc<AtomicU8>, 59} 60 61impl ProtocolHandler for KiirooV2 { 62 fn handle_position_with_duration_cmd( 63 &self, 64 _feature_index: u32, 65 feature_id: Uuid, 66 position: u32, 67 duration: u32, 68 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 69 // In the protocol, we know max speed is 99, so convert here. We have to 70 // use AtomicU8 because there's no AtomicF64 yet. 71 let previous_position = self.previous_position.load(Ordering::Relaxed); 72 let distance = (previous_position as f64 - (position as f64)).abs() / 99f64; 73 let position = position as u8; 74 let calculated_speed = (calculate_speed(distance, duration) * 99f64) as u8; 75 self.previous_position.store(position, Ordering::Relaxed); 76 Ok(vec![ 77 HardwareWriteCmd::new( 78 &[feature_id], 79 Endpoint::Tx, 80 [position, calculated_speed].to_vec(), 81 false, 82 ) 83 .into(), 84 ]) 85 } 86}