Hi all, Following the discussion on PR #20686 [1] and the thread "PR #20686 ― Introducing a Zephyr-based Bluetooth host stack under net/bt" [2], I would like to propose an alternative integration model for a full-featured (BLE + BR/EDR Classic) Bluetooth host on NuttX, and ask for the community's opinion before we start sending patches.
First, thanks to Archer (anchao) for pushing this topic forward. Everyone in the thread seems to agree that NuttX needs a more complete Bluetooth host. The open question is where it should live and how it should be maintained. This proposal only covers that question. ------------------------------------------------------------------------------ 1. Summary ------------------------------------------------------------------------------ - Integrate the Zephyr Bluetooth host as a userspace library in nuttx-apps, under wireless/bluetooth/, the same way NimBLE is integrated today [3]. - The stack source lives in a standalone repository and is fetched at a pinned revision at build time. Zephyr's subsys/bluetooth is kept unmodified; all NuttX adaptation goes into a separate, small port layer. - At the start, the NuttX kernel only provides the HCI transport (the existing drivers/wireless/bluetooth bt_driver_s drivers, exposed to userspace through the H4 character device or the HCI user-channel socket). If the community prefers a BlueZ/Linux-style split, the L2/L3 layers can be moved into the kernel step by step from this base (see §5). - The stack is an optional choice selected by Kconfig, next to the native wireless/bluetooth stack and NimBLE. It does not replace them, and it is not presented as the default NuttX Bluetooth stack. - Fixes go to upstream Zephyr first and come back to NuttX through regular rebases. If the community agrees with this direction, we will upstream our existing, production-proven stack step by step (stack integration first, then tests, then the optional Bluetooth service layer). ------------------------------------------------------------------------------ 2. What we already have ------------------------------------------------------------------------------ The openvela team at Xiaomi has run a Zephyr-based Bluetooth host on NuttX/openvela in production for some time: - Baseline: Zephyr v4.0 (upstream commit 2efc8598e39, 2024-11), plus later upstream fixes and our own work. - Features: LE GAP/GATT/ATT/SMP, and BR/EDR Classic with A2DP (SRC/SNK), AVRCP (CT/TG), HFP (AG/HF), SPP/RFCOMM, SDP, HID Device/Host and GATT over BR/EDR. LE Audio and Mesh come from upstream. - Products: shipping in smart speakers (since 2025), smart panels, and wearables (watches and bands). - Qualification: Bluetooth SIG qualification against Core 6.2 (Declaration ID Q386483). - Qualification testing: the stack plugs directly into AutoPTS through the Zephyr BTP tester. A full dual-mode qualification test run takes about 2 person-days. - Simulation: conformance tests can run in simulation on BSWorld or a software RF controller, without real hardware or phones. This is key to keeping the stack's quality up as it evolves. - Performance: the host runs in userspace in a flat build and reaches about 210 kB/s SPP throughput on a wearable SoC. Running outside the kernel has not been a bottleneck for us. - Upstream work: our team is one of the major contributors to Classic Bluetooth in the Zephyr community. - Public code: https://github.com/open-vela/external_zblue (stack) and https://github.com/open-vela/frameworks_bluetooth (service layer). These repositories contain our 2025 changes. The 2026 changes are still in our internal tree and will be released and upstreamed. ------------------------------------------------------------------------------ 3. Points raised in the PR #20686 discussion ------------------------------------------------------------------------------ My reading of the review comments and the mailing-list thread: a) Profiles, shell commands and other application-level code do not belong in kernel space (Xiang Xiao, raiden00pl). b) A monolithic third-party host stack should live in nuttx-apps or a separate git, integrated by download like NimBLE (Xiang Xiao). c) A stack of this size is a large attack surface. Keeping it out of the kernel protects at least protected and kernel builds (Alan Carvalho de Assis, casaroli). d) It should be one selectable option, not the implicit "official" NuttX Bluetooth stack (Alan Carvalho de Assis). e) Tests are required, e.g. sim-based or BSWorld (LingaoM, cederom). f) Copyright and license headers of the imported code must be handled correctly (jerpelea, acassis, Xiang Xiao). g) Unfinished work should not land on master (raiden00pl, Xiang Xiao). The proposal below tries to meet all of these. ------------------------------------------------------------------------------ 4. Proposed architecture ------------------------------------------------------------------------------ +----------------------------------------------------------+ | Applications / btshell / (optional) Bluetooth service | userspace +----------------------------------------------------------+ | Zephyr Bluetooth host (unmodified subsys/bluetooth) | userspace | GAP/GATT/SMP/L2CAP/RFCOMM/SDP/A2DP/AVRCP/HFP/HID/... | (nuttx-apps) +----------------------------------------------------------+ | Port layer: k_thread/k_sem/k_work/k_timer, net_buf, | userspace | settings backend, logging, iterable sections, HCI glue | +=========================== HCI =========================+ | HCI transport: /dev/ttyHCIx (H4) or HCI user channel | kernel | bt_uart / bt_rpmsghci / bt_slip / sim HCI socket ... | (existing) +----------------------------------------------------------+ | Controller | +----------------------------------------------------------+ Design rules: 1. Upstream code stays unmodified. Zephyr's subsys/bluetooth is not reformatted or edited in place. Like NimBLE, it is third-party code and not subject to nxstyle. Any change the stack needs is sent to Zephyr first. (If parts are later moved into the kernel as described in §5, those parts are maintained in NuttX; the rest keeps this rule.) 2. NuttX adaptation stays in the port layer. Zephyr kernel APIs are implemented on top of NuttX. Upstream Bluetooth code keeps calling the Zephyr API, so upstream patches still apply. 3. The initial kernel/user boundary is HCI. The only kernel component is the HCI transport, which NuttX already has. The host stack uses public interfaces only (open/read/write/poll or the HCI socket). 4. Kconfig is namespaced. One top-level option (e.g. CONFIG_ZBLUE, like CONFIG_NIMBLE) selects the stack. The Zephyr CONFIG_BT_* feature options live under it inside nuttx-apps. If a kernel-side stack also uses CONFIG_BT_*, the two must be made mutually exclusive or renamed; we are happy to work this out with Archer. 5. Build modes: flat build first. Because only public interfaces are used, we plan protected and kernel build support as a follow-up phase (see §7). Why we start with the split at HCI: The Zephyr host is not layered like Linux. L2CAP is tightly coupled with conn.c, ATT, SMP and the buffer and work-queue model. Splitting at HCI keeps the upstream code untouched and gives NuttX a complete, working stack from day one. It is the same model Android uses (a userspace host on top of an HCI transport) and the model NimBLE already uses on NuttX. Moving L2CAP and below into the kernel (the BlueZ model) is possible, but it means restructuring those layers, so we propose it as a separate, step-by-step path (§5). ------------------------------------------------------------------------------ 5. Optional path to a BlueZ/Linux-style split ------------------------------------------------------------------------------ Some community members prefer the Linux/BlueZ layering, where the lower protocol layers (HCI core, connection management, L2CAP, and possibly SMP) live in the kernel and are exposed through AF_BLUETOOTH sockets, while profiles, services and tools stay in userspace. This proposal is compatible with that goal, and our stack can serve as the base for it. The difference from PR #20686 is the direction of migration: - PR #20686 puts the whole host into the kernel first and plans to move parts back to userspace later. - We start with a complete, product-proven host in userspace, and move the L2/L3 layers into the kernel step by step, only where the community agrees. Every intermediate state is a working stack, every step can be reviewed and tested on its own, and the code that has not moved yet keeps tracking upstream Zephyr. Possible steps, each a separate patch series: 1. Define the kernel/user interface first: AF_BLUETOOTH sockets for L2CAP (BTPROTO_L2CAP, struct sockaddr_l2), building on the existing NuttX definitions in include/netpacket/bluetooth.h, plus an HCI management interface. 2. Move the HCI core and connection management into the kernel, next to the existing HCI drivers. 3. Move L2CAP (LE and BR/EDR) into the kernel behind the socket interface. 4. Decide case by case for SMP, ATT/GATT and RFCOMM, based on review and measurements. What stays in nuttx-apps in all cases: profiles (A2DP, AVRCP, HFP, HID, ...), GATT services, the Bluetooth service layer, shell and tools. Trade-off: code moved into the kernel will diverge from upstream Zephyr and must be maintained in NuttX. Moving it layer by layer, and keeping the Zephyr API at the boundary where possible, limits that cost and lets the community decide how far to go. ------------------------------------------------------------------------------ 6. Comparison with PR #20686 ------------------------------------------------------------------------------ PR #20686 (current) This proposal Location nuttx (net/bt, now libs/) nuttx-apps + external repo Upstream code reformatted, Zephyr APIs unmodified; port layer only replaced in place Zephyr sync close to a re-port per rebase onto new Zephyr release (author describes releases it as a fork) Security fixes backported by hand picked from upstream Kernel attack surface whole host in kernel HCI transport only Shell / profiles inside kernel tree userspace Build modes flat only flat first, then protected/kernel License headers need rewriting in tree upstream files keep their headers, not in nuttx.git Evolution path whole host in kernel first, working host in userspace then move parts out first, then move L2/L3 into kernel if agreed Notes: - Sync cost: the PR reformats the code to nxstyle and replaces Zephyr kernel APIs inside protocol files. A whitespace-insensitive diff against Zephyr v4.5.0-rc1 still differs in roughly 19% of lines, so upstream patches no longer apply directly. Archer also wrote on the PR that he does not expect to keep synchronizing with Zephyr ("more like forking"). For a code base this size, with a steady stream of upstream CVE fixes (Alan listed more than 70 since 2019), we think staying close to upstream is the main long-term value. - Performance: as Xiang pointed out, in a flat build a userspace stack has the same direct-call cost as an in-kernel one. The remaining per-packet overhead is the HCI transport (VFS + one copy). Our static estimate on a wearable SoC is a few KB of RAM and negligible CPU. Very constrained parts (for example the 80 MHz M0 / 64 KB case Archer described) can get an optional flat-build-only direct HCI binding later, without moving the host into the kernel. ------------------------------------------------------------------------------ 7. Plan ------------------------------------------------------------------------------ Phase 0 �C Consensus (this thread) Agree on location, naming, Kconfig namespace and coexistence with PR #20686. Phase 1 �C Stack integration (nuttx-apps) - wireless/bluetooth/zblue: Makefile/CMake download at a pinned ref, Kconfig, port layer. - Uses the existing HCI transports; no kernel changes expected (only small, separate fixes if any). - btshell as an NSH builtin (the Zephyr shell, Classic and LE commands). - sim configuration with a host HCI dongle, built in CI. Phase 2 �C Tests - sim-based tests for LE and Classic in CI (BSWorld integration). - AutoPTS support through the Zephyr BTP tester. - Samples: LE peripheral/central, A2DP sink, HFP HF, SPP. Phase 3 �C Protected / kernel build - Port layer audited to use only public NuttX/POSIX interfaces. - Validated on a protected and a kernel build target. Phase 4 �C Bluetooth service layer (optional) - Upstream the openvela Bluetooth service ("btservice"): a stable C API for applications, multi-client IPC, and a stack abstraction layer, so applications do not depend on the host stack API. Phase 5 �C Boards - Board configurations with real controllers (UART / RPMsg HCI). Phase 6 �C L2/L3 migration to the kernel (optional, if agreed) - Follow the steps in §5, one layer per patch series. Ongoing - Track Zephyr releases and send fixes upstream first. - We will provide maintainers for the integration. The main goal of this mail is to collect feedback on the direction. We will follow up with a detailed effort estimate and schedule for each phase once the direction is agreed. ------------------------------------------------------------------------------ 8. Licensing ------------------------------------------------------------------------------ - Zephyr-derived files stay in the external repository with their original Apache-2.0 headers and SPDX tags. They are not copied into apache/nuttx or apache/nuttx-apps. - New glue code in nuttx-apps uses the standard ASF header and is contributed under ICLA/CCLA. ------------------------------------------------------------------------------ 9. Questions for the community ------------------------------------------------------------------------------ 1. Is a userspace Zephyr-based host in nuttx-apps, fetched from an external repository and kept in sync with Zephyr, acceptable as the integration model? 2. Where should the external repository live (open-vela GitHub organization, or another location the PMC prefers)? 3. How should this coexist with PR #20686? We would rather converge on one Zephyr-based host than ship two. We are glad to work with Archer on a common approach. 4. Any preference on the top-level Kconfig name (CONFIG_ZBLUE or other)? 5. Should the long-term target stay at the HCI split, or move towards the BlueZ/Linux-style split described in §5? Feedback is very welcome. [1] https://github.com/apache/nuttx/pull/20686 [2] https://www.mail-archive.com/[email protected]/msg15328.html [3] https://github.com/apache/nuttx-apps/tree/master/wireless/bluetooth/nimble Best regards, Kai Cheng #/******本邮件及其附件含有小米公司的保密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本邮件! This e-mail and its attachments contain confidential information from XIAOMI, which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction, or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender by phone or email immediately and delete it!******/#
