Buttplug v6: It’s Like Firefox v4 For Your Butt

After nearly 9 months of development, Buttplug v6 is out today. If you’re curious what this does, or more likely, doesn’t mean for you, this post will lay out what’s in today’s release and what’s yet to come.

This release isn’t really everything I wanted it to be, but in the end it became obvious that the line of yaks requiring shaving to get this out in a “complete” state was going to stretch on for a few more months at minimum. Therefore, Buttplug v6 mostly contains the foundation for the new features I wanted in the new version of the library, and I’ll be building on that through point releases in the upcoming months to turn it into what I feel it’s supposed to be.

I’ll be covering a lot of these topics in their own blog posts over the next few weeks, but for now here’s a summary of what’s new and future plans.

If you just want the gritty details, check the changelogs of the spec and the library itself.

I’m a User/Dev, How Will This Affect Me?

Right now, users of software that employs buttplug and developers working on games/apps that use the library should not expect to see too much different. This release of Buttplug is mostly for the very few people who are not me that want to work on the Buttplug library itself.

I’ve been blocking almost all new features and fixes to the library since December 2021, in order to keep the development branch clean and easy to work with. Unfortunately the planning for v6 wasn’t great, so the features that caused the largest amount of chaos went in first, meaning that rebasing on top of v5 changes quickly became very difficult.

Getting v6 out in its current version releases this block, and allows device protocol developers to get back to actually implementing new protocols and bug fixes. While there may be new releases of Intiface that use Buttplug v6, many of the new features won’t be completely open to developers for at least a few more weeks at minimum (see the FFI section below for more info on this).

For those curious about the Firefox v4 reference in the title of this post: Firefox v4 development lasted way beyond what it was supposed to, due to many of the same issues I had here (check out this C|Net article for some history). Instead of learning from history, I repeated it. Hopefully I can avoid that in the future, though I’m not sure I can roll to a rapid release schedule for Buttplug since this is still basically a single developer project.

Buttplug Spec v3, ScalarCmd and SensorCmd

By far the biggest change in Buttplug v6 will be the release of the new Buttplug v3 Protocol Spec. The Buttplug Protocol is the low level communication specification between Buttplug Servers (which handle hardware connection and control) and Buttplug Clients (the side of the system that applications, games, and other pieces of software use to connect to Buttplug Servers). Very few people work with this level of the system, as it’s usually only seen by library developers writing clients for other platforms/languages. While these changes are opaque to users, the spec defines the capabilities and scalability of the system to new devices, making it the core of what we do as a project and how users finally get the new features they’re asking for.

The spec moves at a glacial pace, with this being the first major change in 2 years, with the last major being 3 years before that. The good news is that this means that what we have in the spec seems to work for a majority of our users at the moment, but what we had in v2 left us little room to expand for the future. Spec v3 aims to fix that with the addition of 2 new messages, as well as the deprecation of 5 messages that those 2 new messages can replace. There is also additional descriptive information available about devices.

The two new messages are:

  • ScalarCmd
    • Instead of just allowing a developer to say “make a device vibrate”, we can now let them say
      “sets a device actuator to a static level”. For instance, the Lovense Max has an air bladder
      that can inflate/deflate, constricting a certain amount. ScalarCmd can now be used to set that.
    • I’ll have a full blog post detailing the design of this message and our command system in
      general soon.
  • SensorCmd
    • Buttplug has had no capability to actually take input from devices so far. There are multiple
      intimate devices that can hand back certain readings, like button presses, accelerometer data,
      and pressure sensing. SensorCmd gives Buttplug a way to take this information in and relay it to developers so they can create more in-depth experiences for their users.

Initial support for these messages will slim, mostly replacing the older, more specific messages (like battery and RSSI) with the new more general ones. However, there are plans to release new versions of the library that will incorporate either new or missing features from hardware in the upcoming weeks.

Additionally, there will now be more descriptions of devices available. Users will now be able to
create their own names for devices (known as “Display Names”) which can be shown alongside or
instead of the device’s Base Name. There will also be text descriptions of devices features, so that
if a device has multiple vibrators or other actuators, users and developers can denote which
features maps to which actuator. There is currently no UI available for this functionality, but it will be added to Intiface Central at some point in the future. See the “Plans for the Future: Mobile” section below for more info.

Better User Device Configuration Capabilities

Thanks to an overhaul of the user device configuration system, users will now also be able to customize devices to their needs. This includes:

  • Reserving device indexes so the same device shows up at the same index every time a client
  • Setting the usable range for a device, like maximum speeds for vibrators or minimum/maximum stroke ranges for strokers.
  • Allow/deny lists for devices, so users can say exactly which devices will/won’t connect to
    Intiface/Buttplug. Great for making sure you aren’t controlling your neighbors vibrator!

As with device feature descriptions, there is currently no UI available for users to set these configuration values yet. See the “Plans for the Future: Mobile” section below for more info.

New Testing System

In “things only I care about but that make me really happy anyways so you get to hear about them too”, there’s a new test system! It uses a simple procedural YAML-based DSL for defining expected message flows. One of the biggest issues in Buttplug pre-v6 was that changing the device system required changing every protocol single test, and as we continue to amass protocol support, time to update kept getting worse and worse. This allows us to easily update the system and only update the test harness, leaving the test scripts as is.

This will also allow us to test backward compatibility, as Buttplug Servers are supposed to be able to talk to ALL versions of the Buttplug Client, so that we never drop support for software someone is currently fucking. This has… only been a half-truth for the past couple of years, as v0/v1 support has been iffy. Now we’ll be able to make sure every release that goes out supports every version.

… At least once the v0/v1 harnesses are written. Those are currently slated for a point release in v6. v2/v3 support are solid though!

Documentation or Lack Thereof

One of the biggest missing features of Buttplug v6 will be any documentation about Buttplug v6. I haven’t updated much of the API documentation, the Developer’s guide still refers to the v2 spec, etc… Right now the public API won’t look too much different, so developers certainly could start using Buttplug v6 with minimal changes, but using everything available like sensors, user configs, and other new features will definitely require more documentation at both the API and Guide levels. This is definitely in the works.

