Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protocol work #687

Merged
merged 22 commits into from
Feb 9, 2025
Merged
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
641766e
feat: Adding support for Joyhub Vince Maynor and Dallin
blackspherefollower Jan 4, 2025
41f1e91
chore: Bump config version
blackspherefollower Jan 4, 2025
7447066
feat: Adding support for Svakom Emma Neo 2 and Mini Emma Neo
blackspherefollower Jan 5, 2025
46a138e
feat: Adding support for metaXsire Zeus
blackspherefollower Jan 5, 2025
e265fd6
feat: Adding support for Tracy's Dog Craybit Pro
blackspherefollower Jan 5, 2025
1f7cbe8
feat: Adding support for Nexus Revo Stealth
blackspherefollower Jan 7, 2025
02d1ba8
chore: cargo fmt
blackspherefollower Jan 7, 2025
9825878
feat: Adding reported new PrettyLove device identifier
blackspherefollower Jan 7, 2025
a751355
feat: Adding support for Luvmazer Finger Magic
blackspherefollower Jan 8, 2025
55a4ab3
feat: Adding support for JoyHub Melody
blackspherefollower Jan 9, 2025
8d141d9
feat: Support for JoyHub Pathfinder and Scarlett
blackspherefollower Jan 14, 2025
253937d
feat: Adding support for the Fox M70-2
blackspherefollower Jan 14, 2025
a60f3cf
feat: Adding support for 7 more JoyHub devices
blackspherefollower Jan 14, 2025
7caf6e5
feat: Adding service advertisement based Lovense matching
blackspherefollower Jan 14, 2025
6a62ddf
feat: Adding support for Joyhub Viva
blackspherefollower Jan 23, 2025
2538893
feat: Adding support for JoyHub Ryden
blackspherefollower Jan 27, 2025
d13c190
feat: Adding support for Svakom Coco Pro
blackspherefollower Jan 27, 2025
5b95254
feat: Add support for the Joyroid Loob
blackspherefollower Oct 3, 2024
b25bec5
feat: Adding support for Bananasome Rocket X7
blackspherefollower Jan 28, 2025
e9d8cf4
feat: Adding support for the Omobo ViVegg Vibrator (S6) and Kisstoy L…
blackspherefollower Feb 3, 2025
0f69993
feat: Adding support for Kiiroo Spot and WeVibe Wand 2
blackspherefollower Feb 4, 2025
1086b9c
feat: Adding support for 2 Sensee devices: Easylive Vader and Little …
blackspherefollower Feb 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: Adding support for metaXsire Zeus
  • Loading branch information
