Repository navigation
android: fix AirPods AACP on Qualcomm (qti) Bluetooth stacks - #872
Open
jevonlipsey wants to merge 1 commit into
Open
jevonlipsey wants to merge 1 commit into
jevonlipsey wants to merge 1 commit into
Conversation
l2c_fcr_chk_chan_modes() zeroes ccb->ertm_info.allowed_modes before returning, and l2c_fcr_adj_our_req_options() reads that field directly instead of our return value, so forcing the return to 1 is not enough on libbluetooth_qti.so. The channel is torn down before config and the AACP socket never opens. Re-permit Basic mode in the ccb when the original rejected every mode. The field offset is derived at runtime from the LDRB that produces the function's return value, so no per-build constant is needed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes AirPods AACP on Qualcomm's
libbluetooth_qti.soBluetooth stack, which is currently unsupported (#309, #385).Tested on a Retroid Pocket Nova (SM8550
kalama, Android 13, buildRPN_V1.0.0.436), Magisk 30.7 + NeoZygisk 2.4 + Vector 2.2.Root cause
libbluetooth_qti.sois a fork of an older Fluoride. In it,l2c_fcr_chk_chan_modes()does two things:ccb->ertm_info.allowed_modesagainst what the peer supports, clearing the ERTM and Streaming bits, andAirPods speak AACP (PSM
0x1001) in Basic mode only. Stripping ERTM leavesallowed_modes == 0, it logsL2CAP - Peer does not support our desired channel types, and returns 0.The reason the existing hook doesn't help is that the caller,
l2c_fcr_adj_our_req_options(), re-reads theallowed_modesfield directly rather than using the return value:So by the time we return 1, the struct field is already zeroed and the channel is torn down before any config exchange. The socket then fails with
read failed, socket might closed or timeout, read ret: -1.The fix
When the original rejected every mode, re-permit Basic in the ccb. Channels that negotiate ERTM normally never reach this branch, so other devices are unaffected.
The field offset is derived at runtime rather than hardcoded: since the function returns
ccb->ertm_info.allowed_modes, theLDRBthat produces its return value encodes the offset. On the build above this recovers0x109. If derivation fails the value stays-1and the hook behaves exactly as it does today.Evidence
Before:
After:
Peer does not support our desired channel typesgoes from 62 occurrences to 0. Working in the app: per-earbud battery, listening modes, Automatic Ear Detection, head gestures, conversation awareness, and handoff between a Mac, an iPhone and the Android device.Testing status — please read
I want to be precise about what has and hasn't been verified:
libbluetooth_qti.soto forceallowed_modes = BASICon exactly this path and shipping it as a Magisk overlay. AACP then worked end to end; reverting broke it again. This PR performs the same write from the hook instead.libbluetooth_qti.so, compiled and run as C: it returns0x109, matching the value confirmed on-device.-Wall -Wextra), but it needs a real build before merging.Alternative I tried and rejected
I first assumed the cause was the static
tL2CAP_ERTM_INFOthe socket layer passes (allowed_modes = 0x08, ERTM with no Basic) and planned to hookBTA_JvL2capConnectto substitute it. I tested that and it does not work — patching that constant to0x09changed nothing, still 62×orig = 0.btsock_l2cap_listen_or_connecthas a second path that passesertm_info = NULL, which is evidently the one the AACP socket takes. Recording it here so nobody else burns time on it.Happy to iterate, and I can test revisions on the same hardware.