X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=bsb%2Ffirmware%2Fmain.c;h=c54d914fe770e183084cccb071b609f10538a5b5;hb=e4d5f850186da491bd0823a32382a29007569679;hp=778dc4516b15bcebe7841e65a5a31ce89c1e1814;hpb=6f25b29b5e45d6cdae78491f203e27b1d5192323;p=home-hw.git diff --git a/bsb/firmware/main.c b/bsb/firmware/main.c index 778dc45..c54d914 100644 --- a/bsb/firmware/main.c +++ b/bsb/firmware/main.c @@ -6,13 +6,16 @@ #include "util.h" +#include #include #include +#include #include #include #include #include #include +#include #include #include @@ -80,7 +83,7 @@ static void usart_init(void) usart_enable(USART1); } -static const struct usb_device_descriptor dev = { +static const struct usb_device_descriptor device = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, .bcdUSB = 0x0200, @@ -126,16 +129,43 @@ static const struct usb_interface_descriptor iface = { .endpoint = endpoints, }; +static const struct usb_dfu_descriptor dfu_function = { + .bLength = sizeof(struct usb_dfu_descriptor), + .bDescriptorType = DFU_FUNCTIONAL, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeout = 255, + .wTransferSize = 1024, + .bcdDFUVersion = 0x0100, +}; + +static const struct usb_interface_descriptor dfu_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = 0xFE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, + .iInterface = 0, + + .extra = &dfu_function, + .extralen = sizeof(dfu_function), +}; + static const struct usb_interface ifaces[] = {{ .num_altsetting = 1, .altsetting = &iface, +}, { + .num_altsetting = 1, + .altsetting = &dfu_iface, }}; static const struct usb_config_descriptor config = { .bLength = USB_DT_CONFIGURATION_SIZE, .bDescriptorType = USB_DT_CONFIGURATION, .wTotalLength = 0, - .bNumInterfaces = 1, + .bNumInterfaces = 2, .bConfigurationValue = 1, .iConfiguration = 0, .bmAttributes = 0x80, @@ -180,6 +210,25 @@ static enum usbd_request_return_codes control_cb(usbd_device *usbd_dev, return USBD_REQ_HANDLED; } +static void dfu_detach_complete(usbd_device *dev UNUSED, struct usb_setup_data *req UNUSED) +{ + // Reset to bootloader, which implements the rest of DFU + scb_reset_core(); +} + +static enum usbd_request_return_codes dfu_control_cb(usbd_device *dev UNUSED, + struct usb_setup_data *req, + uint8_t **buf UNUSED, + uint16_t *len UNUSED, + void (**complete)(usbd_device *dev, struct usb_setup_data *req)) +{ + if (req->bmRequestType != 0x21 || req->bRequest != DFU_DETACH) + return USBD_REQ_NOTSUPP; + + *complete = dfu_detach_complete; + return USBD_REQ_HANDLED; +} + static void ep81_cb(usbd_device *usbd_dev, uint8_t ep UNUSED) { byte buf[4]; @@ -191,6 +240,10 @@ static void ep81_cb(usbd_device *usbd_dev, uint8_t ep UNUSED) static void set_config_cb(usbd_device *usbd_dev, uint16_t wValue UNUSED) { usbd_register_control_callback(usbd_dev, USB_REQ_TYPE_VENDOR, USB_REQ_TYPE_TYPE, control_cb); + usbd_register_control_callback(usbd_dev, + USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + dfu_control_cb); usbd_ep_setup(usbd_dev, 0x81, USB_ENDPOINT_ATTR_BULK, 64, ep81_cb); usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL); ep81_cb(usbd_dev, 0); @@ -218,7 +271,7 @@ int main(void) gpio_clear(GPIOA, GPIO11 | GPIO12); delay_ms(1000); - usbd_device *usbd_dev = usbd_init(&st_usbfs_v1_usb_driver, &dev, &config, usb_strings, ARRAY_SIZE(usb_strings), usbd_control_buffer, sizeof(usbd_control_buffer)); + usbd_device *usbd_dev = usbd_init(&st_usbfs_v1_usb_driver, &device, &config, usb_strings, ARRAY_SIZE(usb_strings), usbd_control_buffer, sizeof(usbd_control_buffer)); usbd_register_reset_callback(usbd_dev, reset_cb); usbd_register_set_config_callback(usbd_dev, set_config_cb); u32 last_ds_step = 0;