feat: add Svakom Fatima Pro support#908
Open
pktwhisperer wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Following up on #907 — opening the device-support PR you green-lit. Thanks again for the quick reply! 🙏
Summary
Adds protocol support for the Svakom Fatima Pro (advertised BLE name
SL278B).The device is currently unsupported, so Intiface scans past it.
The protocol was derived entirely from a BLE packet capture of the official app (ATT writes on FFE1, notifications on FFE2). It follows the same
0x55-prefixed command family as the existing Svakom Sam / Sam Neo 2 protocols.Four functions are exposed:
Vibrate[0,10]55 03 00 00 01 <0-10>55 03 00 00 00 00Constrict[0,10]55 09 00 00 01 <0-10>55 09 00 00 00 00Oscillate[0,7]55 08 00 00 <pattern 1-7> ff55 08 00 00 00 00Temperature[0,1]55 05 01 37 02 00 0055 05 00 00 02 00 00On connect, an initialization handshake is sent (identical across two separate captures); the device does not respond to control commands without it:
Vibration and suction byte ranges are confirmed against the capture (e.g. vibration max
55 03 00 00 01 0a), and all 7 thrust patterns plus the off bytes match the capture byte-for-byte.Files
crates/buttplug_server/src/device/protocol_impl/svakom/svakom_fatima.rs— protocol handler + initializercrates/buttplug_server_device_config/device-config/protocols/svakom-fatima.yml— device configcrates/buttplug_tests/tests/util/device_test/device_test_case/test_svakom_fatima.yaml— regression fixtureRegistration:
pub mod svakom_fatima;insvakom/mod.rs, theSvakomFatimaIdentifierFactoryentry inprotocol_impl/mod.rs, and thetest_svakom_fatima.yamltest case intest_device_protocols.rs.Design tradeoffs (disclosed)
A few aspects of this device do not map cleanly onto Buttplug's continuous-actuator model. These are deliberate choices, documented here for review:
1. Thrust = pattern-as-intensity (
Oscillate)The thrust function does not expose a continuous speed. The firmware only offers a set of discrete patterns (1–7), selected with
55 08 00 00 <pattern> ff. There is no continuous-speed command in the protocol.Rather than hide the function, the
Oscillatevalue is mapped directly onto the pattern number ([0,7], with 0 = off). So an Oscillate value of, say, 3 selects firmware pattern 3, not "30% of full speed." This is a faithful representation of what the hardware actually does, at the cost ofOscillatenot behaving like a linear intensity for this device.2. Heat = on/off only (
Temperature[0,1])The heat function is modeled as
Temperaturewith a[0,1]range, i.e. on/off. The on/off bytes match the capture and the official app exactly.In practice the hardware heating is imperceptible even on a fully charged device — this matches the behavior of the official app, so the implementation is faithful to both the capture and the app. The capture does contain an additional unmodeled byte position (
55 05 01 37 **01/02** ...) that may correspond to a second heat level; only the02variant is used here, as on/off, which is what the app exercises.Note: the heat actuator is not in the regression fixture, because the device-test Scalar harness (v4) does not accept a
Temperatureactuator. The handler is implemented and the byte sequences are verified faithful to the capture and the official-app behavior, but the heat path is not regression-tested on its own actuator. This is called out plainly so reviewers know its verification status.3. Two independent peripherals — do not hardcode index → function
The Fatima Pro presents as two independent
SL278BBLE peripherals. Each one registers as its own Buttplug device and is driven independently by this protocol — this is the standard Buttplug model for separate BLE peripherals, and they are not forced into a single device.Two things to be aware of:
index -> functionmapping.Both peripherals advertise the same name and speak the same protocol, so the config applies to either; what each physically actuates is determined by the hardware unit that happened to connect, not by index.
Testing
cargo test -p buttplug_tests fatima— protocol regression (vibration / suction / thrust + off paths; heat excluded per the note above).Provenance / licensing
All bytes here come from observing the device's own BLE traffic (a packet capture of the official app). No vendor proprietary code was reverse-engineered or decompiled — this is a clean BLE command encoding, in the same style as the existing Svakom protocols in this repo.
Closes #907