Plans for the Future: New FFI Strategy

Speaking of mistakes: FFI handling in Rust has been a big one!

This is another subject I’ll be expanding on in its own blog post, but for now I’ll just say that the situation for people using Buttplug outside of Rust sucks, and I’m aware (and extra sorry to Unity developers 😐 ).

Trying to extend the native library to be used on both the Client and Server sides has not panned out how I’d like. Buttplug really needs pure language-native Client implementations that don’t depend on Rust (the server will always live in Rust though), and I’ll be looking at getting the system switched back to that soon.

Plans for the Future: Mobile

And you know what also was a mistake? Working with Bluetooth on Desktop!

Ok so I didn’t have quite as much as a choice here but it’s still never exactly been fun.

A good 80% of our support issues these days are weird problems with Bluetooth APIs not working on one desktop platform or another. Either someone has the wrong bluetooth dongle, or it works with some toys but others, or whatever. It’s just a constant barrage of broken and it needs to stop. Sex Toy manufacturers seem to test solely on mobile, so it’s time to move Buttplug and Intiface to mobile too. Buttplug has already been compiled and tested on Android and iOS, so this is mostly a matter of getting UI and build systems together, which is still a tall order but the hard part is done.

Buttplug and Intiface will still support desktop too, but it’ll make life way easier for a lot of our users.

I think. Maybe.

Of course, design of this will get its own blog post too. For someone who usually writes about 1 blog post a year I’m signing myself up for a lot here.

Onward to v6.1

I’m not even considering what v7 is going to look like right now, but rather trying to keep focus on smaller iterations to make things work. Ideally we’ll get v6 documented and debugged, get mobile apps out, then I’m hoping to take some time to actually implement some applications/games with Buttplug after working pretty much solely on the library for over 5 years. Not completely confident that will hold, but I can dream, right?

Looking forward to see what everyone manages to do with the library once it’s usable. Until then, if you still have to bang your head against it while it’s in this new, raw state, please let me know how it goes for you.

Haptics Rerouting for Fun and No Profit

At this point, it’s fair to say that I’ve built at least some of my career on the back of a single trick: Haptics Rerouting, or more appropriately, Rumble Rerouting. This involves taking a video game on PC or Console, catching specific game state or else rumble signals from the game to the gamepad, and pointing them at other things.

Rumble rerouting has become popular on TikTok/Twitch/Youtube/etc too, with people hooking up all sorts of large haptics to desks and basically liquefying furniture (or themselves) with games.

However, in my case, the other things are usually sex toys.

Some examples of my projects include:

These projects are built on more general platforms:

While these projects are fun to post to social media and show off at conferences, I’ve never really written up the technical background of what this requires. With the Elden Ring project done and dusted I figured now’s the time to put together an overview of how these various stunt hacks have come together, including where they sit in the technology stack, how they access the parts of a game or the surrounding system that they need to do what it is they do, and the impact they’ve had around making for good shitposts.

Why Haptics Rerouting?

Why keep doing what amounts to the same project over and over?

Because it still works today just as well as it did in 2005 and before, so why not.

Haptics rerouting uses the tried and true digital/electronic art method of:

  • Take a signal of some kind
  • Remove it from its original context
  • Apply it to a different (hopefully but not necessarily) meaningful context
  • Call it art

In the case of the haptics rerouting I personally do, this means taking the notification system of rumble in gamepads as triggered by video games, and re-contextualizing it to intimacy (for various definitions of the word) via the use of sex toys.

For instance, an early version of my hardware haptics rerouting projects used the game Burnout, a car racing game with a robust system for simulating vehicle collisions and crashes. Taking the rumble from collisions in the game and rerouting them to sex toys takes the context from over-the-top racing game to over-the-top simulation of JG Ballard’s Crash.

With social media the way it is now, though, the act of removing notification context and applying sex toys is enough. Even if initial re-contextualization is given, posting a video showing a game’s rumble events driving a vibrator will elicit different reaction posts in different communities, each making it their own, some positive, some negative. The loss of focused attention on a detail by the project author is traded for near infinite variation as media becomes meme.

Or in other words: It’s a shitpost that keeps on giving.

One thing I won’t be covering in this post is the use of haptics rerouting in multiplayer games and MMOs, as I’d mostly like to cover the technical side here. There’s a lot of ethical issues to unpack when using these tools in multiplayer games, and I usually add warnings to my utilities about playing games in a manner that is private and/or with consent of all players involved. That said, that’s not a whole solution, and it’s a complex issue. I’ll try to do another write-up about how I handle this at some point in the future.

The Stack

Before diving into how haptics rerouting projects work, let’s get familiar with the stack of technology that they run on. In this case, I’ll be using a simplified example with 4 levels.

For all levels outside of Hardware, I’m also assuming that the game is running on a computer with user access to the processes and operating system.

  • Game Process
    • The game itself. This is where all of the game state and code live. This is where game mods
  • Userspace
    • The abstract space including/around the game process, that the user can still interact with. Instead of knowing exactly what game we’re dealing with, in this realm all we know is that there’s a process and, depending on the libraries it uses (which we can usually get a list of), it may use a gamepad.
  • Operating System and Drivers
    • Access to things in and around the operating system kernel, including all data flowing between the gamepad and the computer, before it gets to the game process.
  • Hardware
    • At this point, we’ve left the machine that the game is running on, and are now working on either the interconnect between the machine and the controller, or on the controller itself, or in extreme cases, just building our own controller.

I’ll be covering each of these layers in this article, starting from the top, as that’s what most people will be familiar with, and moving down from there.

Haptics Routing in the Game Process

To start, we’ll visit the area that I actually work in the least.

Haptics routing (not rerouting yet, as we’re assuming here that the developer of the mod creates the events, versus tapping haptics events the game puts out) in the game process is a fancy way of saying “game mods”. This refers to code that modifies or augments a game in such a way that haptics can be triggered by something happening in the game itself.

