Skip to content

Add Sennheiser MOMENTUM 4 / ACCENTUM GAIA support - #122

Open
ErodeNine wants to merge 4 commits into
silverpoetry:mainfrom
ErodeNine:feat/sennheiser-gaia
Open

ErodeNine wants to merge 4 commits into
silverpoetry:mainfrom
ErodeNine:feat/sennheiser-gaia

Conversation

@ErodeNine

@ErodeNine ErodeNine commented Nov 1, 2026 •

Copy link
Copy Markdown

Summary

新增 Sennheiser MOMENTUM 4 / ACCENTUM 的 Qualcomm GAIA V3 适配,覆盖私有整机电量与噪声模式控制。

  • SennheiserGaiaWireCodec:8 字节大端帧编解码、流式重组与重同步、电量 / 子模式表 / 开关解析。
  • SennheiserEarbudAdapter:家族 Adapter、三个型号配置、两种噪声方言。
    • MOMENTUM 4 用 GAIA 的两个主开关驱动四态(0x1A04 ANC、0x1804 通透,0x1A00 只调子行为),含抗风噪;
    • ACCENTUM 与 ACCENTUM True Wireless 用同一对主开关,三态,不声明抗风噪。
    • 写入按已观测状态做差异计算,每条命令只在真的会改变设备时才发。
    • 写入后乐观发布请求模式,并对过渡期报告启用有界延迟抑制,避免界面闪出未请求的中间态。
  • 私有能力全部延迟开放:初始匹配只选择候选,合法 GAIA 响应到达后才逐项解锁电量与噪声模式。
  • MOMENTUM 4 新增 MiLink 抗风噪卡片;Sennheiser Smart Control 加入控制 App 目录与四个作用域。

RFCOMM 端点由 SDP UUID a2129ff3-081b-4c45-8afe-469d9c4842ec 解析,代码不写死 channel:
MOMENTUM 4 的 channel 14 属于 iAP2,向其发送 GAIA 帧会导致耳机关机。

Scope and impact

影响 integration(Adapter 与注册表)、protocol(WireCodec)、system-module(MiLink 卡片、
作用域声明)三个模块,以及兼容性、控制 App、架构三份文档。

  • This change follows the project scope; detailed configuration remains in vendor control apps

均衡器、手势、固件升级与配对管理均未实现,留在厂商 App 内。

Evidence

协议事实来自实机抓包向量,并额外与四份独立公开实现交叉核对(命令表、四态写入序列、
写入副作用)。四份实现在关键语义上一致:

操作 发送 接收
读电量 FF 03 00 00 04 95 06 03 FF 03 00 01 04 95 07 03 2A
读子模式表 FF 03 00 00 04 95 1A 01 FF 03 00 06 04 95 1B 01 01 02 02 00 03 01
读型号 FF 03 00 00 04 95 12 06 FF 03 00 0D 04 95 13 06 + MMMMBT Black\0
开 ANC FF 03 00 01 04 95 1A 04 01 FF 03 00 01 04 95 1B 04 01 + 通知 1A 85 01

写入序列与四态投影见 docs/sennheiser-gaia-protocol.md 第 6 节。要点:

  • 0x1A00 不是主模式开关,只承载抗风噪 1、舒适 2、自适应降噪 3 三个子选择器;
    单写它无法离开直通态。子模式表里的 mode 2 是 Comfort,不是通透。
  • 主开关是 0x1A04(ANC)与 0x1804(通透)。开 ANC 会结束通透并把等级置 0,所以
    「通透」必须先开 ANC 再开通透。
  • MOMENTUM 4 的「关闭」是单独关 0x1A04:通透形式上仍为 1,但 ANC 关着时不产生效果;
    补写 1804 [00] 会丢弃耳机记忆的通透等级前值。
  • 写 0x1A00 自带「结束通透 + 等级置 0」的副作用,所以抗风噪可以一条写入完成切换,
    而清除残留选择器也只能靠它。

