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 ProtocolKeepaliveStrategy,
15 generic_protocol_initializer_setup,
16 },
17};
18use async_trait::async_trait;
19use buttplug_core::errors::ButtplugDeviceError;
20use buttplug_server_device_config::Endpoint;
21use buttplug_server_device_config::{
22 ProtocolCommunicationSpecifier,
23 ServerDeviceDefinition,
24 UserDeviceIdentifier,
25};
26use std::sync::Arc;
27use std::time::Duration;
28use uuid::{Uuid, uuid};
29
30const LETEN_PROTOCOL_UUID: Uuid = uuid!("7d899f44-2676-4a00-9c68-0c800055ee2a");
31
32generic_protocol_initializer_setup!(Leten, "leten");
33#[derive(Default)]
34pub struct LetenInitializer {}
35
36#[async_trait]
37impl ProtocolInitializer for LetenInitializer {
38 async fn initialize(
39 &mut self,
40 hardware: Arc<Hardware>,
41 _: &ServerDeviceDefinition,
42 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> {
43 // There's a more complex auth flow that the app "sometimes" goes through where it
44 // sends [0x04, 0x00] and waits for [0x01] on Rx before calling [0x04, 0x01]
45 hardware
46 .write_value(&HardwareWriteCmd::new(
47 &[LETEN_PROTOCOL_UUID],
48 Endpoint::Tx,
49 vec![0x04, 0x01],
50 true,
51 ))
52 .await?;
53 // Sometimes sending this causes Rx to receive [0x0a]
54 Ok(Arc::new(Leten::default()))
55 }
56}
57
58const LETEN_COMMAND_DELAY_MS: u64 = 1000;
59
60#[derive(Default)]
61pub struct Leten {}
62
63impl ProtocolHandler for Leten {
64 fn keepalive_strategy(&self) -> ProtocolKeepaliveStrategy {
65 // Leten keepalive is shorter
66 ProtocolKeepaliveStrategy::RepeatLastPacketStrategyWithTiming(Duration::from_millis(
67 LETEN_COMMAND_DELAY_MS,
68 ))
69 }
70
71 fn handle_output_vibrate_cmd(
72 &self,
73 _feature_index: u32,
74 feature_id: Uuid,
75 speed: u32,
76 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
77 Ok(vec![
78 HardwareWriteCmd::new(&[feature_id], Endpoint::Tx, vec![0x02, speed as u8], true).into(),
79 ])
80 }
81}