Buttplug sex toy control library
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 uuid::Uuid; 9 10use crate::device::{ 11 hardware::{HardwareCommand, HardwareWriteCmd}, 12 protocol::{ProtocolHandler, generic_protocol_setup}, 13}; 14use buttplug_core::errors::ButtplugDeviceError; 15use buttplug_server_device_config::Endpoint; 16use std::sync::{ 17 Arc, 18 atomic::{AtomicU8, Ordering}, 19}; 20 21generic_protocol_setup!(ServeU, "serveu"); 22 23#[derive(Default)] 24pub struct ServeU { 25 last_position: Arc<AtomicU8>, 26} 27 28impl ProtocolHandler for ServeU { 29 fn handle_position_with_duration_cmd( 30 &self, 31 _feature_index: u32, 32 feature_id: Uuid, 33 position: u32, 34 duration: u32, 35 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 36 let last_pos = self.last_position.load(Ordering::Relaxed); 37 // Need to get "units" (abstracted steps 0-100) per second, so calculate how far we need to move over our goal duration. 38 let goal_pos = position as u8; 39 self.last_position.store(goal_pos, Ordering::Relaxed); 40 let speed_threshold = 41 ((((goal_pos as i8) - last_pos as i8).abs()) as f64 / ((duration as f64) / 1000f64)).ceil(); 42 43 let speed = if speed_threshold <= 0.00001 { 44 // Stop device 45 0 46 } else if speed_threshold <= 50.0 { 47 (speed_threshold / 2.0).ceil() as u8 48 } else if speed_threshold <= 750.0 { 49 ((speed_threshold - 50.0) / 4.0).ceil() as u8 + 25u8 50 } else if speed_threshold <= 2000.0 { 51 ((speed_threshold - 750.0) / 25.0).ceil() as u8 + 200u8 52 } else { 53 // If we're going faster than 2000u/s, just return max value (0xFA) 54 0xFA 55 }; 56 57 Ok(vec![ 58 HardwareWriteCmd::new( 59 &[feature_id], 60 Endpoint::Tx, 61 vec![0x01, goal_pos, speed], 62 false, 63 ) 64 .into(), 65 ]) 66 } 67}