#include "project.h" /* Define this to include the DFU APP interface. */ const struct usb_device_descriptor dev = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, .bcdUSB = 0x0200, .bDeviceClass = 0, .bDeviceSubClass = 0, .bDeviceProtocol = 0, .bMaxPacketSize0 = 64, .idVendor = 0x1d6b, .idProduct = 0xcad5, .bcdDevice = 0x0200, .iManufacturer = 1, .iProduct = 2, .iSerialNumber = 3, .bNumConfigurations = 1, }; const struct usb_interface ifaces[] = { { .num_altsetting = 1, .altsetting = comm_iface, }, { .num_altsetting = 1, .altsetting = data_iface, }, { .num_altsetting = 1, .altsetting = &dfu_iface, }, }; const struct usb_config_descriptor config = { .bLength = USB_DT_CONFIGURATION_SIZE, .bDescriptorType = USB_DT_CONFIGURATION, .wTotalLength = 0, .bNumInterfaces = 3, .bConfigurationValue = 1, .iConfiguration = 4, .bmAttributes = 0xa0, .bMaxPower = 0x31, .interface = ifaces, }; static const char *usb_strings[] = { "candlestick", "candlestick", "candlestick", "composite", "usb serial 0", "usb serial 1", "candlestick dfu device", }; usbd_device *usbd_dev; int usb_is_suspended = 0; int usb_running = 0; static int time_since_sof; void usb_tick (void) { time_since_sof++; if (time_since_sof > 3000) usb_running = 0; } static void usb_sof (void) { usb_running = 1; time_since_sof = 0; } static void usb_suspended (void) { *USB_CNTR_REG |= USB_CNTR_FSUSP; usb_is_suspended = 1; } static void usb_resumed (void) { *USB_CNTR_REG &= ~USB_CNTR_FSUSP; usb_is_suspended = 0; } int usb_wakeup_host (void) { if (!usb_is_suspended) return 1; *USB_CNTR_REG |= USB_CNTR_RESUME; delay_us (1000); delay_us (1000); delay_us (1000); delay_us (1000); delay_us (1000); *USB_CNTR_REG &= ~USB_CNTR_RESUME; return 0; } static int usb_control_request (usbd_device * usbd_dev, struct usb_setup_data *req, uint8_t ** buf, uint16_t * len, int (**complete) (usbd_device * usbd_dev, struct usb_setup_data * req)) { (void) complete; (void) usbd_dev; (void) buf; (void) len; if ((req->bmRequestType != (USB_REQ_TYPE_IN | USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE)) || (req->bRequest != USB_REQ_GET_DESCRIPTOR) || (req->wValue != 0x2200)) return 0; *len = 0; return 0; } int class_control_request (usbd_device * usbd_dev, struct usb_setup_data *req, uint8_t ** buf, uint16_t * len, int (**complete) (usbd_device * usbd_dev, struct usb_setup_data * req)) { if (cdcacm_control_request (usbd_dev, req, buf, len, complete)) return 1; if (dfu_control_request (usbd_dev, req, buf, len, complete)) return 1; return 0; } void usb_set_config (usbd_device * usbd_dev, uint16_t wValue) { (void) wValue; (void) usbd_dev; usbd_ep_setup (usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb); usbd_ep_setup (usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL); usbd_ep_setup (usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); usbd_register_control_callback (usbd_dev, USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, usb_control_request); usbd_register_control_callback (usbd_dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, class_control_request); } /* Buffer to be used for control requests. */ uint8_t usbd_control_buffer[128]; void usb_init (void) { usbd_dev = usbd_init (&stm32f103_usb_driver, &dev, &config, usb_strings, 8, usbd_control_buffer, sizeof (usbd_control_buffer)); usbd_register_set_config_callback (usbd_dev, usb_set_config); usbd_register_suspend_callback (usbd_dev, usb_suspended); usbd_register_resume_callback (usbd_dev, usb_resumed); usbd_register_sof_callback (usbd_dev, usb_sof); } void usb_run (void) { for (;;) { usbd_poll (usbd_dev); serial_poll (); } }