Skip to content

Commit 0ca06db

Browse files
blackspherefollowerqdot
authored andcommitted
feat: Adding support for Kiiroo ProWand
1 parent 71b2dda commit 0ca06db

File tree

6 files changed

+232
-0
lines changed

6 files changed

+232
-0
lines changed

buttplug/buttplug-device-config/build-config/buttplug-device-config-v3.json

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4780,6 +4780,57 @@
47804780
}
47814781
]
47824782
},
4783+
"kiiroo-prowand": {
4784+
"defaults": {
4785+
"name": "Kiiroo ProWand",
4786+
"features": [
4787+
{
4788+
"feature-type": "Vibrate",
4789+
"actuator": {
4790+
"step-range": [
4791+
0,
4792+
255
4793+
],
4794+
"messages": [
4795+
"ScalarCmd"
4796+
]
4797+
}
4798+
},
4799+
{
4800+
"feature-type": "Battery",
4801+
"description": "Battery Level",
4802+
"sensor": {
4803+
"value-range": [
4804+
[
4805+
0,
4806+
100
4807+
]
4808+
],
4809+
"messages": [
4810+
"SensorReadCmd"
4811+
]
4812+
}
4813+
}
4814+
]
4815+
},
4816+
"communication": [
4817+
{
4818+
"btle": {
4819+
"names": [
4820+
"ProWand"
4821+
],
4822+
"services": {
4823+
"00001400-0000-1000-8000-00805f9b34fb": {
4824+
"tx": "00001401-0000-1000-8000-00805f9b34fb"
4825+
},
4826+
"0000180f-0000-1000-8000-00805f9b34fb": {
4827+
"rxblebattery": "00002a19-0000-1000-8000-00805f9b34fb"
4828+
}
4829+
}
4830+
}
4831+
}
4832+
]
4833+
},
47834834
"vorze-cyclone-x": {
47844835
"defaults": {
47854836
"name": "Vorze Cyclone X10 Device",

buttplug/buttplug-device-config/device-config-v3/buttplug-device-config-v3.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,6 +2734,34 @@ protocols:
27342734
whitelist: 00001901-0000-1000-8000-00805f9b34fb
27352735
tx: 00001902-0000-1000-8000-00805f9b34fb
27362736
rx: 00001903-0000-1000-8000-00805f9b34fb
2737+
kiiroo-prowand:
2738+
defaults:
2739+
name: Kiiroo ProWand
2740+
features:
2741+
- feature-type: Vibrate
2742+
actuator:
2743+
step-range:
2744+
- 0
2745+
- 255
2746+
messages:
2747+
- ScalarCmd
2748+
- feature-type: Battery
2749+
description: Battery Level
2750+
sensor:
2751+
value-range:
2752+
- - 0
2753+
- 100
2754+
messages:
2755+
- SensorReadCmd
2756+
communication:
2757+
- btle:
2758+
names:
2759+
- ProWand
2760+
services:
2761+
00001400-0000-1000-8000-00805f9b34fb:
2762+
tx: 00001401-0000-1000-8000-00805f9b34fb
2763+
0000180f-0000-1000-8000-00805f9b34fb:
2764+
rxblebattery: 00002a19-0000-1000-8000-00805f9b34fb
27372765
vorze-cyclone-x:
27382766
defaults:
27392767
name: Vorze Cyclone X10 Device
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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+
8+
use super::fleshlight_launch_helper::calculate_speed;
9+
use crate::{
10+
core::{
11+
errors::ButtplugDeviceError,
12+
message::{
13+
self,
14+
ButtplugDeviceMessage,
15+
ButtplugServerDeviceMessage,
16+
Endpoint,
17+
SensorReadingV4,
18+
SensorType,
19+
},
20+
},
21+
server::device::{
22+
hardware::{
23+
Hardware,
24+
HardwareCommand,
25+
HardwareEvent,
26+
HardwareReadCmd,
27+
HardwareSubscribeCmd,
28+
HardwareUnsubscribeCmd,
29+
HardwareWriteCmd,
30+
},
31+
protocol::{generic_protocol_setup, ProtocolHandler},
32+
},
33+
util::{async_manager, stream::convert_broadcast_receiver_to_stream},
34+
};
35+
use dashmap::DashSet;
36+
use futures::{
37+
future::{self, BoxFuture},
38+
FutureExt,
39+
StreamExt,
40+
};
41+
use std::{
42+
default::Default,
43+
pin::Pin,
44+
sync::{
45+
atomic::{AtomicU8, Ordering::SeqCst},
46+
Arc,
47+
},
48+
};
49+
use tokio::sync::broadcast;
50+
51+
generic_protocol_setup!(KiirooProWand, "kiiroo-prowand");
52+
53+
#[derive(Default)]
54+
pub struct KiirooProWand {}
55+
56+
impl ProtocolHandler for KiirooProWand {
57+
fn handle_scalar_vibrate_cmd(
58+
&self,
59+
_: u32,
60+
scalar: u32,
61+
) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
62+
Ok(vec![HardwareWriteCmd::new(
63+
Endpoint::Tx,
64+
vec![
65+
0x00,
66+
0x00,
67+
0x64,
68+
if scalar == 0 { 0x00 } else { 0xff },
69+
scalar as u8,
70+
scalar as u8,
71+
],
72+
false,
73+
)
74+
.into()])
75+
}
76+
77+
fn handle_battery_level_cmd(
78+
&self,
79+
device: Arc<Hardware>,
80+
message: message::SensorReadCmdV4,
81+
) -> BoxFuture<Result<SensorReadingV4, ButtplugDeviceError>> {
82+
debug!("Trying to get battery reading.");
83+
let message = message.clone();
84+
let msg = HardwareReadCmd::new(Endpoint::RxBLEBattery, 20, 0);
85+
let fut = device.read_value(&msg);
86+
async move {
87+
let hw_msg = fut.await?;
88+
let data = hw_msg.data();
89+
let battery_level = data[0] as i32;
90+
let battery_reading = message::SensorReadingV4::new(
91+
message.device_index(),
92+
*message.feature_index(),
93+
*message.sensor_type(),
94+
vec![battery_level],
95+
);
96+
debug!("Got battery reading: {}", battery_level);
97+
Ok(battery_reading)
98+
}
99+
.boxed()
100+
}
101+
}

buttplug/src/server/device/protocol/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub mod joyhub_v3;
4343
pub mod joyhub_v4;
4444
pub mod joyhub_v5;
4545
pub mod kgoal_boost;
46+
pub mod kiiroo_prowand;
4647
pub mod kiiroo_v2;
4748
pub mod kiiroo_v21;
4849
pub mod kiiroo_v21_initialized;
@@ -310,6 +311,10 @@ pub fn get_default_protocol_map() -> HashMap<String, Arc<dyn ProtocolIdentifierF
310311
&mut map,
311312
joyhub_v5::setup::JoyHubV5IdentifierFactory::default(),
312313
);
314+
add_to_protocol_map(
315+
&mut map,
316+
kiiroo_prowand::setup::KiirooProWandIdentifierFactory::default(),
317+
);
313318
add_to_protocol_map(
314319
&mut map,
315320
kiiroo_v2::setup::KiirooV2IdentifierFactory::default(),

buttplug/tests/test_device_protocols.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ async fn load_test_case(test_file: &str) -> DeviceTestCase {
116116
#[test_case("test_xuanhuan_protocol.yaml" ; "Xuanhuan Protocol")]
117117
#[test_case("test_tcode_linear_and_vibrate.yaml" ; "TCode (Linear + Vibrate)")]
118118
#[test_case("test_serveu_protocol.yaml" ; "ServeU")]
119+
#[test_case("test_kiiroo_prowand.yaml" ; "Kiiroo ProWand Protocol")]
119120
#[tokio::test]
120121
async fn test_device_protocols_embedded_v3(test_file: &str) {
121122
//tracing_subscriber::fmt::init();
@@ -222,6 +223,7 @@ async fn test_device_protocols_embedded_v3(test_file: &str) {
222223
#[test_case("test_xuanhuan_protocol.yaml" ; "Xuanhuan Protocol")]
223224
#[test_case("test_tcode_linear_and_vibrate.yaml" ; "TCode (Linear + Vibrate)")]
224225
#[test_case("test_serveu_protocol.yaml" ; "ServeU")]
226+
#[test_case("test_kiiroo_prowand.yaml" ; "Kiiroo ProWand Protocol")]
225227
#[tokio::test]
226228
async fn test_device_protocols_json_v3(test_file: &str) {
227229
//tracing_subscriber::fmt::init();
@@ -298,6 +300,7 @@ async fn test_device_protocols_json_v3(test_file: &str) {
298300
#[test_case("test_xuanhuan_protocol.yaml" ; "Xuanhuan Protocol")]
299301
#[test_case("test_tcode_linear_and_vibrate.yaml" ; "TCode (Linear + Vibrate)")]
300302
#[test_case("test_serveu_protocol.yaml" ; "ServeU")]
303+
#[test_case("test_kiiroo_prowand.yaml" ; "Kiiroo ProWand Protocol")]
301304
#[tokio::test]
302305
async fn test_device_protocols_embedded_v2(test_file: &str) {
303306
util::device_test::client::client_v2::run_embedded_test_case(&load_test_case(test_file).await)
@@ -373,6 +376,7 @@ async fn test_device_protocols_embedded_v2(test_file: &str) {
373376
#[test_case("test_xuanhuan_protocol.yaml" ; "Xuanhuan Protocol")]
374377
#[test_case("test_tcode_linear_and_vibrate.yaml" ; "TCode (Linear + Vibrate)")]
375378
#[test_case("test_serveu_protocol.yaml" ; "ServeU")]
379+
#[test_case("test_kiiroo_prowand.yaml" ; "Kiiroo ProWand Protocol")]
376380
#[tokio::test]
377381
async fn test_device_protocols_json_v2(test_file: &str) {
378382
util::device_test::client::client_v2::run_json_test_case(&load_test_case(test_file).await).await;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
devices:
2+
- identifier:
3+
name: "ProWand"
4+
expected_name: "Kiiroo ProWand"
5+
device_commands:
6+
# Commands
7+
- !Messages
8+
device_index: 0
9+
messages:
10+
- !Vibrate
11+
- Index: 0
12+
Speed: 0.5
13+
- !Commands
14+
device_index: 0
15+
commands:
16+
- !Write
17+
endpoint: tx
18+
data: [0x00, 0x00, 0x64, 0xff, 0x80, 0x80]
19+
write_with_response: false
20+
- !Messages
21+
device_index: 0
22+
messages:
23+
- !Vibrate
24+
- Index: 0
25+
Speed: 1.0
26+
- !Commands
27+
device_index: 0
28+
commands:
29+
- !Write
30+
endpoint: tx
31+
data: [0x00, 0x00, 0x64, 0xff, 0xff, 0xff]
32+
write_with_response: false
33+
- !Messages
34+
device_index: 0
35+
messages:
36+
- !Stop
37+
- !Commands
38+
device_index: 0
39+
commands:
40+
- !Write
41+
endpoint: tx
42+
data: [0x00, 0x00, 0x64, 0x00, 0x00, 0x00]
43+
write_with_response: false

0 commit comments

Comments
 (0)