Game mods can use either APIs provided by the game itself (i.e. capabilities the developer allows access to via something like Steam Workshop), or outside frameworks such as Melonloader or IPA, which provide generic utilities for accessing game state in certain engines like Unity. These tools allow developers to change assets or trigger devices based on actual game context (state and events), like a player losing or regaining health in combat, hitting a note in a music/rhythm game, etc…

However, this is also the level where anti-cheat systems like Valve Anticheat or Easy Anticheat live (we’ll get to kernel level anti-cheat later in this post). If a developer does not want game state exposed and editable, especially in multiplayer games, they’ll use anti-cheat to remove the ability to check and edit game state from outside the game itself. This means that mods may not have the visibility required to do what the user wants, and finding ways around this that still interacts with the process may end up with the user banned or even the developer arrested.

Mods for games like Minecraft, STALKER, Osu!, and others have been built using Buttplug, and are listed in the Awesome Buttplug Applications Repository. Specifically for haptics routing for intimate devices, mods are the method of choice for communities like healsluts, who are looking for events triggered based on game state (i.e. who healed whom, when, for how much, etc…) in real time.

Pros, Cons, and Impact

Games with mods tend to have communities dedicated to their upkeep. The size of these communities can vary, from a small group of dedicated users (Many indie games end up with these) to multiple gigantic communities, all with their own tools and communication hubs (Skyrim is a good example of this).

I personally avoid game modding for haptics routing because of the upkeep and maintenance cost of being involved. If I’m not working specifically with a game developer, external game mod upkeep means keeping track of when a game updates, what changes were made, how that affects the API, and a raft of other possible issues.

That said, while it’s not my area of choice, games with modding communities usually have developers dedicated to building utilities for updates, as well as keeping track of what changes when and how to update accordingly. It’s a little too niche for me to dedicate myself, but I work with developers from many different mod communities in order to help them access hardware for their chosen game or platform.

Haptics Rerouting in Userspace

Haptics rerouting in userspace takes the game modding idea and abstracts it to look at the process and what it accesses, versus the specific game state. While game mods are a scalpel, this approach is more like a shotgun. A really, really large, blind shotgun. Or a Game Genie, if you remember those.

To explain this with a concrete example, it helps to be familiar with the Intiface Game Haptics Router and its workflow. Here’s the tutorial video for that software:

To quickly summarize the workflow:

  • The GHR Application scans the list of all running processes
  • Any time it sees a process that uses a library the GHR can hook (I’ll get to this in a second), it
    adds it to its list of usable processes.
  • The list is presented to the user, so they can select the game process they’re interested in using
    the GHR with (assuming that process shows up on the list).

Once the user has selected the process, they hit an “Attach To Process” button, and this is where the GHR does its thing. The GHR adds “hooks” to the running game process, which in simplified terms means it finds the code for a certain function of the program, and then redirects it to call another function. In our case, it finds the function that is run whenever the game wants to set a rumble speed in a gamepad, takes the values from that, and sends them elsewhere (in our case, to the controls of another vibrator selected by the user). The user of the GHR can also decide whether the values still to go the gamepad to set its rumble, too.

The GHR supports two different types of processes: games that use XInput (an API for accessing Xbox Compatible Gamepads), and VR games that use the Unity Game Engine. For XInput, hooking happens using the EasyHook library, which allows .Net executables to hook native code. For Unity, we use the Harmony library, which is specifically for hooking for .Net applications (and is also used by some of the frameworks mentioned in the mod section).

The difference between mods and this type of hooking is that we do not have any game state to work from. We are just taking the rumble commands the game sends and rerouting them with no knowledge of the events that caused the game to send them.

Pros, Cons, and Impact

This is personally my favorite layer to work in, because it has the biggest potential for chaos.

Instead of building mods for a specific game, you can hand users a utility that they can try on their whole PC game libraries (this doesn’t work on consoles because we don’t have access to processes easily there). Users then can come back and say what works and what doesn’t. It gives them a way to explore and find emergent patterns and mechanics, experiencing games in new ways.

For instance, I tried the GHR with a twin-stick shooter called Crimsonland. I found all sorts of interesting patterns based on weapons, even though running a sex toy using a game about shooting bugs/zombies/bug-zombies isn’t exactly what most would be into.

Going slightly into the multiplayer realm for a second, I’ve also helped cam models use the GHR to connect with their fan base in more interactive ways than the video/text chat they normally have access to.

Unfortunately, this is also where my work normally gets knocked out by anti-cheat utilities. While the GHR and other hooking programs may not specifically be looking for game state to do malicious things with, anti-cheat (and even a lot of general antivirus programs) consider hooking to be a malicious act and will stop most naive attempts. This is why the GHR doesn’t work with games like Overwatch. There’s ways around that which I’ll get to in the next sections, but that way lies danger.

Haptics Rerouting in the OS and Drivers

If we can’t hook a process, then the next layer down will have to do. We’ll watch things from the kernel.

This is how the Elden Ring project and Buttpcap works.

Instead of hooking a process, I install a filter driver in the kernel, that watches the USB bus and relays all messages going over it out to Administrator Level Userspace (in Windows terms). In the case of the Elden Ring project, I’m using USBPcap, a utility normally used for debugging USB device development.

This allows me to find the data going between the game process and the USB manager of the operating system (which then talks to the gamepad hardware itself), possibly without the game process ever knowing I’m doing it. This is how I work around things like EAC. At the level I’m working at and for the goals of my projects, I don’t mind that I’ve lost all game context, I just want the rumble signal to make another device do something.

Pros, Cons, and Impact

While it works and makes for a good video, using filter drivers has many, many issues.

Installing a filter driver is wildly dangerous, as it means that any program running with administrator privileges can see what’s going over the USB bus. While there’s controller information flying over it, keystrokes from keyboards are also going over USB. This is basically a voluntary keylogger sitting on the system. While I can run this on an air-gapped machine to build projects, recommending anyone else do it would be inadvisable, to put it lightly.

