Wi-Fi and Bluetooth

The ESP32-S31 radio module provides a mac80211/cfg80211 station interface and a Bluetooth controller. For configuration, pairing, service controls, and connection checks, use Wi-Fi and Bluetooth setup. This page covers application interfaces and module parameters.

Wi-Fi

The network interface is normally wlan0; the image includes iw, wpa_supplicant, and wpa_cli. Application data uses normal network sockets. The current SoftMAC frontend exposes one 2.4 GHz station interface. AP and AP+station operation are unavailable. Software monitor reception is incomplete; see Advanced Wi-Fi for filtering and enterprise-validation limits.

Bluetooth

The bundled BTstack application uses /dev/s31-hci. Loading the module with direct_hci=0 instead exposes a Linux HCI controller. A BlueZ-based image also needs its daemon, tools, dependencies, and service configuration retained: post-build.sh explicitly removes BlueZ, D-Bus/GLib, and BlueALSA files. Selecting the package alone is insufficient. See the runtime pruning rules when building that alternative, and stop the direct-HCI service before changing ownership.

Direct HCI device

/dev/s31-hci allows one application to open it at a time and has permissions 0600. Stop BTstack before using the device from another application.

A write sends one complete H4 packet: a packet-type byte followed by the HCI packet data. The accepted write size is 2–1,029 bytes.

The size passed to read() selects the receive format:

Requested read size

Returned data

2–1,029 bytes

One complete H4 frame

More than 1,029 bytes

Up to eight frames, each preceded by a two-byte little-endian length

For a simple client, use a 1,029-byte read buffer. In batch mode, each length includes the H4 packet-type byte. The read finishes when the buffer fills, eight frames have been copied, or the queue becomes empty.

A buffer too small for the next frame returns EMSGSIZE if no frame has been copied yet. A nonblocking read from an empty queue returns EAGAIN. Use poll() to wait for incoming data or space in the transmit queue.

After a controller restart, an open client can receive an HCI Hardware Error event. Reinitialize the host and reconnect devices when that happens. Closing the device releases the host endpoint while leaving the controller enabled. The HCI frontend implements this framing and lifecycle.

Module settings

The module file is esp32s31-radio.ko. Linux shows its name as esp32s31_radio in /sys/module.

Parameter

Default

Description

mode

combo

Enable wifi, bt, or combo

direct_hci

1

Expose /dev/s31-hci; use 0 for Linux HCI

The payload comes from the fixed radio.bin XIP flash slot and must match the kernel/module; no firmware-filename parameter selects it.

These settings are selected when loading the module. Use esp32-config for routine mode selection; low-level applications should stop clients before changing the module configuration. The module implementation defines the mode and direct-HCI defaults.

Radio status

The radio_health attribute reports initialization results, heap use, packet counts, and worker activity:

for file in /sys/bus/platform/devices/*/radio_health; do
    [ -r "$file" ] && cat "$file"
done

Use this together with dmesg when a radio service fails to start or stops making progress.

Kernel interface

The common radio API is declared in the current checkout at linux-esp32-s31/include/linux/esp32s31-radio.h. It defines the Wi-Fi and HCI callbacks used by the frontends. The core and external payload currently use ABI version 1.

Item

Limit

HCI frame

1,029 bytes

Radio bridge frame

4,144 bytes

Raw SoftMAC frame

4,096 bytes

The raw SoftMAC limit is defined in include/linux/esp32s31-radio-control.h. The retained firmware scan API has a 32-entry array, but current station scans use mac80211 software scanning; that array is not the current scan-result limit.

The frontend uses receive_aux borrowed frames whose storage remains valid only during the callback. It copies data that must survive callback return and uses NAPI to deliver frames to mac80211. Atomic allocations can occur in this path. Generic software monitor reception shares the filtered radio receive path and is not a complete promiscuous channel capture.