参考实现与许可记录在 THIRD_PARTY_NOTICES.md:Ariazonaa/momentum4-control 与
HellzYeahh/earshot、Picazsoo/android-momentum-4-widget(均为 MIT)用于核对命令编码、写入
序列与实机抓包;无许可证的 Young-Lord/momentum4-control-android 仅用于理解重同步思路,
未复制代码。

Validation

  • testDebugUnitTest
  • :system-module:lintRelease
  • :system-module:assembleRelease
  • Hardware validation, when behavior changes on a physical headset
  • For a maintained device PR: the final maintenance version has received device revalidation;
    keep this PR in Draft and the original PR open until that feedback arrives
  • Logs, screenshots and Bluetooth addresses are redacted
  • Documentation and compatibility status are updated
  • If controller apps changed: catalog, Adapter declarations, scope.list, tests and
    docs/control-apps.md are synchronized

全量单元测试 651 项通过,其中新增 53 项(codec 21、adapter 32)。

实机验证(2026-11-02,MOMENTUM 4):精确匹配、头戴形态、私有通道连接、协议确认、
私有整机电量 50%、四态(降噪 / 关闭 / 通透 / 抗风噪)切换、MiLink 状态接收与卡片能力查询
全部完成。

实机验证过程中修掉两个问题,均已在本 PR 的后续提交中处理:

  1. 首轮发现「关闭」与「通透」听感相同。根因是只写子模式表、从未驱动主开关,两个目标都
    落到「主开关开着但无子选择器激活」的直通态。改用主开关方案后重新验证通过。
  2. 第二轮反馈切换时响两次提示音、四个状态显示混乱。根因是写入序列与当前状态无关,包含
    大量值未变的冗余写入(耳机会为每条被接受的写入各响一次),且过渡期报告直接漏到界面。
    改为差异写入 + 乐观发布 + 有界延迟抑制后重新验证通过。

细节与仍待复核项记录在协议文档第 9 节。

Risks and rollback

  • channel 误用风险:只经 SDP 解析端点,不提供 channel 常量或手动回退,避免向 iAP2 通道发帧。
  • 能力误开放:初始 capabilities 只声明 battery 与 audioHandoff,私有电量源、噪声模式
    和卡片 ID 都由协议证据裁剪;解析失败按未知帧处理,不影响其他已确认能力。
  • 型号误匹配:accentum-tws 排在 accentum 之前,避免 "ACCENTUM True Wireless" 被更宽的
    标记抢先命中;仅命中 GAIA UUID 的未知设备不进入该家族。
  • 差异写入依赖缓存:写入量取决于本地缓存的主开关与选择器状态,缓存过期会导致多发或少发
    一条命令。协议重置会清空全部缓存,空写入退化为一条主写入,不会变成「控制失败」。
  • 抑制窗口有界:过渡期报告最多被推迟三档(150 / 300 / 500 ms),用尽后强制接受设备报告,
    不会出现界面永远不更新的情况。
  • ACCENTUM 未实测:主开关方言按参考协议记录,尚未有对应设备复核;文档已如实标注为
    「参考协议,待实测」。
  • 回滚:删除 SennheiserAdapterRegistry 的注册项即可完全停用,不影响其他品牌。

Implement the Qualcomm GAIA V3 subset needed for MiLink integration:

- SennheiserGaiaWireCodec: 8-byte big-endian framing, streaming reader with
  resynchronisation, battery / combined noise mode / toggle parsing.
- SennheiserEarbudAdapter: family adapter, three model configs and two noise
  dialects. MOMENTUM 4 uses combined modes (0x1A00 / 0x1A01) and offers four
  states including anti-wind; ACCENTUM and ACCENTUM True Wireless use the
  independent 0x1A04 / 0x1804 switch pair and offer three states.
- Private capabilities stay locked until a valid GAIA response arrives.
- MiLink anti-wind card for MOMENTUM 4, plus the Sennheiser Smart Control
  entry in the control app catalog and all four LSPosed scopes.

The RFCOMM endpoint is resolved from the SDP UUID
a2129ff3-081b-4c45-8afe-469d9c4842ec; no channel number is hardcoded because
channel 14 carries iAP2 and a GAIA frame there powers the headset off.

