Scaffold Swift-implemented drop-in replacement for libbluetooth.so.3 - #63
Open
colemancda wants to merge 53 commits into
Open
Scaffold Swift-implemented drop-in replacement for libbluetooth.so.3#63colemancda wants to merge 53 commits into
colemancda wants to merge 53 commits into
Conversation
colemancda
force-pushed
the
feature/c-abi
branch
from
August 1, 2026 16:26
3990938 to
6db3296
Compare
Parses hci_map tables and header #define/enum values directly out of the reference source and emits Swift literal arrays, avoiding manual transcription of the 232-entry command map and 8x9 feature table.
Bus, device flag, packet type, link policy/mode, version, and command name tables used by the HCI string converter family, generated from BlueZ's hci.c via scripts/generate-hci-tables.py.
hci_bustostr, hci_dtypetostr, hci_typetostr, hci_dflagstostr, hci_ptypetostr/hci_strtoptype, hci_scoptypetostr/hci_strtoscoptype, hci_lptostr/hci_strtolp, hci_lmtostr/hci_strtolm, hci_cmdtostr, hci_commandstostr, hci_vertostr/hci_strtover, lmp_vertostr/lmp_strtover, pal_vertostr/pal_strtover, and lmp_featurestostr — 21 symbols total. hci_lmtostr intentionally does not replicate the reference's fixed 50-byte buffer overflow for large link-mode masks, and hci_commandstostr matches the deployed 5.82 library's trailing-space behavior rather than the 5.85 source tree's trimmed output.
Adds the BluetoothLinuxABI product/target (built against CBluetoothLinuxABI and Bluetooth's BluetoothABI product for bt_malloc/bt_free) plus its test target, gated behind SWIFTPM_BLUETOOTH_CABI=1 alongside the rest of the C ABI surface.
Covers bus, device type, device flags, packet type, link mode, command name, and version conversions.
Also includes the 75 SDP symbols implemented in the Bluetooth dependency, so gen_stubs.py stops generating stubs for either family.
Drops the 96 stubs now covered by BluetoothSDP and BluetoothLinuxABI (105 remaining, 123 implemented).
Exercises all 21 symbols with edge-case inputs (unknown bus/device values, empty and saturated bitmasks, malformed parse strings). Links directly against the system libbluetooth.so.3 since all 21 symbols are exported by it.
Builds conformance_hci_strings.c against both the system reference and libBluetoothLinuxABI.so and diffs the output, using the same known-differences.txt convention as the Bluetooth checkout. The phase-1 and SDP drivers stay in the Bluetooth checkout alongside the symbols they cover.
Adds a BluetoothLinuxABI static library target and links it, along with BluetoothSDP, into the final bluetooth3 artifact via --whole-archive. BluetoothSDP was previously implemented but never actually linked into the CMake build.
hci_open_dev, hci_close_dev, hci_devinfo, hci_devba, hci_devid, hci_for_each_dev, hci_get_route, hci_send_cmd, and hci_send_req — the raw AF_BLUETOOTH/BTPROTO_HCI socket layer that the rest of the HCI command wrappers build on. These call socket/bind/ioctl/writev/poll directly rather than routing through BluetoothLinux's own async HostController/Socket infrastructure, since the ABI surface has to be synchronous and match the reference's wire layout precisely. hci_send_cmd and hci_send_req haven't been exercised against a real or virtual HCI device yet — no differential conformance harness for this family exists.
Covers only what doesn't require a real or virtual adapter: input validation that returns before any socket is touched, and hci_send_cmd's wire format, verified over a plain pipe.
Drops the 9 stubs now covered by BluetoothLinuxABI's device management family (96 remaining, 132 implemented).
hciCommand/hciStatus/hciRequest capture the send/check-status/copy-out shapes that every hci_send_req-based command wrapper in lib/hci.c repeats, so each wrapper is a short, direct transcription of its reference instead of duplicating the boilerplate.
hci_create_connection, hci_disconnect, hci_authenticate_link, hci_encrypt_link, hci_change_link_key, hci_switch_role, hci_park_mode, and hci_exit_park_mode.
hci_read_remote_name(_with_clock_offset), hci_read_remote_name_cancel, hci_read_remote_version, hci_read_remote_features, hci_read_remote_ext_features, and hci_read_clock_offset.
hci_read_local_version, hci_read_local_commands, hci_read_local_features, hci_read_local_ext_features, hci_read_bd_addr, hci_read_local_name, and hci_write_local_name.
White list and resolving list management, scan and advertising control, and LE connection establishment/update/remote-features query.
Class of device, voice setting, inquiry access codes, stored link keys, inquiry/AFH/inquiry-mode toggles, extended inquiry response, simple pairing, OOB data, transmit power, link policy/supervision timeout, AFH classification, and per-connection link quality/RSSI/AFH map/clock queries — 33 symbols.
Unlike the rest of the command wrapper family, this goes through a single ioctl(HCIINQUIRY) rather than hci_send_req — the request header and resulting inquiry_info records share one kernel buffer, the same shape as HCIGETDEVLIST in HCIDevice.swift.
Drops the 71 stubs now covered by the HCI command wrapper family (25 remaining — the SDP session functions — 203 implemented).
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.
Summary
Scaffolding for a drop-in, Swift-implemented replacement for BlueZ's shared
libbluetooth.so.3. The deliverable is a library that loads, resolves all 218 symbols the reference exports, and fails loudly (by symbol name) on any call not implemented yet — so the rest of the port can proceed incrementally, one symbol family at a time.Nothing in the
bluezpackage actually links this shared library —bluetoothd,bluetoothctl,btmon,hciconfigandsdptoolall statically linklibbluetooth-internal.a— so replacing it can't break the Bluetooth stack itself; it exists solely for third-party consumers.Sources/CBluetoothLinuxABIvendors the eleven public BlueZ headers verbatim (GPL-2.0-or-later, isolated in its own directory with its own LICENSE and README) and generates a stub for every symbol not yet implemented, viascripts/gen_stubs.py. Each stub's signature is read out of the vendored headers, so it's checked against the real declaration rather than hand-typed.scripts/symbols.txtrecords the reference export surface (218, split 17/101/100 acrossbluetooth.c/hci.c/sdp.c);scripts/implemented.txtrecords the 203 currently implemented: thebluetooth.c+bt_uuid_*families and the SDP data/list/record/codec layer (both implemented in PureSwift/Bluetooth), plus this repo's own HCI string converter family, HCI device management family, and the 71-symbol HCI command wrapper family (hci_inquiry,hci_create_connection,hci_read_*,hci_write_*,hci_le_*, etc.) — everything BlueZ'slib/hci.cexports excepthci_strtoptype-adjacent string helpers already covered above.scripts/gen_symbols.pyderives the linker version script and the flat export list from these;scripts/check-exports.shasserts the built library against it.scripts/ownership.mdrecords the return/who-frees/lifetime contract for each symbol, ahead of implementation — the conventions aren't uniform (some allocate on the heap, some write into a caller buffer, some return static pointers) and guessing produces leaks or double frees no type checker would catch.Sources/BluetoothLinuxABIimplements the 21-symbol HCI string converter family, using generated lookup tables (scripts/generate-hci-tables.py, parsed directly from BlueZ'shci.c) for the bus/device-flag/packet-type/link-mode/version/command-name mappings; the 9-symbol HCI device management family (rawAF_BLUETOOTH/BTPROTO_HCIsocket open/close, device info/address/id lookup, enumeration, routing, and sending commands/requests); and the 71-symbol HCI command wrapper family (connection/link-policy management, remote-device queries, local controller info, controller configuration, LE commands, and inquiry) built onhciCommand/hciStatus/hciRequesthelpers that capture the send/check-status/copy-out shape every wrapper inlib/hci.crepeats. All of it talks to the kernel directly via socket/bind/ioctl/writev/poll rather than through BluetoothLinux's own async HostController/Socket infrastructure, since the ABI surface has to be synchronous and match the reference's wire layout precisely.CMakeLists.txtbuildslibbluetooth.so.3.19.15by linking aPureSwift/Bluetoothcheckout's static archives (-DBLUETOOTH_PACKAGE_PATH) together withBluetoothLinuxABIand the generated stubs, with the soname, version, and a pinned export list that Package.swift can't express.Conformance/compare.shandConformance/conformance_hci_strings.cdifferentially test the HCI string converter family against the systemlibbluetooth.so.3; the phase-1 and SDP drivers stay in thePureSwift/Bluetoothcheckout alongside the symbols they cover.Verified
check-exportstarget).libbluetooth.so.3, aside from a handful of already-documented deltas (bt_compidtostrnaming, onememcmp-magnitude case) recorded in each repo'sknown-differences.txt.hci_open_dev) aborts withlibbluetooth (PureSwift): hci_open_dev is not implemented yet.rather than crashing unhelpfully or corrupting state.Test plan
swift build— default configuration, unaffectedSWIFTPM_BLUETOOTH_CABI=1 swift build— C ABI target buildsSWIFTPM_BLUETOOTH_CABI=1 swift test— passes, including the newBluetoothLinuxABITestscmake -B build -G Ninja -DBLUETOOTH_PACKAGE_PATH=<Bluetooth checkout> && cmake --build build—libbluetooth.so.3.19.15buildscmake --build build --target check-exports— 218/218 symbols matchConformance/compare.sh— identical output against the reference library for the HCI string converter driverKnown gap
hci_send_cmd/hci_send_reqand everything built on them — the entire 71-symbol HCI command wrapper family, plushci_inquiry'sioctl(HCIINQUIRY)call — have not been exercised against a real or virtual HCI device. Only their non-socket paths (input validation,hci_send_cmd's wire-format framing over a plain pipe) are unit tested. No/dev/vhciaccess was available (root-only in this environment) to build a differential driver for this family; each wrapper is a careful, field-by-field transcription of itslib/hci.creference, cross-checked against the vendored struct layouts, but unverified end-to-end.