Buttplug sex toy control library
1// Buttplug Rust Source Code File - See https://buttplug.io for more info.
2//
3// Copyright 2016-2025 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, HardwareReadCmd, HardwareWriteCmd},
10 protocol::{ProtocolHandler, generic_protocol_setup},
11};
12use buttplug_core::{
13 errors::ButtplugDeviceError,
14 message::{self, InputData, InputReadingV4, InputTypeData},
15};
16use buttplug_server_device_config::Endpoint;
17use futures::{FutureExt, future::BoxFuture};
18use std::sync::atomic::{AtomicU8, Ordering};
19use std::{default::Default, sync::Arc};
20use uuid::{Uuid, uuid};
21const KIIROO_POWERSHUOT_PROTOCOL_UUID: Uuid = uuid!("06f49eb9-0dca-42a8-92f0-58634cc017d0");
22
23generic_protocol_setup!(KiirooPowerShot, "kiiroo-powershot");
24
25#[derive(Default)]
26pub struct KiirooPowerShot {
27 last_cmds: [AtomicU8; 2],
28}
29
30impl KiirooPowerShot {
31 fn form_hardware_command(
32 &self,
33 index: u32,
34 speed: u32,
35 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
36 self.last_cmds[index as usize].store(speed as u8, Ordering::Relaxed);
37 Ok(vec![
38 HardwareWriteCmd::new(
39 &[KIIROO_POWERSHUOT_PROTOCOL_UUID],
40 Endpoint::Tx,
41 vec![
42 0x01,
43 0x00,
44 0x00,
45 self.last_cmds[0].load(Ordering::Relaxed),
46 self.last_cmds[1].load(Ordering::Relaxed),
47 0x00,
48 ],
49 true,
50 )
51 .into(),
52 ])
53 }
54}
55
56impl ProtocolHandler for KiirooPowerShot {
57 fn handle_output_vibrate_cmd(
58 &self,
59 feature_index: u32,
60 _feature_id: Uuid,
61 speed: u32,
62 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
63 self.form_hardware_command(feature_index, speed)
64 }
65
66 fn handle_battery_level_cmd(
67 &self,
68 device_index: u32,
69 device: Arc<Hardware>,
70 feature_index: u32,
71 feature_id: Uuid,
72 ) -> BoxFuture<'_, Result<InputReadingV4, ButtplugDeviceError>> {
73 debug!("Trying to get battery reading.");
74 let msg = HardwareReadCmd::new(feature_id, Endpoint::RxBLEBattery, 20, 0);
75 let fut = device.read_value(&msg);
76 async move {
77 let hw_msg = fut.await?;
78 let data = hw_msg.data();
79 let battery_reading = message::InputReadingV4::new(
80 device_index,
81 feature_index,
82 InputTypeData::Battery(InputData::new(data[0])),
83 );
84 debug!("Got battery reading: {}", data[0]);
85 Ok(battery_reading)
86 }
87 .boxed()
88 }
89}