common: Moved the DFU stub out into its own file with seperate handler registration so we don't cross the handler streams

This commit is contained in:
dragonmux 2022-08-10 08:24:51 +01:00 committed by Piotr Esden-Tempski
parent 400ee0c76c
commit adf8ae1ef1
5 changed files with 147 additions and 73 deletions

View File

@ -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 \

View File

@ -47,86 +47,57 @@
#include "usbuart.h"
#include <libopencm3/usb/cdc.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/usb/dfu.h>
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

View File

@ -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);

View File

@ -0,0 +1,72 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2022 1BitSquared <info@1bitsquared.com>
* Written by Rachel Mant <git@dragonmux.network>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/usb/usbd.h>
#include <libopencm3/usb/dfu.h>
#include <libopencm3/cm3/scb.h>
#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);
}

View File

@ -0,0 +1,28 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2022 1BitSquared <info@1bitsquared.com>
* Written by Rachel Mant <git@dragonmux.network>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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*/