Files
darken bd4d87c06a feat(aap): Add Custom EQ protocol support
Adds decode and encode for AAP opcode 0x63, Apple's iOS 27 "Custom EQ"
(three bands plus a Recommended/Custom mode selector, H2 models).

The wire format comes from librepods commit 7341e41 and has never been
confirmed on hardware, so the decoder validates every field and returns
null on any mismatch -- including a strict payload-length equality, so a
frame carrying trailing unknown bytes is surfaced verbatim in the
unknown-message hex log rather than mis-parsed into plausible values.
Nothing optimistically assumes the write lands: SetCustomEq deliberately
has no optimistic state update and no verification predicate, because an
unacknowledged write must not render as success, and the device is not
known to report this setting at all.

Also recovers two bytes the 0x53 decoder was discarding. Opcode 0x53 is
the Headphone Accommodations configuration -- an iOS Accessibility
feature that the iOS 18.1+ hearing-aid feature reuses -- and payload
bytes 4 and 5 are its "Apply To: Phone / Media" flags. They are plain
0x01 flags, not the Apple-bool 0x01/0x02 encoding used by the 0x09
control settings. They describe scope only and say nothing about whether
a profile exists, so isAllZero stays a pure band-data predicate.

A debug-only card (BuildConfig.DEBUG, mirroring the existing PME chart)
drives the opcode for hardware evaluation. It edits local draft state and
sends exactly one packet per Apply tap; slider-driven sends would flood
the link and make a logcat observation window unreadable. Apply is
disabled while no pod is worn, because AapOutboundController queues
non-exempt commands in that state and the queue collapses repeats,
surfacing them later at an unrelated moment. That guard reads the AAP
EarDetection setting rather than PodDevice's BLE-fallback property, so it
matches the controller's gate in every state -- notably, neither gates
when the AAP setting is absent.

On-device evaluation, both legs negative: AirPods Pro 2 USB-C (A3048,
fw 81.2675000075000000.6814) and AirPods Pro 3 (A3064, fw ...6503)
never advertise 0x63 across settings bursts of 33 and 26 frames, never
echo a write, never persist one across a case-cycle reconnect, and
produce no audible change. Both accept the write at the socket and
discard it. This does not establish that the byte format is wrong -- a
device ignoring an unimplemented opcode is indistinguishable from one
rejecting a malformed frame -- and it is not evidence that privileged
access is required, since neither device advertises the feature at all.
2026-08-21 15:23:32 +02:00
..
2022-09-14 18:00:18 +02:00
2022-09-14 18:00:18 +02:00