Buttplug sex toy control library
at dev 2.4 kB view raw
1// Buttplug Rust Source Code File - See https://buttplug.io for more info. 2// 3// Copyright 2016-2023 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 uuid::{Uuid, uuid}; 9 10use crate::device::{ 11 hardware::{HardwareCommand, HardwareWriteCmd}, 12 protocol::{ProtocolHandler, generic_protocol_setup}, 13}; 14use buttplug_core::errors::ButtplugDeviceError; 15use buttplug_server_device_config::Endpoint; 16use std::num::Wrapping; 17use std::sync::atomic::{AtomicU8, Ordering}; 18 19static KEY_TAB: [[u8; 12]; 4] = [ 20 [0, 24, 0x98, 0xf7, 0xa5, 61, 13, 41, 37, 80, 68, 70], 21 [0, 69, 110, 106, 111, 120, 32, 83, 45, 49, 46, 55], 22 [0, 101, 120, 32, 84, 111, 121, 115, 10, 0x8e, 0x9d, 0xa3], 23 [0, 0xc5, 0xd6, 0xe7, 0xf8, 10, 50, 32, 111, 98, 13, 10], 24]; 25 26const GALAKU_PUMP_PROTOCOL_UUID: Uuid = uuid!("165ae3a9-33be-46a8-b438-9a6fc0f183cb"); 27generic_protocol_setup!(GalakuPump, "galaku-pump"); 28 29pub struct GalakuPump { 30 speeds: [AtomicU8; 2], 31} 32 33impl Default for GalakuPump { 34 fn default() -> Self { 35 Self { 36 speeds: [AtomicU8::new(0), AtomicU8::new(0)], 37 } 38 } 39} 40 41impl GalakuPump { 42 fn hardware_command(&self) -> Vec<HardwareCommand> { 43 let mut data: Vec<u8> = vec![ 44 0x23, 45 0x5a, 46 0x00, 47 0x00, 48 0x01, 49 0x60, 50 0x03, 51 self.speeds[0].load(Ordering::Relaxed), 52 self.speeds[1].load(Ordering::Relaxed), 53 0x00, 54 0x00, 55 ]; 56 data.push(data.iter().fold(0u8, |c, b| (Wrapping(c) + Wrapping(*b)).0)); 57 58 let mut data2: Vec<u8> = vec![0x23]; 59 for i in 1..data.len() { 60 let k = KEY_TAB[(data2[i - 1] & 3) as usize][i]; 61 data2.push((Wrapping((k ^ 0x23) ^ data[i]) + Wrapping(k)).0); 62 } 63 64 vec![HardwareWriteCmd::new(&[GALAKU_PUMP_PROTOCOL_UUID], Endpoint::Tx, data2, true).into()] 65 } 66} 67 68impl ProtocolHandler for GalakuPump { 69 fn handle_output_oscillate_cmd( 70 &self, 71 _feature_index: u32, 72 _feature_id: Uuid, 73 speed: u32, 74 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 75 self.speeds[0].store(speed as u8, Ordering::Relaxed); 76 Ok(self.hardware_command()) 77 } 78 79 fn handle_output_vibrate_cmd( 80 &self, 81 _feature_index: u32, 82 _feature_id: Uuid, 83 speed: u32, 84 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 85 self.speeds[1].store(speed as u8, Ordering::Relaxed); 86 Ok(self.hardware_command()) 87 } 88}