# X6200 WiFi and Bluetooth Architecture A detailed technical account of how WiFi and Bluetooth work on the Xiegu X6200, reverse-engineered during Mestre development (May 2026). ## Hardware Overview The X6200 uses a **Realtek RTL8723D** combo chip for both WiFi and Bluetooth. It is connected to the Allwinner R16 SoC via USB and appears as a single USB device: ``` USB ID: 0bda:d723 Realtek Semiconductor Corp. 802.11n WLAN Adapter Bus: USB 3 (musb-hdrc, high-speed) ``` The device exposes three USB interfaces: - Interface 0+1: Bluetooth (class 0xE0, Wireless, RF) - Interface 2: WiFi (class 0xFF, Vendor Specific) Both WiFi and Bluetooth share the same USB device and antenna. ## The Power Control Problem **The RTL8723D chip is powered off at boot.** It does not appear on the USB bus until explicitly powered on via a GPIO pin. Without this step, neither WiFi nor Bluetooth will work regardless of what drivers or software is loaded. The power control pin is managed via the X6200Control library: ``` GPIO chip: 0 (sun8i-a33 main GPIO controller) GPIO pin: 357 Logic: Active LOW (0 = powered ON, 1 = powered OFF) ``` This is controlled via the `x6200_gpio_set()` function from `libaether_x6200_control.so`: ```python import ctypes lib = ctypes.CDLL("libaether_x6200_control.so") lib.x6200_gpio_init.restype = ctypes.c_bool lib.x6200_gpio_set.argtypes = [ctypes.c_int, ctypes.c_int] lib.x6200_gpio_init() lib.x6200_gpio_set(357, 0) # 0 = ON (active low!) ``` **Critical:** `gpio_init()` must be called before `gpio_set()`. The active-low logic is counterintuitive — sending `1` powers the chip OFF, sending `0` powers it ON. After powering on, the USB device appears within 1-3 seconds: ``` usb 3-1: new high-speed USB device number 2 using musb-hdrc usb 3-1: New USB device found, idVendor=0bda, idProduct=d723 ``` ## Bluetooth ### Driver The Bluetooth interface of the RTL8723D is handled by the standard Linux kernel `btusb` driver with the `btrtl` firmware loader. Required kernel modules (compiled as `=m`): ``` CONFIG_BT=m CONFIG_BT_HCIBTUSB=m CONFIG_BT_RFCOMM=m CONFIG_BT_BNEP=m CONFIG_BT_HIDP=m CONFIG_UHID=y ← required for HID input devices CONFIG_INPUT_UINPUT=y ← required for HID input devices ``` Load order: ```bash modprobe btusb # registers hci0 and loads firmware modprobe uhid # userspace HID device support modprobe hidp # HID over Bluetooth protocol ``` ### Firmware The RTL8723D Bluetooth requires two firmware files: | File | Purpose | |------|---------| | `rtl_bt/rtw8723d_fw.bin` | Main BT firmware | | `rtl_bt/rtw8723d_config.bin` | Configuration (10 bytes) | **Both files are required.** Without `rtw8723d_config.bin`, `hciconfig hci0 up` fails with: ``` Bluetooth: hci0: RTL: mandatory config file rtl_bt/rtw8723d_config not found ``` `rtw8723d_config.bin` is **not included** in Buildroot's `BR2_PACKAGE_LINUX_FIRMWARE_RTL_87XX_BT` package (as of 2025.02). It must be added to the rootfs overlay manually: ``` br2_external/board/x6200/rootfs-overlay/lib/firmware/rtl_bt/rtw8723d_config.bin ``` Source: https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/rtl_bt/rtw8723d_config.bin ### BlueZ Version **BlueZ 5.64 is required.** BlueZ 5.79 (Buildroot 2025.02 default) has a build system bug where the HID input plugin (`input_init`) is not linked into `bluetoothd` despite `--enable-hid` being passed to configure. Symptoms: ``` Failed to connect: org.bluez.Error.NotAvailable br-connection-profile-unavailable ``` The bug manifests because `builtin_modules` in the generated Makefile is empty and the input profile is never registered via `btd_profile_register()`. Downgrading to BlueZ 5.64 resolves the issue. To force BlueZ 5.64 in Buildroot, override the version in a local `.mk` file or patch `buildroot/package/bluez5_utils/bluez5_utils.mk`. ### HID Profile Requirements For Bluetooth HID devices (keyboard, mouse) to connect, bluetoothd must be started with `--compat`: ```bash /usr/libexec/bluetooth/bluetoothd --compat & ``` And `/etc/bluetooth/input.conf` must have: ```ini [General] UserspaceHID=true ClassicBondedOnly=false ``` ### Pairing a Device First-time pairing via `bluetoothctl`: ``` power on agent on default-agent scan on # Wait for device to appear, then: pair XX:XX:XX:XX:XX:XX trust XX:XX:XX:XX:XX:XX connect XX:XX:XX:XX:XX:XX ``` Once trusted, subsequent connections are automatic via the `S85bt-keyboard` init script. ### Auto-reconnect The `S85bt-keyboard` init script polls every 20 seconds and reconnects if the device is not connected. It uses `scan on` before each connection attempt to make the device visible: ```sh { echo "power on"; sleep 1 echo "scan on"; sleep 8 echo "scan off"; sleep 1 echo "connect $KEYBOARD_ADDR"; sleep 3 echo "quit" } | bluetoothctl ``` ## WiFi ### Driver **The RTL8723D USB WiFi interface is NOT supported by any in-tree driver in Linux 6.1.** Specifically: | Driver | Status in 6.1 | |--------|---------------| | `rtl8xxxu` | Does not support 0bda:d723 | | `r8723bs` | SDIO only, not USB | | `rtw88` | Only has PCIe variant (RTW88_8723DE), USB variant added in 6.2 | The solution is the **out-of-tree `lwfinger/rtw88` driver**, which backports USB support for RTL8723D to older kernels. This is the same approach used by the Xiegu X6100 community. Buildroot package: `br2_external/package/rtw88/rtw88.mk` ```makefile RTW88_VERSION = 461b696b51317ba4ca585a4ddb32f2e72cd4efc9 RTW88_SITE = https://github.com/lwfinger/rtw88 RTW88_SITE_METHOD = git RTW88_LICENSE = GPL-2.0 $(eval $(kernel-module)) $(eval $(generic-package)) ``` After loading, the driver creates `wlan0`: ``` 3: wlan0: mtu 1500 qdisc noop qlen 1000 link/ether cc:64:1a:52:91:85 brd ff:ff:ff:ff:ff:ff ``` ### Firmware Two firmware components are required: | Component | Buildroot symbol | File | |-----------|-----------------|------| | WiFi firmware | `BR2_PACKAGE_LINUX_FIRMWARE_RTL_RTW88` | `rtw88/rtw8723d_fw.bin` | | Regulatory DB | `BR2_PACKAGE_LINUX_FIRMWARE_REGULATORY` | `regulatory.db` | **Note:** After adding `BR2_PACKAGE_LINUX_FIRMWARE_RTL_RTW88`, you must run `linux-firmware-dirclean` before rebuilding, otherwise the `br-firmware.tar` archive is not regenerated and the firmware file will not appear in the target: ```bash ./scripts/build.sh linux-firmware-dirclean ./scripts/build.sh linux-firmware ./scripts/build.sh ``` ### Network Configuration WiFi is configured via `wpa_supplicant` with a multi-network configuration file at `/etc/wpa_supplicant.conf`: ```ini ctrl_interface=/var/run/wpa_supplicant update_config=1 country=SE network={ ssid="Network_1" psk="password_1" priority=10 } network={ ssid="Network_2" psk="password_2" priority=5 } ``` `wpa_supplicant` automatically connects to the highest-priority available network. Add as many `network={}` blocks as needed. The file is installed in the rootfs overlay but should be considered sensitive — do not commit real passwords to git. ### Boot Sequence ``` S35wifi-bt (or S45wifi-bt) → x6200_gpio_init() → x6200_gpio_set(357, 0) ← powers on RTL8723D → modprobe btusb ← registers hci0 → modprobe uhid → modprobe hidp → sleep 3 ← wait for USB enumeration S40bluetoothd → bluetoothd --compat ← BlueZ daemon S46wifi → ip link set wlan0 up → wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.conf → udhcpc -i wlan0 ← DHCP client S85bt-keyboard → auto-connect loop (scan + connect every 20s) ``` **Ordering is critical:** The GPIO power-on script must run before `bluetoothd` and `wpa_supplicant`. Without GPIO 357 = 0, neither WiFi nor Bluetooth hardware is visible on the USB bus. ## Known Quirks **GPIO is active low.** `gpio_set(357, 0)` = ON, `gpio_set(357, 1)` = OFF. This is the opposite of what one might expect. **Single USB device, two functions.** WiFi and BT share `0bda:d723`. Powering on the chip enables both simultaneously. There is no way to enable one without the other. **rtw8723d_config.bin is missing from linux-firmware package.** Buildroot's `BR2_PACKAGE_LINUX_FIRMWARE_RTL_87XX_BT` does not include this 10-byte config file. Must be added to overlay manually. **BlueZ 5.79 HID input plugin is broken.** Downgrade to 5.64 for working Bluetooth keyboard and mouse support. **lwfinger/rtw88 is pinned to a specific commit.** The driver is under active development; newer commits may break things. Pin to a known-good commit in `rtw88.mk`. **linux-firmware-dirclean required after adding RTW88 firmware.** Buildroot caches `br-firmware.tar` and does not regenerate it when new firmware symbols are added to `.config`. Always run `linux-firmware-dirclean` after changing firmware selection. ## References - [lwfinger/rtw88](https://github.com/lwfinger/rtw88) — out-of-tree RTW88 driver with USB support for RTL8723DU - [AetherRadio/X6200Control](https://github.com/gdyuldin/X6200Control) — GPIO control library; `x6200_pin_wifi` (pin 357) is defined in `include/aether_radio/x6200_control/low/gpio.h` - [gdyuldin/AetherX6200Buildroot](https://github.com/gdyuldin/AetherX6200Buildroot) — reference Buildroot configuration; provided the `rtw88` package recipe that Mestre adapts - Linux kernel `drivers/net/wireless/realtek/rtw88/` — mainline RTW88 driver (USB variant added in 6.2, not available in 6.1) - Realtek RTL8723D datasheet — combo WiFi+BT chip used in X6200