Summary
docs/AAP Definitions.md documents two notification-request packets and says of the first:
04 00 04 00 0F 00 FF FF FE FF
This packet also works.
On AirPods Pro 2 (Lightning), model A2698, firmware 81.2675000075000000.6877 it does not — it produces no battery notifications at all, while the FF FF FF FF variant produces them in under a second.
The doc is headed "As per AirPods Pro 2 (USB-C) Firmware 7A305", so this is most likely a model/firmware difference rather than a plain error. But as written the claim is unqualified, and following it leads you to conclude that battery reporting is broken on your firmware rather than that you sent the wrong subscribe packet.
Measurement
Same device, same session, same handshake (00 00 04 00 01 00 02 00 00 00 00 00 00 00 00 00) and same 4D set-features packet. Only the last two bytes of the notification request differ.
| Notification request |
Battery packets |
Other notifications |
04 00 04 00 0F 00 FF FF FE FF |
0 in 70 s |
11 ear-detection events |
04 00 04 00 0F 00 FF FF FF FF |
first at 0.94 s, then unprompted |
yes |
The eleven ear-detection events on the FE run are the important control: the L2CAP link was up and the device was actively notifying, so this is not a dead socket or a failed handshake. It subscribes to something, just not to battery.
Reproduced across several runs with a minimal stdlib-Python L2CAP client (no library involved), so it is not an artifact of the daemon.
Suggested change
Qualify the line, e.g.:
This packet also works on AirPods Pro 2 (USB-C) firmware 7A305, but does not deliver battery notifications on all models — AirPods Pro 2 (A2698, firmware 81.2675…6877) returns none. Prefer 04 00 04 00 0F 00 FF FF FF FF.
Happy to open a PR if that wording is close to what you'd want.
Environment
- AirPods Pro 2, model A2698, firmware
81.2675000075000000.6877
- Arch Linux, BlueZ 5.87, kernel 7.1.9
- Direct L2CAP on PSM
0x1001, Python stdlib AF_BLUETOOTH/SOCK_SEQPACKET
Thanks for the doc — reverse-engineering from it was otherwise completely straightforward, and everything else in it matched what I saw on the wire byte for byte.
Summary
docs/AAP Definitions.mddocuments two notification-request packets and says of the first:On AirPods Pro 2 (Lightning), model A2698, firmware
81.2675000075000000.6877it does not — it produces no battery notifications at all, while theFF FF FF FFvariant produces them in under a second.The doc is headed "As per AirPods Pro 2 (USB-C) Firmware 7A305", so this is most likely a model/firmware difference rather than a plain error. But as written the claim is unqualified, and following it leads you to conclude that battery reporting is broken on your firmware rather than that you sent the wrong subscribe packet.
Measurement
Same device, same session, same handshake (
00 00 04 00 01 00 02 00 00 00 00 00 00 00 00 00) and same4Dset-features packet. Only the last two bytes of the notification request differ.04 00 04 00 0F 00 FF FF FE FF04 00 04 00 0F 00 FF FF FF FFThe eleven ear-detection events on the
FErun are the important control: the L2CAP link was up and the device was actively notifying, so this is not a dead socket or a failed handshake. It subscribes to something, just not to battery.Reproduced across several runs with a minimal stdlib-Python L2CAP client (no library involved), so it is not an artifact of the daemon.
Suggested change
Qualify the line, e.g.:
Happy to open a PR if that wording is close to what you'd want.
Environment
81.2675000075000000.68770x1001, Python stdlibAF_BLUETOOTH/SOCK_SEQPACKETThanks for the doc — reverse-engineering from it was otherwise completely straightforward, and everything else in it matched what I saw on the wire byte for byte.