189 lines
7.0 KiB
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;
|
|
}
|