docs: add publish plan and decision log
PLAN.md: 5-phase plan to publish as a multi-protocol headset tool (rename away from Corsair trademark, abstract device layer, port additional protocols, publish, upstream to HeadsetControl). DECISIONS.md: rationale for GPLv3 relicense, naming constraints, and the multi-protocol architecture.
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
# Plan: Publish as Multi-Protocol Headset Tool
|
||||
|
||||
## Status: DRAFT — awaiting review
|
||||
|
||||
## Goal
|
||||
|
||||
Publish `corsairctl` as an open-source, multi-headset CLI tool under GPLv3.
|
||||
Rename away from "Corsair" trademark. Support additional headset protocols
|
||||
using HeadsetControl (C, GPLv3) as reference.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Rename & License (no functional changes)
|
||||
|
||||
1. **Pick a new name** — candidates:
|
||||
- `headsetctl` (clear, follows Linux conventions: `brightnessctl`, `bluetoothctl`)
|
||||
- `hsetctl` (shorter, less likely to collide)
|
||||
- `openheadset` (explicit open-source angle)
|
||||
- Decision needed before anything else — name affects crate name, binary, repo, docs
|
||||
|
||||
2. **License file** — ✅ Done (GPLv3 LICENSE + Cargo.toml updated)
|
||||
|
||||
3. **Rename crate & binary** — update `Cargo.toml` name, all references in code,
|
||||
CLAUDE.md, README, udev rules, Waybar wrapper, PKGBUILD
|
||||
|
||||
4. **Add SPDX headers** — GPLv3 requires license notice in each source file
|
||||
|
||||
5. **Clean up repo** — there's a nested `src/corsairctl/` directory that looks like
|
||||
an old copy of the entire repo (has its own `.git/`, `Cargo.toml`, `CLAUDE.md`).
|
||||
Investigate and remove if it's dead weight.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Abstract device layer (architecture)
|
||||
|
||||
Current state: `BragiDevice` directly uses `hidapi` and the Bragi protocol.
|
||||
Everything is Corsair-specific (VID, PIDs, handshake).
|
||||
|
||||
Target state: a trait-based backend system so multiple protocols can coexist.
|
||||
|
||||
```
|
||||
src/
|
||||
├── backend/
|
||||
│ ├── mod.rs // Headset trait + DeviceInfo struct
|
||||
│ ├── bragi.rs // Corsair Bragi (current code, extracted)
|
||||
│ ├── steelseries.rs // future
|
||||
│ └── logitech.rs // future
|
||||
├── hid.rs // generic HID helpers (send/recv/flush)
|
||||
├── cli.rs
|
||||
├── output.rs
|
||||
├── error.rs
|
||||
└── main.rs
|
||||
```
|
||||
|
||||
### The `Headset` trait
|
||||
|
||||
```rust
|
||||
pub trait Headset {
|
||||
fn name(&self) -> &str;
|
||||
fn battery_level(&self) -> Result<f32>;
|
||||
fn battery_status(&self) -> Result<BatteryStatus>;
|
||||
fn brightness(&self) -> Option<Result<u16>>; // not all headsets have LEDs
|
||||
fn set_brightness(&self, value: u16) -> Option<Result<()>>;
|
||||
fn sidetone(&self) -> Option<Result<u8>>; // not all have sidetone
|
||||
fn set_sidetone(&self, value: u8) -> Option<Result<()>>;
|
||||
fn info(&self) -> Result<DeviceInfo>;
|
||||
}
|
||||
```
|
||||
|
||||
### Auto-detection
|
||||
|
||||
Scan HID devices, try each backend's `probe()` function:
|
||||
|
||||
```rust
|
||||
pub fn detect() -> Result<Box<dyn Headset>> {
|
||||
// Try Bragi first (checks Corsair VID + known PIDs)
|
||||
// Then SteelSeries, Logitech, etc.
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Port first additional protocol
|
||||
|
||||
Pick the easiest one from HeadsetControl as proof of concept.
|
||||
Good candidates (simple protocol, popular hardware):
|
||||
|
||||
- **SteelSeries Arctis Nova 7** — straightforward HID, well-documented in HeadsetControl
|
||||
- **Logitech G PRO X** — also relatively simple
|
||||
|
||||
Steps per protocol:
|
||||
1. Study HeadsetControl's C implementation
|
||||
2. Implement as a Rust module behind the `Headset` trait
|
||||
3. Add VID/PID to auto-detection
|
||||
4. Update udev rules generator
|
||||
5. Test (needs hardware or community testers)
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Publish
|
||||
|
||||
1. **GitHub repo** — rename or create new repo
|
||||
2. **README** — features, supported devices, install instructions
|
||||
3. **crates.io** — publish crate
|
||||
4. **AUR package** — update PKGBUILD
|
||||
5. **HeadsetControl community** — announce, invite testers for untested protocols
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Upstream contribution to HeadsetControl
|
||||
|
||||
Contribute Bragi protocol support back to [Sapd/HeadsetControl](https://github.com/Sapd/HeadsetControl).
|
||||
|
||||
### Why this is feasible
|
||||
|
||||
HeadsetControl already has `corsair_void_v2w.hpp` which uses a near-identical
|
||||
protocol pattern to Bragi: multi-step handshake (firmware query → software mode
|
||||
→ heartbeat), receiver + headset endpoints, HID buffer flushing with 5ms timeout,
|
||||
sidetone 0-1000 range. The `CorsairDevice` base class provides shared helpers
|
||||
for sidetone mapping, battery parsing, and LED control.
|
||||
|
||||
### What a `corsair_bragi.hpp` would contain
|
||||
|
||||
- New class inheriting from `CorsairDevice`
|
||||
- Bragi-specific PIDs: `0x0A6B` (HS80), potentially HS65, Virtuoso SE
|
||||
- Our Bragi property ID set (from `properties.rs`)
|
||||
- LED brightness support (0-1000, not in existing Corsair implementations)
|
||||
- Init handshake adapted to Bragi's two-phase sequence (receiver → headset)
|
||||
|
||||
### Steps
|
||||
|
||||
1. Study `corsair_device.hpp` and `corsair_void_v2w.hpp` in detail
|
||||
2. Write `corsair_bragi.hpp` in C++20, following their patterns
|
||||
3. Test with our HS80 hardware
|
||||
4. Open PR with protocol documentation (`docs/bragi-protocol.md`)
|
||||
5. List all known Bragi PIDs we can find (community input helps here)
|
||||
|
||||
### Alternative: documentation-only contribution
|
||||
|
||||
If writing C++ is too much effort, contribute just the protocol documentation
|
||||
as a PR. HeadsetControl's community can implement it from there. We already
|
||||
have `docs/bragi-protocol.md` which covers the full protocol.
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
- [ ] Final name?
|
||||
- [ ] Should sidetone stay ALSA-based or also go through HID where supported?
|
||||
- [ ] Minimum supported Rust version (MSRV)?
|
||||
- [ ] Do we want a config file for per-device settings?
|
||||
- [ ] The nested `src/corsairctl/` directory — is this an old copy or something active?
|
||||
Reference in New Issue
Block a user