Skip to content

Restore GAP device name after GATT reset#426

Merged
h2zero merged 1 commit into
h2zero:masterfrom
chmorgan:feature/restore-after-ble-svc-gap-init
Jul 5, 2026
Merged

Restore GAP device name after GATT reset#426
h2zero merged 1 commit into
h2zero:masterfrom
chmorgan:feature/restore-after-ble-svc-gap-init

Conversation

@chmorgan

@chmorgan chmorgan commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

NOTE: Codex 5.5 created this patch and writeup etc but I reviewed it and it looks like what I would have done by hand, and tested it here and it does resolve the issue and explains why I've been seeing my device misnamed for a bit. Not sure how or when I broke it, or if the issue was library side or a nimble change but figured others might be hitting this issue.

ESP-IDF NimBLE can reset the GAP Device Name when the standard GAP service is reinitialized during GATT server startup. NimBLEDevice::init(deviceName) calls NimBLEDevice::setDeviceName(deviceName), but that happens before the server is started. Later, starting advertising starts the server and resets/re-registers the GAP service, causing the C GAP name backing storage to be rebuilt from CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME. In projects where that Kconfig default remains "nimble", the advertised Local Name can be correct while the Generic Access Device Name characteristic reports "nimble".

The failing sequence is:

-> pAdvertising->start()
-> NimBLEAdvertising::start()
-> NimBLEDevice::getServer()->start()
-> NimBLEServer::resetGATT()
-> ble_gatts_reset()
-> ble_svc_gap_init()
-> ESP-IDF NimBLE resets GAP name to CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME
-> "nimble"
-> ble_svc_gatt_init()

Fix this by saving the device name supplied through NimBLEDevice::setDeviceName() and reapplying it immediately after ble_svc_gap_init() in NimBLEServer::resetGATT(). This preserves the C++ wrapper contract that the configured device name remains effective even when the wrapper internally resets the GATT/GAP service tables.

Summary by CodeRabbit

  • Bug Fixes
    • Preserved the Bluetooth device name and appearance when the GATT server is reset, so these settings no longer revert unexpectedly after a reset.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a8e9e6fe-aa41-4a44-a5ef-e49aa901364c

📥 Commits

Reviewing files that changed from the base of the PR and between 4063b55 and 975c084.

📒 Files selected for processing (1)
  • src/NimBLEServer.cpp

📝 Walkthrough

Walkthrough

Arr, this here change makes NimBLEServer::resetGATT() hoist the ship's flag afore scuttlin' the deck: it grabs the current GAP device name and appearance before ble_gatts_reset(), then plants 'em back after ble_gatts_reset() and ble_svc_gap_init() be done, keepin' the treasure from bein' lost overboard.

Changes

GATT Reset GAP Value Preservation

Layer / File(s) Summary
Preserve and restore GAP name/appearance
src/NimBLEServer.cpp
resetGATT() now saves ble_svc_gap_device_name() and ble_svc_gap_device_appearance() (guarded by \!CONFIG_USING_NIMBLE_COMPONENT) before ble_gatts_reset(), and restores them via the corresponding setters after ble_svc_gap_init().

Estimated code review effort: 1 (Trivial) | ~5 minutes

Poem

