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 crate::device::{ 9 hardware::{Hardware, HardwareCommand, HardwareWriteCmd}, 10 protocol::{ 11 ProtocolHandler, 12 ProtocolIdentifier, 13 ProtocolInitializer, 14 generic_protocol_initializer_setup, 15 }, 16}; 17use async_trait::async_trait; 18use buttplug_core::errors::ButtplugDeviceError; 19use buttplug_core::message::OutputType; 20use buttplug_server_device_config::Endpoint; 21use buttplug_server_device_config::{ 22 ProtocolCommunicationSpecifier, 23 ServerDeviceDefinition, 24 UserDeviceIdentifier, 25}; 26use std::sync::Arc; 27use std::sync::atomic::{AtomicU8, Ordering}; 28use uuid::{Uuid, uuid}; 29 30const WEVIBE_PROTOCOL_UUID: Uuid = uuid!("3658e33d-086d-401e-9dce-8e9e88ff791f"); 31generic_protocol_initializer_setup!(WeVibe, "wevibe"); 32 33#[derive(Default)] 34pub struct WeVibeInitializer {} 35 36#[async_trait] 37impl ProtocolInitializer for WeVibeInitializer { 38 async fn initialize( 39 &mut self, 40 hardware: Arc<Hardware>, 41 def: &ServerDeviceDefinition, 42 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> { 43 debug!("calling WeVibe init"); 44 hardware 45 .write_value(&HardwareWriteCmd::new( 46 &[WEVIBE_PROTOCOL_UUID], 47 Endpoint::Tx, 48 vec![0x0f, 0x03, 0x00, 0x99, 0x00, 0x03, 0x00, 0x00], 49 true, 50 )) 51 .await?; 52 hardware 53 .write_value(&HardwareWriteCmd::new( 54 &[WEVIBE_PROTOCOL_UUID], 55 Endpoint::Tx, 56 vec![0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 57 true, 58 )) 59 .await?; 60 let num_vibrators = def 61 .features() 62 .iter() 63 .filter(|x| { 64 x.output() 65 .as_ref() 66 .is_some_and(|x| x.contains(OutputType::Vibrate)) 67 }) 68 .count() as u8; 69 Ok(Arc::new(WeVibe::new(num_vibrators))) 70 } 71} 72 73pub struct WeVibe { 74 num_vibrators: u8, 75 speeds: [AtomicU8; 2], 76} 77 78impl WeVibe { 79 fn new(num_vibrators: u8) -> Self { 80 Self { 81 num_vibrators, 82 speeds: [AtomicU8::default(), AtomicU8::default()], 83 } 84 } 85} 86 87impl ProtocolHandler for WeVibe { 88 fn handle_output_vibrate_cmd( 89 &self, 90 feature_index: u32, 91 _feature_id: uuid::Uuid, 92 speed: u32, 93 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 94 self.speeds[feature_index as usize].store(speed as u8, Ordering::Relaxed); 95 let max_vibrators = if self.num_vibrators > 1 { 1 } else { 0 }; 96 let r_speed_int = self.speeds[0].load(Ordering::Relaxed); 97 let r_speed_ext = self.speeds[max_vibrators].load(Ordering::Relaxed); 98 let data = if r_speed_int == 0 && r_speed_ext == 0 { 99 vec![0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] 100 } else { 101 vec![ 102 0x0f, 103 0x03, 104 0x00, 105 r_speed_ext | (r_speed_int << 4), 106 0x00, 107 0x03, 108 0x00, 109 0x00, 110 ] 111 }; 112 Ok(vec![ 113 HardwareWriteCmd::new(&[WEVIBE_PROTOCOL_UUID], Endpoint::Tx, data, true).into(), 114 ]) 115 } 116}