Zephyr API Documentation 4.4.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
Bluetooth HCI lockstep command helper

Bluetooth HCI lockstep command helper. More...

Data Structures

struct  bt_hci_lockstep
 Lockstep helper. More...

Typedefs

typedef int(* bt_hci_lockstep_send_t) (const struct device *dev, const uint8_t *pkt, size_t len)
 Transport send function of a lockstep helper.

Functions

void bt_hci_lockstep_init (struct bt_hci_lockstep *ls, const struct device *dev, bt_hci_lockstep_send_t send)
 Initialize a lockstep helper.
bool bt_hci_lockstep_feed (struct bt_hci_lockstep *ls, const uint8_t *pkt, size_t len)
 Feed a received HCI packet to a lockstep helper.
int bt_hci_lockstep_cmd_send_sync (struct bt_hci_lockstep *ls, uint16_t opcode, struct net_buf_simple *cmd, struct net_buf_simple *rsp)
 Send an HCI command and wait for its response.

Detailed Description

Bluetooth HCI lockstep command helper.

Since
4.5
Version
0.1.0

Helper for sending HCI commands one at a time and waiting for their responses, for HCI drivers that exchange HCI commands with the controller over their own transport — typically for vendor-specific controller initialization — without the Bluetooth Host's command machinery and regardless of whether a Host is present in the build.

The helper relies on the HCI traffic being in lockstep: while a command is outstanding no other command is sent, so the next command response received is the response to that command. This holds during controller initialization, before the HCI transport is handed over to its user, and removes the need for an opcode correlation state machine. Command flow control still applies: a command is sent only once the controller allows one, which it does initially and through the Num_HCI_Command_Packets field of every command response, including the HCI_Command_Complete event with the NOP opcode that a controller sends to allow commands on its own.

The driver provides the send function of its transport, and feeds the packets it receives from the controller to bt_hci_lockstep_feed(), which consumes the awaited response and leaves every other packet to the driver. Commands are built with the helpers of hci_pkt.h, which this header includes.

The helper is part of every build with CONFIG_BT enabled.

Note
This is not an application API: the intended users are HCI drivers. Applications that need to send HCI commands alongside a running Host use the higher-level bt_hci_cmd_alloc(), bt_hci_cmd_send() and bt_hci_cmd_send_sync() APIs of hci.h, which cooperate with the Host's command flow control.

Typedef Documentation

◆ bt_hci_lockstep_send_t

typedef int(* bt_hci_lockstep_send_t) (const struct device *dev, const uint8_t *pkt, size_t len)

#include <zephyr/drivers/bluetooth/hci_lockstep.h>

Transport send function of a lockstep helper.

Transmits a complete HCI packet to the controller.

A negative return means that the command was not submitted to the controller: the helper keeps the command allowance it would have used. A transport that cannot tell whether a command reached the controller before it failed returns 0 and leaves the outcome to the response wait.

Parameters
devHCI device given to bt_hci_lockstep_init().
pktPacket to send, starting with its packet indicator.
lenLength of pkt in bytes.
Return values
0The packet has been submitted to the controller.
Returns
Negative errno value on failure, the packet not having been submitted; propagated to the caller of bt_hci_lockstep_cmd_send_sync().

Function Documentation

◆ bt_hci_lockstep_cmd_send_sync()

int bt_hci_lockstep_cmd_send_sync ( struct bt_hci_lockstep * ls,
uint16_t opcode,
struct net_buf_simple * cmd,
struct net_buf_simple * rsp )

#include <zephyr/drivers/bluetooth/hci_lockstep.h>

Send an HCI command and wait for its response.

Frames the command parameters in cmd into a complete HCI command packet with bt_hci_pkt_push_cmd_hdr(), waits for the controller to allow a command, transmits the packet with the transport send function and waits for the controller's HCI_Command_Complete or HCI_Command_Status response to arrive through bt_hci_lockstep_feed(). The call waits at most bt_hci_lockstep::timeout in total, for the controller to allow a command and then to respond to it.

The response is stored in rsp, which is emptied first: its status, followed by the return parameters of an HCI_Command_Complete, which is the layout of the bt_hci_rp_* structures of hci_types.h. Bytes beyond the capacity of rsp are discarded, so size it for the expected return parameters. An HCI_Command_Status response carries no return parameters, so rsp holds its status alone, which only means that the controller has accepted the command, with completion reported later through the command's own event.

Must be called from thread context, one call at a time: the driver serializes its callers. On -EINVAL and -EMSGSIZE cmd is unchanged; on every other return it holds the complete command packet, so use bt_hci_pkt_reset_cmd() before reusing it. Every failure is logged together with the opcode, so the caller need not log it again. A transport send failure reported after the response has already arrived is only logged: the command reached the controller, and its response counts.

-EAGAIN means an unresponsive controller, to be treated as such rather than retried: either it allowed no command within the timeout, or it did not respond to the command, after which it allows no further command and a late response could not be told apart from the response to a subsequent command with the same opcode.

Parameters
lsLockstep helper.
opcodeHCI command opcode.
cmdBuffer holding the command parameters, set up with BT_HCI_PKT_CMD_DEFINE() or bt_hci_pkt_reset_cmd(), or NULL for a command without parameters.
rspBuffer for the return parameters, or NULL to discard them.
Return values
0The command completed successfully.
-EIOThe controller responded with an error status, logged and stored in rsp.
-EAGAINThe controller allowed no command, or did not respond, within bt_hci_lockstep::timeout.
-EINVALcmd has insufficient headroom for the packet prefix.
-EMSGSIZEcmd holds more parameter bytes than an HCI command can carry.
Returns
Negative errno value on a transport send failure, as returned by the send function; the command was not submitted.

◆ bt_hci_lockstep_feed()

bool bt_hci_lockstep_feed ( struct bt_hci_lockstep * ls,
const uint8_t * pkt,
size_t len )
isr-ok

#include <zephyr/drivers/bluetooth/hci_lockstep.h>

Feed a received HCI packet to a lockstep helper.

To be called by the driver for every packet received from the controller while the helper is in use. When the packet is the response to the command that bt_hci_lockstep_cmd_send_sync() is waiting for, the helper consumes it and wakes the waiter; any other packet is left to the driver to process as usual. The packet is not modified.

Every command response fed, consumed or not, also updates the number of commands the controller allows, which bt_hci_lockstep_cmd_send_sync() waits for; the HCI_Command_Complete event with the NOP opcode exists for that alone.

Can be called from any context, including ISRs. Calls are serialized by the driver's single receive path and come in the order the packets were received.

Parameters
lsLockstep helper.
pktReceived packet, starting with its packet indicator.
lenLength of pkt in bytes.
Return values
trueThe packet was the awaited response and has been consumed.
falseThe packet is not the awaited response.

◆ bt_hci_lockstep_init()

void bt_hci_lockstep_init ( struct bt_hci_lockstep * ls,
const struct device * dev,
bt_hci_lockstep_send_t send )

#include <zephyr/drivers/bluetooth/hci_lockstep.h>

Initialize a lockstep helper.

To be called once, typically from the driver's device initialization function: the helper can then be used every time the transport is opened, without its semaphore being re-initialized. Initializing the helper again restores the initial allowance of one command, for a controller reset by other means than an HCI command; the helper must be idle at that point, with no bt_hci_lockstep_cmd_send_sync() or bt_hci_lockstep_feed() call in progress, so the driver's receive path is stopped first.

Parameters
lsLockstep helper.
devHCI device, passed to send.
sendTransport send function.