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, HardwareReadCmd, 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::Arc; 26use uuid::{Uuid, uuid}; 27 28generic_protocol_initializer_setup!(Ankni, "ankni"); 29 30const ANKNI_PROTOCOL_UUID: Uuid = uuid!("9859232d-57ee-4135-a93c-c8988bf8cbbf"); 31 32#[derive(Default)] 33pub struct AnkniInitializer {} 34 35#[async_trait] 36impl ProtocolInitializer for AnkniInitializer { 37 async fn initialize( 38 &mut self, 39 hardware: Arc<Hardware>, 40 _: &ServerDeviceDefinition, 41 ) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> { 42 let msg = HardwareReadCmd::new(ANKNI_PROTOCOL_UUID, Endpoint::Generic0, 16, 100); 43 let reading = hardware.read_value(&msg).await?; 44 45 // No mac address on PnP characteristic, assume no handshake required 46 if reading.data().len() > 6 { 47 return Ok(Arc::new(Ankni::default())); 48 } 49 50 let mut addrdata = Vec::with_capacity(7); 51 addrdata.push(0x01); 52 addrdata.extend(reading.data()); 53 54 let check = ((crc16(addrdata) & 0xff00) >> 8) as u8; 55 debug!("Ankni Checksum: {:#02X}", check); 56 57 let msg = HardwareWriteCmd::new( 58 &[ANKNI_PROTOCOL_UUID], 59 Endpoint::Tx, 60 vec![ 61 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 62 0x01, 0x01, 0x01, 0x01, 0x01, 63 ], 64 true, 65 ); 66 hardware.write_value(&msg).await?; 67 let msg = HardwareWriteCmd::new( 68 &[ANKNI_PROTOCOL_UUID], 69 Endpoint::Tx, 70 vec![ 71 0x01, 0x02, check, check, check, check, check, check, check, check, check, check, check, 72 check, check, check, check, check, 0x00, 0x00, 73 ], 74 true, 75 ); 76 hardware.write_value(&msg).await?; 77 Ok(Arc::new(Ankni::default())) 78 } 79} 80 81#[derive(Default)] 82pub struct Ankni {} 83 84impl ProtocolHandler for Ankni { 85 fn handle_output_vibrate_cmd( 86 &self, 87 _feature_index: u32, 88 feature_id: Uuid, 89 speed: u32, 90 ) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> { 91 Ok(vec![ 92 HardwareWriteCmd::new( 93 &[feature_id], 94 Endpoint::Tx, 95 vec![ 96 0x03, 97 0x12, 98 speed as u8, 99 0x00, 100 0x00, 101 0x00, 102 0x00, 103 0x00, 104 0x00, 105 0x00, 106 0x00, 107 0x00, 108 0x00, 109 0x00, 110 0x00, 111 0x00, 112 0x00, 113 0x00, 114 0x00, 115 0x00, 116 ], 117 true, 118 ) 119 .into(), 120 ]) 121 } 122} 123 124fn crc16(advert_data: Vec<u8>) -> u16 { 125 let mut remain: u16 = 0; 126 for byte in advert_data { 127 remain ^= (byte as u16) << 8; 128 for _ in 0..8 { 129 if (remain & (1 << (u16::BITS - 1))) != 0 { 130 remain <<= 1; 131 remain ^= 0x1021; 132 } else { 133 remain <<= 1; 134 } 135 } 136 } 137 remain 138}