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:
parent
400ee0c76c
commit
adf8ae1ef1
|
@ -21,7 +21,8 @@
|
||||||
VPATH += platforms/common
|
VPATH += platforms/common
|
||||||
CFLAGS += -Iplatforms/common
|
CFLAGS += -Iplatforms/common
|
||||||
|
|
||||||
SRC += \
|
SRC += \
|
||||||
jtagtap.c \
|
jtagtap.c \
|
||||||
swdptap.c \
|
swdptap.c \
|
||||||
usb.c \
|
usb.c \
|
||||||
|
usb_dfu_stub.c \
|
||||||
|
|
|
@ -47,86 +47,57 @@
|
||||||
#include "usbuart.h"
|
#include "usbuart.h"
|
||||||
|
|
||||||
#include <libopencm3/usb/cdc.h>
|
#include <libopencm3/usb/cdc.h>
|
||||||
#include <libopencm3/cm3/scb.h>
|
|
||||||
#include <libopencm3/usb/dfu.h>
|
|
||||||
|
|
||||||
static int configured;
|
static int configured;
|
||||||
static int cdcacm_gdb_dtr = 1;
|
static int cdcacm_gdb_dtr = 1;
|
||||||
|
|
||||||
static void cdcacm_set_modem_state(usbd_device *dev, int iface, bool dsr, bool dcd);
|
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)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:
|
case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
|
||||||
cdcacm_set_modem_state(dev, req->wIndex, true, true);
|
cdcacm_set_modem_state(dev, req->wIndex, true, true);
|
||||||
switch(req->wIndex) {
|
cdcacm_gdb_dtr = req->wValue & 1;
|
||||||
case UART_IF_NO:
|
return USBD_REQ_HANDLED;
|
||||||
#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;
|
|
||||||
}
|
|
||||||
case USB_CDC_REQ_SET_LINE_CODING:
|
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_NOTSUPP;
|
||||||
|
return USBD_REQ_HANDLED; /* Ignore on GDB Port */
|
||||||
|
}
|
||||||
|
return USBD_REQ_NOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
switch(req->wIndex) {
|
static enum usbd_request_return_codes debug_uart_control_request(usbd_device *dev, struct usb_setup_data *req,
|
||||||
case UART_IF_NO:
|
uint8_t **buf, uint16_t *const len, void (**complete)(usbd_device *dev, struct usb_setup_data *req))
|
||||||
usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf);
|
{
|
||||||
return USBD_REQ_HANDLED;
|
(void)complete;
|
||||||
case GDB_IF_NO:
|
/* Is the request for the physical/debug UART interface? */
|
||||||
return USBD_REQ_HANDLED; /* Ignore on GDB Port */
|
if (req->wIndex != UART_IF_NO)
|
||||||
default:
|
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;
|
return USBD_REQ_NOTSUPP;
|
||||||
}
|
usbuart_set_line_coding((struct usb_cdc_line_coding *)*buf);
|
||||||
case DFU_GETSTATUS:
|
return USBD_REQ_HANDLED;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
return USBD_REQ_NOTSUPP;
|
return USBD_REQ_NOTSUPP;
|
||||||
}
|
}
|
||||||
|
@ -189,10 +160,10 @@ void cdcacm_set_config(usbd_device *dev, uint16_t wValue)
|
||||||
64, trace_buf_drain);
|
64, trace_buf_drain);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
usbd_register_control_callback(dev,
|
usbd_register_control_callback(dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
|
||||||
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
|
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, debug_uart_control_request);
|
||||||
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
|
usbd_register_control_callback(dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
|
||||||
cdcacm_control_request);
|
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, gdb_uart_control_request);
|
||||||
|
|
||||||
/* Notify the host that DCD is asserted.
|
/* Notify the host that DCD is asserted.
|
||||||
* Allows the use of /dev/tty* devices on *BSD/MacOS
|
* Allows the use of /dev/tty* devices on *BSD/MacOS
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "general.h"
|
#include "general.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "usb_descriptors.h"
|
#include "usb_descriptors.h"
|
||||||
|
#include "usb_dfu_stub.h"
|
||||||
#include "cdcacm.h"
|
#include "cdcacm.h"
|
||||||
#include "serialno.h"
|
#include "serialno.h"
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ void blackmagic_usb_init(void)
|
||||||
usbd_control_buffer, sizeof(usbd_control_buffer));
|
usbd_control_buffer, sizeof(usbd_control_buffer));
|
||||||
|
|
||||||
usbd_register_set_config_callback(usbdev, cdcacm_set_config);
|
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_set_priority(USB_IRQ, IRQ_PRI_USB);
|
||||||
nvic_enable_irq(USB_IRQ);
|
nvic_enable_irq(USB_IRQ);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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*/
|
Loading…
Reference in New Issue