Buttplug sex toy control library
at dev 3.1 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; 9 10use crate::device::{ 11 hardware::{Hardware, HardwareCommand, HardwareWriteCmd}, 12 protocol::{ 13 ProtocolHandler, 14 ProtocolIdentifier, 15 ProtocolInitializer, 16 generic_protocol_initializer_setup, 17 }, 18}; 19use async_trait::async_trait; 20use buttplug_core::errors::ButtplugDeviceError; 21use buttplug_server_device_config::Endpoint; 22use buttplug_server_device_config::{ 23 ProtocolCommunicationSpecifier, 24 ServerDeviceDefinition, 25 UserDeviceIdentifier, 26}; 27use std::sync::{ 28 Arc, 29 atomic::{AtomicU8, Ordering}, 30}; 31use uuid::{Uuid, uuid}; 32 33const KIIROO_V21_INITIALIZED_PROTOCOL_UUID: Uuid = uuid!("22329023-5464-41b6-a0de-673d7e993055"); 34 35generic_protocol_initializer_setup!(KiirooV21Initialized, "kiiroo-v21-initialized"); 36 37#[derive(Default)] 38pub struct KiirooV21InitializedInitializer {} 39 40#[async_trait] 41impl ProtocolInitializer for KiirooV21InitializedInitializer { 42 async fn initialize( 43 &mut self, 44 hardware: Arc<Hardware>, 45 _: &ServerDeviceDefinition, 46 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> { 47 debug!("calling Onyx+ init"); 48 hardware 49 .write_value(&HardwareWriteCmd::new( 50 &[KIIROO_V21_INITIALIZED_PROTOCOL_UUID], 51 Endpoint::Tx, 52 vec![0x03u8, 0x00u8, 0x64u8, 0x19u8], 53 true, 54 )) 55 .await?; 56 hardware 57 .write_value(&HardwareWriteCmd::new( 58 &[KIIROO_V21_INITIALIZED_PROTOCOL_UUID], 59 Endpoint::Tx, 60 vec![0x03u8, 0x00u8, 0x64u8, 0x00u8], 61 true, 62 )) 63 .await?; 64 Ok(Arc::new(KiirooV21Initialized::default())) 65 } 66} 67 68#[derive(Default)] 69pub struct KiirooV21Initialized { 70 previous_position: Arc<AtomicU8>, 71} 72 73impl ProtocolHandler for KiirooV21Initialized { 74 fn handle_output_vibrate_cmd( 75 &self, 76 _feature_index: u32, 77 feature_id: Uuid, 78 speed: u32, 79 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 80 Ok(vec![ 81 HardwareWriteCmd::new(&[feature_id], Endpoint::Tx, vec![0x01, speed as u8], false).into(), 82 ]) 83 } 84 85 fn handle_position_with_duration_cmd( 86 &self, 87 _feature_index: u32, 88 feature_id: Uuid, 89 position: u32, 90 duration: u32, 91 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 92 // In the protocol, we know max speed is 99, so convert here. We have to 93 // use AtomicU8 because there's no AtomicF64 yet. 94 let previous_position = self.previous_position.load(Ordering::Relaxed); 95 let distance = (previous_position as f64 - (position as f64)).abs() / 99f64; 96 let calculated_speed = (calculate_speed(distance, duration) * 99f64) as u8; 97 98 self 99 .previous_position 100 .store(position as u8, Ordering::Relaxed); 101 Ok(vec![ 102 HardwareWriteCmd::new( 103 &[feature_id], 104 Endpoint::Tx, 105 [0x03, 0x00, calculated_speed, position as u8].to_vec(), 106 false, 107 ) 108 .into(), 109 ]) 110 } 111}