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 crate::device::{ 9 hardware::{Hardware, HardwareCommand, HardwareSubscribeCmd, 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_server_device_config::Endpoint; 20use buttplug_server_device_config::{ 21 ProtocolCommunicationSpecifier, 22 ServerDeviceDefinition, 23 UserDeviceIdentifier, 24}; 25use std::sync::{ 26 Arc, 27 atomic::{AtomicU8, Ordering}, 28}; 29use uuid::{Uuid, uuid}; 30 31const LELO_F1S_PROTOCOL_UUID: Uuid = uuid!("4987f232-40f9-47a3-8d0c-e30b74e75310"); 32generic_protocol_initializer_setup!(LeloF1s, "lelo-f1s"); 33 34#[derive(Default)] 35pub struct LeloF1sInitializer {} 36 37#[async_trait] 38impl ProtocolInitializer for LeloF1sInitializer { 39 async fn initialize( 40 &mut self, 41 hardware: Arc<Hardware>, 42 _: &ServerDeviceDefinition, 43 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> { 44 // The Lelo F1s needs you to hit the power button after connection 45 // before it'll accept any commands. Unless we listen for event on 46 // the button, this is more likely to turn the device off. 47 hardware 48 .subscribe(&HardwareSubscribeCmd::new( 49 LELO_F1S_PROTOCOL_UUID, 50 Endpoint::Rx, 51 )) 52 .await?; 53 Ok(Arc::new(LeloF1s::new(false))) 54 } 55} 56 57pub struct LeloF1s { 58 speeds: [AtomicU8; 2], 59 write_with_response: bool, 60} 61 62impl LeloF1s { 63 pub fn new(write_with_response: bool) -> Self { 64 Self { 65 write_with_response, 66 speeds: [AtomicU8::new(0), AtomicU8::new(0)], 67 } 68 } 69} 70 71impl ProtocolHandler for LeloF1s { 72 fn handle_output_vibrate_cmd( 73 &self, 74 feature_index: u32, 75 _feature_id: Uuid, 76 speed: u32, 77 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 78 self.speeds[feature_index as usize].store(speed as u8, Ordering::Relaxed); 79 let mut cmd_vec = vec![0x1]; 80 self 81 .speeds 82 .iter() 83 .for_each(|v| cmd_vec.push(v.load(Ordering::Relaxed))); 84 Ok(vec![ 85 HardwareWriteCmd::new( 86 &[LELO_F1S_PROTOCOL_UUID], 87 Endpoint::Tx, 88 cmd_vec, 89 self.write_with_response, 90 ) 91 .into(), 92 ]) 93 } 94}