That means that, while I can make a video showing things like Elden Ring, I can’t really share with users the same way that I can with userspace solutions like the GHR. It’s fine for a one-off, and it’ll get attention, but it’s the last resort.

This method may also be on the way out as we start to see kernel level anti-cheat become popular. While I build mostly for silly projects, kernel level snooping is used by commercial cheat manufacturers, so game vendors are fighting back by putting defenses in the kernel. While USB and other I/O may be considered innocuous for games for now, this method may not work forever.

Haptics Rerouting at the Hardware Level

Finally, there’s tapping the physical line between the controller and computer/console, or event building your own damn controller. This is the method I’ve used a few times, but only when required (because either I had no choice or I didn’t know better).

For the SeXBox, all I did was remove the rumble motors from a Xbox controller, and solder the wires to the battery leads of a vibrator. This is about a rudimentary as you can get, and it worked maybe half the time at best. I didn’t do any tests on load to the motors I connected, so many times they’d either overdraw or just not run at all. I wasn’t the first to do this by far, as projects like the G4 TV Xshok happened in 2003.

For the Console Game Haptics Router and Animal Crossing, things were far more complicated. Since I didn’t want to reverse engineer the Switch or jailbreak the system, I had to run a Man-In-The-Middle attack over bluetooth (specifically L2CAP). This meant making a Raspberry Pi identify as a Switch Joycon, then having it relay packets to/from the actual Switch Joycon. While this did work, it was incredibly slow, mostly due to the radio timing.

Pros, Cons, and Impact

No matter how simple they may be, hardware hacks always look neat. Having a physical device, especially with wires and exposed circuitry, has a hacker aesthetic like little else. Even if things aren’t doing much, it makes for much, much better visuals than software projects.

That said, it’s also time consuming and usually very difficult to put the hardware together, and it’s a very high bar for anyone else to replicate the project.

In terms of projects like this being shut down, it mostly depends on the platform. For computers, as long as gamepads identify as certain standard (HID, XInput, etc…), it’s fairly easy to work with. For consoles however, there may be signing/encryption between the gamepads and the consoles that is either not possible to work around, or else requires extra hardware to accommodate. For instance on playstation, the GIMX project allows users to hook up new controls that can identify and operate as Playstation controllers.


Between things like speed-running, alternative controllers, and mods, games are being pulled in all sorts of direction they may not have been originally designed for. My projects are just a small part of this overall trend to take interactive media and repurpose it in sometimes useful, sometimes silly ways. It’s great fun to watch people take utilities like the GHR and use them to find new ways to enjoy games they love, and the new projects coming up on social media for either better immersion or just pure shitposting are always entertaining to watch.

I hope this post was helpful in showing the multiple ways to get this kind of data out to games so you can throw it at whatever you want.

Now go build something dumb.

When Buttplug Won’t Buttplug, Part 1: Oh No

There comes a time in every software poorly planned open source software project where you have to sit back and say “Wait, am I completely off the mark? Did I totally fuck this up?”.

Of course, these times really shouldn’t happen at a frequency of once a month, but here we are. Unlike prior fuckups, this time I have a blog, so instead of fixing things, I can write about them!

But to be fair, a bit of self reflection is good before starting on the fixings.

Buttplugging So Far

Buttplug is itself an experiment with a general goal but no real focused direction to get there. The idea is to hand developers a way to easily access sex toys (this will come back to haunt us very soon) and then see what they do with this newfound raunchy power.

Thanks to the glorious lack of direction on how to achieve that goal of easy access, it’s also ended up as an exploration of technical niches like hardware drivers, implementation languages, and platform features. Its how we’ve gone from being a single library written in C# to two libraries written in C# and Javascript back to one library written in Rust with C# and Javascript/WASM layers on top of it, while also ending up maintaining a cross-platform Bluetooth LE library along the way. Buttplug at this point is balanced between being a useful sex toy library and a shitpost made of bleeding-edge development technologies, and I wouldn’t have it any other way.

One of the core philosophies of the library is that it should only maintain direct access with the hardware it works with. Currently, it uses only local communications systems like Bluetooth, Serial, or USB to talk to hardware. This means that, even if a company’s services go away, I can still provide users with a way to access their toy across software that works with our library. The library already supports out-of-production toys like the Real Touch, and many toys it can connect to now will suffer this same fate of obsolescence in the future, and we will be there, make sure they vibrate until the heat death of the sun or the usable lifetime of their $0.43 motor. This work has even gotten us to the point where sex toy manufacturers like The Handy actively engage with library development to provide support for their hardware. This strategy also helps preserve the privacy of the user, letting them choose hardware while being free of having to live on whatever ecosystem is provided by that hardware’s manufacturer.

During this time, Buttplug has stayed mostly desktop focused. While there have been web apps that work on Android and some via some alternative iOS web browsers, mobile offerings have been sparse at best, mostly due to lack of development resources. This happened while pretty much every sex toy manufacturer focused solely on mobile.

While all of this has been a mostly successful endeavor, it also assumes a usage model that may not always work for users of certain kinds of toys or in certain situations. Ironically, this includes many situations involving the type of toy from which I took the project name.

Buttplug, Buttplugs, and Social VR Worlds

Up until 2020, most applications for Buttplug assumed that a user was near their computer. Be it media players, single player game interaction, or other interactive applications, I mostly assumed that the user would stay still and near whatever computer was controlling the toy while using it. Even in teledildonics situations or mobile applications, there hadn’t really been any applications built where the device user and the controlling computer were assumed to be all that far away from each other.

Every so often I’d hear about random hardware disconnection issues in Buttplug (my library, not the toy), mostly with insertable toys, and in that niche, mostly with buttplugs (the toy, not my library). These toys use Bluetooth LE, a system that was not really made for fast updates, or butts, or updating things in butts in a fast, reliable way. Bluetooth LE is fine when you have line of sight or not much distance between radios and their hosts, and just need to throw data around in a leisurely way. Since Bluetooth is radio, it also would very much like to not be impeded by things like water. Overall, this means Bluetooth LE is great for things like mobile phones and small IoT devices that will stay near each other, not so much for desktops or gaming laptops, and definitely not for desktops/laptops talking to devices is in one of the deeper, harder to reach parts of a (mostly water based) human body. The past few years have been a lesson in doing this the hard way, as developing cross-platform bluetooth applications for desktop operating systems for body-immersed hardware has been nothing short of an absolute nightmare.

