From 0306539c7154c3905d3607bc23c1e2a0c80ac8d6 Mon Sep 17 00:00:00 2001 From: blackspherefollower Date: Thu, 2 Jul 2026 10:53:20 +0100 Subject: [PATCH 1/5] feat: New Svakom Emma Neo identifier --- .../build-config/buttplug-device-config-v5.json | 6 ++++-- .../device-config/protocols/svakom-v1.yml | 2 ++ .../device-config/version.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json b/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json index 54d841f9a..8c2d9a5b2 100644 --- a/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json +++ b/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json @@ -1,7 +1,7 @@ { "version": { "major": 5, - "minor": 13 + "minor": 14 }, "protocols": { "activejoy": { @@ -21969,6 +21969,7 @@ "Aogu SUV", "Aogu SCB", "Emma NEO", + "Emma Neo", "Phoenix NEO" ], "services": { @@ -21998,7 +21999,8 @@ { "id": "68d39a06-e350-47ef-8834-e3197178b00e", "identifier": [ - "Emma NEO" + "Emma NEO", + "Emma Neo" ], "name": "Svakom Emma Neo" } diff --git a/crates/buttplug_server_device_config/device-config/protocols/svakom-v1.yml b/crates/buttplug_server_device_config/device-config/protocols/svakom-v1.yml index bf8affe2b..3d6c9d42f 100644 --- a/crates/buttplug_server_device_config/device-config/protocols/svakom-v1.yml +++ b/crates/buttplug_server_device_config/device-config/protocols/svakom-v1.yml @@ -21,6 +21,7 @@ configurations: id: c9556aba-5bda-4f23-a690-623c4b9ee04b - identifier: - Emma NEO + - Emma Neo name: Svakom Emma Neo id: 68d39a06-e350-47ef-8834-e3197178b00e communication: @@ -29,6 +30,7 @@ communication: - Aogu SUV - Aogu SCB - Emma NEO + - Emma Neo - Phoenix NEO services: 0000ffe0-0000-1000-8000-00805f9b34fb: diff --git a/crates/buttplug_server_device_config/device-config/version.yaml b/crates/buttplug_server_device_config/device-config/version.yaml index c69f148aa..f70e82f4e 100644 --- a/crates/buttplug_server_device_config/device-config/version.yaml +++ b/crates/buttplug_server_device_config/device-config/version.yaml @@ -1,3 +1,3 @@ version: major: 5 - minor: 13 + minor: 14 From 7f2308da7329337b6bbfde7cf50c983ec099583f Mon Sep 17 00:00:00 2001 From: blackspherefollower Date: Thu, 2 Jul 2026 12:40:58 +0100 Subject: [PATCH 2/5] feat: Adding new JoyHub devices * Punisher * Prismcy * AresIII Also swapping the features on the Perseus --- .../buttplug-device-config-v5.json | 74 +++++++++++++++++-- .../device-config/protocols/joyhub.yml | 45 ++++++++++- .../device-config/version.yaml | 2 +- 3 files changed, 110 insertions(+), 11 deletions(-) diff --git a/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json b/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json index 8c2d9a5b2..512eb921a 100644 --- a/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json +++ b/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json @@ -1,7 +1,7 @@ { "version": { "major": 5, - "minor": 14 + "minor": 16 }, "protocols": { "activejoy": { @@ -6080,7 +6080,10 @@ "J-MutantX", "J-Marino", "J-Jason", - "J-MartinoIII" + "J-MartinoIII", + "J-Punisher", + "J-Prismcy", + "J-AresIII" ], "services": { "0000ffa0-0000-1000-8000-00805f9b34fb": { @@ -9561,10 +9564,10 @@ { "features": [ { - "id": "12f36e6d-e9ce-439c-b6f5-3f80a4f4b47d", + "id": "cbd851bb-a0de-43b6-89df-947d5872454d", "index": 0, "output": { - "oscillate": { + "vibrate": { "value": [ 0, 255 @@ -9573,10 +9576,10 @@ } }, { - "id": "94025679-badf-49bb-a247-1dab022d9204", + "id": "2e5385b3-82be-4047-b998-49ee07aefa5e", "index": 2, "output": { - "vibrate": { + "oscillate": { "value": [ 0, 255 @@ -10641,6 +10644,65 @@ "J-MartinoIII" ], "name": "JoyHub Martino III" + }, + { + "features": [ + { + "id": "4272e178-cfb0-4e1f-a6cc-1083d83ede14", + "index": 0, + "output": { + "oscillate": { + "value": [ + 0, + 255 + ] + } + } + }, + { + "id": "de639d48-47e2-440d-b2c7-3c46068fc13d", + "index": 1, + "output": { + "vibrate": { + "value": [ + 0, + 255 + ] + } + } + }, + { + "id": "95a9b5b2-fc5f-45e9-b307-bd2941fd6883", + "index": 2, + "output": { + "vibrate": { + "value": [ + 0, + 255 + ] + } + } + } + ], + "id": "e437baf4-9e60-431e-a30f-5870faf5c1ad", + "identifier": [ + "J-Punisher" + ], + "name": "JoyHub Punisher" + }, + { + "id": "fcf3aa9b-8e2f-4751-8f7d-b208a62ef6c9", + "identifier": [ + "J-Prismcy" + ], + "name": "JoyHub Prismcy" + }, + { + "id": "5f902050-ee3f-4503-abcb-d0794c27180c", + "identifier": [ + "J-AresIII" + ], + "name": "JoyHub Ares III" } ], "defaults": { diff --git a/crates/buttplug_server_device_config/device-config/protocols/joyhub.yml b/crates/buttplug_server_device_config/device-config/protocols/joyhub.yml index 114ce0f7a..2f943dfe3 100644 --- a/crates/buttplug_server_device_config/device-config/protocols/joyhub.yml +++ b/crates/buttplug_server_device_config/device-config/protocols/joyhub.yml @@ -2028,16 +2028,16 @@ configurations: - J-Perseus name: JoyHub Perseus features: - - id: 12f36e6d-e9ce-439c-b6f5-3f80a4f4b47d + - id: cbd851bb-a0de-43b6-89df-947d5872454d output: - oscillate: + vibrate: value: - 0 - 255 index: 0 - - id: 94025679-badf-49bb-a247-1dab022d9204 + - id: 2e5385b3-82be-4047-b998-49ee07aefa5e output: - vibrate: + oscillate: value: - 0 - 255 @@ -2651,6 +2651,40 @@ configurations: - 7 index: 4 id: 67da4fc4-66d4-49ea-bd40-dbca9f0e5fed +- identifier: + - J-Punisher + name: JoyHub Punisher + features: + - id: 4272e178-cfb0-4e1f-a6cc-1083d83ede14 + output: + oscillate: + value: + - 0 + - 255 + index: 0 + - id: de639d48-47e2-440d-b2c7-3c46068fc13d + output: + vibrate: + value: + - 0 + - 255 + index: 1 + - id: 95a9b5b2-fc5f-45e9-b307-bd2941fd6883 + output: + vibrate: + value: + - 0 + - 255 + index: 2 + id: e437baf4-9e60-431e-a30f-5870faf5c1ad +- identifier: + - J-Prismcy + name: JoyHub Prismcy + id: fcf3aa9b-8e2f-4751-8f7d-b208a62ef6c9 +- identifier: + - J-AresIII + name: JoyHub Ares III + id: 5f902050-ee3f-4503-abcb-d0794c27180c communication: - btle: names: @@ -2806,6 +2840,9 @@ communication: - J-Marino - J-Jason - J-MartinoIII + - J-Punisher + - J-Prismcy + - J-AresIII services: 0000ffa0-0000-1000-8000-00805f9b34fb: tx: 0000ffa1-0000-1000-8000-00805f9b34fb diff --git a/crates/buttplug_server_device_config/device-config/version.yaml b/crates/buttplug_server_device_config/device-config/version.yaml index f70e82f4e..a00065ff2 100644 --- a/crates/buttplug_server_device_config/device-config/version.yaml +++ b/crates/buttplug_server_device_config/device-config/version.yaml @@ -1,3 +1,3 @@ version: major: 5 - minor: 14 + minor: 16 From 06f23f145f6bd789772f4a13ec0923726e077fb4 Mon Sep 17 00:00:00 2001 From: blackspherefollower Date: Fri, 3 Jul 2026 13:54:13 +0100 Subject: [PATCH 3/5] feat: Adding Umove support * Mira * Vero * Nexo --- .../src/device/protocol_impl/mod.rs | 2 + .../src/device/protocol_impl/umove.rs | 256 ++++++++++++++++++ .../buttplug-device-config-v5.json | 147 +++++++++- .../device-config/protocols/umove.yml | 89 ++++++ .../device-config/version.yaml | 2 +- 5 files changed, 494 insertions(+), 2 deletions(-) create mode 100644 crates/buttplug_server/src/device/protocol_impl/umove.rs create mode 100644 crates/buttplug_server_device_config/device-config/protocols/umove.yml diff --git a/crates/buttplug_server/src/device/protocol_impl/mod.rs b/crates/buttplug_server/src/device/protocol_impl/mod.rs index 5e9ff3293..a3df9f299 100644 --- a/crates/buttplug_server/src/device/protocol_impl/mod.rs +++ b/crates/buttplug_server/src/device/protocol_impl/mod.rs @@ -114,6 +114,7 @@ pub mod thehandy_v3; pub mod tryfun; pub mod tryfun_blackhole; pub mod tryfun_meta2; +pub mod umove; pub mod utimi; pub mod vibcrafter; pub mod vibratissimo; @@ -549,6 +550,7 @@ pub fn get_default_protocol_map() -> HashMap &str { + "umove" + } + + fn create(&self) -> Box { + Box::new(super::UmoveIdentifier::default()) + } + } +} + +#[derive(Default)] +pub struct UmoveIdentifier {} + +#[async_trait] +impl ProtocolIdentifier for UmoveIdentifier { + async fn identify( + &mut self, + hardware: Arc, + _specifier: ProtocolCommunicationSpecifier, + ) -> Result<(UserDeviceIdentifier, Box), ButtplugDeviceError> { + let device_identifier = hardware.name()[2..4].to_string(); + Ok(( + UserDeviceIdentifier::new(hardware.address(), "umove", &Some(device_identifier)), + Box::new(UmoveInitializer::default()), + )) + } +} + +#[derive(Default)] +pub struct UmoveInitializer {} + +#[async_trait] +impl ProtocolInitializer for UmoveInitializer { + async fn initialize( + &mut self, + hardware: Arc, + _device_definition: &ServerDeviceDefinition, + ) -> Result, ButtplugDeviceError> { + let state = Arc::new(Umove::default()); + buttplug_core::spawn!( + "Umove update linear movement", + update_linear_movement(hardware.clone(), state.clone(),) + ); + Ok(state) + } +} + +#[derive(Default)] +pub struct Umove { + packet_id: AtomicU32, + vibrate: AtomicU16, + goal_position: AtomicU32, + current_position: AtomicU32, + duration: AtomicU32, +} + +async fn update_linear_movement(device: Arc, state: Arc) { + let mut last_goal_position = 0i32; + let mut current_move_amount = 0i32; + let mut current_position = 0i32; + loop { + // See if we've updated our goal position + let goal_position = state.goal_position.load(Ordering::Relaxed) as i32; + // If we have and it's not the same, recalculate based on current status. + if last_goal_position != goal_position { + last_goal_position = goal_position; + // We move every 100ms, so divide the movement into that many chunks. + // If we're moving so fast it'd be under our 100ms boundary, just move in 1 step. + let move_steps = (state.duration.load(Ordering::Relaxed) / 100).max(1); + let distance = goal_position - current_position; + current_move_amount = distance / move_steps as i32; + if current_move_amount == 0 { + current_move_amount = distance.signum(); + } + } + + // If we aren't going anywhere, just pause then restart + if current_position == last_goal_position { + async_manager::sleep(Duration::from_millis(100)).await; + continue; + } + + // Update our position, make sure we don't overshoot + current_position += current_move_amount; + if current_move_amount < 0 { + if current_position < last_goal_position { + current_position = last_goal_position; + } + } else if current_position > last_goal_position { + current_position = last_goal_position; + } + state + .current_position + .store(current_position as u32, Ordering::Relaxed); + + let hardware_cmd: HardwareWriteCmd = HardwareWriteCmd::new( + &[UMOVE_PROTOCOL_UUID], + Endpoint::Tx, + form_command(state.as_ref()), + false, + ); + if device.write_value(&hardware_cmd).await.is_err() { + return; + } + async_manager::sleep(Duration::from_millis(50)).await; + } +} + +fn form_command(state: &Umove) -> Vec { + let mut data = vec![0x5A, 0xA5, 0x55, 0x00]; + data.append(&mut state.vibrate.load(Ordering::Relaxed).to_le_bytes().to_vec()); + data.append(&mut 1u16.to_le_bytes().to_vec()); + data.append( + &mut state + .packet_id + .fetch_add(1u32, Ordering::Relaxed) + .to_le_bytes() + .to_vec(), + ); + data.append( + &mut state + .current_position + .load(Ordering::Relaxed) + .to_le_bytes() + .to_vec(), + ); + info!("Formed command: {:?}", data); + data +} + +impl ProtocolHandler for Umove { + fn keepalive_strategy(&self) -> ProtocolKeepaliveStrategy { + ProtocolKeepaliveStrategy::RepeatLastPacketStrategyWithTiming(Duration::from_millis(500)) + } + + fn handle_output_vibrate_cmd( + &self, + _feature_index: u32, + _feature_id: Uuid, + speed: u32, + ) -> Result, ButtplugDeviceError> { + self.vibrate.store(speed as u16, Ordering::Relaxed); + if self.current_position.load(Ordering::Relaxed) != self.goal_position.load(Ordering::Relaxed) { + return Ok(vec![]); + } + Ok(vec![ + HardwareWriteCmd::new( + &[UMOVE_PROTOCOL_UUID], + Endpoint::Tx, + form_command(self), + false, + ) + .into(), + ]) + } + + fn handle_hw_position_with_duration_cmd( + &self, + _feature_index: u32, + _feature_id: Uuid, + position: u32, + duration: u32, + ) -> Result, ButtplugDeviceError> { + self.goal_position.store(position, Ordering::Relaxed); + self.duration.store(duration, Ordering::Relaxed); + Ok(vec![]) + } + fn handle_output_position_cmd( + &self, + _feature_index: u32, + _feature_id: Uuid, + position: u32, + ) -> Result, ButtplugDeviceError> { + self.goal_position.store(position, Ordering::Relaxed); + self.current_position.store(position, Ordering::Relaxed); + self.duration.store(0, Ordering::Relaxed); + Ok(vec![ + HardwareWriteCmd::new( + &[UMOVE_PROTOCOL_UUID], + Endpoint::Tx, + form_command(self), + false, + ) + .into(), + ]) + } + + fn handle_output_temperature_cmd( + &self, + _feature_index: u32, + feature_id: Uuid, + level: i32, + ) -> Result, ButtplugDeviceError> { + Ok(vec![ + HardwareWriteCmd::new( + &[feature_id], + Endpoint::Tx, + vec![ + 0x5a, + 0xa5, + 0x55, + 0x06, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + level as u8, + 0xff, + ], + false, + ) + .into(), + ]) + } +} diff --git a/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json b/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json index 512eb921a..b774940e2 100644 --- a/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json +++ b/crates/buttplug_server_device_config/build-config/buttplug-device-config-v5.json @@ -1,7 +1,7 @@ { "version": { "major": 5, - "minor": 16 + "minor": 20 }, "protocols": { "activejoy": { @@ -23241,6 +23241,151 @@ "name": "Twerking Butt" } }, + "umove": { + "communication": [ + { + "btle": { + "names": [ + "ALVxB*", + "ALMiB*", + "ALNxB*", + "UMVxB*", + "UMMiB*", + "UMNxB*" + ], + "services": { + "6e400001-b5a3-f393-e0a9-e50e24dcca9e": { + "rx": "6e400003-b5a3-f393-e0a9-e50e24dcca9e", + "tx": "6e400002-b5a3-f393-e0a9-e50e24dcca9e" + } + } + } + } + ], + "configurations": [ + { + "id": "65dba547-9ebd-4a7a-a6a1-b4b7f34bb7e8", + "identifier": [ + "Mi" + ], + "name": "Umove Mira" + }, + { + "features": [ + { + "id": "0d6dc2b6-87cf-44a1-ac79-8b3d0c50ad6f", + "index": 1, + "output": { + "hw_position_with_duration": { + "duration": [ + 0, + 10000 + ], + "value": [ + 0, + 732 + ] + }, + "position": { + "value": [ + 0, + 732 + ] + } + } + } + ], + "id": "ebfa5881-cab0-4218-a14f-592ef44fd2c8", + "identifier": [ + "Vx" + ], + "name": "Umove Vero" + }, + { + "features": [ + { + "id": "8f08d8a1-0f5e-4915-af56-e02d4553ae89", + "index": 1, + "output": { + "hw_position_with_duration": { + "duration": [ + 0, + 10000 + ], + "value": [ + 0, + 1232 + ] + }, + "position": { + "value": [ + 0, + 1232 + ] + } + } + } + ], + "id": "1694dace-5a53-4d56-9620-9251be4da5ce", + "identifier": [ + "Nx" + ], + "name": "Umove Nexo" + } + ], + "defaults": { + "features": [ + { + "id": "27d5e07a-5880-4595-8c12-2f231b4ef2d2", + "index": 0, + "output": { + "vibrate": { + "value": [ + 0, + 10000 + ] + } + } + }, + { + "id": "44cef1b2-dc95-4abf-a27b-a6d8a266d827", + "index": 1, + "output": { + "hw_position_with_duration": { + "duration": [ + 0, + 10000 + ], + "value": [ + 0, + 632 + ] + }, + "position": { + "value": [ + 0, + 632 + ] + } + } + }, + { + "id": "2d7f0be1-b41f-4cb9-aea6-585d2b0ee7ba", + "index": 2, + "output": { + "temperature": { + "value": [ + 37, + 42 + ] + } + } + } + ], + "id": "45648a20-cb18-43a0-9d6c-8bc4ed63ef63", + "name": "Umove Device" + } + }, "utimi": { "communication": [ { diff --git a/crates/buttplug_server_device_config/device-config/protocols/umove.yml b/crates/buttplug_server_device_config/device-config/protocols/umove.yml new file mode 100644 index 000000000..299dbed17 --- /dev/null +++ b/crates/buttplug_server_device_config/device-config/protocols/umove.yml @@ -0,0 +1,89 @@ +--- +defaults: + name: Umove Device + features: + - id: 27d5e07a-5880-4595-8c12-2f231b4ef2d2 + output: + vibrate: + value: + - 0 + - 10000 + index: 0 + - id: 44cef1b2-dc95-4abf-a27b-a6d8a266d827 + output: + hw_position_with_duration: + value: + - 0 + - 632 + duration: + - 0 + - 10000 + position: + value: + - 0 + - 632 + index: 1 + - id: 2d7f0be1-b41f-4cb9-aea6-585d2b0ee7ba + output: + temperature: + value: + - 37 + - 42 + index: 2 + id: 45648a20-cb18-43a0-9d6c-8bc4ed63ef63 +configurations: + - identifier: + - Mi + name: Umove Mira + id: 65dba547-9ebd-4a7a-a6a1-b4b7f34bb7e8 + - identifier: + - Vx + name: Umove Vero + features: + - id: 0d6dc2b6-87cf-44a1-ac79-8b3d0c50ad6f + output: + hw_position_with_duration: + value: + - 0 + - 732 + duration: + - 0 + - 10000 + position: + value: + - 0 + - 732 + index: 1 + id: ebfa5881-cab0-4218-a14f-592ef44fd2c8 + - identifier: + - Nx + name: Umove Nexo + features: + - id: 8f08d8a1-0f5e-4915-af56-e02d4553ae89 + output: + hw_position_with_duration: + value: + - 0 + - 1232 + duration: + - 0 + - 10000 + position: + value: + - 0 + - 1232 + index: 1 + id: 1694dace-5a53-4d56-9620-9251be4da5ce +communication: +- btle: + names: + - ALVxB* + - ALMiB* + - ALNxB* + - UMVxB* + - UMMiB* + - UMNxB* + services: + 6e400001-b5a3-f393-e0a9-e50e24dcca9e: + tx: 6e400002-b5a3-f393-e0a9-e50e24dcca9e + rx: 6e400003-b5a3-f393-e0a9-e50e24dcca9e diff --git a/crates/buttplug_server_device_config/device-config/version.yaml b/crates/buttplug_server_device_config/device-config/version.yaml index a00065ff2..8491137a6 100644 --- a/crates/buttplug_server_device_config/device-config/version.yaml +++ b/crates/buttplug_server_device_config/device-config/version.yaml @@ -1,3 +1,3 @@ version: major: 5 - minor: 16 + minor: 20 From 343f2f8736ac8912e4f017b2114fb0301cb66ea2 Mon Sep 17 00:00:00 2001 From: blackspherefollower Date: Fri, 3 Jul 2026 17:06:31 +0100 Subject: [PATCH 4/5] feat: Adding support for Kiiroo Keon 2 and Spot 2 --- .../device/protocol_impl/kiiroo_spot_v2.rs | 67 +++++++++++ .../src/device/protocol_impl/mod.rs | 5 + .../buttplug-device-config-v5.json | 107 +++++++++++++++++- .../protocols/kiiroo-spot-v2.yml | 31 +++++ .../device-config/protocols/kiiroo-v3.yml | 81 ++++++++----- .../device-config/version.yaml | 2 +- 6 files changed, 264 insertions(+), 29 deletions(-) create mode 100644 crates/buttplug_server/src/device/protocol_impl/kiiroo_spot_v2.rs create mode 100644 crates/buttplug_server_device_config/device-config/protocols/kiiroo-spot-v2.yml diff --git a/crates/buttplug_server/src/device/protocol_impl/kiiroo_spot_v2.rs b/crates/buttplug_server/src/device/protocol_impl/kiiroo_spot_v2.rs new file mode 100644 index 000000000..bb81e3e30 --- /dev/null +++ b/crates/buttplug_server/src/device/protocol_impl/kiiroo_spot_v2.rs @@ -0,0 +1,67 @@ +// Buttplug Rust Source Code File - See https://buttplug.io for more info. +// +// Copyright 2016-2026 Nonpolynomial Labs LLC. All rights reserved. +// +// Licensed under the BSD 3-Clause license. See LICENSE file in the project root +// for full license information. + +use crate::device::{ + hardware::{Hardware, HardwareCommand, HardwareReadCmd, HardwareWriteCmd}, + protocol::{ProtocolHandler, generic_protocol_setup}, +}; +use buttplug_core::{ + errors::ButtplugDeviceError, + message::{self, InputReadingV4, InputTypeReading, InputValue}, +}; +use buttplug_server_device_config::Endpoint; +use futures::{FutureExt, future::BoxFuture}; +use std::{default::Default, sync::Arc}; +use uuid::Uuid; + +generic_protocol_setup!(KiirooSpotV2, "kiiroo-spot-v2"); + +#[derive(Default)] +pub struct KiirooSpotV2 {} + +impl ProtocolHandler for KiirooSpotV2 { + fn handle_output_vibrate_cmd( + &self, + _feature_index: u32, + feature_id: Uuid, + speed: u32, + ) -> Result, ButtplugDeviceError> { + Ok(vec![ + HardwareWriteCmd::new( + &[feature_id], + Endpoint::Tx, + vec![0x01, speed as u8, speed as u8, 0x03, 0xe8, 0xff], + true, + ) + .into(), + ]) + } + + fn handle_battery_level_cmd( + &self, + device_index: u32, + device: Arc, + feature_index: u32, + feature_id: Uuid, + ) -> BoxFuture<'_, Result> { + debug!("Trying to get battery reading."); + let msg = HardwareReadCmd::new(feature_id, Endpoint::RxBLEBattery, 20, 0); + let fut = device.read_value(&msg); + async move { + let hw_msg = fut.await?; + let data = hw_msg.data(); + let battery_reading = message::InputReadingV4::new( + device_index, + feature_index, + InputTypeReading::Battery(InputValue::new(data[0])), + ); + debug!("Got battery reading: {}", data[0]); + Ok(battery_reading) + } + .boxed() + } +} diff --git a/crates/buttplug_server/src/device/protocol_impl/mod.rs b/crates/buttplug_server/src/device/protocol_impl/mod.rs index a3df9f299..b9c2811f7 100644 --- a/crates/buttplug_server/src/device/protocol_impl/mod.rs +++ b/crates/buttplug_server/src/device/protocol_impl/mod.rs @@ -45,6 +45,7 @@ pub mod kgoal_boost; pub mod kiiroo_powershot; pub mod kiiroo_prowand; pub mod kiiroo_spot; +pub mod kiiroo_spot_v2; pub mod kiiroo_v2; pub mod kiiroo_v21; pub mod kiiroo_v21_initialized; @@ -247,6 +248,10 @@ pub fn get_default_protocol_map() -> HashMap Date: Fri, 3 Jul 2026 17:09:40 +0100 Subject: [PATCH 5/5] chore: clean up linter errors on ossm --- .../buttplug_server/src/device/protocol_impl/ossm.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/crates/buttplug_server/src/device/protocol_impl/ossm.rs b/crates/buttplug_server/src/device/protocol_impl/ossm.rs index 78f014985..6081691b7 100644 --- a/crates/buttplug_server/src/device/protocol_impl/ossm.rs +++ b/crates/buttplug_server/src/device/protocol_impl/ossm.rs @@ -5,7 +5,7 @@ // Licensed under the BSD 3-Clause license. See LICENSE file in the project root // for full license information. -use crate::device::hardware::{HardwareEvent, HardwareReadCmd, HardwareSubscribeCmd}; +use crate::device::hardware::{HardwareEvent, HardwareSubscribeCmd}; use crate::device::{ hardware::{Hardware, HardwareCommand, HardwareWriteCmd}, protocol::{ @@ -17,7 +17,6 @@ use crate::device::{ }; use async_trait::async_trait; use buttplug_core::errors::ButtplugDeviceError; -use buttplug_core::util::sleep; use buttplug_server_device_config::{ Endpoint, ProtocolCommunicationSpecifier, @@ -25,13 +24,9 @@ use buttplug_server_device_config::{ UserDeviceIdentifier, }; use futures_util::FutureExt; -use serde_json::ser::State; use std::collections::HashMap; -use std::ops::Index; -use std::str::from_utf8; -use std::sync::atomic::{AtomicBool, AtomicU8, Ordering}; -use std::sync::{Arc, RwLock}; -use std::time::{Duration, Instant}; +use std::sync::Arc; +use std::sync::atomic::{AtomicU8, Ordering}; use tokio::select; use uuid::{Uuid, uuid}; @@ -105,7 +100,6 @@ impl ProtocolInitializer for OSSMInitializer { hardware .subscribe(&HardwareSubscribeCmd::new(OSSM_PROTOCOL_UUID, Endpoint::Rx)) .await?; - let state = Arc::new(RwLock::new(String::new())); buttplug_core::spawn!("OssmStateReader", ossm_statereader(hardware.clone(),));