mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-17 18:43:50 +01:00
This commit adds support for URBs (USB Request/Response Blocks). These allow for submitting multi-transfer sized buffers with USBUS handling the individual usbdev xmits. Multiple URBs can be queued at once for a single endpoint and USBUS will handle them in the order of submission. OUT endpoint URBs must always consist of a whole number of full-sized transfers (N x MaxEndpointSize). They will automatically finish after the endpoint received a transfer less than the endpoint size. IN endpoints can be arbitrary-sized and do not have to consist of a whole number of full-sized transmissions. They support a flag to indicate that the last transfer in the sequence must be less than a full sized transfer (USBUS_URB_FLAG_AUTO_ZLP) and this adds a zero length transfer at the end of the transmissions if the last transfer was equal to the maximum transfer size. URBs can be cancelled, but if the URB is already being processed it will be cancelled after the current transmission within the URB is finished. If it is still in the queue it will immediately be removed from the queue.
758 lines
25 KiB
C
758 lines
25 KiB
C
/*
|
|
* Copyright (C) 2018 Koen Zandberg
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
/**
|
|
* @defgroup usb_usbus USBUS device and endpoint manager
|
|
* @ingroup usb
|
|
* @brief USBUS (Universal Serial Bus Unified Stack), USB device
|
|
* management interface
|
|
*
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief USBUS basic interface
|
|
*
|
|
* @author Koen Zandberg <koen@bergzand.net>
|
|
*/
|
|
|
|
#ifndef USB_USBUS_H
|
|
#define USB_USBUS_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "clist.h"
|
|
#include "event.h"
|
|
#include "sched.h"
|
|
#include "modules.h"
|
|
#include "msg.h"
|
|
#include "thread.h"
|
|
|
|
#include "usb.h"
|
|
#include "periph/usbdev.h"
|
|
#include "usb/descriptor.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @defgroup usb_usbus_conf USBUS compile time configurations
|
|
* @ingroup usb_conf
|
|
* @{
|
|
*/
|
|
/**
|
|
* @brief USBUS thread stack size
|
|
*/
|
|
#ifndef USBUS_STACKSIZE
|
|
#define USBUS_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
|
|
#endif
|
|
|
|
/**
|
|
* @brief USBUS thread priority
|
|
*/
|
|
#ifndef USBUS_PRIO
|
|
#define USBUS_PRIO (THREAD_PRIORITY_MAIN - 6)
|
|
#endif
|
|
|
|
/**
|
|
* @brief USBUS auto attach setting
|
|
*
|
|
* When set to 1, the USBUS thread will automatically enable the USB pull-up
|
|
* resistor after initializing the thread. This will signal to the host
|
|
* that the USB peripheral is ready for use.
|
|
*/
|
|
#ifndef CONFIG_USBUS_AUTO_ATTACH
|
|
#if !IS_ACTIVE(KCONFIG_MODULE_USBUS)
|
|
#define CONFIG_USBUS_AUTO_ATTACH 1
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* @brief USBUS endpoint 0 buffer size
|
|
*
|
|
* This configures the buffer size of the control endpoint. Unless you transfer
|
|
* large amount of data often over the control endpoint, a minimal size should
|
|
* be sufficient
|
|
*/
|
|
#if IS_ACTIVE(CONFIG_USBUS_EP0_SIZE_8)
|
|
#define CONFIG_USBUS_EP0_SIZE 8
|
|
#elif IS_ACTIVE(CONFIG_USBUS_EP0_SIZE_16)
|
|
#define CONFIG_USBUS_EP0_SIZE 16
|
|
#elif IS_ACTIVE(CONFIG_USBUS_EP0_SIZE_32)
|
|
#define CONFIG_USBUS_EP0_SIZE 32
|
|
#elif IS_ACTIVE(CONFIG_USBUS_EP0_SIZE_64)
|
|
#define CONFIG_USBUS_EP0_SIZE 64
|
|
#endif
|
|
|
|
#ifndef CONFIG_USBUS_EP0_SIZE
|
|
#define CONFIG_USBUS_EP0_SIZE 64
|
|
#endif
|
|
/** @} */
|
|
|
|
/**
|
|
* @brief USBUS thread name
|
|
*/
|
|
#define USBUS_TNAME "usbus"
|
|
|
|
/**
|
|
* @name USBUS thread flags
|
|
*
|
|
* Thread flags used by the USBUS thread. @ref THREAD_FLAG_EVENT is also used,
|
|
* but defined elsewhere
|
|
* @{
|
|
*/
|
|
#define USBUS_THREAD_FLAG_USBDEV (0x02) /**< usbdev esr needs handling */
|
|
#define USBUS_THREAD_FLAG_USBDEV_EP (0x04) /**< One or more endpoints requires
|
|
servicing */
|
|
/** @} */
|
|
|
|
/**
|
|
* @name USBUS handler subscription flags
|
|
*
|
|
* @{
|
|
*/
|
|
#define USBUS_HANDLER_FLAG_RESET (0x0001) /**< Report reset event */
|
|
#define USBUS_HANDLER_FLAG_SOF (0x0002) /**< Report SOF events */
|
|
#define USBUS_HANDLER_FLAG_SUSPEND (0x0004) /**< Report suspend events */
|
|
#define USBUS_HANDLER_FLAG_RESUME (0x0008) /**< Report resume from suspend */
|
|
|
|
/**
|
|
* @brief Report transfer fail
|
|
*
|
|
* @deprecated This event is deprecated as only a limited number of low level
|
|
* devices report this and it doesn't offer value for upper layer
|
|
* code. This flag will be removed after the 2022.07 release
|
|
*/
|
|
#define USBUS_HANDLER_FLAG_TR_FAIL (0x0010)
|
|
#define USBUS_HANDLER_FLAG_TR_STALL (0x0020) /**< Report transfer stall complete */
|
|
/** @} */
|
|
|
|
/**
|
|
* @name USBUS URB flags
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief End the URB with a zero length packet if the URB is a full number of
|
|
* USB transfers in length
|
|
*/
|
|
#define USBUS_URB_FLAG_AUTO_ZLP (0x0001)
|
|
|
|
/**
|
|
* @brief URB needs a zero length packet and it is requested
|
|
* @internal
|
|
*/
|
|
#define USBUS_URB_FLAG_NEEDS_ZLP (0x1000)
|
|
|
|
/**
|
|
* @brief URB must be cancelled after the next finished xmit
|
|
* @internal
|
|
*/
|
|
#define USBUS_URB_FLAG_CANCELLED (0x2000)
|
|
/** @} */
|
|
|
|
/**
|
|
* @brief USB handler events
|
|
*/
|
|
typedef enum {
|
|
USBUS_EVENT_USB_RESET, /**< USB reset event */
|
|
USBUS_EVENT_USB_SOF, /**< USB start of frame received */
|
|
USBUS_EVENT_USB_SUSPEND, /**< USB suspend condition detected */
|
|
USBUS_EVENT_USB_RESUME, /**< USB resume condition detected */
|
|
} usbus_event_usb_t;
|
|
|
|
/**
|
|
* @brief USB endpoint transfer status events
|
|
*/
|
|
typedef enum {
|
|
USBUS_EVENT_TRANSFER_COMPLETE, /**< Transfer successfully completed */
|
|
USBUS_EVENT_TRANSFER_FAIL, /**< Transfer nack replied by peripheral */
|
|
USBUS_EVENT_TRANSFER_STALL, /**< Transfer stall replied by peripheral */
|
|
} usbus_event_transfer_t;
|
|
|
|
/**
|
|
* @brief state machine states for the global USBUS thread
|
|
*/
|
|
typedef enum {
|
|
USBUS_STATE_DISCONNECT, /**< Device is disconnected from the host */
|
|
USBUS_STATE_RESET, /**< Reset condition received */
|
|
USBUS_STATE_ADDR, /**< Address configured */
|
|
USBUS_STATE_CONFIGURED, /**< Peripheral is configured */
|
|
USBUS_STATE_SUSPEND, /**< Peripheral is suspended by the host */
|
|
} usbus_state_t;
|
|
|
|
/**
|
|
* @brief USBUS control request state machine
|
|
*/
|
|
typedef enum {
|
|
USBUS_CONTROL_REQUEST_STATE_READY, /**< Ready for new control request */
|
|
USBUS_CONTROL_REQUEST_STATE_INDATA, /**< Request received with expected
|
|
DATA IN stage */
|
|
USBUS_CONTROL_REQUEST_STATE_OUTACK, /**< Expecting a zero-length ack OUT
|
|
request from the host */
|
|
USBUS_CONTROL_REQUEST_STATE_OUTDATA, /**< Data OUT expected */
|
|
USBUS_CONTROL_REQUEST_STATE_INACK, /**< Expecting a zero-length ack IN
|
|
request from the host */
|
|
} usbus_control_request_state_t;
|
|
|
|
/**
|
|
* @brief USBUS string type
|
|
*/
|
|
typedef struct usbus_string {
|
|
struct usbus_string *next; /**< Ptr to the next registered string */
|
|
const char *str; /**< C string to use as content */
|
|
uint16_t idx; /**< USB string index */
|
|
} usbus_string_t;
|
|
|
|
/**
|
|
* @brief USBUS context forward declaration
|
|
*/
|
|
typedef struct usbus usbus_t;
|
|
|
|
/**
|
|
* @brief USBUS event handler forward declaration
|
|
*/
|
|
typedef struct usbus_handler usbus_handler_t;
|
|
|
|
/**
|
|
* @brief descriptor length types for USB descriptor generators
|
|
*/
|
|
typedef enum {
|
|
USBUS_DESCR_LEN_FIXED, /**< Descriptor always generates a fixed length */
|
|
USBUS_DESCR_LEN_FUNC, /**< Descriptor length is calculated by a function */
|
|
} usbus_descr_len_type_t;
|
|
|
|
/**
|
|
* @brief USBUS descriptor generator function pointers
|
|
*/
|
|
typedef struct {
|
|
/**
|
|
* @brief function pointer to format the descriptor content of this
|
|
* descriptor generator. The content of this descriptor is prefixes before
|
|
* the descriptor of the object it is part of.
|
|
*
|
|
* @param usbus The usbus context
|
|
* @param arg Additional argument for the descriptor generator
|
|
*
|
|
* @return Length of the generated descriptor
|
|
*/
|
|
size_t (*fmt_pre_descriptor)(usbus_t *usbus, void *arg);
|
|
|
|
/**
|
|
* @brief function pointer to format the descriptor content of this
|
|
* descriptor generator. The content of this descriptor is appended after
|
|
* the descriptor of the object it is part of.
|
|
*
|
|
* @param usbus The usbus context
|
|
* @param arg Additional argument for the descriptor generator
|
|
*
|
|
* @return Length of the generated descriptor
|
|
*/
|
|
size_t (*fmt_post_descriptor)(usbus_t *usbus, void *arg);
|
|
union {
|
|
/**
|
|
* @brief USBUS generic descriptor generator generated length
|
|
*
|
|
* Must return the total length of the descriptors that will be
|
|
* generated by @ref fmt_pre_descriptor and @ref fmt_post_descriptor
|
|
* This function is used when @ref len_type is set to
|
|
* @ref USBUS_DESCR_LEN_FUNC.
|
|
*
|
|
* @param usbus The usbus context
|
|
* @param arg Additional argument for the descriptor generators
|
|
*
|
|
* @return Length of the generated descriptors
|
|
*/
|
|
size_t (*get_descriptor_len)(usbus_t *usbus, void *arg);
|
|
/**
|
|
* @brief Fixed total length of the generated descriptors
|
|
*
|
|
* Must return the total length of the descriptors that will be
|
|
* generated by the @ref fmt_pre_descriptor and @ref fmt_post_descriptor.
|
|
* This value is used when @ref len_type is set to
|
|
* @ref USBUS_DESCR_LEN_FIXED.
|
|
*/
|
|
size_t fixed_len;
|
|
} len; /**< Fixed or generated length of the descriptor */
|
|
usbus_descr_len_type_t len_type; /**< Either USBUS_DESCR_LEN_FIXED or USBUS_DESCR_LEN_FUNC */
|
|
} usbus_descr_gen_funcs_t;
|
|
|
|
/**
|
|
* @brief USBUS descriptor generator
|
|
*
|
|
* The functions are called to allow custom modules to define their own
|
|
* descriptors in addition to the USB descriptor. The top level (@ref usbus_t), the
|
|
* interface (@ref usbus_interface_t), interface alternative settings
|
|
* (@ref usbus_interface_alt_t) and endpoints (@ref usbus_endpoint_t) allow for
|
|
* generating additional descriptors
|
|
*/
|
|
typedef struct usbus_descr_gen {
|
|
struct usbus_descr_gen *next; /**< ptr to the next descriptor generator */
|
|
const usbus_descr_gen_funcs_t *funcs; /**< Function pointers */
|
|
void *arg; /**< Extra context argument for the
|
|
descriptor functions */
|
|
} usbus_descr_gen_t;
|
|
|
|
/**
|
|
* @brief USBUS endpoint context
|
|
*/
|
|
typedef struct usbus_endpoint {
|
|
struct usbus_endpoint *next; /**< Next endpoint in the
|
|
@ref usbus_interface_t list of
|
|
endpoints */
|
|
usbus_descr_gen_t *descr_gen; /**< Linked list of optional additional
|
|
descriptor generators */
|
|
usbdev_ep_t *ep; /**< ptr to the matching usbdev endpoint */
|
|
#ifdef MODULE_USBUS_URB
|
|
clist_node_t urb_list; /**< clist of urbs */
|
|
#endif
|
|
uint16_t maxpacketsize; /**< Max packet size of this endpoint */
|
|
uint8_t interval; /**< Poll interval for interrupt endpoints */
|
|
bool active; /**< If the endpoint should be activated after
|
|
reset */
|
|
} usbus_endpoint_t;
|
|
|
|
/**
|
|
* @brief USBUS USB request/response block
|
|
*/
|
|
typedef struct usbus_urb {
|
|
clist_node_t list; /**< clist block in the queue */
|
|
uint32_t flags; /**< Transfer flags */
|
|
uint8_t *buf; /**< Pointer to the (aligned) buffer */
|
|
size_t len; /**< Length of the data */
|
|
size_t transferred; /**< amount transferred, only valid for OUT */
|
|
} usbus_urb_t;
|
|
|
|
/**
|
|
* @brief USBUS interface alternative setting
|
|
*
|
|
* Used for specifying alternative interfaces for an @ref usbus_interface_t
|
|
*/
|
|
typedef struct usbus_interface_alt {
|
|
struct usbus_interface_alt *next; /**< Next alternative setting */
|
|
usbus_descr_gen_t *descr_gen; /**< Linked list of optional additional
|
|
descriptor generators */
|
|
usbus_endpoint_t *ep; /**< List of associated endpoints for
|
|
this alternative setting */
|
|
usbus_string_t *descr; /**< Descriptor string */
|
|
} usbus_interface_alt_t;
|
|
|
|
/**
|
|
* @brief USBUS interface
|
|
*/
|
|
typedef struct usbus_interface {
|
|
struct usbus_interface *next; /**< Next interface (set by USBUS during
|
|
registration) */
|
|
usbus_descr_gen_t *descr_gen; /**< Linked list of optional additional
|
|
descriptor generators */
|
|
usbus_endpoint_t *ep; /**< Linked list of endpoints belonging
|
|
to this interface */
|
|
struct usbus_interface_alt *alts; /**< List of alt settings */
|
|
usbus_handler_t *handler; /**< Handlers for this interface */
|
|
usbus_string_t *descr; /**< Descriptor string */
|
|
uint16_t idx; /**< Interface index, (set by USBUS
|
|
during registration */
|
|
uint8_t class; /**< USB interface class */
|
|
uint8_t subclass; /**< USB interface subclass */
|
|
uint8_t protocol; /**< USB interface protocol */
|
|
} usbus_interface_t;
|
|
|
|
/**
|
|
* @brief USBUS event handler function pointers
|
|
*/
|
|
typedef struct usbus_handler_driver {
|
|
|
|
/**
|
|
* @brief Initialize the event handler
|
|
*
|
|
* This function is called in the USBUS thread context to initialize the
|
|
* event handler
|
|
*
|
|
* @param usbus USBUS context
|
|
* @param handler handler context
|
|
*/
|
|
void (*init)(usbus_t * usbus, struct usbus_handler *handler);
|
|
|
|
/**
|
|
* @brief event handler function
|
|
*
|
|
* This function is passed USBUS events
|
|
*
|
|
* @param usbus USBUS context
|
|
* @param handler handler context
|
|
* @param event @ref usbus_event_usb_t event to handle
|
|
*/
|
|
void (*event_handler)(usbus_t * usbus, struct usbus_handler *handler,
|
|
usbus_event_usb_t event);
|
|
|
|
/**
|
|
* @brief transfer handler function
|
|
*
|
|
* This function receives transfer based events
|
|
*
|
|
* @param usbus USBUS context
|
|
* @param handler handler context
|
|
* @param ep usbdev endpoint that triggered the event
|
|
* @param event @ref usbus_event_transfer_t event
|
|
*/
|
|
void (*transfer_handler)(usbus_t * usbus, struct usbus_handler *handler,
|
|
usbdev_ep_t *ep, usbus_event_transfer_t event);
|
|
|
|
/**
|
|
* @brief control request handler function
|
|
*
|
|
* This function receives USB control requests from the USBUS stack.
|
|
*
|
|
* @param usbus USBUS context
|
|
* @param handler handler context
|
|
* @param state control request state
|
|
* @param setup setup packet
|
|
*
|
|
* @return Size of the returned data when the request is handled
|
|
* @return negative to have the stack return an USB stall to the
|
|
* host
|
|
* @return zero when the request is not handled by this handler
|
|
*/
|
|
int (*control_handler)(usbus_t * usbus, struct usbus_handler *handler,
|
|
usbus_control_request_state_t state,
|
|
usb_setup_t *request);
|
|
} usbus_handler_driver_t;
|
|
|
|
/**
|
|
* @brief USBUS handler struct
|
|
*
|
|
* Inherit from this struct for custom USB functionality
|
|
*/
|
|
struct usbus_handler {
|
|
struct usbus_handler *next; /**< List of handlers (to be used by
|
|
@ref usbus_t) */
|
|
const usbus_handler_driver_t *driver; /**< driver for this handler */
|
|
usbus_interface_t *iface; /**< Interface this handler belongs
|
|
to */
|
|
uint32_t flags; /**< Report flags */
|
|
};
|
|
|
|
/**
|
|
* @brief USBUS context struct
|
|
*/
|
|
struct usbus {
|
|
usbus_string_t manuf; /**< Manufacturer string */
|
|
usbus_string_t product; /**< Product string */
|
|
usbus_string_t config; /**< Configuration string */
|
|
usbus_string_t serial; /**< serial string */
|
|
usbus_endpoint_t ep_out[USBDEV_NUM_ENDPOINTS]; /**< USBUS OUT endpoints */
|
|
usbus_endpoint_t ep_in[USBDEV_NUM_ENDPOINTS]; /**< USBUS IN endpoints */
|
|
event_queue_t queue; /**< Event queue */
|
|
usbdev_t *dev; /**< usb phy device of the usb manager */
|
|
usbus_handler_t *control; /**< Ptr to the control endpoint handler */
|
|
usbus_descr_gen_t *descr_gen; /**< Linked list of top level descriptor
|
|
generators */
|
|
usbus_string_t *strings; /**< List of descriptor strings */
|
|
usbus_interface_t *iface; /**< List of USB interfaces */
|
|
usbus_handler_t *handlers; /**< List of event callback handlers */
|
|
uint32_t ep_events; /**< bitflags with endpoint event state */
|
|
kernel_pid_t pid; /**< PID of the usb manager's thread */
|
|
uint16_t str_idx; /**< Number of strings registered */
|
|
usbus_state_t state; /**< Current state */
|
|
usbus_state_t pstate; /**< state to recover to from suspend */
|
|
uint8_t addr; /**< Address of the USB peripheral */
|
|
#ifndef CONFIG_USB_SERIAL_STR
|
|
/**
|
|
* @brief Hex representation of the device serial number
|
|
*/
|
|
char serial_str[2 * CONFIG_USB_SERIAL_BYTE_LENGTH + 1];
|
|
#endif
|
|
};
|
|
|
|
/**
|
|
* @brief Submit an event to the usbus thread
|
|
*
|
|
* @param usbus USBUS context
|
|
* @param event event to post
|
|
*/
|
|
static inline void usbus_event_post(usbus_t *usbus, event_t *event)
|
|
{
|
|
event_post(&usbus->queue, event);
|
|
}
|
|
|
|
/**
|
|
* @brief Add a string descriptor to the USBUS thread context
|
|
*
|
|
* @param[in] usbus USBUS context
|
|
* @param[in] desc string descriptor context
|
|
* @param[in] str C string to use
|
|
*
|
|
* @return Index of the string descriptor
|
|
*/
|
|
uint16_t usbus_add_string_descriptor(usbus_t *usbus, usbus_string_t *desc,
|
|
const char *str);
|
|
|
|
/**
|
|
* @brief Add an interface to the USBUS thread context
|
|
*
|
|
* @param[in] usbus USBUS context
|
|
* @param[in] iface USB interface to add
|
|
*
|
|
* @return interface index
|
|
*/
|
|
uint16_t usbus_add_interface(usbus_t *usbus, usbus_interface_t *iface);
|
|
|
|
/**
|
|
* @brief Add alternate settings to a given interface
|
|
*
|
|
* @param[in] iface USB interface
|
|
* @param[in] alt alternate settings interface to add
|
|
*/
|
|
void usbus_add_interface_alt(usbus_interface_t *iface,
|
|
usbus_interface_alt_t *alt);
|
|
|
|
/**
|
|
* @brief Find an endpoint from an interface based on the endpoint properties
|
|
*
|
|
* This iterates over the endpoints in an interface and will return the first
|
|
* endpoint from the interface matching the @p type and @p dir. It will return
|
|
* NULL when no matching endpoint is found.
|
|
*
|
|
* @param[in] interface interface to look in
|
|
* @param[in] type endpoint type to match
|
|
* @param[in] dir endpoint direction to match
|
|
*
|
|
* @return ptr to the first matching endpoint
|
|
* @return NULL when no endpoint is found
|
|
*/
|
|
usbus_endpoint_t *usbus_interface_find_endpoint(usbus_interface_t *interface,
|
|
usb_ep_type_t type,
|
|
usb_ep_dir_t dir);
|
|
|
|
/**
|
|
* @brief Add an endpoint to the specified interface
|
|
*
|
|
* An @ref usbdev_ep_t is requested from the low level peripheral matching the
|
|
* type, direction and buffer length.
|
|
*
|
|
* @param[in] usbus USBUS context
|
|
* @param[in] iface USB interface to add the endpoint to
|
|
* @param[in] type USB endpoint type
|
|
* @param[in] dir USB endpoint direction
|
|
* @param[in] len Buffer space for the endpoint to allocate
|
|
*
|
|
* @return Pointer to the endpoint struct
|
|
* @return NULL when no endpoint available
|
|
*/
|
|
usbus_endpoint_t *usbus_add_endpoint(usbus_t *usbus, usbus_interface_t *iface,
|
|
usb_ep_type_t type, usb_ep_dir_t dir,
|
|
size_t len);
|
|
|
|
/**
|
|
* @brief Add a generator for generating additional top level USB descriptor
|
|
* content
|
|
*
|
|
* @param[in] usbus USBUS context
|
|
* @param[in] descr_gen descriptor generator to add
|
|
*/
|
|
void usbus_add_conf_descriptor(usbus_t *usbus, usbus_descr_gen_t *descr_gen);
|
|
|
|
/**
|
|
* @brief Add an event handler to the USBUS context
|
|
*
|
|
* The handler must also belong to an interface
|
|
* (@ref usbus_interface_t::handler must point to @p handler) for
|
|
* transfer event callbacks to work.
|
|
*
|
|
* @param[in] usbus USBUS context
|
|
* @param[in] handler event handler to register
|
|
*/
|
|
void usbus_register_event_handler(usbus_t *usbus, usbus_handler_t *handler);
|
|
|
|
/**
|
|
* @brief Initialize an USBUS context.
|
|
*
|
|
* @param[in] usbus context to initialize
|
|
* @param[in] usbdev usbdev peripheral to use by USBUS
|
|
*/
|
|
void usbus_init(usbus_t *usbus, usbdev_t *usbdev);
|
|
|
|
/**
|
|
* @brief Create and start the USBUS thread
|
|
*
|
|
* @param[in] stack The stack for the USBUS thread.
|
|
* @param[in] stacksize Size of @p stack.
|
|
* @param[in] priority Priority for the USBUS thread.
|
|
* @param[in] name Name for the USBUS thread May be NULL.
|
|
* @param[in] usbus context to start the thread for
|
|
*/
|
|
void usbus_create(char *stack, int stacksize, char priority,
|
|
const char *name, usbus_t *usbus);
|
|
|
|
/**
|
|
* @brief Initialize a new URB.
|
|
*
|
|
* Must be called before submitting an URB to an endpoint.
|
|
*
|
|
* @note When using this for OUT endpoints, the buffer size and the @p len
|
|
* argument must allow for a whole number of max length transfers.
|
|
*
|
|
* @note Requires the `usbus_urb` module.
|
|
*
|
|
* @param[in] urb URB to submit
|
|
* @param[in] buf Buffer to store or transmit the data from
|
|
* @param[in] len Length of @p buf in bytes
|
|
* @param[in] flags Flags to set for the URB such as @ref USBUS_URB_FLAG_AUTO_ZLP
|
|
*/
|
|
static inline void usbus_urb_init(usbus_urb_t *urb,
|
|
uint8_t *buf,
|
|
size_t len,
|
|
uint32_t flags)
|
|
{
|
|
urb->buf = buf;
|
|
urb->len = len;
|
|
urb->flags = flags;
|
|
urb->transferred = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Submit an URB to an endpoint.
|
|
*
|
|
* @note Requires the `usbus_urb` module.
|
|
*
|
|
* @param[in] usbus USBUS context
|
|
* @param[in] endpoint USBUS endpoint the URB is queued to
|
|
* @param[in] urb URB to submit
|
|
*/
|
|
void usbus_urb_submit(usbus_t *usbus, usbus_endpoint_t *endpoint, usbus_urb_t *urb);
|
|
|
|
/**
|
|
* @brief Cancel and already queued URB.
|
|
*
|
|
* The URB will be cancelled after the next transmission if the URB is already
|
|
* partially completed. It is up to the handler code to gracefully handle the
|
|
* partially aborted transfer on the endpoint pipe.
|
|
*
|
|
* The callback will be called if the URB was already started and cancelled
|
|
* while (partially) transferred
|
|
*
|
|
* @note Requires the `usbus_urb` module.
|
|
*
|
|
* @param[in] usbus USBUS context
|
|
* @param[in] endpoint USBUS endpoint the URB is queued to
|
|
* @param[in] urb URB to cancel
|
|
*
|
|
* @returns 0 if the URB is partially completed
|
|
* 1 if the URB was not yet started
|
|
* -1 if the URB was not found in the endpoint queue
|
|
*/
|
|
int usbus_urb_cancel(usbus_t *usbus, usbus_endpoint_t *endpoint, usbus_urb_t *urb);
|
|
|
|
/**
|
|
* @brief Enable an endpoint
|
|
*
|
|
* @note must only be used before the usb peripheral is attached to the host
|
|
*
|
|
* @param[in] ep endpoint to enable
|
|
*/
|
|
static inline void usbus_enable_endpoint(usbus_endpoint_t *ep)
|
|
{
|
|
ep->active = true;
|
|
}
|
|
|
|
/**
|
|
* @brief Disable an endpoint
|
|
*
|
|
* @note must only be used before the usb peripheral is attached to the host
|
|
*
|
|
* @param[in] ep endpoint to disable
|
|
*/
|
|
static inline void usbus_disable_endpoint(usbus_endpoint_t *ep)
|
|
{
|
|
ep->active = false;
|
|
}
|
|
|
|
/**
|
|
* @brief enable a specific handler flag
|
|
*
|
|
* @param[in] handler handler to enable the flag for
|
|
* @param[in] flag flag to enable
|
|
*/
|
|
static inline void usbus_handler_set_flag(usbus_handler_t *handler,
|
|
uint32_t flag)
|
|
{
|
|
handler->flags |= flag;
|
|
}
|
|
|
|
/**
|
|
* @brief disable a specific handler flag
|
|
*
|
|
* @param[in] handler handler to disable the flag for
|
|
* @param[in] flag flag to disable
|
|
*/
|
|
static inline void usbus_handler_remove_flag(usbus_handler_t *handler,
|
|
uint32_t flag)
|
|
{
|
|
handler->flags &= ~flag;
|
|
}
|
|
|
|
/**
|
|
* @brief check if a specific handler flag is set
|
|
*
|
|
* @param[in] handler handler to check for flag
|
|
* @param[in] flag flag to check
|
|
*
|
|
* @return true if the flag is set for this handler
|
|
*/
|
|
static inline bool usbus_handler_isset_flag(usbus_handler_t *handler,
|
|
uint32_t flag)
|
|
{
|
|
return handler->flags & flag;
|
|
}
|
|
|
|
/**
|
|
* @brief enable an URB flag
|
|
*
|
|
* @param[in] urb URB to enable the flag for
|
|
* @param[in] flag flag to enable
|
|
*/
|
|
static inline void usbus_urb_set_flag(usbus_urb_t *urb,
|
|
uint32_t flag)
|
|
{
|
|
urb->flags |= flag;
|
|
}
|
|
|
|
/**
|
|
* @brief disable an URB flag
|
|
*
|
|
* @param[in] urb URB to disable the flag for
|
|
* @param[in] flag flag to disable
|
|
*/
|
|
static inline void usbus_urb_remove_flag(usbus_urb_t *urb,
|
|
uint32_t flag)
|
|
{
|
|
urb->flags &= ~flag;
|
|
}
|
|
|
|
/**
|
|
* @brief check if an URB flag is set
|
|
*
|
|
* @param[in] urb URB to check for flag
|
|
* @param[in] flag flag to check
|
|
*
|
|
* @return true if the flag is set for this URB
|
|
*/
|
|
static inline bool usbus_urb_isset_flag(usbus_urb_t *urb,
|
|
uint32_t flag)
|
|
{
|
|
return urb->flags & flag;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* USB_USBUS_H */
|
|
/** @} */
|