From adf8ae1ef14af49234511c13fd344e17c7a50439 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Wed, 10 Aug 2022 08:24:51 +0100 Subject: [PATCH] common: Moved the DFU stub out into its own file with seperate handler registration so we don't cross the handler streams --- src/platforms/common/Makefile.inc | 9 ++- src/platforms/common/cdcacm.c | 109 ++++++++++------------------ src/platforms/common/usb.c | 2 + src/platforms/common/usb_dfu_stub.c | 72 ++++++++++++++++++ src/platforms/common/usb_dfu_stub.h | 28 +++++++ 5 files changed, 147 insertions(+), 73 deletions(-) create mode 100644 src/platforms/common/usb_dfu_stub.c create mode 100644 src/platforms/common/usb_dfu_stub.h diff --git a/src/platforms/common/Makefile.inc b/src/platforms/common/Makefile.inc index 774faa8..accebf0 100644 --- a/src/platforms/common/Makefile.inc +++ b/src/platforms/common/Makefile.inc @@ -21,7 +21,8 @@ VPATH += platforms/common CFLAGS += -Iplatforms/common -SRC += \ - jtagtap.c \ - swdptap.c \ - usb.c \ +SRC += \ + jtagtap.c \ + swdptap.c \ + usb.c \ + usb_dfu_stub.c \ diff --git a/src/platforms/common/cdcacm.c b/src/platforms/common/cdcacm.c index 3b0d62a..f7baa6b 100644 --- a/src/platforms/common/cdcacm.c +++ b/src/platforms/common/cdcacm.c @@ -47,86 +47,57 @@ #include "usbuart.h" #include -#include -#include static int configured; static int cdcacm_gdb_dtr = 1; static void cdcacm_set_modem_state(usbd_device *dev, int iface, bool dsr, bool dcd); -static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) +static enum usbd_request_return_codes gdb_uart_control_request(usbd_device *dev, struct usb_setup_data *req, + uint8_t **buf, uint16_t *const len, void (**complete)(usbd_device *dev, struct usb_setup_data *req)) { - (void)dev; - (void)req; - - platform_request_boot(); - - /* Reset core to enter bootloader */ -#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) - scb_reset_core(); -#endif -} - -static enum usbd_request_return_codes cdcacm_control_request(usbd_device *dev, - struct usb_setup_data *req, uint8_t **buf, uint16_t *len, - void (**complete)(usbd_device *dev, struct usb_setup_data *req)) -{ - (void)dev; - (void)complete; (void)buf; - (void)len; + (void)complete; + /* Is the request for the GDB UART interface? */ + if (req->wIndex != GDB_IF_NO) + return USBD_REQ_NEXT_CALLBACK; - switch(req->bRequest) { + switch (req->bRequest) { case USB_CDC_REQ_SET_CONTROL_LINE_STATE: cdcacm_set_modem_state(dev, req->wIndex, true, true); - switch(req->wIndex) { - case UART_IF_NO: - #ifdef USBUSART_DTR_PIN - gpio_set_val(USBUSART_PORT, USBUSART_DTR_PIN, !(req->wValue & 1)); - #endif - #ifdef USBUSART_RTS_PIN - gpio_set_val(USBUSART_PORT, USBUSART_RTS_PIN, !((req->wValue >> 1) & 1)); - #endif - return USBD_REQ_HANDLED; - case GDB_IF_NO: - cdcacm_gdb_dtr = req->wValue & 1; - return USBD_REQ_HANDLED; - default: - return USBD_REQ_NOTSUPP; - } + cdcacm_gdb_dtr = req->wValue & 1; + return USBD_REQ_HANDLED; case USB_CDC_REQ_SET_LINE_CODING: - if(*len < sizeof(struct usb_cdc_line_coding)) + if (*len < sizeof(struct usb_cdc_line_coding)) return USBD_REQ_NOTSUPP; + return USBD_REQ_HANDLED; /* Ignore on GDB Port */ + } + return USBD_REQ_NOTSUPP; +} - switch(req->wIndex) { - case UART_IF_NO: - usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf); - return USBD_REQ_HANDLED; - case GDB_IF_NO: - return USBD_REQ_HANDLED; /* Ignore on GDB Port */ - default: +static enum usbd_request_return_codes debug_uart_control_request(usbd_device *dev, struct usb_setup_data *req, + uint8_t **buf, uint16_t *const len, void (**complete)(usbd_device *dev, struct usb_setup_data *req)) +{ + (void)complete; + /* Is the request for the physical/debug UART interface? */ + if (req->wIndex != UART_IF_NO) + return USBD_REQ_NEXT_CALLBACK; + + switch (req->bRequest) { + case USB_CDC_REQ_SET_CONTROL_LINE_STATE: + cdcacm_set_modem_state(dev, req->wIndex, true, true); +#ifdef USBUSART_DTR_PIN + gpio_set_val(USBUSART_PORT, USBUSART_DTR_PIN, !(req->wValue & 1)); +#endif +#ifdef USBUSART_RTS_PIN + gpio_set_val(USBUSART_PORT, USBUSART_RTS_PIN, !((req->wValue >> 1) & 1)); +#endif + return USBD_REQ_HANDLED; + case USB_CDC_REQ_SET_LINE_CODING: + if (*len < sizeof(struct usb_cdc_line_coding)) return USBD_REQ_NOTSUPP; - } - case DFU_GETSTATUS: - if(req->wIndex == DFU_IF_NO) { - (*buf)[0] = DFU_STATUS_OK; - (*buf)[1] = 0; - (*buf)[2] = 0; - (*buf)[3] = 0; - (*buf)[4] = STATE_APP_IDLE; - (*buf)[5] = 0; /* iString not used here */ - *len = 6; - - return USBD_REQ_HANDLED; - } - return USBD_REQ_NOTSUPP; - case DFU_DETACH: - if(req->wIndex == DFU_IF_NO) { - *complete = dfu_detach_complete; - return USBD_REQ_HANDLED; - } - return USBD_REQ_NOTSUPP; + usbuart_set_line_coding((struct usb_cdc_line_coding *)*buf); + return USBD_REQ_HANDLED; } return USBD_REQ_NOTSUPP; } @@ -189,10 +160,10 @@ void cdcacm_set_config(usbd_device *dev, uint16_t wValue) 64, trace_buf_drain); #endif - usbd_register_control_callback(dev, - USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, - USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, - cdcacm_control_request); + usbd_register_control_callback(dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, debug_uart_control_request); + usbd_register_control_callback(dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, gdb_uart_control_request); /* Notify the host that DCD is asserted. * Allows the use of /dev/tty* devices on *BSD/MacOS diff --git a/src/platforms/common/usb.c b/src/platforms/common/usb.c index 53bfe65..ecc0426 100644 --- a/src/platforms/common/usb.c +++ b/src/platforms/common/usb.c @@ -23,6 +23,7 @@ #include "general.h" #include "usb.h" #include "usb_descriptors.h" +#include "usb_dfu_stub.h" #include "cdcacm.h" #include "serialno.h" @@ -39,6 +40,7 @@ void blackmagic_usb_init(void) usbd_control_buffer, sizeof(usbd_control_buffer)); usbd_register_set_config_callback(usbdev, cdcacm_set_config); + usbd_register_set_config_callback(usbdev, dfu_set_config); nvic_set_priority(USB_IRQ, IRQ_PRI_USB); nvic_enable_irq(USB_IRQ); diff --git a/src/platforms/common/usb_dfu_stub.c b/src/platforms/common/usb_dfu_stub.c new file mode 100644 index 0000000..1ad3405 --- /dev/null +++ b/src/platforms/common/usb_dfu_stub.c @@ -0,0 +1,72 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2022 1BitSquared + * Written by Rachel Mant + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "general.h" +#include "usb_dfu_stub.h" + +static void dfu_detach_complete(usbd_device *const dev, struct usb_setup_data *const req) +{ + (void)dev; + (void)req; + platform_request_boot(); + + /* Reset core to enter bootloader */ +#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) + scb_reset_core(); +#endif +} + +static enum usbd_request_return_codes dfu_control_request(usbd_device *const dev, struct usb_setup_data *req, + uint8_t **buf, uint16_t *len, void (**complete)(usbd_device *dev, struct usb_setup_data *req)) +{ + (void)dev; + /* Is the request for the DFU interface? */ + if (req->wIndex != DFU_IF_NO) + return USBD_REQ_NEXT_CALLBACK; + + switch (req->bRequest) { + case DFU_GETSTATUS: + (*buf)[0] = DFU_STATUS_OK; + (*buf)[1] = 0; + (*buf)[2] = 0; + (*buf)[3] = 0; + (*buf)[4] = STATE_APP_IDLE; + (*buf)[5] = 0; /* iString not used here */ + *len = 6; + + return USBD_REQ_HANDLED; + case DFU_DETACH: + *complete = dfu_detach_complete; + return USBD_REQ_HANDLED; + } + /* If the request isn't one of the two above, we don't care as this is a DFU stub. */ + return USBD_REQ_NOTSUPP; +} + +void dfu_set_config(usbd_device *const dev, const uint16_t value) +{ + (void)value; + usbd_register_control_callback(dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, dfu_control_request); +} diff --git a/src/platforms/common/usb_dfu_stub.h b/src/platforms/common/usb_dfu_stub.h new file mode 100644 index 0000000..0e6b6b6 --- /dev/null +++ b/src/platforms/common/usb_dfu_stub.h @@ -0,0 +1,28 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2022 1BitSquared + * Written by Rachel Mant + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef USB_DFU_STUB_H +#define USB_DFU_STUB_H + +#include "usb.h" + +void dfu_set_config(usbd_device *dev, uint16_t value); + +#endif /*USB_DFU_STUB_H*/