blob: 894ed719f457d6239451d3f36fea33f65430d070 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_USBDEV_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_USBDEV_H_
/**
* @file
* @brief <a href="/hw/ip/usbdev/doc/">USB Device</a> Device Interface Functions
*/
#include <stddef.h>
#include <stdint.h>
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_warn_unused_result.h"
/**
* Hardware constants.
*/
#define USBDEV_NUM_ENDPOINTS 12
#define USBDEV_MAX_PACKET_SIZE 64
// Internal constant that should not be used by clients. Defined here because
// it is used in the definition of `dif_usbdev_buffer_pool` below.
#define USBDEV_NUM_BUFFERS 32
/**
* Free buffer pool.
*
* A USB device has a fixed number of buffers that are used for storing incoming
* and outgoing packets and the software is responsible for keeping track of
* free buffers. The pool is implemented as a stack for constant-time add and
* remove. `top` points to the last free buffer added to the pool. The pool is
* full when `top == USBDEV_NUM_BUFFERS - 1` and empty when `top == -1`.
*/
typedef struct dif_usbdev_buffer_pool {
uint8_t buffers[USBDEV_NUM_BUFFERS];
int8_t top;
} dif_usbdev_buffer_pool_t;
/**
* Buffer types.
*/
typedef enum dif_usbdev_buffer_type {
/**
* For reading payloads of incoming packets.
*/
kDifUsbdevBufferTypeRead,
/**
* For writing payloads of outgoing packets.
*/
kDifUsbdevBufferTypeWrite,
/**
* Clients must not use a buffer after it is handed over to hardware or
* returned to the free buffer pool. This type exists to protect against such
* cases.
*/
kDifUsbdevBufferTypeStale,
} dif_usbdev_buffer_type_t;
/**
* A USB device buffer.
*
* This struct represents a USB device buffer that has been provided to a client
* in response to a buffer request. Clients should treat instances of this
* struct as opaque objects and should pass them to the appropriate functions of
* this library to read and write payloads of incoming and outgoing packets,
* respectively.
*
* See also: `dif_usbdev_recv`, `dif_usbdev_buffer_read`,
* `dif_usbdev_buffer_request`, `dif_usbdev_buffer_write`,
* `dif_usbdev_send`, `dif_usbdev_buffer_return`.
*/
typedef struct dif_usbdev_buffer {
/**
* Hardware buffer id.
*/
uint8_t id;
/**
* Byte offset for the next read or write operation.
*/
uint8_t offset;
/**
* For read buffers: remaining number of bytes to read.
* For write buffers: remaining number of bytes that can be written.
*/
uint8_t remaining_bytes;
/**
* Type of this buffer.
*/
dif_usbdev_buffer_type_t type;
} dif_usbdev_buffer_t;
/**
* Internal state of a USB device.
*
* Instances of this struct must be initialized by `dif_usbdev_init()` before
* being passed to other functions in this library. Its fields should be
* considered private and are only provided here so that callers can allocate
* it.
*/
typedef struct dif_usbdev {
mmio_region_t base_addr;
dif_usbdev_buffer_pool_t buffer_pool;
} dif_usbdev_t;
/**
* Enumeration for enabling/disabling various functionality.
*/
typedef enum dif_usbdev_toggle {
kDifUsbdevToggleDisable,
kDifUsbdevToggleEnable,
} dif_usbdev_toggle_t;
/**
* Set of allowed configurations for USB power sense override.
*/
typedef enum dif_usbdev_power_sense_override {
kDifUsbdevPowerSenseOverrideDisabled,
kDifUsbdevPowerSenseOverridePresent,
kDifUsbdevPowerSenseOverrideNotPresent
} dif_usbdev_power_sense_override_t;
/**
* Configuration for initializing a USB device.
*/
typedef struct dif_usbdev_config {
/**
* Base address of the USB device.
*/
mmio_region_t base_addr;
/**
* Use the differential rx signal instead of the single-ended signals.
*/
dif_usbdev_toggle_t differential_rx;
/**
* Use the differential tx signal instead of the single-ended signals.
*/
dif_usbdev_toggle_t differential_tx;
/*
* Recognize a single SE0 bit as end of packet instead of requiring
* two bits.
*/
dif_usbdev_toggle_t single_bit_eop;
/**
* Override USB power sense.
*/
dif_usbdev_power_sense_override_t power_sense_override;
/**
* Flip the D+/D- pins.
*/
dif_usbdev_toggle_t pin_flip;
/**
* Reference signal generation for clock synchronization.
*/
dif_usbdev_toggle_t clock_sync_signals;
} dif_usbdev_config_t;
/**
* Common return codes for the functions in this library.
*/
typedef enum dif_usbdev_result {
/**
* Indicates that the call succeeded.
*/
kDifUsbdevOK = 0,
/**
* Indicates that a non-specific error occurred and the hardware is in an
* invalid or irrecoverable state.
*/
kDifUsbdevError = 1,
/**
* Indicates that the caller supplied invalid arguments but the call did not
* cause any side-effects and the hardware is in a valid and recoverable
* state.
*/
kDifUsbdevBadArg = 2,
} dif_usbdev_result_t;
/**
* Initialize a USB device.
*
* A USB device must first be initialized by this function before calling other
* functions in this library.
*
* @param config Configuration for initializing a USB device.
* @param[out] usbdev Internal state of the initialized USB device.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_init(dif_usbdev_config_t *config,
dif_usbdev_t *usbdev);
/**
* Fill the available buffer FIFO of a USB device.
*
* The USB device has a small FIFO (AV FIFO) that stores free buffers for
* incoming packets. It is the responsibility of the software to ensure that the
* AV FIFO is never empty. If the host tries to send a packet when the AV FIFO
* is empty, the USB device will respond with a NAK. While this will typically
* cause the host to retry transmission for regular data packets, there are
* transactions in the USB protocol during which the USB device is not allowed
* to send a NAK. Thus, the software must make sure that the AV FIFO is never
* empty by calling this function periodically.
*
* @param usbdev A USB device.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_fill_available_fifo(dif_usbdev_t *usbdev);
/**
* Enable or disable reception of SETUP packets for an endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param new_state New SETUP packet reception state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_endpoint_setup_enable(
dif_usbdev_t *usbdev, uint8_t endpoint, dif_usbdev_toggle_t new_state);
/**
* Enable or disable reception of OUT packets for an endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param new_state New OUT packet reception state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_endpoint_out_enable(
dif_usbdev_t *usbdev, uint8_t endpoint, dif_usbdev_toggle_t new_state);
/**
* Enable or disable STALL for an endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param new_state New STALL state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_endpoint_stall_enable(
dif_usbdev_t *usbdev, uint8_t endpoint, dif_usbdev_toggle_t new_state);
/**
* Get STALL state of an endpoint.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param[out] state Current STALL state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_endpoint_stall_get(dif_usbdev_t *usbdev,
uint8_t endpoint,
bool *state);
/**
* Enable or disable isochronous mode for an endpoint.
*
* Isochronous endpoints transfer data periodically. Since isochronous transfers
* do not have a handshaking stage, isochronous endpoints cannot report errors
* or STALL conditions.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param new_state New isochronous state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_endpoint_iso_enable(
dif_usbdev_t *usbdev, uint8_t endpoint, dif_usbdev_toggle_t new_state);
/**
* Enable the USB interface of a USB device.
*
* Calling this function causes the USB device to assert the full-speed pull-up
* signal to indicate its presence to the host.
*
* @param usbdev A USB device.
* @param new_state New interface state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_interface_enable(dif_usbdev_t *usbdev,
dif_usbdev_toggle_t new_state);
/**
* Information about a received packet.
*/
typedef struct dif_usbdev_rx_packet_info {
/**
* Endpoint of the packet.
*/
uint8_t endpoint;
/**
* Payload length in bytes.
*/
uint8_t length;
/**
* Indicates if the packet is a SETUP packet.
*/
bool is_setup;
} dif_usbdev_rx_packet_info_t;
/**
* Return codes for `dif_usbdev_recv`.
*/
typedef enum dif_usbdev_recv_result {
/**
* Indicates that the call succeeded.
*/
kDifUsbdevRecvResultOK = kDifUsbdevOK,
/**
* Indicates that a non-specific error occurred and the hardware is in an
* invalid or irrecoverable state.
*/
kDifUsbdevRecvResultError = kDifUsbdevError,
/**
* Indicates that the caller supplied invalid arguments but the call did not
* cause any side-effects and the hardware is in a valid and recoverable
* state.
*/
kDifUsbdevRecvResultBadArg = kDifUsbdevBadArg,
/**
* Indicates that RX FIFO is empty.
*/
kDifUsbdevRecvResultNoNewPacket,
} dif_usbdev_recv_result_t;
/**
* Get the packet at the front of RX FIFO.
*
* The USB device has a small FIFO (RX FIFO) that stores received packets until
* the software has a chance to process them. It is the responsibility of the
* software to ensure that the RX FIFO is never full. If the host tries to send
* a packet when the RX FIFO is full, the USB device will respond with a NAK.
* While this will typically cause the host to retry transmission for regular
* data packets, there are transactions in the USB protocol during which the USB
* device is not allowed to send a NAK. Thus, the software must read received
* packets as soon as possible.
*
* Reading received packets involves two main steps:
* - Calling this function, i.e. `dif_usbdev_recv`, and
* - Calling `dif_usbdev_buffer_read` until the entire packet payload
* is read.
*
* In order to read an incoming packet, clients should first call this function
* to get information about the packet and the buffer that holds the packet
* payload. Then, clients should call `dif_usbdev_buffer_read` with this buffer
* one or more times (depending on the sizes of their internal buffers) until
* the entire packet payload is read. Once the entire payload is read, the
* buffer is returned to the free buffer pool. If the clients want to ignore the
* payload of a packet, e.g. for an unsupported or a zero-length packet, they
* can call `dif_usbdev_buffer_return` to immediately return the buffer to the
* free buffer pool.
*
* @param usbdev A USB device.
* @param[out] packet_info Packet information.
* @param[out] buffer Buffer that holds the packet payload.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_recv_result_t dif_usbdev_recv(
dif_usbdev_t *usbdev, dif_usbdev_rx_packet_info_t *packet_info,
dif_usbdev_buffer_t *buffer);
/**
* Return codes for `dif_usbdev_buffer_read`.
*/
typedef enum dif_usbdev_buffer_read_result {
/**
* Indicates that the call succeeded and the entire packet payload is read.
*/
kDifUsbdevBufferReadResultOK,
/**
* Indicates that a non-specific error occurred and the hardware is in an
* invalid or irrecoverable state.
*/
kDifUsbdevBufferReadResultError,
/**
* Indicates that the caller supplied invalid arguments but the call did not
* cause any side-effects and the hardware is in a valid and recoverable
* state.
*/
kDifUsbdevBufferReadResultBadArg,
/**
* Indicates that the call was successful but there are remaining bytes to be
* read.
*/
kDifUsbdevBufferReadResultContinue,
} dif_usbdev_buffer_read_result_t;
/**
* Read incoming packet payload.
*
* Clients should call this function with a buffer provided by `dif_usbdev_recv`
* to read the payload of an incoming packet. This function copies the smaller
* of `dst_len` and remaining number of bytes in the buffer to `dst`. The buffer
* that holds the packet payload is returned to the free buffer pool when the
* entire packet payload is read.
*
* See also: `dif_usbdev_recv`.
*
* @param usbdev A USB device.
* @param buffer A buffer provided by `dif_usbdev_recv`.
* @param[out] dst Destination buffer.
* @param dst_len Length of the destination buffer.
* @param[out] bytes_written Number of bytes written to destination buffer.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_buffer_read_result_t dif_usbdev_buffer_read(
dif_usbdev_t *usbdev, dif_usbdev_buffer_t *buffer, uint8_t *dst,
size_t dst_len, size_t *bytes_written);
/**
* Return a buffer to the free buffer pool.
*
* This function immediately returns the given buffer to the free buffer pool.
* Since `dif_usbdev_buffer_read` and `dif_usbdev_get_tx_status` return the
* buffers that they work on to the free buffer pool automatically, this
* function should only be called to discard the payload of a received
* packet or a packet that was being prepared for transmission before it is
* queued for transmission from an endpoint.
*
* See also: `dif_usbdev_recv`, `dif_usbdev_buffer_request`.
*
* @param usbdev A USB device.
* @param buffer A buffer provided by `dif_usbdev_recv` or
* `dif_usbdev_buffer_request`.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_buffer_return(dif_usbdev_t *usbdev,
dif_usbdev_buffer_t *buffer);
/**
* Return codes for `dif_usbdev_buffer_request`.
*/
typedef enum dif_usbdev_buffer_request_result {
/**
* Indicates that the call succeeded.
*/
kDifUsbdevBufferRequestResultOK = kDifUsbdevOK,
/**
* Indicates that a non-specific error occurred and the hardware is in an
* invalid or irrecoverable state.
*/
kDifUsbdevBufferRequestResultError = kDifUsbdevError,
/**
* Indicates that the caller supplied invalid arguments but the call did not
* cause any side-effects and the hardware is in a valid and recoverable
* state.
*/
kDifUsbdevBufferRequestResultBadArg = kDifUsbdevBadArg,
/**
* Indicates that there are no free buffers.
*/
kDifUsbdevBufferRequestResultNoBuffers,
} dif_usbdev_buffer_request_result_t;
/**
* Request a buffer for outgoing packet payload.
*
* Clients should call this function to request a buffer to write the payload of
* an outgoing packet. Sending a packet from a particular endpoint to the host
* involves four main steps:
* - Calling this function, i.e. `dif_usbdev_buffer_request`,
* - Calling `dif_usbdev_buffer_write`,
* - Calling `dif_usbdev_send`, and
* - Calling `dif_usbdev_get_tx_status`.
*
* In order to send a packet, clients should first call this function to obtain
* a buffer for the packet payload. Clients should then call
* `dif_usbdev_buffer_write` (one or more times depending on the sizes of their
* internal buffers) to write the packet payload to this buffer. After writing
* the packet payload, clients should call `dif_usbdev_send` to mark the packet
* as ready for transmission from a particular endpoint. Then, clients should
* call `dif_usbdev_get_tx_status` to check the status of the transmission.
* `dif_usbdev_get_tx_status` returns the buffer that holds the packet payload
* to the free buffer pool once the packet is either successfully transmitted or
* canceled due to an incoming SETUP packet or a link reset. If the packet
* should no longer be sent, clients can call `dif_usbdev_buffer_return` to
* return the buffer to the free buffer pool as long as `dif_usbdev_send` is not
* called yet.
*
* See also: `dif_usbdev_buffer_write`, `dif_usbdev_send`,
* `dif_usbdev_get_tx_status`, `dif_usbdev_buffer_return`.
*
* @param usbdev A USB device.
* @param[out] buffer A buffer for writing outgoing packet payload.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_buffer_request_result_t dif_usbdev_buffer_request(
dif_usbdev_t *usbdev, dif_usbdev_buffer_t *buffer);
typedef enum dif_usbdev_buffer_write_result {
/**
* Indicates that the call succeeded.
*/
kDifUsbdevBufferWriteResultOK = kDifUsbdevOK,
/**
* Indicates that a non-specific error occurred and the hardware is in an
* invalid or irrecoverable state.
*/
kDifUsbdevBufferWriteResultError = kDifUsbdevError,
/**
* Indicates that the caller supplied invalid arguments but the call did not
* cause any side-effects and the hardware is in a valid and recoverable
* state.
*/
kDifUsbdevBufferWriteResultBadArg = kDifUsbdevBadArg,
/**
* Indicates that the requested write exceeds the device buffer size.
*/
kDifUsbdevBufferWriteResultFull,
} dif_usbdev_buffer_write_result_t;
/**
* Write outgoing packet payload.
*
* Clients should call this function with a buffer provided by
* `dif_usbdev_buffer_request` to write the payload of an outgoing packet. This
* function copies the smaller of `src_len` and remaining number of bytes in the
* buffer to the buffer. Clients should then call `dif_usbdev_send` to queue the
* packet for transmission from a particular endpoint.
*
* See also: `dif_usbdev_buffer_request`, `dif_usbdev_send`,
* `dif_usbdev_get_tx_status`, `dif_usbdev_buffer_return`.
*
* @param usbdev A USB device.
* @param buffer A buffer provided by `dif_usbdev_buffer_request`.
* @param src Source buffer.
* @param src_len Length of the source buffer.
* @param[out] bytes_written Number of bytes written to the USB device buffer.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_buffer_write_result_t dif_usbdev_buffer_write(
dif_usbdev_t *usbdev, dif_usbdev_buffer_t *buffer, uint8_t *src,
size_t src_len, size_t *bytes_written);
/**
* Mark a packet ready for transmission from an endpoint.
*
* The USB device has 12 endpoints, each of which can be used to send packets to
* the host. Since a packet is not actually transmitted to the host until the
* host sends an IN token, clients must write the packet payload to a device
* buffer and mark it as ready for transmission from a particular endpoint. A
* packet queued for transmission from a particular endpoint is transmitted once
* the host sends an IN token for that endpoint.
*
* After a packet is queued for transmission, clients should check its status by
* calling `dif_usbdev_get_tx_status`. While the USB device handles transmission
* errors automatically by retrying transmission, transmission of a packet may
* be canceled if the endpoint receives a SETUP packet or the link is reset
* before the queued packet is transmitted. In these cases, clients should
* handle the SETUP packet or the link reset first and then optionally send the
* same packet again. Clients must also make sure that the given endpoint does
* not already have a packet pending for transmission before calling this
* function.
*
* See also: `dif_usbdev_buffer_request`, `dif_usbdev_buffer_write`,
* `dif_usbdev_get_tx_status`, `dif_usbdev_buffer_return`.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param buffer A buffer provided by `dif_usbdev_buffer_request`.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_send(dif_usbdev_t *usbdev, uint8_t endpoint,
dif_usbdev_buffer_t *buffer);
/**
* Status of an outgoing packet.
*/
typedef enum dif_usbdev_tx_status {
/**
* There is no packet for the given endpoint.
*/
kDifUsbdevTxStatusNoPacket,
/**
* Packet is pending transmission.
*/
kDifUsbdevTxStatusPending,
/**
* Packet was sent successfully.
*/
kDifUsbdevTxStatusSent,
/**
* Transmission was canceled due to an incoming SETUP packet.
*/
kDifUsbdevTxStatusCancelled,
} dif_usbdev_tx_status_t;
/**
* Get the status of a packet that has been queued to be sent from an endpoint.
*
* While the USB device handles transmission errors automatically by retrying
* transmission, transmission of a packet may be canceled if the endpoint
* receives a SETUP packet or the link is reset before the queued packet is
* transmitted. In these cases, clients should handle the SETUP packet or the
* link reset first and then optionally send the same packet again.
*
* This function returns the buffer that holds the packet payload to the free
* buffer pool once the packet is either successfully transmitted or canceled
* due to an incoming SETUP packet or a link reset.
*
* @param usbdev A USB device.
* @param endpoint An endpoint.
* @param[out] status Status of the packet.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_get_tx_status(dif_usbdev_t *usbdev,
uint8_t endpoint,
dif_usbdev_tx_status_t *status);
/**
* Set the address of a USB device.
*
* @param usbdev A USB device.
* @param addr New address. Only the last 7 bits are significant.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_address_set(dif_usbdev_t *usbdev, uint8_t addr);
/**
* Get the address of a USB device.
*
* @param usbdev A USB device.
* @param[out] addr Current address.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_address_get(dif_usbdev_t *usbdev, uint8_t *addr);
/**
* Get USB frame index.
*
* @param usbdev A USB device.
* @param[out] frame_index USB frame index.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_frame(dif_usbdev_t *usbdev,
uint16_t *frame_index);
/**
* Check if the host is lost.
*
* The host is lost if the link is still active but a start of frame packet has
* not been received in the last 4.096ms.
*
* @param usbdev A USB device.
* @param[out] host_lost Status of the host. `true` if the host is lost, `false`
* otherwise.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_host_lost(dif_usbdev_t *usbdev,
bool *host_lost);
/**
* USB link state.
*/
typedef enum dif_usbdev_link_state {
kDifUsbdevLinkStateDisconnected,
kDifUsbdevLinkStatePowered,
kDifUsbdevLinkStatePoweredSuspend,
kDifUsbdevLinkStateActive,
kDifUsbdevLinkStateSuspend,
} dif_usbdev_link_state_t;
/**
* Get USB link state.
*
* @param usbdev A USB device.
* @param[out] link_state USB link state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_link_state(
dif_usbdev_t *usbdev, dif_usbdev_link_state_t *link_state);
/**
* Get the state of the sense pin.
*
* @param usbdev A USB device.
* @param[out] sense State of the sense pin. `true` if the host is providing
* VBUS, `false` otherwise.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_sense(dif_usbdev_t *usbdev,
bool *sense);
/**
* Get the depth of the AV FIFO.
*
* See also: `dif_usbdev_fill_available_fifo`.
*
* @param usbdev A USB device.
* @param[out] depth Depth of the AV FIFO.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_available_fifo_depth(
dif_usbdev_t *usbdev, uint8_t *depth);
/**
* Check if AV FIFO is full.
*
* See also: `dif_usbdev_fill_available_fifo`.
*
* @param usbdev A USB device.
* @param[out] is_full State of the AV FIFO. `true` if full, false otherwise.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_available_fifo_full(
dif_usbdev_t *usbdev, bool *is_full);
/**
* Get the depth of the RX FIFO.
*
* See also: `dif_usbdev_recv`.
*
* @param usbdev A USB device.
* @param[out] depth Depth of the RX FIFO.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_rx_fifo_depth(dif_usbdev_t *usbdev,
uint8_t *depth);
/**
* Check if the RX FIFO is empty.
*
* See also: `dif_usbdev_recv`.
*
* @param usbdev A USB device.
* @param[out] is_empty State of the RX FIFO. `true` if empty, `false`
* otherwise.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_status_get_rx_fifo_empty(dif_usbdev_t *usbdev,
bool *is_empty);
/**
* USB device interrupts.
*/
typedef enum dif_usbdev_irq {
/**
* \internal First USB device interrupt.
*/
kDifUsbdevIrqFirst,
/**
* A packet was received as part of an OUT or SETUP transaction.
*/
kDifUsbdevIrqPktReceived = kDifUsbdevIrqFirst,
/**
* A packet was sent as part of an IN transaction.
*/
kDifUsbdevIrqPktSent,
/**
* VBUS was lost and the link was disconnected.
*/
kDifUsbdevIrqDisconnected,
/**
* A Start-of-Frame (SOF) packet was not received on an active link
* for 4.096 ms. The host must send a SOF packet every 1 ms.
*/
kDifUsbdevIrqHostLost,
/**
* Link was reset by the host.
*/
kDifUsbdevIrqLinkReset,
/**
* Link was suspended by the host.
*/
kDifUsbdevIrqLinkSuspend,
/**
* Link became active again after being suspended.
*/
kDifUsbdevIrqLinkResume,
/**
* Available buffer FIFO was empty.
*/
kDifUsbdevIrqAvEmpty,
/**
* Received buffer FIFO was full.
*/
kDifUsbdevIrqRxFull,
/**
* A write was done to available buffer FIFO when it was full.
*/
kDifUsbdevIrqAvOverflow,
/**
* The ACK packet expected in response to an IN transaction was
* not received.
*/
kDifUsbdevIrqLinkInError,
/**
* A CRC error occurred.
*/
kDifUsbdevIrqRxCrcError,
/**
* A packet with an invalid packet identifier (PID) was received.
*/
kDifUsbdevIrqRxPidError,
/**
* A packet with invalid bitstuffing was received.
*/
kDifUsbdevIrqRxBitstuffError,
/**
* USB frame number was updated with a valid SOF packet.
*/
kDifUsbdevIrqFrame,
/**
* VBUS was detected.
*/
kDifUsbdevIrqConnected,
/**
* \internal Last USB device interrupt.
*/
kDifUsbdevIrqLast = kDifUsbdevIrqConnected
} dif_usbdev_irq_t;
/**
* Enable or disable an interrupt.
*
* @param usbdev A USB device.
* @param irq An interrupt.
* @param state New state of the interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_enable(dif_usbdev_t *usbdev,
dif_usbdev_irq_t irq,
dif_usbdev_toggle_t state);
/**
* Check if there is a pending request for an interrupt.
*
* @param usbdev A USB device.
* @param irq An interrupt.
* @param[out] state State of the interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_get(dif_usbdev_t *usbdev,
dif_usbdev_irq_t irq, bool *state);
/**
* Clear an interrupt.
*
* @param usbdev A USB device.
* @param irq An interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_clear(dif_usbdev_t *usbdev,
dif_usbdev_irq_t irq);
/**
* Clear all pending interrupts.
*
* @param usbdev A USB device.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_clear_all(dif_usbdev_t *usbdev);
/**
* Disable all interrupts and optionally return the current interrupt
* configuration.
*
* @param usbdev A USB device.
* @param[out] cur_config Current interrupt configuration.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_disable_all(dif_usbdev_t *usbdev,
uint32_t *cur_config);
/**
* Restore interrupt configuration.
*
* @param usbdev A USB device.
* @param new_config New interrupt configuration.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_restore(dif_usbdev_t *usbdev,
uint32_t new_config);
/**
* Test an interrupt.
*
* @param usbdev A USB device.
* @param irq An interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_usbdev_result_t dif_usbdev_irq_test(dif_usbdev_t *usbdev,
dif_usbdev_irq_t irq);
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_USBDEV_H_