Conversation
A controller that supports LE Extended Advertising refuses legacy advertising commands with Command Disallowed once any extended command has been issued (Core Spec Vol 4 Part E 3.1.1). The adapter sent `LE Read Maximum Advertising Data Length` at enable time and then legacy `LE Set Advertising Parameters`, so `start_advertising()` failed with HCI status 0x0C on the ESP32-C6 AirLift (Fruit Jam). On such controllers, use the extended command set for all advertising, with legacy PDUs so the 31-byte limit and 4.x central compatibility are unchanged. Also complete the extended path: send advertising and scan response data, fill in `prim_adv_phy`, `filter_policy` and the peer address type, and disable via the extended enable command. Fixes adafruit#11322 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
`hci_send_acl_pkt()` tagged host-to-controller ACL data with PB flag 0b10 (first automatically flushable). NimBLE controllers such as the ESP32-C6 treat any PB above 0b01 as a bad packet and drop it silently, so every ATT response was lost and peers hung in service discovery. Use 0b00 (first non-flushable), as BlueZ and Zephyr do. The ESP32 BTDM controller accepted either value. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
Diagnosis and code by Claude, with hardware testing by @dhalbert on a Fruit Jam (ESP32-C6 AirLift) and a Metro M4 AirLift Lite (ESP32), both running NINA-FW 3.3.0.
The problem
start_advertising()on the Fruit Jam failed withHCI status error: 0c(Command Disallowed). Thedevices/ble_hciadapter sentLE Read Maximum Advertising Data Lengthat enable time whenever the controller reported the LE Extended Advertising feature. That is an extended advertising command, and per Core Spec Vol 4 Part E §3.1.1 a controller must then refuse every legacy advertising command until the next HCI Reset; NimBLE enforces this inble_ll_is_valid_adv_mode(). The ESP32's BLE 4.2 controller has no extended-advertising feature bit, so it never took that path.With advertising working, connections then hung in service discovery: the controller was dropping every ATT response.
The fixes
LE Set Extended Advertising Parameters / Data / Scan Response Data / Enable. The set uses legacy PDUs (BT_HCI_LE_ADV_PROP_LEGACY), so the 31-byte data limit and visibility to 4.x centrals are unchanged. Legacy commands remain in use on 4.x controllers.prim_adv_phy,filter_policyand the peer address type unset inhci_le_set_extended_advertising_parameters(); these are now filled in, andstop_advertising()uses the extended disable.hci_send_acl_pkt()sent host-to-controller ACL data with packet boundary flag0b10(first automatically flushable). NimBLE controllers discard any host ACL packet with a PB flag above0b01as malformed, silently. Changed to0b00(first non-flushable), which is what BlueZ and Zephyr send; the ESP32 controller accepted either.Testing
Fruit Jam and Metro M4 AirLift Lite,
adafruit_bleUART example (ProvideServicesAdvertisement+UARTService): advertise, connect and echo from Bluefruit Connect on iOS; from Linux,bluetoothctldiscovers all attributes of the UART service on both boards. On the Fruit Jam also checkedstop_advertising(),timeout=expiry, non-connectable and scannable advertisements.Not addressed
anonymous=Truefails withHCI status error: 12on both controllers: the adapter never sets a random address. Pre-existing and separate.check_data_fit();bleio_hciis peripheral-only, so no scanning or central changes were needed.