#include <stm32h747xx.h>
#include "usb.h"
#ifndef USB_DEVICE_H
#define USB_DEVICE_H
typedef enum {
// error states first so they are lowest
CONTROL_ERROR = -4,
UNKNOWN_CONTROL_COMMAND = -4,
ERROR = -3,
UNKNOWN_INTERRUPT = -2,
OTG_ERROR = -1, // shouldn't happen, since otg is not used
INIT = 0,
RESET = 1,
RESET_DONE = 2,
SET_ADDRESS_RCVD = 3,
ENUMERATED = 4,
} usb_device_state_t;
typedef struct {
volatile uint32_t data[128];
} usb_fifo_t;
struct usb_class_header_t;
struct usb_device_t;
typedef struct usb_device_t usb_device_t;
typedef struct {
struct usb_class_header_t *(*init)(usb_device_t *device,
uint16_t id_vendor, uint16_t id_product,
char *vendor_name, char *product_name,
uint16_t serial_number, char* serial_name);
void (*send_configuration)(usb_device_t* device, usb_setup_command_t* cmd);
void (*setup_endpoints)(usb_device_t* device, uint8_t configuration);
void (*reset_endpoints)(usb_device_t* device);
void (*reset_callback)(usb_device_t* device);
void (*setup_packet_callback)(usb_device_t* device, usb_setup_command_t* cmd);
void (*enumeration_done_callback)(usb_device_t* device);
void (*txfifo_empty_callback)(usb_device_t* device, uint8_t endpoint);
void (*rxfifo_empty_callback)(usb_device_t* device, uint8_t endpoint);
void (*transmit_done_callback)(usb_device_t* device, uint8_t endpoint);
void (*nak_callback)(usb_device_t* device, uint8_t endpoint);
void (*nyet_callback)(usb_device_t* device, uint8_t endpoint);
} usb_class_vtable_t;
typedef struct {
usb_interface_descriptor_t interface_descriptor;
uint8_t endpoint_descriptors_count;
usb_endpoint_descriptor_t *endpoint_descriptors;
} usb_interface_t;
struct usb_class_header_t {
usb_device_descriptor_t device_descriptor;
usb_device_qualifier_t device_qualifier;
usb_configuration_descriptor_t configuration_descriptor;
uint8_t interfaces_count;
usb_interface_t *interfaces;
usb_string_descriptor_zero_t string_descriptor_zero;
usb_unicode_string_descriptor_t *string_descriptors;
};
typedef struct usb_class_header_t usb_class_header_t;
typedef enum {
SETUP_STAGE_NONE,
SETUP_STAGE_RCVD_SETUP_PACKET,
SETUP_STAGE_AWAITING_RESPONSE,
SETUP_STAGE_SENDING_RESPONSE,
SETUP_STAGE_SENDING_ACK,
SETUP_STAGE_AWAITING_ACK,
} usb_setup_command_stage_t;
struct usb_device_t {
USB_OTG_GlobalTypeDef *core;
USB_OTG_DeviceTypeDef *device;
USB_OTG_OUTEndpointTypeDef *out;
USB_OTG_INEndpointTypeDef *in;
usb_fifo_t *fifos;
usb_class_vtable_t vt;
usb_class_header_t* class;
usb_device_state_t state;
// TODO: is this count field required?
uint8_t received_setup_commands_count;
uint8_t received_setup_commands_index;
usb_setup_command_stage_t setup_stage;
uint8_t detected_setup_errors;
usb_setup_command_t received_setup_commands[3];
};
// has configuration etc
typedef enum {
USB_OTG_HS1 = 0,
USB_OTG_FS2 = 1,
} usb_device_slot_t;
extern usb_device_t usb_devices[2];
void *usb_device_init(usb_device_slot_t slot, usb_class_vtable_t *class,
uint16_t id_vendor, uint16_t id_product,
char *vendor_name, char *product_name,
uint16_t serial_number, char* serial_name);
void usb_device_setup(void* device);
void usb_device_wait_for_handshake(void* device);
#endif // USB_DEVICE_H