pico-extras/src/rp2_common/usb_device/include/pico/usb_device.h

188 wiersze
6.6 KiB
C

/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _USB_USB_DEVICE_H
#define _USB_USB_DEVICE_H
#include "usb/usb_common.h"
#include "pico/assert.h"
#ifndef PICO_USBDEV_ENABLE_DEBUG_TRACE
#define PICO_USBDEV_ENABLE_DEBUG_TRACE 0
#endif
#ifndef PICO_USBDEV_ASSUME_ZERO_INIT
#define PICO_USBDEV_ASSUME_ZERO_INIT 0
#endif
#ifndef PICO_USBDEV_MAX_ENDPOINTS
#define PICO_USBDEV_MAX_ENDPOINTS USB_NUM_ENDPOINTS
#endif
static_assert(PICO_USBDEV_MAX_ENDPOINTS >= 1 && PICO_USBDEV_MAX_ENDPOINTS <= 16, "");
#ifndef PICO_USBDEV_MAX_DESCRIPTOR_SIZE
#define PICO_USBDEV_MAX_DESCRIPTOR_SIZE 64
#endif
// Enabling configuration items can reduce the size of the runtime code at the cost of some functionality
// or improve speed at the cost of some flexibility
// no custom per device setup packet handler
#ifndef PICO_USBDEV_NO_DEVICE_SETUP_HANDLER
#define PICO_USBDEV_NO_DEVICE_SETUP_HANDLER 0
#endif
// no custom per endpoint setup packet handlers
#ifndef PICO_USBDEV_NO_ENDPOINT_SETUP_HANDLER
#define PICO_USBDEV_NO_ENDPOINT_SETUP_HANDLER 0
#endif
// if all endpoints are bulk, then it allows simplification of some code
#ifndef PICO_USBDEV_BULK_ONLY_EP1_THRU_16
#define PICO_USBDEV_BULK_ONLY_EP1_THRU_16 0
#endif
// our interfaces are zero based number in the order they appear on the device - require that
#ifndef PICO_USBDEV_USE_ZERO_BASED_INTERFACES
#define PICO_USBDEV_USE_ZERO_BASED_INTERFACES 0
#endif
// no_init method for transfer
#ifndef PICO_USBDEV_NO_TRANSFER_ON_INIT_METHOD
#define PICO_USBDEV_NO_TRANSFER_ON_INIT_METHOD 0
#endif
// do on_cancel method for transfer
#ifndef PICO_USBDEV_NO_TRANSFER_ON_CANCEL_METHOD
#define PICO_USBDEV_NO_TRANSFER_ON_CANCEL_METHOD 0
#endif
// todo this needs to be part of configuration
#ifndef PICO_USBDEV_NO_INTERFACE_ALTERNATES
#define PICO_USBDEV_NO_INTERFACE_ALTERNATES 0
#endif
// todo this needs to be part of configuration
#ifndef PICO_USBDEV_ISOCHRONOUS_BUFFER_STRIDE_TYPE
#define PICO_USBDEV_ISOCHRONOUS_BUFFER_STRIDE_TYPE 0
#endif
static_assert((PICO_USBDEV_ISOCHRONOUS_BUFFER_STRIDE_TYPE >= 0) && (PICO_USBDEV_ISOCHRONOUS_BUFFER_STRIDE_TYPE < 4),
"");
// don't zero out most structures (since we do so globablly for BSS)
//#define USB_SKIP_COMMON_INIT
// only 16 bytes saved to not set a sense code
//#define USB_SILENT_FAIL_ON_EXCLUSIVE
struct usb_transfer;
struct usb_endpoint;
typedef void (*usb_transfer_func)(struct usb_endpoint *ep);
typedef void (*usb_transfer_completed_func)(struct usb_endpoint *ep, struct usb_transfer *transfer);
struct usb_buffer {
uint8_t *data;
uint8_t data_len;
uint8_t data_max;
// then...
bool valid; // aka user owned
};
#include "usb_device_private.h"
struct usb_transfer_type {
// for IN transfers this is called to setup new packet buffers
// for OUT transfers this is called with packet data
//
// In any case usb_packet_done must be called if this function has handled the buffer
usb_transfer_func on_packet;
#if !PICO_USBDEV_NO_TRANSFER_ON_INIT_METHOD
usb_transfer_func on_init;
#endif
#if !PICO_USBDEV_NO_TRANSFER_ON_CANCEL_METHOD
usb_transfer_func on_cancel;
#endif
uint8_t initial_packet_count;
};
struct usb_interface *usb_interface_init(struct usb_interface *interface, const struct usb_interface_descriptor *desc,
struct usb_endpoint *const *endpoints, uint endpoint_count,
bool double_buffered);
struct usb_device *usb_device_init(const struct usb_device_descriptor *desc,
const struct usb_configuration_descriptor *config_desc,
struct usb_interface *const *interfaces, uint interface_count,
const char *(*get_descriptor_string)(uint index));
void usb_device_start();
void usb_device_stop();
// explicit stall
void usb_halt_endpoint_on_condition(struct usb_endpoint *ep);
void usb_halt_endpoint(struct usb_endpoint *endpoint);
void usb_clear_halt_condition(struct usb_endpoint *ep);
static inline bool usb_is_endpoint_stalled(struct usb_endpoint *endpoint);
void usb_set_default_transfer(struct usb_endpoint *ep, struct usb_transfer *transfer);
void usb_reset_transfer(struct usb_transfer *transfer, const struct usb_transfer_type *type,
usb_transfer_completed_func on_complete);
void usb_start_transfer(struct usb_endpoint *ep, struct usb_transfer *transfer);
void usb_reset_and_start_transfer(struct usb_endpoint *ep, struct usb_transfer *transfer,
const struct usb_transfer_type *type, usb_transfer_completed_func on_complete);
void usb_chain_transfer(struct usb_endpoint *ep, struct usb_transfer *transfer);
void usb_grow_transfer(struct usb_transfer *transfer, uint packet_count);
void usb_start_default_transfer_if_not_already_running_or_halted(struct usb_endpoint *ep);
typedef void (*usb_transfer_func)(struct usb_endpoint *ep);
struct usb_buffer *usb_current_in_packet_buffer(struct usb_endpoint *ep);
struct usb_buffer *usb_current_out_packet_buffer(struct usb_endpoint *ep);
uint8_t *usb_get_single_packet_response_buffer(struct usb_endpoint *ep, uint len);
// call during (or asynchronously after) on_packet to mark the packet as done
void usb_packet_done(struct usb_endpoint *ep);
extern const struct usb_transfer_type usb_current_packet_only_transfer_type;
static inline struct usb_endpoint *usb_get_control_in_endpoint();
static inline struct usb_endpoint *usb_get_control_out_endpoint();
void usb_start_empty_control_in_transfer(usb_transfer_completed_func on_complete);
void usb_start_empty_control_in_transfer_null_completion();
void usb_start_tiny_control_in_transfer(uint32_t data, uint len);
void usb_start_single_buffer_control_in_transfer();
void usb_start_control_out_transfer(const struct usb_transfer_type *type);
void usb_start_empty_transfer(struct usb_endpoint *endpoint, struct usb_transfer *transfer,
usb_transfer_completed_func on_complete);
void usb_soft_reset_endpoint(struct usb_endpoint *ep);
void usb_hard_reset_endpoint(struct usb_endpoint *ep);
#if PICO_USBDEV_ENABLE_DEBUG_TRACE
void usb_dump_trace(void);
void usb_reset_trace(void);
#else
static inline void usb_dump_trace() {}
static inline void usb_reset_trace() {}
#endif
#define usb_warn(format, args...) ({printf("WARNING: "); printf(format, ## args); })
#if false && !defined(NDEBUG)
#define usb_debug(format,args...) printf(format, ## args)
#else
#define usb_debug(format, ...) ((void)0)
#endif
#if false && !defined(NDEBUG)
#define usb_trace(format,args...) printf(format, ## args)
#else
#define usb_trace(format, ...) ((void)0)
#endif
#endif