|
Zephyr API Documentation 4.4.99
A Scalable Open Source RTOS
|
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. | |
Bluetooth HCI lockstep command helper.
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.
#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.
| dev | HCI device given to bt_hci_lockstep_init(). |
| pkt | Packet to send, starting with its packet indicator. |
| len | Length of pkt in bytes. |
| 0 | The packet has been submitted to the controller. |
| 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.
| ls | Lockstep helper. |
| opcode | HCI command opcode. |
| cmd | Buffer 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. |
| rsp | Buffer for the return parameters, or NULL to discard them. |
| 0 | The command completed successfully. |
| -EIO | The controller responded with an error status, logged and stored in rsp. |
| -EAGAIN | The controller allowed no command, or did not respond, within bt_hci_lockstep::timeout. |
| -EINVAL | cmd has insufficient headroom for the packet prefix. |
| -EMSGSIZE | cmd holds more parameter bytes than an HCI command can carry. |
|
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.
| ls | Lockstep helper. |
| pkt | Received packet, starting with its packet indicator. |
| len | Length of pkt in bytes. |
| 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.
| ls | Lockstep helper. |
| dev | HCI device, passed to send. |
| send | Transport send function. |