blackspherefollower committed Jan 9, 2025
commit 46a138e39926808be04b522e918f14936f025c07
Original file line number Diff line number Diff line change
@@ -11075,14 +11075,47 @@
"TAY009"
],
"name": "metaXsire Tay 9"
},
{
"identifier": [
"TA-S001A"
],
"name": "metaXsire Zeus",
"features": [
{
"feature-type": "Vibrate",
"actuator": {
"step-range": [
0,
20
],
"messages": [
"ScalarCmd"
]
}
},
{
"feature-type": "Oscillate",
"actuator": {
"step-range": [
0,
20
],
"messages": [
"ScalarCmd"
]
}
}
]
}
],
"communication": [
{
"btle": {
"names": [
"TAY001",
"TAY009"
"TAY009",
"TA-S001A"
],
"services": {
"0000fff0-0000-1000-8000-00805f9b34fb": {
Original file line number Diff line number Diff line change
@@ -6307,11 +6307,30 @@ protocols:
- identifier:
- TAY009
name: metaXsire Tay 9
- identifier:
- TA-S001A
name: metaXsire Zeus
features:
- feature-type: Vibrate
actuator:
step-range:
- 0
- 20
messages:
- ScalarCmd
- feature-type: Oscillate
actuator:
step-range:
- 0
- 20
messages:
- ScalarCmd
communication:
- btle:
names:
- TAY001
- TAY009
- TA-S001A
services:
0000fff0-0000-1000-8000-00805f9b34fb:
tx: 0000fe02-0000-1000-8000-00805f9b34fb
98 changes: 60 additions & 38 deletions buttplug/src/server/device/protocol/metaxsire_v3.rs
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
// Licensed under the BSD 3-Clause license. See LICENSE file in the project root
// for full license information.

use crate::core::message::ActuatorType;
use crate::{
core::{errors::ButtplugDeviceError, message::Endpoint},
server::device::{
@@ -20,11 +21,9 @@ use crate::{
util::{async_manager, sleep},
};
use async_trait::async_trait;
use std::sync::{
atomic::{AtomicU8, Ordering},
Arc,
};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::RwLock;

generic_protocol_initializer_setup!(MetaXSireV3, "metaxsire-v3");
#[derive(Default)]
@@ -35,46 +34,59 @@ impl ProtocolInitializer for MetaXSireV3Initializer {
async fn initialize(
&mut self,
hardware: Arc<Hardware>,
_: &UserDeviceDefinition,
device_definition: &UserDeviceDefinition,
) -> Result<Arc<dyn ProtocolHandler>, ButtplugDeviceError> {
Ok(Arc::new(MetaXSireV3::new(hardware)))
let feature_count = device_definition
.features()
.iter()
.filter(|x| x.actuator().is_some())
.count();
Ok(Arc::new(MetaXSireV3::new(hardware, feature_count)))
}
}

const METAXSIRE_COMMAND_DELAY_MS: u64 = 100;

async fn command_update_handler(device: Arc<Hardware>, command_holder: Arc<AtomicU8>) {
async fn command_update_handler(device: Arc<Hardware>, command_holder: Arc<RwLock<Vec<u8>>>) {
trace!("Entering metaXsire v3 Control Loop");
let mut current_command = command_holder.load(Ordering::Relaxed);
while current_command == 0
|| device
.write_value(&HardwareWriteCmd::new(
Endpoint::Tx,
vec![0xa1, 0x04, current_command, 0x01],
false,
))
.await
.is_ok()
{
let mut current_commands = command_holder.read().await.clone();
let mut errored = false;
while !errored {
for i in 0..current_commands.len() {
if current_commands[i] == 0 {
continue;
}
errored = !device
.write_value(&HardwareWriteCmd::new(
Endpoint::Tx,
vec![0xa1, 0x04, current_commands[i], i as u8 + 1],
false,
))
.await
.is_ok();
if errored {
break;
}
}
sleep(Duration::from_millis(METAXSIRE_COMMAND_DELAY_MS)).await;
current_command = command_holder.load(Ordering::Relaxed);
trace!("metaXsire v3 Command: {:?}", current_command);
current_commands = command_holder.read().await.clone();
trace!("metaXsire v3 Command: {:?}", current_commands);
}
trace!("metaXsire v3 control loop exiting, most likely due to device disconnection.");
}

pub struct MetaXSireV3 {
current_command: Arc<AtomicU8>,
current_commands: Arc<RwLock<Vec<u8>>>,
}

impl MetaXSireV3 {
fn new(device: Arc<Hardware>) -> Self {
let current_command = Arc::new(AtomicU8::new(0));
let current_command_clone = current_command.clone();
fn new(device: Arc<Hardware>, feature_count: usize) -> Self {
let current_commands = Arc::new(RwLock::new(vec![0u8; feature_count]));
let current_commands_clone = current_commands.clone();
async_manager::spawn(
async move { command_update_handler(device, current_command_clone).await },
async move { command_update_handler(device, current_commands_clone).await },
);
Self { current_command }
Self { current_commands }
}
}

@@ -83,19 +95,29 @@ impl ProtocolHandler for MetaXSireV3 {
super::ProtocolKeepaliveStrategy::RepeatLastPacketStrategy
}

fn handle_scalar_vibrate_cmd(
fn handle_scalar_cmd(
&self,
_index: u32,
scalar: u32,
commands: &[Option<(ActuatorType, u32)>],
) -> Result<Vec<HardwareCommand>, ButtplugDeviceError> {
let current_command = self.current_command.clone();
current_command.store(scalar as u8, Ordering::Relaxed);

Ok(vec![HardwareWriteCmd::new(
Endpoint::Tx,
vec![0xa1, 0x04, scalar as u8, 0x01],
true,
)
.into()])
let mut cmds = vec![];
for i in 0..commands.len() {
if let Some(cmd) = commands[i] {
let current_commands = self.current_commands.clone();
async_manager::spawn(async move {
let write_mutex = current_commands.clone();
let mut command_writer = write_mutex.write().await;
command_writer[i] = cmd.1 as u8;
});
cmds.push(
HardwareWriteCmd::new(
Endpoint::Tx,
vec![0xa1, 0x04, cmd.1 as u8, i as u8 + 1],
true,
)
.into(),
);
}
}
Ok(cmds)
}
}