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, message::OutputType}; 26use buttplug_server_device_config::{ 27 Endpoint, 28 ProtocolCommunicationSpecifier, 29 ServerDeviceDefinition, 30 UserDeviceIdentifier, 31}; 32 33generic_protocol_initializer_setup!(WeVibe8Bit, "wevibe-8bit"); 34 35const WEVIBE8BIT_PROTOCOL_UUID: Uuid = uuid!("f5e48973-09e9-4063-8177-487f6292e2ed"); 36 37#[derive(Default)] 38pub struct WeVibe8BitInitializer {} 39 40#[async_trait] 41impl ProtocolInitializer for WeVibe8BitInitializer { 42 async fn initialize( 43 &mut self, 44 _hardware: Arc<Hardware>, 45 def: &ServerDeviceDefinition, 46 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> { 47 let num_vibrators = def 48 .features() 49 .iter() 50 .filter(|x| { 51 x.output() 52 .as_ref() 53 .is_some_and(|x| x.contains(OutputType::Vibrate)) 54 }) 55 .count() as u8; 56 Ok(Arc::new(WeVibe8Bit::new(num_vibrators))) 57 } 58} 59 60pub struct WeVibe8Bit { 61 num_vibrators: u8, 62 speeds: [AtomicU8; 2], 63} 64 65impl WeVibe8Bit { 66 fn new(num_vibrators: u8) -> Self { 67 Self { 68 num_vibrators, 69 speeds: [AtomicU8::default(), AtomicU8::default()], 70 } 71 } 72} 73 74impl ProtocolHandler for WeVibe8Bit { 75 fn handle_output_vibrate_cmd( 76 &self, 77 feature_index: u32, 78 _feature_id: uuid::Uuid, 79 speed: u32, 80 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 81 self.speeds[feature_index as usize].store(speed as u8, Ordering::Relaxed); 82 let max_vibrators = if self.num_vibrators > 1 { 1 } else { 0 }; 83 let r_speed_int = self.speeds[0].load(Ordering::Relaxed); 84 let r_speed_ext = self.speeds[max_vibrators].load(Ordering::Relaxed); 85 let data = if r_speed_int == 0 && r_speed_ext == 0 { 86 vec![0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] 87 } else { 88 let status_byte: u8 = 89 (if r_speed_ext == 0 { 0 } else { 2 }) | (if r_speed_int == 0 { 0 } else { 1 }); 90 vec![ 91 0x0f, 92 0x03, 93 0x00, 94 r_speed_ext + 3, 95 r_speed_int + 3, 96 status_byte, 97 0x00, 98 0x00, 99 ] 100 }; 101 Ok(vec![ 102 HardwareWriteCmd::new(&[WEVIBE8BIT_PROTOCOL_UUID], Endpoint::Tx, data, true).into(), 103 ]) 104 } 105}