This user is fine and normal and good.

Unfortunately, I just don’t have many options to offer otherwise. No one seems to want a USB cable coming out of their butt (the luddites), and most people want their toy to be able to talk to their phone (as those are considered the most “private”/”intimate” technology accessing device), and phones either need WiFi (which is power hungry and complex to configure and implement) or Bluetooth to talk to the devices.

Doesn’t stop me from yelling into the void though. I’ve groused in the media for years about Bluetooth LE being bad for sex toys, though people that actually manufacture products and are better at this than I am have said otherwise.

“The antennas aren’t good enough!”

“There’s not enough transmit power in the toy!”

“Sex toy manufacturers don’t have the experience to build what’s needed!”

Up until 2020, it wasn’t much of an issue though. A few reports here and there, some recommendations on dongles and buying USB extension cables, and we’d be on our way.

Then Buttplug integration with VR social worlds like Neos and VRChat happened, and suddenly disconnection reports spiked. Thanks to COVID-19, these worlds went from social outliers to life-saving spaces, and as with any and all spaces, people fucked in it. The invariant of people being near their computers while using their toys was broken, thanks to being able to inhabit, walk around in, and hump these new shared virtual spaces instead of just sitting quietly like a good user. Not only do they move more, their sessions are longer, with reports of some users using VR social worlds plus Buttplug related plugins (both hardware and software) for upwards of 6 hours at a time.

This user is a support problem, and also an asshole

The combination of “Room scale” VR plus lengthy sessions plus hiding radios in the meat and water caves we call butts means devices often lose connections as users move around and power levels decrease, and thus cause the support channel on my discord server to see far more traffic.

This is not good.

What now?

Buttplug’s current connection methods aren’t cutting it. It works fine for people being near their machines, but that doesn’t work for VR, nor for those who just want to use their phone for certain situations. The current development strategy also puts the library at odds with toy manufacturers, who develop for and test on mobile and basically ignores desktops.

To fix this, I need to figure out ways to combine phones (or small machines like Raspberry Pis) and desktops/laptops in order to work with more situations. This needs to happen while balancing three considerations:

  • Not ceding ground to manufacturers for online services, so the library isn’t just a frontend for a bunch of services we don’t own or can’t replicate.
  • Preserving the privacy of the user, making sure that someone who is fine with their local connection setup and doesn’t want to use network/remote control never has to.
  • Making sure development ergonomics don’t suffer, while also making sure developers understand and expose features to their users in a way that doesn’t undo the preserving privacy point.

A few solutions to this problem already exist, in the form of the Lovense Connect application, as well as the XToys web based toy control and scripting system. In the next couple of blog posts, I’ll be outlining how these two systems have built their solutions, and what the next iterations of Buttplug can steal from their products. I’ll finish out with a concrete overview of where Buttplug is headed, both in terms of fixing insertable toy connectivity issues as well as thinking ahead to building remote services with the library. Along the way we’ll learn about how to design these kind of services, check out new technologies available to speed development, and most importantly, have ample time to appreciate the selection of clip art images I hastily googled for while writing these posts.

Onward and inward!

Buttplug Rust v3.0 Released: Less is Less

When I released Buttplug Rust v1, I figured I’d be rolling major versions whenever we updated the Buttplug Protocol. Here we are, at major version 3.0, still running the same protocol, but with more surface API changes. So much for those plans.

Why v3.0?

Since the release of Buttplug Rust v1, I’ve been getting steady pings from game developers asking when the Buttplug Unity plugin would be updated, in order to support new hardware as well as IL2CPP compilation. I finally got time to start work on this project a couple of weeks ago. Unfortunately it didn’t get off to a great start.

Using the C# FFI to Buttplug Rust worked fine, everything basically compiled with no real changes outside of some module paths, which was great. However, the development cycle after that basically became unusable. We found we could run Unity in Play Mode once, but any subsequent run would stall.

There’s more info in the related bug, but long story short, Unity’s Mono implementation wasn’t able to properly shut down Buttplug Rust’s async handling runtime. This meant threads got left open, and when Mono tries to reset itself (as is common, to save Unity game developers from having to manage their own state resets), it’d just stall forever.

The fix to this was moving from our current runtime (async-std on top of smol) to Tokio. Tokio provided far more granular runtime lifetime handling and passing, meaning we can easily manage when we bring up and take down the system. We now don’t spin up any runtimes (which brings up a number of threads) until we need to, and we can tear it down once all of our devices and clients disappear.

With that work done, Unity seems to be pretty happy. It compiles Buttplug support to either Mono or IL2CPP, and the development loop seems stable. I also took some time to work more with the fantastic tracing crate to improve logging in the library, making it easier to follow device connection lifetimes. This work also made me realize that my “batteries included” philosophy for Buttplug Rust maybe included a few too many batteries.

What Got Removed

One of the original tenets of Buttplug followed my philosophy about sex toy design: that it should be as quick as possible to start using, and able to run basically standalone while also having the ability to extend where needed. Developers can just get the library and integrate it with their program, not having to worry about how devices connect, how IPC mechanisms works, or other boring details. This hopefully allows for developers to concentrate on implementing interesting things with sex toys.

Sometimes though, this gets overrun by me learning things while implementing the library, so we end up with more features than might really be needed, or that I can support. Optimizing the library for Unity brought up a few things that could be removed.

Removing async-std and ThreadPool Runtimes

