#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 = ID_PRODUCT, .bcdDevice = 0x0200, .iManufacturer = 1, .iProduct = 2, .iSerialNumber = 3, .bNumConfigurations = 1, }; const struct usb_interface ifaces[] = { { .num_altsetting = 1, .altsetting = &keyboard_iface, }, { .num_altsetting = 1, .altsetting = &consumer_iface, }, { .num_altsetting = 1, .altsetting = &tablet_iface, }, { .num_altsetting = 1, .altsetting = &mouse_iface, }, #ifdef INCLUDE_DFU_INTERFACE { .num_altsetting = 1, .altsetting = &dfu_iface, }, #endif }; const struct usb_config_descriptor config = { .bLength = USB_DT_CONFIGURATION_SIZE, .bDescriptorType = USB_DT_CONFIGURATION, .wTotalLength = 0, #ifdef INCLUDE_DFU_INTERFACE .bNumInterfaces = 5, #else .bNumInterfaces = 4, #endif .bConfigurationValue = 1, .iConfiguration = 4, .bmAttributes = 0xa0, .bMaxPower = 0x31, .interface = ifaces, }; static const char *usb_strings[] = { "Cabbages are good for you", "fish", "soup", "kvm composite", "kvm keyboard", "kvm consumer", "kvm tablet", "kvm mouse", "kvm dfu device", }; usbd_device *usbd_dev; int usb_time_since_sof = 0; int usb_is_suspended = 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, void (**complete) (usbd_device * usbd_dev, struct usb_setup_data * req)) { (void) complete; (void) usbd_dev; if ((req->bmRequestType != 0x81) || (req->bRequest != USB_REQ_GET_DESCRIPTOR) || (req->wValue != 0x2200)) return 0; switch (req->wIndex) { case 0: keyboard_get_descriptor (buf, len); return 1; case 1: consumer_get_descriptor (buf, len); return 1; case 2: tablet_get_descriptor (buf, len); return 1; case 3: mouse_get_descriptor (buf, len); return 1; } *len = 0; return 0; } void usb_set_config (usbd_device * usbd_dev, uint16_t wValue) { (void) wValue; (void) usbd_dev; usbd_ep_setup (usbd_dev, 0x81, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL); usbd_ep_setup (usbd_dev, 0x82, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL); usbd_ep_setup (usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL); usbd_ep_setup (usbd_dev, 0x84, USB_ENDPOINT_ATTR_INTERRUPT, 4, 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); #ifdef INCLUDE_DFU_INTERFACE usbd_register_control_callback (usbd_dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, dfu_control_request); #endif } static void usb_sof (void) { usb_time_since_sof = 0; } void usb_tick (void) { if (usb_is_suspended) { usb_time_since_sof = 0; return; } usb_time_since_sof++; if (usb_time_since_sof > 1000) { usb_time_since_sof = 0; _usbd_reset (usbd_dev); } } /* Buffer to be used for control requests. */ static 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); }