⚠️ OS NOTICE: Thismainbranch is strictly for the native Linux version of the Moto Buds Desktop Utility. If you are looking for the Windows version, please switch to the dev-windows branch for Windows-specific Files and build instructions.
An open-source, fully-featured desktop utility for configuring and controlling Motorola Moto Buds on Linux. This project successfully reverse-engineers the proprietary Bluetooth RFCOMM communication protocol used by the official Android application and implements a beautiful, premium skeuomorphic desktop user interface using React and Electron.
What's New in Version 2.1: We have officially released v2.1.0, which introduces a persistent background System Tray for quick access to battery and ANC controls. We also completely rewrote the UI layout to feature a dual-pane aesthetic, vastly improved connection reliability through daemon-level adapter bouncing, and achieved complete 100% feature parity with the official Android application (excluding Adaptive ANC). Every single feature has been rigorously tested and is confirmed to be fully working on native Linux!
MotoBudsController now includes full system tray integration that allows the application to continue running in the background after the main window is closed. Users can quickly view battery information, switch noise control modes, and reopen the full application directly from the tray.
Enable background operation by allowing the application to minimize to the system tray when closed.
All current protocol reverse-engineering, payload cryptography, and feature implementations have been strictly tested and verified on the Moto Buds (Base Model).
The following functionalities are confirmed to be 100% working:
- Gestures Control (Advanced): Highly customizable tap settings (Double Tap, Triple Tap, Press & Hold) for each earbud independently. This desktop app securely injects opcode
0x0100and offers more granular customization than the official Motorola mobile app. We have implemented native AVRCP bridging viampris-proxy, ensuring your taps accurately pause, play, and skip media globally across your Linux desktop. - Trust Protocol Integration: We have implemented a native D-Bus command sequence that makes the Linux host device automatically trust the earbuds. This ensures that tap gestures and in-ear detection function flawlessly without manual Bluetooth pairing intervention or trust command-line hacking.
- Custom 10-Band Equalizer (With Presets): A full implementation of the
0x0306equalizer protocol. Uses a custom 173-byte payload to offer precise floating-point gain control across 10 frequency bands. You can seamlessly switch between pre-configured custom presets (Flat, Bass Boost, Treble Boost, etc.) or dial in your own Custom EQ. - Hi-Res Audio (LDAC) Negotiation: Successfully implemented codec negotiation directly from the desktop client, entirely replicating the functionality that was previously restricted to the Android app. Our backend gracefully survives the deliberate Bluetooth protocol disconnect triggered by the earbuds, and forcefully re-routes the Linux PipeWire A2DP stack to accept the new LDAC sample rates. Handles mutual exclusivity with Game Mode out of the box.
- System Tray Integration: Quickly access battery levels, toggle Noise Control, and manage connections directly from your Linux system tray/panel, ensuring the app remains accessible without cluttering your workspace.
- In-Ear Detection: Accurately detects whether the earphones are physically inside the ear and seamlessly auto-pauses/resumes system media.
- Fit Test (Improved Diagnostics): Accurately tests the seal quality and provides distinct, independent pass/fail results for the left and right earbuds using dedicated visual indicators. It utilizes a state machine to track the
1024and1025response codes from the earbuds during the diagnostic sweep. - Find My Device: Individually ring your left or right misplaced earbuds with safety checks (prevents ringing if the earbud is physically detected inside your ear to prevent hearing damage).
- Connection State Machine: A seamless background state machine provides visual feedback (loading spinners, connection checks, dropped statuses) while the earbuds momentarily disconnect to renegotiate codecs or drop connections. The UI instantly reflects the daemon's internal RFCOMM socket state.
- Active Noise Cancellation (ANC): Verified working across all states (Off, Transparency, Active Noise Cancellation).
- Game Mode: Verified working via latency reduction opcodes. Automatically handles mutual exclusivity with Hi-Res Audio via custom UI dialogs.
- Volume Booster: Verified working.
- Battery & Charging Telemetry:
- Granular battery reporting for individual earbuds (Left/Right).
- Accurate Case battery reporting (even when only one earbud is inside the case).
- Real-time charging tracking. Earbuds show a charging indicator when placed inside the case, and the case accurately reports its own charging status when plugged in.
Note: Spatial Audio is partially supported and dynamically surfaces only when the connected device is a Moto Buds+.
We strictly maintain our repository to only contain raw source code. All runtime dependencies, including the Python daemon components and Bluetooth bridging utilities, are automatically resolved during packaging.
Pre-packaged standalone binaries for Debian-based systems (.deb) and other Linux distributions (.AppImage) are available in the Releases section of this repository. The .deb package specifically declares dependencies on python3 and bluez to ensure mpris-proxy is available on your system for media gestures.
⚠️ Connection Warning: Please ensure your earbuds are natively connected to your OS via your Bluetooth manager before pressing the "Connect" button on the first screen. If you connect them after reaching the connection screen, you may experience slight connectivity issues. If this happens, simply disconnect and reconnect the earbuds from your OS Bluetooth manager.
🖥️ Windows Version: The Windows codebase is maintained on a separate branch. Windows setup executables and portable
.exebinaries are provided directly in the Releases panel. Please visit the dev-windows branch to view the Windows-specific source code and build instructions.
This application consists of two completely decoupled components: a lightweight Python background daemon that speaks natively to the earbuds over RFCOMM, and a gorgeous React/Electron frontend that gives you visual control.
Here is exactly what happens under the hood when you use the app:
- You launch the application.
- The app starts on the "Unconnected" screen.
- When you click Connect, the React app sends an IPC (Inter-Process Communication) message to Electron's main process.
- Electron uses Node's
child_process.spawn()to silently boot upbackend/moto_control.pyin daemon mode. - The Python daemon opens a Classic Bluetooth RFCOMM socket (Port 16) directly to your earbuds and negotiates the initialization handshake.
- Upon establishing a successful connection, the Python daemon fires up
mpris-proxyin the background to handle AVRCP gesture bridging, and prints{"type": "status", "status": "connected"}to its standard output. - Electron reads this output, forwards it to the React app, and the UI visually transitions to the Main Dashboard.
- The React app immediately requests a full state synchronization by injecting a
syncopcode sequence into the daemon, fetching Battery, ANC, Gestures, and Hi-Res states.
- You click a control, such as the "ANC" toggle, on the Main Dashboard.
- The React UI does not optimistically change the slider position. Instead, it fires an IPC command:
window.api.motoCommand({ op: 'anc', mode: 1 }). (Note: The sole exception to this rule is the In-Ear Detection toggle, which is optimistically updated locally because the earbuds' firmware does not emit an asynchronous confirmation packet for opcode1027.) - Electron receives this command and pipes it into the
stdin(Standard Input) of the running Python daemon. - The Python daemon reads the input, formats the proprietary Protocol Data Unit (PDU) packet, appends a dynamically calculated CRC32 checksum, and writes it to the Bluetooth RFCOMM socket.
- The earbuds receive the packet, physically enable Active Noise Cancellation, and immediately broadcast a confirmation PDU packet back to the host.
- The Python daemon's asynchronous polling loop reads the raw hex response from the socket and prints it as a JSON event to
stdout. - Electron captures the
stdout, pipes it back to React, and the Zustand state manager (useDeviceStore.ts) parses the packet. - The Zustand state updates
ancModeto1, which triggers React to re-render the Dashboard, finally updating the ANC segment in the UI.
This entire round-trip takes milliseconds. Because the UI only updates upon guaranteed hardware broadcast, the interface represents the absolute physical truth of the earbuds.
- PROTOCOL.md: A complete, in-depth breakdown of the proprietary reverse-engineered Bluetooth protocol, opcodes, CRC32 algorithms, and payload structures.
- INTERFACE.md: Documentation on the decoupling between the React frontend and the Python backend, explaining the state management system for developers or AI agents wanting to completely redesign the UI.
- A Demonstration/Tutorial Video for v2 (last updated on 12/06/2026)
If you wish to build the application from source or contribute to the project:
- Ensure your Moto Buds are paired and connected to your Linux machine via standard OS Bluetooth settings.
- Install the necessary Node modules for the Electron frontend:
npm install
- The Python backend scripts rely purely on standard libraries (
socket,struct,binascii,subprocess,json), so no externalpippackages are necessary.
Simply run:
npm run devTo compile the standalone binaries yourself:
npm run dist:linuxTo ensure the SPP parser logic is robust and doesn't drop asynchronous packets, we have a mock local test server that mimics the exact Moto Buds PDU flow. You can run the full automated integration test without your earbuds being physically present:
source .venv/bin/activate
python backend/test_integration.py

