#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; }