MOMENTUM 4 is hardware-verified on 2026-11-02: exact match, headphone form
factor, private channel, protocol confirmation, private aggregate battery and
all four noise states. ACCENTUM remains reference-protocol pending hardware.

44 new unit tests cover framing, parsing, mode projection, write sequences and
capability gating.
The noise layer only wrote the 0x1A00 sub-mode table and never touched the
ANC master switch (0x1A04), so "off" and "transparency" both landed on
"master switch on, no sub-selector active" -- the headset pass-through
state -- and were indistinguishable to the listener.

0x1A00 is not the master switch: it tunes anti-wind (1), comfort (2) and
adaptive (3) on top of it, and writing it always ends transparent hearing
and resets the level. Drive 0x1A04 / 0x1804 directly instead:

- off  -> 1A04 [00] alone; transparent hearing stays formally on but has
  no effect without ANC, and switching it off would discard the level
- anc  -> 1A04 [01], 1804 [00]
- th   -> 1A04 [01], 1804 [01] (ANC first: switching ANC on ends TH)
- wind -> 1A04 [01], 1804 [00], 1A00 [01 02]

Projection now reads the two switches plus the anti-wind selector, and
the mode table no longer claims selector 2 is transparency -- it is
comfort. Both dialects share the same readback and notification set.

Covered by 24 adapter tests including the previously untested off path.
The first round of hardware testing found two regressions: every mode switch
played two confirmation chimes, and the four states flickered through modes the
user never selected.

The write path built a fixed frame list that ignored the observed state, so each
switch resent frames whose value was already correct. Every accepted write is
answered by the headset with a chime, and every write also pushes its own
notification, which is how the intermediate states leaked into the snapshot.

Writes are now computed as a diff against the observed master switches and the
cached anti-wind selector, so a frame is only sent when it actually changes the
device. The anti-wind selector is cleared when entering ANC, because nothing
else clears it, and the protocol reset now drops the cached selector as well.

Reports that disagree with a pending request are held behind a bounded delay
ladder (150/300/500 ms) instead of being published, while the requested mode is
published optimistically right after the write. Device-initiated reports pass
through untouched.

The state query no longer re-registers notifications on every poll: it re-reads
the three noise commands only.
The changelog described the master-switch rework but not the write
minimisation and the intermediate-report suppression that followed the second
round of hardware testing.
@silverpoetry

Copy link
Copy Markdown
Owner

@ErodeNine 谢谢你把主开关语义、写入副作用和实测过程整理得这么完整。我基于你的提交建立了独立维护版 #125,原始提交和署名都保留了,补了几处需要一起确认的边界:

  1. MOMENTUM 4 关闭时通透开关可能仍记为开;再次开启 ANC 会清除它。因此“关闭 → 通透”需要随后明确再开一次通透,不能因为旧缓存为 true 而跳过。
  2. ACCENTUM 的通透是独立开关。回读 ANC=0、通透=1 应显示通透,原公共投影会先落到关闭。
  3. MOMENTUM 4 收到合法抗风噪选择器后才开放四态;补齐厂商 ID、布尔值及电量载荷检查,非法应答不再确认握手。型号也改为规范化完整名称,其他 ACCENTUM 变体先保留标准能力。

沿用了你的差异写入、有界读回和现有抗风噪卡片扩展,没有加入详细设置页面或固定 RFCOMM 通道。

下载最终官方签名维护包 b1244027(登录 GitHub,下载 ZIP 后解压 APK),CI/构建记录。本地回归、CI 和签名构建均通过。

方便时请用这一版重点确认“关闭后再开通透”、四态互切与实际效果、卡片重开回读、重连,以及 Smart Control 导航和退避恢复。开启模块详细日志,在 LSPosed 关闭「禁用详细日志」、开启「输出日志到守护进程」,复现后从 HyperEars 导出日志即可。若发现差异,也欢迎直接基于维护分支补充。

原版 MOMENTUM 4 的实测记录已保留;ACCENTUM 仍按参考协议标注。本 PR 继续开放,#125 保持 Draft,待最终维护版复核后再合入。

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.

2 participants