Several LOG_ and __ASSERT format strings use %u or %d for arguments
that are size_t or ssize_t, which produces -Wformat= warnings on
LP64 targets (e.g. AArch64). Switch to %zu / %zd.
* subsys/bluetooth/host/classic/sdp.c: three format strings that
compare against sizeof() or use ssize_t counters.
* drivers/bluetooth/hci/hci_nxp_setup.c: matching V1 and V3
"Out of sending buffer range" messages (both LOG_ERR and the
neighbouring __ASSERT that uses the same string).
No functional change; eliminates 5 build warnings on
nitrogen93_smarc/mimx9352/a55/nx611.
Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Ryan Erickson <ryan.erickson@ezurio.com>
nxp_bt_send_vs_command() framed every vendor command in one buffer
sized for the longest of them, the calibration data, with a length
check for the others. Every platform reserved that buffer, although
only those with CONFIG_HCI_NXP_SET_CAL_DATA send the command, and a
longer command added later would have had to change the constant the
buffer is sized by.
Each caller now defines a buffer from the size of its own parameters
and passes it to the helper, so there is no shared size to maintain
and a build frames only the commands it sends. Measured with
-fstack-usage, bt_nxp_open() on frdm_mcxw71, which sends the address
command only, needs 24 bytes less stack; on frdm_rw612, which sends
three of the commands, the compiler now inlines their callers into it
and the stack use grows by 8 bytes.
Build-tested with the peripheral_hr sample on frdm_mcxw71 (public
address) and frdm_rw612 (calibration data and automatic sleep). Not
run on hardware.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Make BLECB_Indication() set ll_state_busy and return 1 only when packet
handling fails with -ENOMEM.
Previously, all receive errors were treated as a busy condition, including
malformed packets and other parsing failures. This could incorrectly signal
that the host was unable to accept data and trigger unnecessary
flow-control behavior.
Refactor treat_evt(), treat_acl(), and treat_iso() to return explicit error
codes and pass the received net_buf through an output parameter so the
caller can distinguish buffer exhaustion from other receive failures.
treat_evt() ignores discardable events on memory allocation failure without
returning an error
Fixes#118805
Signed-off-by: Michele Sardo <msmttchr@gmail.com>
Enable the IEEE 802.15.4 radio on the BL70x (BL702) series: add the
ieee802154 devicetree node, compile the RF/platform shim, link the
lmac154/RF blobs, and place the timing-critical lmac154 .tcm_code in ITCM
(otherwise those input sections become orphans at an unloaded address).
Provide CONFIG_BT_HCI_DRIVER_LOG_LEVEL for 802.15.4-only builds so the
shared BLE/802.15.4 platform shim compiles without Bluetooth enabled.
Signed-off-by: William Markezana <william.markezana@gmail.com>
Enable the IEEE 802.15.4 radio on the BL70xL (BL702L) series: add the
ieee802154 devicetree node, compile the RF/platform shim, place the
timing-critical lmac154 code in ITCM, and link the lmac154/RF blobs.
Signed-off-by: William Markezana <william.markezana@gmail.com>
Enable the IEEE 802.15.4 radio on the BL61x (BL616) series: add the
ieee802154 devicetree node, RF/PHY init via the shared wl_api blobs, the
TCM code section, and link the lmac154 blob. The GLB reset / memcpy shims
required by the BL616 blobs live with the other HAL shims.
Signed-off-by: William Markezana <william.markezana@gmail.com>
Wire the BL808 on-chip controller into the Bouffalo Lab HCI driver:
add the SoC platform block and controller init/deinit, and set the
ACL TX and event RX buffer counts (7/8) to match the buffer size the
controller reports in LE Read Buffer Size.
Signed-off-by: William Markezana <william.markezana@gmail.com>
setup() is Host code living in the HCI driver vtable: most
implementations call bt_hci_cmd_send_sync(), which is why the op exists
at all, and why a driver's vendor-specific initialization has nowhere
to run in a build without a Host. A driver does that work inside open()
instead, over its own transport, with the packet and lockstep helpers,
taking the public address from bt_hci_get_public_addr().
Deprecate the op, bt_hci_setup(), its parameter structure and
BT_HCI_SETUP, so that an out-of-tree driver still implementing setup()
is pointed at the replacement. The Host keeps calling the op through
the deprecation window; the op, its Kconfig and the h4 vendor hook are
removed two releases from now.
No attribute is put on the op or the function: the Host reads the
member to call it, so an attribute would warn on the Host rather than
on the drivers the deprecation is for. Selecting the deprecated Kconfig
symbol is what makes a build say so, and that fires exactly for the
drivers that have not moved.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Send the resets, the baud rate updates, the firmware download, the
public address and the SCO route from the H:4 driver's open-time hook
through the lockstep helper, instead of from bt_h4_vnd_setup() with
the Host's command API, so that a build without a Host, which did not
link, runs the same sequence. The public address comes from
bt_hci_get_public_addr(),
and the firmware blocks are sent from a static command buffer sized
for the longest command, off the caller's stack. The extension selects
BT_H4_VND_OPEN instead of BT_HCI_SETUP.
Build-tested with the peripheral_hr and hci_uart samples on
cy8cproto_062_4343w, the latter with an overlay choosing the c2h UART,
and with peripheral_hr on arduino_giga_r1/stm32h747xx/m7. Not run on
hardware.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Send the baud rate update, the calibration data and the IR
configuration from the H:4 driver's open-time hook through the
lockstep helper, instead of from bt_h4_vnd_setup() with the Host's
command API. A build without a Host did not link, and would have
skipped the calibration commands, which returned success without being
sent; they are now sent in every build. The firmware upload stays in
bt_hci_transport_setup(), and the extension selects BT_H4_VND_OPEN
instead of BT_HCI_SETUP.
Build-tested with the peripheral_hr and hci_uart samples on
mimxrt1170_evk@B/mimxrt1176/cm7, the latter with an overlay choosing
the c2h UART, and with peripheral_hr on frdm_mcxn947/mcxn947/cpu0 with
the nxp_arduino_aw510_wifi_bt shield. Not run on hardware.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
The vendor extensions of the H:4 driver initialize their controller
from bt_h4_vnd_setup(), called from the setup() op with the Host's
command API, so a controller-only build, which has no such API, does
not link, and the sequence could only ever run below a Host.
Add bt_h4_vnd_open(), which the driver calls last in open(), once the
UART is running, with a lockstep helper: the extension's commands go
through the driver's own TX path from a buffer of their own, and the
RX thread feeds every received packet to the helper before delivering
it. A failing hook fails open(), which then drops what is queued or
half received, as close() now does too, so that a retry starts clean.
bt_h4_vnd_setup() keeps working through the setup() op.
The extension's commands go through a buffer of up to
CONFIG_BT_BUF_CMD_TX_SIZE parameter bytes, the option for the longest
HCI command a build sends, which the Infineon extension already raises
for its firmware download; the driver fails a longer command with
-EMSGSIZE instead of overflowing the buffer.
Build-tested with the H:4 samples of the in-tree extensions, which the
following commits convert, and with peripheral_hr on arduino_portenta_c33,
whose H:4 driver has no extension. Not run on hardware.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
A received packet longer than the buffer allocated for it was logged
and dropped, but the buffer was never freed, so every such packet cost
the pool one buffer for good.
Build-tested with the peripheral_hr sample on
cyw920829m2evk_02/cyw20829b0lkml. Not run on hardware.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
wiced_bt_dev_vendor_specific_command() exists for the btstack-integration
asset to link, and sent the asset's vendor commands with the Host's
bt_hci_cmd_alloc() and bt_hci_cmd_send(), ignoring the completion
callback. Neither of the asset's callers is reached: the driver's
wiced_bt_stack_init_internal() drops the post stack initialization
callback that would enable the sleep mode, which
cyw208xx_bt_enable_low_power_mode() does instead, and the only caller of
cybt_prm_download(), cybt_patchram_download.c, is not part of the build.
Report the command as unsupported instead. This was the driver's last
use of a Host API, so a build without a Host, such as the hci_uart
sample, now links.
Build-tested with the peripheral_hr and hci_uart samples on
cyw920829m2evk_02/cyw20829b0lkml, the latter with an overlay choosing
the UART. Not run on hardware.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Reset the controller, download its firmware, set the public address and
enable the low power mode from within open(), through the HCI lockstep
helper and the driver's own send path, instead of implementing the
setup() driver API op on top of the Host's bt_hci_cmd_send_sync(). The
public address comes from bt_hci_get_public_addr(), which gives
BT_ADDR_ANY when none has been set, so the controller's hard-coded
default address is still always overridden. The responses are consumed
in the driver's receive path by feeding received packets to the helper
before they are delivered.
The platform task resets the controller every time it is started, so
open() restores the helper's initial command allowance with
bt_hci_lockstep_reset() before it sends the first command: the reset
controller allows one command again without announcing it.
The firmware blocks are sent from a static command buffer sized for the
longest HCI command, to keep it off the stack of the thread that opens
the driver; the caller serializes open().
A failing or unanswered command fails open() with an error instead of
failing the Host's HCI initialization later, and is logged by the
helper. open() then shuts the platform task down again, as close()
does, since a failed open() is not followed by close(), and a platform
task that fails to start makes open() return -EIO instead of the
asset's positive result code. open() moves below close() for that.
The raw send path is factored out of send() so that it serves both the
send() op and the helper. It takes the packet with its packet indicator
instead of pulling the indicator off the buffer, so a buffer that could
not be sent is returned to the caller unmodified.
The driver no longer selects BT_HCI_SETUP. BT_AIROC still selects it
for every AIROC part, because the H4 extension of the UART-attached
ones implements the setup hook, and the Host treats a missing setup()
op as nothing to do.
Build-tested with the peripheral_hr sample on
cyw920829m2evk_02/cyw20829b0lkml. Not run on hardware.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Send the vendor-specific initialization commands, the calibration data,
the sleep configuration and the public address, from within open(),
through the HCI lockstep helper and the driver's own send path, instead
of implementing the setup() driver API op on top of the Host's
bt_hci_cmd_send_sync(). The public address comes from
bt_hci_get_public_addr(). The responses are consumed in the driver's
receive path by feeding received packets to the helper before they are
delivered.
Without a Host the helper function for these commands returned success
without sending anything, and setup() was not called there in the first
place, bt_enable_raw() opening the driver only, so a controller-only
build left the controller without its calibration data, sleep
configuration and address. They are now sent in every build, and the
driver no longer selects BT_HCI_SETUP.
A failing or unanswered command, or a failed HCI start, fails open()
with an error instead of failing the Host's HCI initialization later,
and open() then unregisters the receive callback again, as close()
does, since a failed open() is not followed by close(). open() moves
below close() for that. The helper's command allowance is restored at
every open() and after the controller's own reset that follows the
annex 55 calibration data, as neither reset announces one. The stale
comment claiming the address command gets no Command Complete goes: it
already went through bt_hci_cmd_send_sync(), which waits for one.
The raw send path is factored out of send() so that it serves both the
send() op, which keeps intercepting the vendor commands it handles
locally, and the helper.
Build-tested with the peripheral_hr sample on frdm_mcxw71 (public
address) and frdm_rw612 (calibration data and automatic sleep). Not run
on hardware.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Send the BlueNRG ACI configuration commands, the link-layer-only mode
and the public address, from within open(), through the HCI lockstep
helper and the driver's own SPI send path, instead of implementing the
setup() driver API op on top of the Host's bt_hci_cmd_send_sync(). The
public address comes from bt_hci_get_public_addr(). The responses are
consumed in the driver's receive thread by feeding received packets to
the helper before they are delivered.
That also replaces the second way the driver had of sending the
link-layer-only command: in a controller-only build it called the raw
bt_send() from inside its own open(), before the transport was open to
its user, and left the response to reach the application. Both build
types now share one path, and the driver no longer selects
BT_HCI_SETUP.
A failing or unanswered command fails open() with an error instead of
failing the Host's HCI initialization later, and is logged by the
helper. open() stops the receive thread, aborting it if it does not
exit, and resets the controller when it fails after having started
them, which also covers the existing boot timeout, since a failed
open() is not followed by close(). open() moves below close() for that,
without other changes.
The raw send path is factored out of send() and takes the device, so
that it serves both the send() op and the helper.
Build-tested on disco_l475_iot1 (st,hci-spi-v1) with the peripheral_hr
and hci_uart samples, and on nucleo_l476rg with the x_nucleo_bnrg2a1
shield (st,hci-spi-v2) with peripheral_hr. Not run on hardware.
open() takes the controller out of reset through its reset line on
every call, so it also restores the helper's initial command allowance
with bt_hci_lockstep_reset(): the controller allows one command again
without announcing it.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Write the public address into the controller from within open(), taking
it from bt_hci_get_public_addr(), instead of implementing the setup()
driver API op. The command goes through BleStack_Request() as before,
so no Host command API was involved and nothing else changes in how it
is sent.
The address is now also set in controller-only builds, where the driver
did not select BT_HCI_SETUP and bt_enable_raw() would not have called
setup() anyway: with no public address to set, which is always the case
there, it is the one derived from the device UID, as before. The driver
no longer selects BT_HCI_SETUP.
A failure to set the address fails open() instead of the Host's HCI
initialization later. open() then closes what it had opened, since a
failed open() is not followed by close(). open() moves below close()
and the address functions for that, without other changes.
Build-tested on nucleo_wba55cg with the peripheral_hr and hci_uart
samples. Not run on hardware.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
apollox_blue.h declares bt_apollo_vnd_setup() with a struct
bt_hci_lockstep parameter but does not include the header that defines
the type, relying on its includers to have done so. Include it, and
document the parameter. Both includers already include it first, so
nothing changes for them.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
A failed open() stops the RX thread and takes the controller down, but
leaves transport_open set and the session counter unchanged, so a send
that is waiting for the SPI semaphore, or sleeping between its attempts,
goes on to talk to a controller that is down, or to the one a later
open() brings up. End the session in the failed-open unwind the way
close() does. The semaphore take gets an explicit void cast: the
semaphore is never reset, so the take cannot fail, and there is nothing
the unwind could do about it if it did.
Build-tested on apollo4p_blue_kxr_evb. Not run on hardware.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
bt_apollo_controller_init() resets the controller through its reset
line and loads it over the raw SPI path, outside the lockstep helper,
so the helper's command allowance does not follow. After a close(), the
helper is left in whatever state the last command left it, and the
freshly started controller allows one command again without announcing
it. Restore the helper's initial allowance with bt_hci_lockstep_reset()
before the vendor setup sends its first command.
Build-tested on apollo4p_blue_kxr_evb. Not run on hardware.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
The rx_thread assembles a whole HCI packet in a single static frame
buffer before handing it to the host. That buffer was hardcoded to 512
bytes. A full ACL data packet can be larger than this: the host's
receive buffer is CONFIG_BT_BUF_ACL_RX_SIZE bytes and defaults up to
1300 for Classic, and an A2DP media packet fills it. When such a packet
arrives, frame_size reaches the buffer size, the driver logs "HCI Packet
is too big for frame (512 bytes). Dropping data" and discards it. The
host then sees the truncated stream and rejects it with "Unexpected
L2CAP continuation", so no A2DP media is ever received.
Size the frame buffer from BT_BUF_RX_SIZE, which the host already uses
for its RX buffers: it includes the H4 type octet and the maximum of the
ACL, event and ISO receive-buffer sizes, so the buffer holds every
packet type get_rx() accepts, including ISO packets whose MTU can exceed
both 512 and the ACL RX size.
Verified on native_sim with a real Bluetooth dongle (HCI User Channel):
before the fix A2DP media reception failed as described above; after it,
an A2DP SBC stream from a phone is received continuously (packets both
below and above the old 512-byte limit) with no dropped-frame or L2CAP
continuation errors.
Signed-off-by: Kai Cheng <chengkai@xiaomi.com>
close() sent its vendor-specific reset command with
bt_hci_cmd_send_sync(), that is, through the Bluetooth Host. The Host
is only one possible user of the driver, which therefore cannot rely on
it, and close() was for that reason compiled only into builds with a
Host, leaving a controller-only build with a transport it could open
but not close. It did not work with the Host either: bt_disable() marks
the transport closed before it calls close(), after which the Host
refuses the command with -EHOSTDOWN, so bt_disable() failed.
Send the command with the HCI lockstep helper over the driver's own
transport instead, as open() does for its commands. The receive thread
is still running at that point and feeds the response to the helper; it
is stopped afterwards, as before. With that the driver calls no Host
API any more, and close() is part of every build.
Build-tested on nucleo_wb55rg with the peripheral_hr and hci_uart
samples. Not run on hardware.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Send the two vendor-specific initialization commands, the public
address derived from the device UID and the transmit power level, from
within open(), through the HCI lockstep helper and the driver's own
send path, instead of implementing the setup() driver API op on top of
the Host's bt_hci_cmd_send_sync(). The responses are consumed in the
driver's receive thread by feeding received packets to the lockstep
helper before delivering them to the host.
The commands no longer depend on the Host, so they now also run in
controller-only builds, where they were both compiled out and never
reached, bt_enable_raw() opening the driver without calling setup(), so
the controller kept its default address and transmit power. The driver
no longer selects BT_HCI_SETUP. A failing or unanswered command fails
open() with an error instead of failing the Host's HCI initialization
later, and is logged by the helper.
A failed address command fails open(), as it has failed setup() since
commit 19c58a5a3b ("Bluetooth: ipm_stm32wb: Fail setup when the
address write fails"). open() aborts the receive thread it started when
the vendor initialization fails, so that a second bt_enable() does not
create a thread that is still running.
When open() restarts the coprocessor after a close(), it also restores
the helper's initial command allowance with bt_hci_lockstep_reset():
the restarted coprocessor allows one command again without announcing
it.
The raw send path is factored out of send() and takes the device, so
that it serves both the send() op and the helper.
close() still sends its reset command through the Host and stays behind
CONFIG_BT_HCI_HOST.
Build-tested on nucleo_wb55rg with the peripheral_hr sample. Not run on
hardware.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
close() has been compiled only with CONFIG_BT_HCI_HOST since the driver
was added, while the driver API table has always referenced it
unconditionally, so a build of this driver without the Bluetooth Host
fails with "'bt_da1469x_close' undeclared". The function disables the
CMAC interrupt and the CMAC core and uses nothing of the Host, so drop
the guard.
Compile-tested for da1469x_dk_pro: the driver object in a
CONFIG_BT_HCI_RAW configuration, which failed before, and the
peripheral_hr sample. Not run on hardware.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Store the public identity address that the Host hands to the driver's
setup() op also in the common HCI driver data, through the new
bt_hci_set_public_addr() API, before the HCI transport is opened. The
driver reads it with bt_hci_get_public_addr() and can apply it during
open(), i.e. from vendor-specific initialization that does not depend
on the Host's command APIs being available.
bt_hci_get_public_addr() returns BT_ADDR_ANY while no public address
has been set, which is what setup() receives in that case, so a driver
moving from one to the other keeps the check it has, and driver data
that has never been written needs no flag to say so. BT_ADDR_NONE is
the name that suggests itself for this, so the choice is spelled out
where a driver author looks: on both functions, with the check a driver
is expected to make, on the field, on the setup() parameter, which did
not document its value until now, and in the Kconfig help. The test
pins the value.
The channel is set on every bt_enable() and cleared when there is no
public identity, so that an address an earlier enable left behind is
not applied to the controller by a later one.
The setup() path keeps receiving the address as before; both channels
coexist until the drivers implementing setup() have migrated. So that
enabling the new channel no longer pulls in the mechanism it replaces,
BT_HCI_SET_PUBLIC_ADDR stops selecting BT_HCI_SETUP; the drivers that
apply the address in setup() (BlueNRG ACI, STM32WBA, CYW208XX) now
select BT_HCI_SETUP themselves, matching the conditions their setup()
implementations are compiled under.
Both functions are declared unconditionally, as coding guideline rule
A.1 requires of a header, so that their callers can select on the
option with IS_ENABLED() rather than the preprocessor, and defined in
a source file that is compiled only when the option is enabled, so
that a call that is not guarded fails to link rather than quietly
doing nothing. Only the field they work on is conditional, so a driver
that does not announce the capability pays nothing for it.
The driver API group version goes to 0.3.0 for the two functions added
to it.
The host identity test gains a scenario that creates a public identity
before bt_enable() and checks what the driver is handed while the
transport is opened, including that an enable without a public identity
hands it nothing rather than what the previous one left. The scenario
enables the capability through a prompt the test adds to it, since the
option is otherwise selected by drivers only. Its fake driver gains a
close() op, which the test needs in order to cycle the transport.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Send the vendor-specific set-public-address command from within open(),
through the HCI lockstep helper and the driver's own send path, instead
of implementing the setup() driver API op on top of the Host's
bt_hci_cmd_send_sync(). The response is consumed in the driver's event
handler by feeding received packets to the lockstep helper before
delivering them to the host.
The driver no longer calls any Host command API, so the address is now
also configured in controller-only builds, where bt_enable_raw() only
opens the driver and never called setup(), and it no longer selects
BT_HCI_SETUP. A failing or unanswered command fails open() with an
error instead of failing the Host's HCI initialization later, and is
logged by the helper.
open() aborts the receive thread it started when the command fails, so
that a second bt_enable() does not create a thread that is still
running.
The raw send path is factored out of send() and takes the device, so
that it serves both the send() op and the helper. It now reports a
failed Cy_BLE_SoftHciSendAppPkt() to its caller instead of logging and
returning success, which the helper needs in order to tell a command
that was not submitted from one that went unanswered.
Build-tested on cy8cproto_063_ble with the peripheral_hr sample. Not run
on hardware.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
close() takes the controller down and aborts the receive thread with no
regard for an SPI transfer in progress. The receive thread holds
sem_spi_available for the duration of a transfer, and
k_thread_abort() does not give the semaphore back, so a close() that
lands in a transfer leaves it taken and the next send blocks forever.
Before that, the controller is put in reset and its clocks are turned
off with the transfer still in flight.
Hold the semaphore across both, so that close() waits for the transfer
in progress to finish before it touches the controller or the thread.
bt_apollo_controller_deinit() does no SPI transfer of its own, so it
cannot wait for the semaphore close() holds.
Holding the semaphore does not stop a send that is already under way,
though: the send path gives it back between its attempts, which it
repeats for up to five seconds, so that the receive path can drain the
controller in the meantime. The driver therefore keeps track of whether
the transport is open and of how often that has changed. open() and
close() update both while holding the semaphore, and the send path
gives up with -ENETDOWN if on getting the semaphore the transport is
closed or the count has moved on since the send began. The count is
what stops a send that slept through a close() and the open() after it
from delivering the old session's packet to the new one; the flag is
what stops a send that starts while close() is finishing. The count is
atomic because a send notes it before it has the semaphore: what
counts is the session the call began in, not the one in which it first
gets the semaphore. open() makes its update before the controller
initialization, which already sends through the same path.
A close() from the receive callback aborts the calling thread, which
never returns to give the semaphore back, so that case gives it back
before the abort.
Build-tested on apollo4p_blue_kxr_evb and apollo3_evb with the
peripheral_hr sample. Not run on hardware.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Send the vendor-specific NVDS configuration command from within open(),
through the HCI lockstep helper and the driver's own SPI send path,
instead of implementing the setup() driver API op on top of the Host's
bt_hci_cmd_send_sync(). The responses are consumed in the driver's
receive thread by feeding received packets to the lockstep helper
before they reach the host.
The command no longer depends on the Host, so the two code paths that
existed for it, one building the packet by hand for controller-only
builds and one going through the Host, collapse into one, and the
driver no longer selects BT_HCI_SETUP. The hand-built path was in fact
unreachable: bt_enable_raw() opens the driver without calling setup(),
so a controller-only build sent neither the NVDS command nor the reset
that follows it. Both now run there. A failing or unanswered command
fails open() with an error instead of failing the Host's HCI
initialization later, and is logged by the helper.
The reset that makes the NVDS parameters take effect is now sent in
every build. Only the controller-only path sent it before; builds with
a Host relied on the Host's own reset, which follows a few HCI
transactions later.
open() aborts the receive thread it started when the controller
initialization or the vendor command fails, so that a second
bt_enable() does not create a thread that is still running.
The raw send path is factored out of send() and takes the device, so
that it serves both the send() op and the helper.
Build-tested on apollo4p_blue_kxr_evb and apollo3_evb with the
peripheral_hr sample. Not run on hardware.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
bt_ipm_ble_init() logs an error when bt_ipm_set_addr() fails and
carries on regardless, so a controller that rejects
ACI_HAL_WRITE_CONFIG_DATA comes up with a silently different identity
address. Return the error instead, so that bt_enable() fails and the
caller learns that the controller is in an unexpected state.
The UID64 is factory programmed on every part, so bt_get_ble_addr()
returning NULL is not an expected case either and fails setup the same
way.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
- preserve buffer ownership on error paths, consistent with API
expectations [See also bt_hci_send documentation], preventing
double unref.
- fix the data length check as the pre-allocated event buffer
already carried the H:4 indicator, so its tailroom was one byte
short of the 71-byte Read Local Supported Commands response, and
smaller responses only passed because net_buf_reset() discarded
that byte before the copy.
- Factorize common code to improve maintainability, keeping flow
control only in the indication
Signed-off-by: Michele Sardo <msmttchr@gmail.com>
Enabling CONFIG_BT restricts SYSTEM_WORKQUEUE_PRIORITY to the
cooperative range for every build, but the requirement comes from the
individual components that submit work to the system workqueue, not
from Bluetooth being enabled.
An application that asks for a preemptible system workqueue therefore
cannot build with Bluetooth enabled at all, even when no Bluetooth
code uses that queue. Running the system workqueue below every other
thread is a common way to service a watchdog only while the whole
system is still making progress.
Add BT_SYSTEM_WORKQUEUE_COOP and apply the range only when it is set.
The components that need the system workqueue to stay cooperative
select the option themselves, so the requirement is recorded next to
the code that has it and a new work item cannot slip past it: the
host stack, the H:5 and STM32WB0 drivers, the NXP wake-on-BT LED
blink option, and BT_CTLR_PRIVACY when the split link layer builds
ull_filter.c.
Mesh, Audio and the other Host users need the Host, so they are
covered by its select; they get their own when the Host drops it.
No in-tree configuration changes behavior: SYSTEM_WORKQUEUE_PRIORITY
already defaults to -1, and no Bluetooth test or sample overrides it.
Signed-off-by: Wai-Hong Tam <waihong@google.com>
Send the vendor-specific RF power mode command from within open(),
through the HCI lockstep helper and the driver's own send path, instead
of implementing the setup() driver API op on top of the Host's
bt_hci_cmd_send_sync(). The response is consumed in the driver's
receive callback by feeding received packets to the lockstep helper
before delivering them to the host.
The driver no longer calls any Host command API, so the configuration
now also runs in controller-only builds, and it no longer selects
BT_HCI_SETUP. A failing or unanswered command fails open() with an
error instead of failing the Host's HCI initialization later, and is
logged by the helper.
The raw send path is factored out of send() and takes the device, so
that it serves both the send() op and the helper. The helper is
initialized once, from the device init function, so that reopening the
transport does not re-initialize its semaphore.
Tested on siwx917_rb4338a with the peripheral_hr sample.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Enable Bluetooth for Series 3 devices by adding new stubs for
symbols from blobs and increasing the link layer stack size.
Signed-off-by: Aksel Skauge Mellbye <aksel.mellbye@silabs.com>
Rename the Kconfig option to SOC_VENDOR_SILABS_HAS_RADIO to
match the guidelines requiring all Kconfig symbols in soc/
to have specific prefixes.
Signed-off-by: Aksel Skauge Mellbye <aksel.mellbye@silabs.com>
Since this driver can and will also be used for series 1, move it one level
up into the respective if-guard.
Signed-off-by: Michael Zimmermann <michael.zimmermann@sevenlab.de>
Signed-off-by: Aksel Skauge Mellbye <aksel.mellbye@silabs.com>
The controller-only build sends the link layer only configuration from
open() for every BlueNRG ACI controller, while the Host build's setup()
sends it only when the device tree sets req-ll-only, as introduced for
the X-NUCLEO-WBA25A1 support in commit a8c09c2e34 ("drivers:
bluetooth: hci: Modify BLE driver to support X-Nucleo-WBA25A1"). Apply
the same condition in open(), and fail open() when the command cannot
be sent instead of ignoring the result.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
bt_spi_bluenrg_setup() ignores the return value of the
ACI_HAL_WRITE_CONFIG_DATA command that puts the BlueNRG into link layer
only mode, while checking the one that sets the public address a few
lines further down. The command was originally sent from the RX
thread's vendor event handler, where there was no caller to report to,
and kept its unchecked form when it moved into setup().
Link layer only mode is a precondition for the Zephyr Host, which needs
a plain HCI controller underneath, and the controller only accepts the
write as its first command after reset, so a failure cannot be retried
later. Return the error, so that bt_enable() fails instead of the stack
coming up on a controller whose embedded host is still active.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
hci_lock exists to serialize the accesses to the controller through
BleStack_Request(), but only send() takes it: the vendor commands that
setup() and close() send bypass it. Nothing else calls into the
controller at those points of the current call sequence, so this is
not an observed race, but the invariant is the driver's own and is
cheap to hold unconditionally. Take the lock around both calls, with
the same error handling as send().
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
The structure has no users: bt_hci_stm32wba_setup() builds the
ACI_HAL_WRITE_CONFIG_DATA command in a byte array instead.
Assisted-by: Claude:claude-fable-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
Enable the esp32 HCI driver on the ESP32-C61: extend the
controller Kconfig gates, report the C61 vendor hardware
variant id, add the hci devicetree node and enable it on the
esp32c61_devkitc board. The C61 BLE controller reuses the C6
controller sources and blobs through the hal.
Assisted-by: Claude:opus-4-8
Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
BT_USERCHAN is currently limited to BOARD_NATIVE_SIM, but the
driver is implemented for native simulator based targets that use
the native host environment rather than for that specific board.
Bluetooth host-only applications can be built separately from the
controller and communicate with an external controller over HCI.
Allow native simulator based targets to use the same userchan HCI
transport when the application devicetree selects a
zephyr,bt-hci-userchan device.
Relax the dependency from BOARD_NATIVE_SIM to NATIVE_LIBRARY so
host-only Bluetooth applications can use userchan on native simulator
based targets, including out-of-tree boards, when they run in real
time.
This enables split host/controller simulation setups where the
Bluetooth host runs as one native simulator process and connects
over userchan to an external HCI controller process.
Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
Rename the ESP32_SOC_* capability symbols to SOC_ESP32_* so
that symbols defined under the soc folder follow the Zephyr
Kconfig naming policy. Update all references in the common
soc code and in the counter and bluetooth drivers.
Signed-off-by: Sylvio Alves <sylvio.alves@espressif.com>
Use controller/peripheral and SDO/SDI terminology in the remaining
SPI-using drivers (audio, auxdisplay, bluetooth HCI, dac, eeprom,
ethernet, flash, fpga, gpio, haptics, hdlc_rcp_if, ieee802154,
input, led, led_strip, lora, mfd, misc, mux, rtc, sdhc, stepper,
video, watchdog, wifi) and the ec_host_cmd SPI STM32 backend,
following coding guideline rule A.2: switch to
SPI_OP_MODE_CONTROLLER/PERIPHERAL and SPI_SDO_OVERRUN_DT, rename
Zephyr-owned identifiers (the HCI SPI header buffers, the winc1500
bus wrapper transfer parameters), and update comments, log messages
and Kconfig help prose.
Vendor and out-of-scope identifiers keep their names: STM32
LL_SPI_MODE_SLAVE in the ec_host_cmd backend, the ATWINC1500 SDK I2C
SLAVE_ADDRESS definition, and the I2S codec clock-role variable in
tlv320aic26.
Assisted-by: Claude:fable-5
Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
Two-line copyright notices were wrapped in the SPDX "<text>...</text>"
construct, which is only valid in an SPDX document, not a file header.
The REUSE tool then folds the literal "<text>" into the holder name
and drops the second line from the SBOM.
Remove the markers and tag the continuation line. Holder, year and
e-mail are left unchanged; only the syntax is fixed.
Signed-off-by: Parthiban Nallathambi <parthiban@linumiz.com>
Recently reworked ICBMSG IPC service backend executes receive callback
from an interrupt context of the mailbox driver. Additional thread is
needed and processing of received messages is deferred to that thread.
It is a similar approach like in case of uart (h4.c). Implementation
utilizes RX buffer holding feature so no need to allocate additional
buffer. IPC RX buffer is hold in the receive callback and thread
releases it.
Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
bt_nxp_close() was a no-op, violating the bt_hci_close() contract that
requires the transport to be fully closed before the function returns.
After bt_hci_close() cleared data->recv, the NXP HAL could still fire
the RX callback, and on a quick reopen stale packets could be delivered
into the new session.
Deregister the HCI RX callback via PLATFORM_SetHciRxCallback(NULL) and
propagate any error so bt_hci_close() only clears data->recv after the
transport is confirmed closed. With CONFIG_HCI_NXP_RX_THREAD, a plain
K_NO_WAIT drain loop is not sufficient: when bt_rx_thread is blocked in
k_msgq_get(K_FOREVER), k_msgq_put() hands the frame directly into the
thread's stack buffer without touching msgq->used_msgs, so the drain
misses any frame the thread already holds. Add bt_nxp_rx_drain(): flush
buffered frames, post a sentinel (data == NULL) with K_FOREVER, and
wait on rx_drain_sem until bt_rx_thread acknowledges it. Because the
queue is FIFO, the acknowledgement guarantees every pre-close frame has
been processed before close returns.
Signed-off-by: Guotao Zhang <guotao.zhang@nxp.com>
Replace direct NVIC_SetPendingIRQ()/NVIC_ClearPendingIRQ()/
NVIC_EnableIRQ() calls with the portable k_irq_set_pending()/
k_irq_clear_pending()/irq_enable() equivalents. The Smartbond DA1469x
is a plain-NVIC Cortex-M33, so the pending-state capabilities are
always available where this code builds.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
MISRA C:2012 Rule 8.2 requires every parameter in a function type to be
named, including the parameters of function pointer parameters.
The LLCP remote request helper, the LLL test and scan helpers and the
PSoC 6 BLESS receive thread left parameters unnamed. The BLESS thread
gets ARG_UNUSED() for the arguments it deliberately ignores.
Name them after the arguments the documentation or the
definitions already use. No functional change.
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
bt_hci_stm32wba_send() calls BleStack_Request() while holding hci_sem.
If the controller indicates an event from within that call, the
resulting BLECB_Indication() takes the same semaphore from the same
thread and blocks forever, since a semaphore has no notion of an owner.
Use a mutex instead, which the owning thread is allowed to lock
recursively.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>
hci_tx_pkt is a file-scope variable, but psoc6_bless_send() clears and
populates it before taking psoc6_bless_operation_sem, so two senders
can overwrite each other's packet information, and the one holding the
semaphore can end up handing the controller a packet that describes the
other buffer.
Nothing else uses the variable, and it does not need to outlive the
call: Cy_BLE_SoftHciSendAppPkt() copies the packet into the
controller's buffer before returning, as documented in cy_ble_stack.h.
Make it a local variable, which removes the shared state instead of
locking it.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Johan Hedberg <johan.hedberg@silabs.com>