Yarrr, the name be lost when the deck be swept clean,
So a wee rabbit stashed it where none could be seen! 🐇🏴‍☠️
After the storm o' ble_gatts_reset,
The name and look sail back home, no regrets.
Anchors aweigh, GAP treasure be kept!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Arrr, the title clearly summarizes the main fix: preserving the GAP device name across GATT reset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/NimBLEServer.cpp`:
- Around line 894-896: The static members NimBLEDevice::m_deviceName and
NimBLEDevice::m_deviceNameSet are accessed without synchronization in the
resetGATT() method, creating a potential race condition if another thread calls
setDeviceName() concurrently. To fix this, add a static mutex member (like
m_deviceNameMutex) to the NimBLEDevice class, then protect all accesses to
m_deviceName and m_deviceNameSet with std::lock_guard in both the
setDeviceName() method and the resetGATT() method. In resetGATT(), acquire the
lock, cache the values of m_deviceNameSet and m_deviceName into local variables,
release the lock, then perform the conditional call to setDeviceName() with the
cached name outside the critical section.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a7ecf420-5f09-4fa4-8875-aea742681393

📥 Commits

Reviewing files that changed from the base of the PR and between 1eddc28 and 4063b55.

📒 Files selected for processing (3)
  • src/NimBLEDevice.cpp
  • src/NimBLEDevice.h
  • src/NimBLEServer.cpp

Comment thread src/NimBLEServer.cpp Outdated
@h2zero

h2zero commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Looks like espressif changed the behavior of this :(
https://github.com/espressif/esp-nimble/blob/685675c0128deafdd201c9eb82e61d227364646c/nimble/host/services/gap/src/ble_svc_gap.c#L597

I think a better solution is to save the values in resetGATT and reapply the name and appearance after reinitializing the gap services.

Personally I don't use espressifs fork anymore for this reason.

Comment thread src/NimBLEServer.cpp
Comment thread src/NimBLEServer.cpp
@h2zero

h2zero commented Jun 24, 2026

Copy link
Copy Markdown
Owner

@finger563

If your confusion was my remark about the espressif fork, I use this instead: https://github.com/h2zero/esp-nimble-component

Updated to mynewt/nimble 1.9, doesn't have much of the espressif changes and is more stable.

@chmorgan

chmorgan commented Jun 24, 2026 via email

Copy link
Copy Markdown
Contributor Author

@h2zero

h2zero commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Sure, we can use this flag: #ifndef CONFIG_USING_NIMBLE_COMPONENT

@finger563

Copy link
Copy Markdown
Contributor

Has that been updated or does it work for esp idf v6?

@h2zero

h2zero commented Jun 25, 2026

Copy link
Copy Markdown
Owner

It's a bit of work in progress still, haven't checked it against IDF v6. The same code is being used in nimble-arduino as well so it will be well tested.

@h2zero

h2zero commented Jun 28, 2026

Copy link
Copy Markdown
Owner

@finger563, updated now, idf 5 and 6 working.

@chmorgan

chmorgan commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Looks like espressif changed the behavior of this :( https://github.com/espressif/esp-nimble/blob/685675c0128deafdd201c9eb82e61d227364646c/nimble/host/services/gap/src/ble_svc_gap.c#L597

I think a better solution is to save the values in resetGATT and reapply the name and appearance after reinitializing the gap services.

Personally I don't use espressifs fork anymore for this reason.

are you using that mynewt version with esp-idf or another platform? I figured there were a ton of porting changes present to support the particular ble devices so it seemed overwhelming to consider going that route.

ESP-IDF NimBLE can reset the GAP Device Name when the standard GAP service is reinitialized during GATT server startup. NimBLEDevice::init(deviceName) calls NimBLEDevice::setDeviceName(deviceName), but that happens before the server is started. Later, starting advertising starts the server and resets/re-registers the GAP service, causing the C GAP name backing storage to be rebuilt from CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME. In projects where that Kconfig default remains "nimble", the advertised Local Name can be correct while the Generic Access Device Name characteristic reports "nimble".

The failing sequence is:

  -> pAdvertising->start()
     -> NimBLEAdvertising::start()
        -> NimBLEDevice::getServer()->start()
           -> NimBLEServer::resetGATT()
              -> ble_gatts_reset()
              -> ble_svc_gap_init()
                 -> ESP-IDF NimBLE resets GAP name to CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME
                 -> "nimble"
              -> ble_svc_gatt_init()

Fix this by saving the device name supplied through NimBLEDevice::setDeviceName() and reapplying it immediately after ble_svc_gap_init() in NimBLEServer::resetGATT(). This preserves the C++ wrapper contract that the configured device name remains effective even when the wrapper internally resets the GATT/GAP service tables.
@chmorgan chmorgan force-pushed the feature/restore-after-ble-svc-gap-init branch from 4063b55 to 975c084 Compare July 3, 2026 02:06
@chmorgan chmorgan requested a review from h2zero July 3, 2026 02:06
@h2zero

h2zero commented Jul 5, 2026

Copy link
Copy Markdown
Owner

It's working with IDF, took a bit of work for sure but no too bad

@h2zero h2zero merged commit 657583a into h2zero:master Jul 5, 2026
66 checks passed
@chmorgan chmorgan deleted the feature/restore-after-ble-svc-gap-init branch July 6, 2026 01:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants