{"id":49362962,"url":"https://github.com/aaronsb/bosectl","last_synced_at":"2026-04-27T17:34:05.291Z","repository":{"id":349270749,"uuid":"1201694767","full_name":"aaronsb/bosectl","owner":"aaronsb","description":"Control Bose QC Ultra 2 headphones from Linux — no app, no cloud, no account. Reverse-engineered BMAP protocol.","archived":false,"fork":false,"pushed_at":"2026-04-12T04:25:19.000Z","size":454,"stargazers_count":5,"open_issues_count":4,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-12T06:06:16.593Z","etag":null,"topics":["bluetooth","bmap","bose","cli","headphones","linux","noise-cancellation","python","reverse-engineering","rfcomm"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aaronsb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-05T03:00:18.000Z","updated_at":"2026-04-12T04:25:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/aaronsb/bosectl","commit_stats":null,"previous_names":["aaronsb/bosectl"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/aaronsb/bosectl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronsb%2Fbosectl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronsb%2Fbosectl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronsb%2Fbosectl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronsb%2Fbosectl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aaronsb","download_url":"https://codeload.github.com/aaronsb/bosectl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aaronsb%2Fbosectl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32348048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-27T17:12:42.749Z","status":"ssl_error","status_checked_at":"2026-04-27T17:12:41.658Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bluetooth","bmap","bose","cli","headphones","linux","noise-cancellation","python","reverse-engineering","rfcomm"],"created_at":"2026-04-27T17:34:02.942Z","updated_at":"2026-04-27T17:34:05.287Z","avatar_url":"https://github.com/aaronsb.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# bosectl\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![Release](https://img.shields.io/github/v/release/aaronsb/bosectl)](https://github.com/aaronsb/bosectl/releases/latest)\n[![Devices](https://img.shields.io/badge/Devices-2_supported_·_14_known-green)](docs/architecture.md#device-catalog)\n[![Python 3](https://img.shields.io/badge/Python-3-3572A5.svg)](python/)\n[![Rust](https://img.shields.io/badge/Rust-1.70+-DEA584.svg)](rust/)\n[![C++17](https://img.shields.io/badge/C++-17-f34b7d.svg)](cpp/)\n[![Platform: Linux](https://img.shields.io/badge/Platform-Linux-orange.svg)](https://kernel.org)\n\n**Control Bose headphones from Linux — no app, no cloud, no account.**\n\n![bosectl CLI](docs/media/screenshot.png)\n\nLibraries in Python, Rust, and C++ implementing the Bose BMAP protocol\nover Bluetooth RFCOMM. Full control over noise cancellation, EQ, spatial\naudio, button mapping, profiles, and device settings through a direct\nconnection to the headphones.\n\n\u003e **This is not an exploit.** We use the BMAP protocol's standard SETGET\n\u003e operator, which the headphones accept without authentication. No keys\n\u003e are extracted, no encryption is broken, no traffic is replayed.\n\n## Supported Devices\n\n| Device | NC Control | EQ | Spatial | Profiles | Buttons | Status |\n|--------|-----------|-----|---------|----------|---------|--------|\n| **QC Ultra Headphones 2** | CNC 0-10 slider | 3-band | room/head | 7 custom slots | Shortcut remap | Verified |\n| **QuietComfort 35 / 35 II** | ANR off/high/wind/low | — | — | — | Action remap (VPA/ANC) | Verified |\n\n### Device Roadmap\n\nThe library includes a [device catalog](docs/architecture.md#device-catalog)\nof all known BMAP-capable Bose products. These are recognized by Bluetooth\nproduct ID but don't have tested configurations yet — contributions welcome:\n\n| Device | Codename | Category | PID |\n|--------|----------|----------|-----|\n| Noise Cancelling Headphones 700 | goodyear | Headphones | `0x4024` |\n| QuietComfort 45 | duran | Headphones | `0x4039` |\n| QuietComfort Headphones | prince | Headphones | `0x4075` |\n| QuietComfort Ultra Headphones | lonestarr | Headphones | `0x4066` |\n| QuietComfort Earbuds II | smalls | Earbuds | `0x4064` |\n| QuietComfort Ultra Earbuds | scotty | Earbuds | `0x4072` |\n| Ultra Open Earbuds | serena | Earbuds | `0x4068` |\n| SoundLink Flex | phelps | Speaker | `0xBC59` |\n| SoundLink Flex 2 | mathers | Speaker | `0xBC61` |\n\nAdding a new device is a configuration entry — no library code changes needed.\nSee [Adding a New Device](docs/architecture.md#adding-a-new-device).\n\n## Quick Start\n\n### Library Usage\n\n```python\nimport pybmap\n\nwith pybmap.connect() as dev:\n    print(dev.battery())            # 80\n    print(dev.name())               # \"Obsidian Countess\"\n    dev.set_anr(\"high\")             # QC35: full noise cancellation\n    dev.set_cnc(8)                  # QC Ultra 2: CNC level 0-10\n    dev.set_eq(3, 0, -2)            # Bass +3, mid flat, treble -2\n    dev.set_buttons(0x10, 4, 2)     # Remap Action button to ANC\n```\n\n```rust\nuse bmap::connect;\n\nlet dev = connect(None, None)?;\nprintln!(\"{}%\", dev.battery()?);    // 80\ndev.set_anr(\"high\")?;              // QC35\ndev.set_cnc(8)?;                   // QC Ultra 2\n```\n\n```cpp\n#include \"bmap.h\"\n\nauto dev = bmap::connect();\nstd::cout \u003c\u003c (int)dev-\u003ebattery() \u003c\u003c \"%\\n\";\ndev-\u003eset_anr(\"high\");              // QC35\ndev-\u003eset_cnc(8);                   // QC Ultra 2\n```\n\n### CLI Usage\n\n```bash\n# Auto-detects paired Bose device\nbosectl status              # Show model, battery, mode, settings\nbosectl cnc 7               # Noise cancellation level (QC Ultra 2)\nbosectl anr high            # Noise cancellation mode (QC35)\nbosectl eq 3 0 -2           # EQ: bass/mid/treble\nbosectl buttons set ANC     # Remap programmable button\nbosectl quiet               # Switch to Quiet mode\n```\n\n### Device Catalog API\n\n```python\nimport pybmap\n\n# Look up any known Bose device by product ID\ndev = pybmap.lookup_device(0x4082)\nprint(dev.name)       # \"QuietComfort Ultra Headphones (2nd Gen)\"\nprint(dev.codename)   # \"wolverine\"\n\n# USB/Bluetooth identification\npybmap.usb_ids(0x4082)    # (0x05A7, 0x4082)\npybmap.modalias(0x4082)   # \"bluetooth:v05A7p4082d0000\"\n\n# Check support status\npybmap.is_supported(0x4082)  # True — has tested config\npybmap.is_supported(0x4039)  # False — QC45, recognized but untested\npybmap.supported_devices()   # [wolfcastle, baywolf, edith, wolverine]\npybmap.known_devices()       # full catalog\n```\n\n## Installation\n\n### Prerequisites\n\n- **Linux** with BlueZ (standard Bluetooth stack)\n- **Bluetooth** adapter (built-in or USB)\n- **Bose headphones** paired via `bluetoothctl`\n\n### From Release Binaries\n\n```bash\n# Download from GitHub releases\ncurl -LO https://github.com/aaronsb/bosectl/releases/latest/download/bmapctl-rust-linux-x86_64\ncurl -LO https://github.com/aaronsb/bosectl/releases/latest/download/SHA256SUMS\nsha256sum -c SHA256SUMS\nchmod +x bmapctl-rust-linux-x86_64\nsudo cp bmapctl-rust-linux-x86_64 /usr/local/bin/bmapctl\n```\n\n### From Source\n\n```bash\ngit clone https://github.com/aaronsb/bosectl.git\ncd bosectl\nmake test          # Run all tests (Python + Rust + C++)\nmake artifacts     # Build release binaries + SHA256SUMS\n```\n\nSee `make help` for all targets.\n\n### Pairing\n\nIf your headphones aren't already paired:\n\n```bash\nbluetoothctl\n\u003e scan on\n\u003e pair XX:XX:XX:XX:XX:XX\n\u003e trust XX:XX:XX:XX:XX:XX\n\u003e connect XX:XX:XX:XX:XX:XX\n\u003e exit\n```\n\n`bosectl` auto-detects paired Bose devices by their BMAP service UUID —\nno MAC address configuration needed, even with renamed headphones.\n\n## Architecture\n\nThree libraries sharing the same layered design:\n\n```\nApplication → BmapConnection → Device Config → Transport → Protocol → Bluetooth RFCOMM\n```\n\n- **Protocol** — binary BMAP packet codec\n- **Transport** — RFCOMM socket with drain mode for async responses\n- **Device Config** — data-only description of each headphone model (addresses, parsers, quirks)\n- **BmapConnection** — typed API that dispatches to the right address/parser per device\n- **Catalog** — all known Bose BMAP devices with product IDs, codenames, and USB identifiers\n\nDevice differences (RFCOMM channel, init packets, feature availability) are\nexpressed as config data, not code branches. Adding a new device is a\nconfig entry pointing to existing parsers.\n\nFull documentation: **[docs/architecture.md](docs/architecture.md)**\n\n## How It Works\n\nBose headphones speak **BMAP** (Bose Messaging and Protocol) over\nBluetooth RFCOMM. The protocol is organized into function blocks\n(groups of features) and operators (read, write, action).\n\nThe key insight: while Bose gates SET (operator 0) behind cloud-mediated\nECDH authentication, **SETGET** (operator 2) and **START** (operator 5)\nare unauthenticated on the Settings and AudioModes blocks. This gives\nfull control over every user-facing setting.\n\nFull protocol reference: **[NOTES.md](NOTES.md)**\n\n### How We Found This\n\n1. Connected over RFCOMM, probed all channels — channel 2 (QC Ultra 2) and 8 (QC35) responded with BMAP\n2. Captured Bluetooth HCI traffic while toggling settings in the Bose app\n3. DNS-hijacked the cloud API and noticed mode switching still worked — the app uses START, not SET\n4. Systematically tested every operator on every function block to map the auth boundary\n\n## Project Structure\n\n```\n├── python/pybmap/       # Python library + bosectl CLI\n├── rust/src/            # Rust library + bmapctl CLI\n├── cpp/src/             # C++ library + bmapctl CLI\n├── docs/                # Architecture guide, device docs\n├── NOTES.md             # Protocol reverse engineering notes\n├── Makefile             # Build, test, release across all languages\n└── fixtures/            # Captured protocol data\n```\n\n## Building \u0026 Releasing\n\n```bash\nmake test                       # All tests (119 Python, 59 Rust, 51 C++)\nmake artifacts                  # Build + strip + SHA256SUMS in dist/\nmake release VERSION=v0.2.0     # Test → build → gh release create\nmake clean                      # Remove all build artifacts\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faaronsb%2Fbosectl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faaronsb%2Fbosectl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faaronsb%2Fbosectl/lists"}