docs(aap): Revise PME hypothesis to Personal Medical Equipment

This commit is contained in:
darken
2026-04-24 15:27:18 +02:00
committed by Matthias Urhahn
parent f0531796dd
commit 89e8b83be4
5 changed files with 28 additions and 18 deletions
@@ -403,10 +403,11 @@ fun DeviceSettingsScreen(
}
// PME Config visualization (debug only, opcode 0x53).
// The Wireshark dissector calls this "PME Config"; captures so far are
// all-zero on in-production firmware, so the bar chart stays hidden in
// that case — showing empty bars would imply the device has a flat EQ,
// which we don't actually know.
// PME = Personal Medical Equipment (hearing-aid band gains for iOS
// 18.1+ AirPods Pro 2 hearing-aid mode). The bar chart reuses the
// EQ visualization because the data shape (per-ear × per-profile ×
// band gains) renders identically; hidden on all-zero payloads, which
// just mean the user hasn't configured a hearing-aid profile yet.
val pmeConfig = device.pmeConfig
if (eu.darken.capod.BuildConfig.DEBUG &&
pmeConfig != null &&
@@ -590,7 +590,7 @@ internal class AapSessionEngine(
AapMessageType.UARP_DATA.value, // 0x004F
AapMessageType.UNKNOWN_0X50.value, // 0x0050
AapMessageType.SOURCE_CONTEXT.value, // 0x0052
AapMessageType.SET_BAND_EDGES.value, // 0x0054 (real EQ; distinct from 0x53 PmeConfig which CAPod decodes)
AapMessageType.SET_BAND_EDGES.value, // 0x0054 (neighbouring opcode; distinct from 0x53 PmeConfig/hearing-aid which CAPod decodes)
AapMessageType.UNKNOWN_0X55.value, // 0x0055
AapMessageType.SLEEP_DETECTION_UPDATE.value, // 0x0057
AapMessageType.UNKNOWN_0X58.value, // 0x0058
@@ -90,9 +90,11 @@ enum class AapMessageType(val value: Int, val wiresharkName: String) {
SOURCE_CONTEXT(0x0052, "Source Context"),
/**
* PME (Personal Mixing Engine?) config per Wireshark. CAPod decodes this as
* 4 × 8 Float32 values (see [AapSetting.PmeConfig]). Real EQ likely lives
* at [SET_BAND_EDGES].
* PME = Personal Medical Equipment (cf. PPE = Personal Protective Equipment) —
* hearing-aid configuration for the iOS 18.1+ hearing-aid feature on AirPods
* Pro 2. Decoded as 4 × 8 Float32 values (see [AapSetting.PmeConfig]); see
* that data class for the layout rationale. "PME Config" is the label the
* Wireshark AAP dissector uses for this opcode.
*/
PME_CONFIG(0x0053, "PME Config"),
@@ -164,13 +164,18 @@ sealed class AapSetting {
}
/**
* Payload of message type 0x0053. The Wireshark AAP dissector calls this
* "PME Config" (Personal Mixing Engine). CAPod used to label it as EQ
* bands, but captures so far show this data is all zeros on in-production
* firmware — the real equalizer path is likely 0x0054 "Set Band Edges".
* Payload of message type 0x0053 — "PME Config" in the Wireshark AAP dissector.
* PME = Personal Medical Equipment (cf. PPE = Personal Protective Equipment):
* the hearing-aid configuration for Apple's iOS 18.1+ hearing-aid feature on
* AirPods Pro 2.
*
* The payload is decoded as 4 sets × 8 Float32 values until the true schema
* is confirmed. Callers should treat all-zero [sets] as "no config reported".
* Decoded as 4 × 8 Float32 values — consistent with per-ear × per-profile
* audiogram band gains (e.g. L/R × two environment profiles, 8 frequency
* bands). CAPod previously called this "EQ bands".
*
* Callers should treat all-zero [sets] as "no hearing-aid profile configured"
* — stock firmware reports zeros until the user runs Apple's Hearing Test /
* hearing-aid setup.
*/
data class PmeConfig(
val sets: List<List<Float>>,
@@ -158,10 +158,12 @@ class DefaultAapDeviceProfile(
return AapSetting.AudioSource::class to AapSetting.AudioSource(mac, type)
}
// 0x53 is "PME Config" per the Wireshark AAP dissector. CAPod decodes the
// 4-set × 8-band Float32 payload verbatim; captures so far have all-zero
// payloads so the schema is unconfirmed. Real EQ likely lives on 0x54
// "Set Band Edges" with a different byte layout.
// 0x53 is "PME Config" per the Wireshark AAP dissector — Personal Medical
// Equipment (cf. PPE), i.e. the iOS 18.1+ hearing-aid profile on AirPods
// Pro 2. Decoded verbatim as 4 × 8 Float32 (per-ear × per-profile band
// gains); stock firmware reports all-zero until the user runs Apple's
// Hearing Test. 0x54 "Set Band Edges" is a neighbouring opcode with a
// different payload — not decoded here.
if (message.commandType == AapMessageType.PME_CONFIG.value) {
if (message.payload.size < 6 + 128) return null
val sets = mutableListOf<List<Float>>()