Unlike many languages with async capabilities (C#, JS, etc…), Rust’s async execution system is designed in such a way that the language comes without a way to execute tasks. Rather, it depends on outside implementations that can tune to the specific requirements of an application. While this is overall a win for the ecosystem, it can sometimes cause frustration.

Supporting multiple runtimes in Rust is common, but usually for libraries that will have widespread use: network services, database connectors, etc… While there are certainly developers using Rust to develop Buttplug applications, they are a minority compared to developers using FFI libraries, where this runtime selection will be hidden.

Buttplug Rust as it exists now was started in September 2019, slightly before the release of async features in Rust 1.36. At the time, async-std was developing alongside the nightly branch of rust, and looked more like what the async ecosystem does now. Thanks to that, I ended up going with that for our initial execution system, and it has worked great up until our current issues with Unity.

This also functioned as a way for me to learn how to live as a library developer in the new Rust async ecosystem. This was a combination of interesting and frustrating, especially as requirements sometimes differed greatly between libraries.

With subsequent releases of Tokio over the past 18 months, it has grown to integrate with the async facilities of Rust in a more ergonomic way, while still providing more granular control (and the cost of some added complexity sometimes, i.e. runtime handle management). Thanks to this, it now fits Buttplug’s needs better, and comes stocked with some very useful sync primitives and channels, including Broadcast (which I use heavily to simulate the event systems we had in C#/Javascript).

On top of this, most of the async work we still need to happen (Windows Named Pipes, serial ports) is farther along in tokio/mio (as far as I’m aware, and it’s currently stalled), meaning we can just integrate with that when it comes along by using tokio as our main implementation.

After switching Buttplug to Tokio, it became apparent that maintaining 4 runtimes (tokio, async-std, futures crate ThreadPool, and wasm-bindgen) was silly, since I don’t really have users split across those (and many users may not even know why the runtimes are there). Some of our other dependencies like async-tungstenite could handle the differences, but the complexity of the feature system for Buttplug was getting out of hand, as was remembering where to put all of the relevant #[cfg()] calls. I’ve now removed async-std and ThreadPool implementations, leaving us with just Tokio and wasm-bindgen (required for WASM). Ideally it’d be great if we could use Tokio’s executor for everything, but that’s not quite possible as of yet. The current system is managed using an internal system similar to the async_executors crate, which works well enough for abstracting task systems.

This does not mean that Buttplug isn’t usable with other runtimes now. Outside of the Device Communication Managers (which, granted, are possibly the most important part of the library), most of the library is runtime agnostic, and async-std contains tokio compatibility systems that will allow the library to run using its runtime also. This change mostly reduces the amount of thinking I have to do when updating the library and its direct dependencies. This is open source self care more than anything.

Removing Secure Sockets for Buttplug Servers

When Buttplug C# first started in 2017, Chrome allowed for localhost websocket connections via mixed contexts (i.e. https:// website calling through ws:// for localhost websockets). Firefox did not have a feature like this, so we implemented the ability to create self signed certs and load them into the server to run a self signed websocket server for Buttplug. This allowed us to get applications working in Firefox.

Firefox changed this in 2020, now also allowing mixed context localhost connections. With this addition meaning that Chrome, Firefox, and Edge all supported mixed context connections, the need for including the batteries of a secure socket connection went away. Any users that require this feature can still set up a reverse proxy in front the server port, but managing the certificate generation and loading system is well out of scope of Buttplug’s core goals. Removing this will hopefully simplify changes to our connector system in the future, and also removes the burden of keeping cert libraries in lockstep.

For most of the talk of async in this post, the secure socket change is actually what drove the major version update. Removing secure sockets changes our Websocket connection API, which is exposed to developers, and therefore is a breaking change in the general public API. This change only happens in the Rust library, as the server is not exposed in the FFI, so while Rust moves to v3, the FFI APIs will continue on the v1 track.

What’s Next

Now that Buttplug v3 is done, there are quite a few releases to make on top of it:

  • Updating the C# and WASM FFIs, though only C# will see much of a change.
  • Finishing the Buttplug Unity update and releasing v1 of that package
  • Updating Intiface to remove the Secure Socket options

These updates will be happening throughout the next week.

After that, the main focus is going to be more documentation and the implementation of a WebRTC based proxy system. This stems from the rather startling discovery that Buttplug (the library) doesn’t work very well with buttplugs (the sex toy), which I’ll be making another post about soon.

With this proxy system (inspired by the work of xtoys.app), we can start using mobile hardware (phones, linux SoCs like RPis, etc) as connection points, giving users more freedom in where and how they use toys. Alongside this will be more hardware and QoL updates, but the goal for now is making our system usable to the wave of social VR users we’ve seen over the past few months.

Onto v4! But hopefully via many v3 point releases first.

Nonpolynomial Software Updates for January 19, 2021

Another week, another release of almost every piece of software in our stack!

btleplug 0.5.5

btleplug is our cross platform Rust Bluetooth LE library, which Buttplug uses for all bluetooth access.

Updates include:

  • Dependency update to fix issues with async-std v1.9 API move, needed so apps using Buttplug would build at all (we depended on some unstable things that ended up disappearing).
  • Preparation for bringing in a new Bluez core thanks to some contributor work!

Buttplug Rust v2.0.2

It’s been almost a month since releasing Buttplug Rust v1, so now obviously it’s time to release v2!…?

This is mostly a cleanup release, but some of that cleanup had fairly major effects on the surface API, hence the major version roll.

v2.0.0 and v2.0.1 were both yanked due to bugs found quickly after release, so v2.0.2 is really the first released version of the v2 chain.

Updates include:

  • Move our internal channel structures to using tokio-rs‘s sync module, as its mpsc and broadcast modules are more suited for our needs (blog post on this endeavor coming soon).
  • Restructured internal event loops to make things cleaner
  • Fixes for device scanning and discovery issues with the Lovense Dongle
  • Added hardware support for the Lovense Ferri

Buttplug JS v1.0.3, Buttplug C# v1.0.9

Not a lot to say here, other than “there were updates”. Both Buttplug JS and Buttplug C# got updates to Buttplug Rust v2.0.2, but the only change that may be visible is that Rust panics (crashes) are now communicated through the logging system, so more information can be provided for debugging.

Intiface CLI v25, Intiface GHR v11

Same as the FFI libraries, Intiface CLI (used in Intiface Desktop) and the Game Haptics Router was mostly an update to Buttplug Rust v2.0.2, along with the same addition for more crash logging.

Here’s hoping it’s more than a month before Buttplug Rust v3 needs to be a thing.

Nonpolynomial Software Updates for January 10, 2021

I made a rule for myself that I’d wait 2 days after any software update to announce it on the blog, just to make sure I didn’t have to go back and fix even more things and flood the blog with “fixes and performance improvement” posts. The last blog being 2 weeks ago says a lot about the release schedule lately.

Thanks to a lot of interaction with developers using the libraries after the v1 launch, I’ve been making a ton of patches and bugfixes. There’s a pretty severe lack of tests in several parts of the platform at the moment, so it’s a very “testing in production” situation. With production for our software being what it is, it means seeing bug reports like “multiple gigabyte memory leaks during hours of intimate hardware usage.”

Anyways, here’s a list of things I threw the fire extinguisher at over the past 2 weeks:

Buttplug Rust

buttplug-rs is now at v1.0.5, having seen the following major updates since v1.0.2:

  • XInput (XBox compatible gamepads) will now emit disconnect events, as well as rescanning every 1 second during the scanning period (versus only scanning once then stopping until StartScanning is called again)
  • Fixed bug with Bluetooth LE scanning missing some devices in certain situations.
  • Contributor Patch: Fix handling of Sync/Send traits on certain future types
  • Contributor Patch: LTO now used on release builds, shrinking library size by about 12%.
  • Contributor Patch: Support for LiBo, Prettylove toys. Thanks to the good people at IOSTIndex for this patch.

Buttplug C#

buttplug-csharp is now at v1.0.8, having seen the following major updates since v1.0.2:

  • Updated Rust dependency to v1.0.5, so all previously mentioned fixes/additions for buttplug-rs are available
  • Fix issue with device disconnect/reconnect causing collisions in the C# API
  • Fix issue with certain commands not triggering on all features as expected (i.e. a device with multiple vibrators only has one that reacts to commands, when all should react)
  • Contributor Patch: Fix issue with events not doing null checks, thus throwing if no listener is available.

Buttplug JS

buttplug-js is now at v1.0.2, having seen the following major updates since v1.0.1:

  • Updated Rust dependency to v1.0.5, so all previously mentioned fixes/additions for buttplug-rs are available
  • That’s about it, really. Most of the major fixing has been in device access in our native libraries. JS certainly still has bugs, but is currently seeing less complaints about them.

Intiface Game Haptics Router

After getting all of these library updates done, I’m finally moving back to being able to work on some of our first party applications. This includes the Intiface Game Haptics Router, the gamepad-rumble-to-sex-toy-control mod maintain.

The GHR is now at v10, which includes the following major updates:

  • GHR can now connect to Intiface Desktop, as well as still using a standalone version of Buttplug that it comes with.
  • Settings are now persisted between sessions
  • XInput hooked processes can now be detached/reattached (Unity VR hooked processes still can’t detach yet).
  • Sped up process finding by a factor of however many processors you have.
  • Users can now set packet gaps, to reduce issues with command flooding to toys.

That’s it for now. Be on the lookout for updates to programs like Intiface Desktop and VAMLaunch, and of course more fixes and features in the core library soon!

Buttplug C# v1.0.2 and JS v1.0.1 Released

So nice to finally be able to have release notes that aren’t tweets!

Buttplug C# v1.0.2

Really simple fix here, but it was stopping the logging system from working at all in some cases, so very important.

  • #44: Log Handler now held for the lifetime of the process, meaning it will no longer throw an error when the GC sees the only reference is possibly held by a bare pointer in a native library. Isn’t FFI fun?

Buttplug JS v1.0.1

Even simpler:

  • #43: Forgot to include protobufjs as a dependency (was a devdep), meaning typescript would cry when trying to resolve types

That’s it. That’s the change list.

Buttplug Hits v1 Milestone

After 3.5 years of development, Buttplug, the open source intimate haptics controls library created and maintained by Nonpolynomial, has finally arrived at its v1 release. Fitting that it’s also the first real blog post on the new Nonpolynomial Blog!

For the project, this is actually a contraction rather than an expansion. Version 1 means that the project has slimmed down to a core Rust implementation upon which the ecosystem can continue to grow.

Buttplug v1.0.0 is available in the following flavors:

The Buttplug Developer Guide covers basic usage, with examples in all of the aforementioned languages.

What Even Is Buttplug?

Buttplug is a haptics abstraction library for intimate hardware.

Which is a fancy way of saying “a way of telling a bunch of different vibrators how to vibrate”. Though it can tell hardware how to do things other than vibrate, and it supports more form factors than buttplugs.

Basically, there are hundreds of computer controlled sex toys out there. Most of them have unique protocols to control them. Buttplug tries to centralize these control protocols, handles cross platform USB/Bluetooth/serial/etc for the developer, and presents a uniform way of controlling the whatever toy the user may have. Instead of knowing what operating system the user is on and how to talk to their specific toy, developers can use Buttplug to enumerate for a supported device, then send generic commands like “vibrate/rotate at [speed]”. That’s it.

While the sex toy control part of Buttplug is probably the most recognizable and memorable feature, it’s not the only goal of the project. Buttplug was established as an experiment for creating user-focused haptics and interface device abstraction. Libraries and engines like Chai3D and H3D work as generalized haptics engines for studying mechanical systems, texture and force creation/simulation, while other systems like VRPN work as a sort of user-space HID manager for systems that may not conform to general HID protocol boundaries. Buttplug seeks to take these two paradigms, and smoosh them together while also servicing a niche that doesn’t get much engineering attention. This leads to many interesting questions, like:

  • How do we quickly and reliably bring up hardware communication across multiple platforms?
  • How do we interact with a user whose affective state may differ from someone using “normal” software like a word processor or database?
  • How do we create a language expressive enough to generate the experience a user wants, while also abstract enough to not be device specific?
  • What are the ethical implications of building open source technology for intimacy?
  • Can these questions be approached through technology in a way that is maintainable by a small, possibly one person team?

We’ve heard from our community that some users are just interested in controlling sex toys, though, and that’s fine too. I guess.

If you’re curious about what users are doing with Buttplug, check out our awesome-buttplug project list repo.

A Short-ish History of Buttplug

Here’s an overview of the 16 year path from my start in sex tech to a v1 library for the field.

  • 2004
  • 2007
  • 2013
  • Fall 2016
    • First Rust implementation. Stalls due to lack of platform support for Bluetooth (most hardware we interact with is Bluetooth LE) and other hardware.
  • April 2017
  • May 2017
    • First JS implementation, using WebBluetooth to access BTLE through the Chrome web browser. Later included native Node implementation using noble and other hardware libraries.
  • August 2017
  • December 2017
    • Generic messages added to the Buttplug Protocol Spec, making it easier to command a wide range of devices. Due to maintenance timing and life in general, this is the last change to protocol spec for the next 3 years.
  • April 2019
  • May 2019
  • Sept 2019
    • Realize that maintaining 2 full implementations of Buttplug was untenable for a 1 person development team, work started on a new core implementation of Buttplug in (at that point unstable) async Rust, with other language implementations would then live on top of.
  • January 2020
    • Forked Rumble into btleplug (begrudgingly changing the name because rumble would’ve been GREAT to have in Buttplug but the original author was AWOL so package couldn’t be transfers on crates.io), brought up minimum BTLE capabilities in Windows, macOS, and Linux.
  • October 2020
    • Core async Rust Buttplug implementation hits feature parity with the C# and JS libraries. Move to porting C#/JS to using Rust via FFI. C# calls into the native Rust library using exported C calls, while JS uses a WASM layer.
  • December 2020
    • v1 release, along with the first shipping of a new spec version since December 2017. FFI C#/JS libraries at parity with original native C#/JS libraries, original native libraries deprecated and archived. Buttplug Developer Guide in good enough shape to guide users on building simple Buttplug Applications. Metafetish closes after 16 years in order to make way for new Nonpolynomial blog.

What Buttplug Version 1 Means

To me, a lot. To you, possibly not so much.

As mentioned, Buttplug Version 1 doesn’t really come with a lot of new features. It’s mostly a point where I can cut old stuff and start looking toward the future.

Buttplug C# and Buttplug JS will now be archived, as implementations now live in our FFI repo, and their respective nuget and npm packages will still live on as v1 and beyond. There will definitely be breaking changes between the v0.x and v1 versions for C#/JS, so if you’ve been developing on those, be ready. I did my best to keep the APIs similar, but also used this as a way to clean up some problems that had cropped up along the way.

Before v1, adding new features or hardware protocols meant implementing things in at least 2 places. Now, features can be implemented in Rust, then all that is required is a rebuild of the FFI and package version numbers being rolled. At worse, the FFI API surface may require changes, but that’s fairly trivial work versus having to redo full feature implementations. Most of the FFI work is up front in the initial implementation, and the hope is that continued maintenance will be much simpler. Time will tell whether this was a total mistake.

Success will be measured via this possible reduction of rote coding work. I’d like to spend more time on design with a flexible system versus having to re-implement my ideas multiple times to test them out across all platforms.

The Version 1 release will also probably be the only time that multiple libraries are released in lockstep with the same version number. I suspect that the FFI libraries will have API surface level issues that will require major version rolls outside of when the rust library updates. Everyone who has an affinity for version numbers, enjoy these stars aligning now, because it’s probably the last time it’ll happen.

What’s Next

There’s so many directions to go now that it’s almost hard to pick which to start with, but here’s some general ideas of what I’d like to do next:

  • Blog Posts
    • I have this shiny new blog now and I’d like to use it more. I have a lot of thoughts about Rust, WASM, and other technologies I’m using that I’d like to cover here.
  • Documentation
    • Buttplug v1 is documented just enough to maybe get people started, but the developer guide and API documentation for the various implementations definitely need more love.
  • More FFI Implementations
    • Python is on the way soon, and C/C++ (especially for Unreal Engine suppot) and Java/Kotlin have been requested by the community.
  • Application Updates
  • Hardware Support
    • The v1 slog (this was supposed to be done in October, then Hades happened. Oops.) means hardware support for things like the OSR2 and Nintendo Joycon are still in development and running behind.
  • Actually Making New Stuff
    • Everything listed so far is continued maintenance. It’d be nice to actually make some new things too. Don’t know what those will be, but I need to actually create with my creation, instead of just creating my creation.


Thanks go to:

  • Loved ones and friends who’ve had to put up with me being “The Buttplug Guy” for the past 16 years (with no sign of that ending soon).
  • My Patreon and Github Sponsors Subscribers, who’ve kept the project funded enough for me to buy new hardware.
  • My consulting clients for Nonpolynomial, who’ve helped keep the business cash positive while also helping my project along with support in their products.
  • Everyone who worked on reverse engineering toys and donating info to our Sex Toys Protocols I Have Known And Loved (STPIHKAL) documentation project.
  • Sex tech projects like IOSTIndex, XToys, Eroscripts, and others who manage information and help grow sex tech communities in other directions. Buttplug is just a small component in what will hopefully be a larger ecosystem and community someday.
  • The community of developers who’ve been using the library, either as part of project they’ve shared with communities, or even for things they’ve just done for themselves and kept closed. It’s nice to know people are using things I build.
  • People who’ve been watching and interacting on social media, at conferences, etc… This project is as much if not more social than it is technical, so it’s been great to get other perspectives.

Having Buttplug hit v1 feels great, but there’s no time to rest. On to v2!

Welcome to Nonpolynomial

Welcome to the new blog for Nonpolynomial! Pivoting from our previous strategy of random tweetstorms, we’ll be using this space to post updates and in-depth technical articles about our various products. We’ll also include posts on haptics (intimate and otherwise), product design and marketing, and other topics we cover as part of our consultancy.

Stay tuned for more content!