Skip to content

feat: add Svakom Fatima Pro support#908

Open
pktwhisperer wants to merge 1 commit into
buttplugio:masterfrom
pktwhisperer:svakom-fatima-pro
Open

feat: add Svakom Fatima Pro support#908
pktwhisperer wants to merge 1 commit into
buttplugio:masterfrom
pktwhisperer:svakom-fatima-pro

Conversation

@pktwhisperer

Copy link
Copy Markdown

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:

Function Buttplug actuator Command form Off
Vibration Vibrate [0,10] 55 03 00 00 01 <0-10> 55 03 00 00 00 00
Suction Constrict [0,10] 55 09 00 00 01 <0-10> 55 09 00 00 00 00
Thrust Oscillate [0,7] 55 08 00 00 <pattern 1-7> ff 55 08 00 00 00 00
Heat Temperature [0,1] on 55 05 01 37 02 00 00 55 05 00 00 02 00 00

On connect, an initialization handshake is sent (identical across two separate captures); the device does not respond to control commands without it:

55 00
55 04 00 00 01 80 aa
55 00
55 04 00 00 00 00 aa

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 + initializer
  • crates/buttplug_server_device_config/device-config/protocols/svakom-fatima.yml — device config
  • crates/buttplug_tests/tests/util/device_test/device_test_case/test_svakom_fatima.yaml — regression fixture

Registration: pub mod svakom_fatima; in svakom/mod.rs, the SvakomFatimaIdentifierFactory entry in protocol_impl/mod.rs, and the test_svakom_fatima.yaml test case in test_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 Oscillate value 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 of Oscillate not behaving like a linear intensity for this device.

2. Heat = on/off only (Temperature [0,1])

The heat function is modeled as Temperature with 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 the 02 variant 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 Temperature actuator. 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 SL278B BLE 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:

  • Connection is unstable: sometimes only one of the two peripherals connects.
  • Index is connection-order, not a stable function identity. Which physical function lands on device index 0 vs. index 1 depends on connection order and can vary between sessions. Consumers should not hardcode an index -> function mapping.

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).
  • Vibration / suction / thrust verified on hardware (individually, concurrently, and with live level changes).
  • Heat verified faithful to the capture and the official-app behavior; not regression-tested on the heat actuator (see tradeoff 2).

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

@CLAassistant

CLAassistant commented Jun 14, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Protocol support for Svakom Fatima Pro (SL278B)

2 participants