rp2040/example/peripherals/usb/usb_device/main.c

189 lines
7.0 KiB
C

#include "system.h"
#include "resets.h"
#include "gpio.h"
#include "timer.h"
#include "usb.h"
#include "stdio.h"
extern struct usb_device_configuration dev_config;
extern void ep0_in_handler(uint8_t *buf, uint16_t len);
extern void ep0_out_handler(uint8_t *buf, uint16_t len);
void ep1_out_handler(uint8_t *buf, uint16_t len)
{
printf("RX %d bytes from host\n", len);
buf[len] = 0;
printf("received data: %s\r\n", buf);
// Send data back to host
struct usb_endpoint_configuration *ep = usb_get_endpoint_configuration(EP2_IN_ADDR);
usb_start_transfer(ep, buf, len);
}
void ep2_in_handler(uint8_t *buf, uint16_t len)
{
printf("Sent %d bytes to host\n", len);
// Get ready to rx again from host
usb_start_transfer(usb_get_endpoint_configuration(EP1_OUT_ADDR), NULL, 64);
}
static const struct usb_endpoint_descriptor ep0_out = {
.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP0_OUT_ADDR, // EP number 0, OUT from host (rx to device)
.bmAttributes = USB_TRANSFER_TYPE_CONTROL,
.wMaxPacketSize = 64,
.bInterval = 0
};
static const struct usb_endpoint_descriptor ep0_in = {
.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP0_IN_ADDR, // EP number 0, OUT from host (rx to device)
.bmAttributes = USB_TRANSFER_TYPE_CONTROL,
.wMaxPacketSize = 64,
.bInterval = 0
};
static const struct usb_endpoint_descriptor ep1_out = {
.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP1_OUT_ADDR, // EP number 1, OUT from host (rx to device)
.bmAttributes = USB_TRANSFER_TYPE_BULK,
.wMaxPacketSize = 64,
.bInterval = 0
};
static const struct usb_endpoint_descriptor ep2_in = {
.bLength = sizeof(struct usb_endpoint_descriptor),
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = EP2_IN_ADDR, // EP number 2, IN from host (tx from device)
.bmAttributes = USB_TRANSFER_TYPE_BULK,
.wMaxPacketSize = 64,
.bInterval = 0
};
// Descriptors
static const struct usb_device_descriptor device_descriptor = {
.bLength = sizeof(struct usb_device_descriptor),
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = 0x0110, // USB 1.1 device
.bDeviceClass = 0, // Specified in interface descriptor
.bDeviceSubClass = 0, // No subclass
.bDeviceProtocol = 0, // No protocol
.bMaxPacketSize0 = 64, // Max packet size for ep0
.idVendor = 0x0000, // Your vendor id
.idProduct = 0x0001, // Your product ID
.bcdDevice = 0, // No device revision number
.iManufacturer = 1, // Manufacturer string index
.iProduct = 2, // Product string index
.iSerialNumber = 0, // No serial number
.bNumConfigurations = 1, // One configuration
};
static const struct usb_interface_descriptor interface_descriptor = {
.bLength = sizeof(struct usb_interface_descriptor),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 2, // Interface has 2 endpoints
.bInterfaceClass = 0xff, // Vendor specific endpoint
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = 0,
};
static const struct usb_configuration_descriptor config_descriptor = {
.bLength = sizeof(struct usb_configuration_descriptor),
.bDescriptorType = USB_DT_CONFIG,
.wTotalLength = (sizeof(config_descriptor) +
sizeof(interface_descriptor) +
sizeof(ep1_out) +
sizeof(ep2_in)),
.bNumInterfaces = 1,
.bConfigurationValue = 1, // Configuration 1
.iConfiguration = 0, // No string
.bmAttributes = 0xc0, // attributes: self powered, no remote wakeup
.bMaxPower = 0x32 // 100ma
};
static const unsigned char lang_descriptor[] = {
4, // bLength
0x03, // bDescriptorType == String Descriptor
0x09, 0x04 // language id = us english
};
static const unsigned char *descriptor_strings[] = {
(unsigned char *) "Raspberry Pi", // Vendor
(unsigned char *) "Pico Test Device" // Product
};
// Struct defining the device configuration
struct usb_device_configuration dev_config = {
.device_descriptor = &device_descriptor,
.interface_descriptor = &interface_descriptor,
.config_descriptor = &config_descriptor,
.lang_descriptor = lang_descriptor,
.descriptor_strings = descriptor_strings,
.endpoints = {
{
.descriptor = &ep0_out,
.handler = &ep0_out_handler,
.endpoint_control = NULL, // NA for EP0
.buffer_control = &usb_dpram->ep_buf_ctrl[0].out,
// EP0 in and out share a data buffer
.data_buffer = &usb_dpram->ep0_buf_a[0],
},
{
.descriptor = &ep0_in,
.handler = &ep0_in_handler,
.endpoint_control = NULL, // NA for EP0,
.buffer_control = &usb_dpram->ep_buf_ctrl[0].in,
// EP0 in and out share a data buffer
.data_buffer = &usb_dpram->ep0_buf_a[0],
},
{
.descriptor = &ep1_out,
.handler = &ep1_out_handler,
// EP1 starts at offset 0 for endpoint control
.endpoint_control = &usb_dpram->ep_ctrl[0].out,
.buffer_control = &usb_dpram->ep_buf_ctrl[1].out,
// First free EPX buffer
.data_buffer = &usb_dpram->epx_data[0 * 64],
},
{
.descriptor = &ep2_in,
.handler = &ep2_in_handler,
.endpoint_control = &usb_dpram->ep_ctrl[1].in,
.buffer_control = &usb_dpram->ep_buf_ctrl[2].in,
// Second free EPX buffer
.data_buffer = &usb_dpram->epx_data[1 * 64],
}
}
};
int main(void)
{
uint64_t time_start, time_stop;
system_init();
usb_device_init(&dev_config);
while (usb_is_configured() == 0);
printf("enumed time: %ld\r\n", (uint32_t)timer_count_read());
// Get ready to rx from host
usb_start_transfer(usb_get_endpoint_configuration(EP1_OUT_ADDR), NULL, 64);
time_start = timer_count_read();
while (1) {
time_stop = timer_count_read();
if (time_stop - time_start > 30 * 1000 * 1000) {
usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
reset_unreset_blocks_wait(RESETS_BLOCK_USBCTRL);
printf("time 1s, stop USB\r\n");
break;
}
}
return 0;
}