Compare commits

...

11 Commits

  1. 4
      src/platforms/common/usb.c
  2. 130
      src/platforms/common/usb_descriptors.h
  3. 22
      src/platforms/common/usb_serial.c
  4. 5
      src/platforms/common/usbuart.h
  5. 76
      src/platforms/stm32/usbuart.c

4
src/platforms/common/usb.c

@ -37,9 +37,11 @@ void blackmagic_usb_init(void)
{ {
read_serial_number(); read_serial_number();
usbdev = usbd_init(&USB_DRIVER, &dev_desc, &config, usb_strings, sizeof(usb_strings) / sizeof(char *), usbdev = usbd_init(&USB_DRIVER, &dev_desc, &config, usb_strings, ARRAY_LENGTH(usb_strings),
usbd_control_buffer, sizeof(usbd_control_buffer)); usbd_control_buffer, sizeof(usbd_control_buffer));
usbd_register_bos_descriptor(usbdev, &bos);
microsoft_os_register_descriptor_sets(usbdev, microsoft_os_descriptor_sets, DESCRIPTOR_SETS);
usbd_register_set_config_callback(usbdev, usb_serial_set_config); usbd_register_set_config_callback(usbdev, usb_serial_set_config);
usbd_register_set_config_callback(usbdev, dfu_set_config); usbd_register_set_config_callback(usbdev, dfu_set_config);

130
src/platforms/common/usb_descriptors.h

@ -22,8 +22,10 @@
#define USB_DESCRIPTORS_H #define USB_DESCRIPTORS_H
#include <libopencm3/usb/usbd.h> #include <libopencm3/usb/usbd.h>
#include <libopencm3/usb/bos.h>
#include <libopencm3/usb/cdc.h> #include <libopencm3/usb/cdc.h>
#include <libopencm3/usb/dfu.h> #include <libopencm3/usb/dfu.h>
#include <libopencm3/usb/microsoft.h>
#include "usb.h" #include "usb.h"
#include "serialno.h" #include "serialno.h"
@ -35,7 +37,7 @@
static const struct usb_device_descriptor dev_desc = { static const struct usb_device_descriptor dev_desc = {
.bLength = USB_DT_DEVICE_SIZE, .bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE, .bDescriptorType = USB_DT_DEVICE,
.bcdUSB = 0x0200, .bcdUSB = 0x0201,
.bDeviceClass = 0xEF, /* Miscellaneous Device */ .bDeviceClass = 0xEF, /* Miscellaneous Device */
.bDeviceSubClass = 2, /* Common Class */ .bDeviceSubClass = 2, /* Common Class */
.bDeviceProtocol = 1, /* Interface Association */ .bDeviceProtocol = 1, /* Interface Association */
@ -46,7 +48,7 @@ static const struct usb_device_descriptor dev_desc = {
#endif #endif
.idVendor = 0x1D50, .idVendor = 0x1D50,
.idProduct = 0x6018, .idProduct = 0x6018,
.bcdDevice = 0x0100, .bcdDevice = 0x0108,
.iManufacturer = 1, .iManufacturer = 1,
.iProduct = 2, .iProduct = 2,
.iSerialNumber = 3, .iSerialNumber = 3,
@ -406,9 +408,131 @@ static const char *const usb_strings[] = {
"Black Magic GDB Server", "Black Magic GDB Server",
"Black Magic UART Port", "Black Magic UART Port",
"Black Magic DFU", "Black Magic DFU",
#if defined(PLATFORM_HAS_TRACESWO) #ifdef PLATFORM_HAS_TRACESWO
"Black Magic Trace Capture", "Black Magic Trace Capture",
#endif #endif
}; };
#define DESCRIPTOR_SETS 1U
static const struct {
microsoft_os_feature_compatible_id_descriptor driver_binding;
} microsoft_os_dfu_if_features = {
.driver_binding =
{
.header =
{
.wLength = MICROSOFT_OS_FEATURE_COMPATIBLE_ID_DESCRIPTOR_SIZE,
.wDescriptorType = MICROSOFT_OS_FEATURE_COMPATIBLE_ID,
},
.compatible_id = MICROSOFT_OS_COMPATIBLE_ID_WINUSB,
.sub_compatible_id = MICROSOFT_OS_COMPATIBLE_ID_NONE,
},
};
#ifdef PLATFORM_HAS_TRACESWO
static const struct {
microsoft_os_feature_compatible_id_descriptor driver_binding;
} microsoft_os_trace_if_features = {
.driver_binding =
{
.header =
{
.wLength = MICROSOFT_OS_FEATURE_COMPATIBLE_ID_DESCRIPTOR_SIZE,
.wDescriptorType = MICROSOFT_OS_FEATURE_COMPATIBLE_ID,
},
.compatible_id = MICROSOFT_OS_COMPATIBLE_ID_WINUSB,
.sub_compatible_id = MICROSOFT_OS_COMPATIBLE_ID_NONE,
},
};
#endif
static const microsoft_os_descriptor_function_subset_header microsoft_os_descriptor_function_subsets[] = {
{
.wLength = MICROSOFT_OS_DESCRIPTOR_FUNCTION_SUBSET_HEADER_SIZE,
.wDescriptorType = MICROSOFT_OS_SUBSET_HEADER_FUNCTION,
.bFirstInterface = DFU_IF_NO,
.bReserved = 0,
.wTotalLength = 0,
.feature_descriptors = &microsoft_os_dfu_if_features,
.num_feature_descriptors = 1,
},
#ifdef PLATFORM_HAS_TRACESWO
{
.wLength = MICROSOFT_OS_DESCRIPTOR_FUNCTION_SUBSET_HEADER_SIZE,
.wDescriptorType = MICROSOFT_OS_SUBSET_HEADER_FUNCTION,
.bFirstInterface = TRACE_IF_NO,
.bReserved = 0,
.wTotalLength = 0,
.feature_descriptors = &microsoft_os_trace_if_features,
.num_feature_descriptors = 1,
},
#endif
};
static const microsoft_os_descriptor_config_subset_header microsoft_os_descriptor_config_subset = {
.wLength = MICROSOFT_OS_DESCRIPTOR_CONFIG_SUBSET_HEADER_SIZE,
.wDescriptorType = MICROSOFT_OS_SUBSET_HEADER_CONFIGURATION,
.bConfigurationValue = 1,
.bReserved = 0,
.wTotalLength = 0,
.function_subset_headers = microsoft_os_descriptor_function_subsets,
.num_function_subset_headers = ARRAY_LENGTH(microsoft_os_descriptor_function_subsets),
};
static const microsoft_os_descriptor_set_header microsoft_os_descriptor_sets[DESCRIPTOR_SETS] = {
{
.wLength = MICROSOFT_OS_DESCRIPTOR_SET_HEADER_SIZE,
.wDescriptorType = MICROSOFT_OS_SET_HEADER,
.dwWindowsVersion = MICROSOFT_WINDOWS_VERSION_WINBLUE,
.wTotalLength = 0,
.vendor_code = 1,
.num_config_subset_headers = 1,
.config_subset_headers = &microsoft_os_descriptor_config_subset,
},
};
static const microsoft_os_descriptor_set_information microsoft_os_descriptor_set_info = {
.dwWindowsVersion = MICROSOFT_WINDOWS_VERSION_WINBLUE,
.wMSOSDescriptorSetTotalLength =
MICROSOFT_OS_DESCRIPTOR_SET_HEADER_SIZE + MICROSOFT_OS_DESCRIPTOR_CONFIG_SUBSET_HEADER_SIZE +
#ifdef PLATFORM_HAS_TRACESWO
MICROSOFT_OS_DESCRIPTOR_FUNCTION_SUBSET_HEADER_SIZE + MICROSOFT_OS_FEATURE_COMPATIBLE_ID_DESCRIPTOR_SIZE +
#endif
MICROSOFT_OS_DESCRIPTOR_FUNCTION_SUBSET_HEADER_SIZE + MICROSOFT_OS_FEATURE_COMPATIBLE_ID_DESCRIPTOR_SIZE,
.bMS_VendorCode = 1,
.bAltEnumCode = 0,
};
static const struct {
usb_platform_device_capability_descriptor platform_descriptor;
} __attribute__((packed)) device_capability_descriptors = {
.platform_descriptor =
{
.device_capability_descriptor =
{
.bLength = USB_DCT_PLATFORM_SIZE + MICROSOFT_OS_DESCRIPTOR_SET_INFORMATION_SIZE,
.bDescriptorType = USB_DT_DEVICE_CAPABILITY,
.bDevCapabilityType = USB_DCT_PLATFORM,
},
.bReserved = 0,
.PlatformCapabilityUUID = MICROSOFT_OS_DESCRIPTOR_PLATFORM_CAPABILITY_ID,
.CapabilityData = &microsoft_os_descriptor_set_info,
},
};
static const usb_bos_descriptor bos = {
.bLength = USB_DT_BOS_SIZE,
.bDescriptorType = USB_DT_BOS,
.wTotalLength = 0,
.bNumDeviceCaps = 1,
.device_capability_descriptors = &device_capability_descriptors,
};
#endif /*USB_DESCRIPTORS_H*/ #endif /*USB_DESCRIPTORS_H*/

22
src/platforms/common/usb_serial.c

@ -67,9 +67,20 @@ static enum usbd_request_return_codes gdb_uart_control_request(usbd_device *dev,
gdb_uart_dtr = req->wValue & 1; gdb_uart_dtr = req->wValue & 1;
return USBD_REQ_HANDLED; return USBD_REQ_HANDLED;
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(usb_cdc_line_coding_s))
return USBD_REQ_NOTSUPP; return USBD_REQ_NOTSUPP;
return USBD_REQ_HANDLED; /* Ignore on GDB Port */ return USBD_REQ_HANDLED; /* Ignore on GDB Port */
case USB_CDC_REQ_GET_LINE_CODING: {
if (*len < sizeof(usb_cdc_line_coding_s))
return USBD_REQ_NOTSUPP;
usb_cdc_line_coding_s *line_coding = (usb_cdc_line_coding_s *)*buf;
/* This tells the host that we talk 1MBaud, 8-bit no parity w/ 1 stop bit */
line_coding->dwDTERate = 1 * 1000 * 1000;
line_coding->bCharFormat = USB_CDC_1_STOP_BITS;
line_coding->bParityType = USB_CDC_NO_PARITY;
line_coding->bDataBits = 8;
return USBD_REQ_HANDLED;
}
} }
return USBD_REQ_NOTSUPP; return USBD_REQ_NOTSUPP;
} }
@ -93,9 +104,14 @@ static enum usbd_request_return_codes debug_uart_control_request(usbd_device *de
#endif #endif
return USBD_REQ_HANDLED; return USBD_REQ_HANDLED;
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(usb_cdc_line_coding_s))
return USBD_REQ_NOTSUPP;
usbuart_set_line_coding((usb_cdc_line_coding_s *)*buf);
return USBD_REQ_HANDLED;
case USB_CDC_REQ_GET_LINE_CODING:
if (*len < sizeof(usb_cdc_line_coding_s))
return USBD_REQ_NOTSUPP; return USBD_REQ_NOTSUPP;
usbuart_set_line_coding((struct usb_cdc_line_coding *)*buf); usbuart_get_line_coding((usb_cdc_line_coding_s *)*buf);
return USBD_REQ_HANDLED; return USBD_REQ_HANDLED;
} }
return USBD_REQ_NOTSUPP; return USBD_REQ_NOTSUPP;

5
src/platforms/common/usbuart.h

@ -23,9 +23,12 @@
#include <libopencm3/usb/usbd.h> #include <libopencm3/usb/usbd.h>
#include <libopencm3/usb/cdc.h> #include <libopencm3/usb/cdc.h>
typedef struct usb_cdc_line_coding usb_cdc_line_coding_s;
void usbuart_init(void); void usbuart_init(void);
void usbuart_set_line_coding(struct usb_cdc_line_coding *coding); void usbuart_set_line_coding(const usb_cdc_line_coding_s *coding);
void usbuart_get_line_coding(usb_cdc_line_coding_s *coding);
void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep); void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep);
void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep); void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep);

76
src/platforms/stm32/usbuart.c

@ -25,11 +25,10 @@
#include <libopencm3/cm3/cortex.h> #include <libopencm3/cm3/cortex.h>
#include <libopencm3/cm3/nvic.h> #include <libopencm3/cm3/nvic.h>
#include <libopencm3/cm3/scs.h> #include <libopencm3/cm3/scs.h>
#include <libopencm3/usb/usbd.h>
#include <libopencm3/usb/cdc.h>
#include "general.h" #include "general.h"
#include "usb.h" #include "usb.h"
#include "usbuart.h"
#ifdef DMA_STREAM0 #ifdef DMA_STREAM0
#define dma_channel_reset(dma, channel) dma_stream_reset(dma, channel) #define dma_channel_reset(dma, channel) dma_stream_reset(dma, channel)
@ -57,6 +56,7 @@
#define RX_FIFO_SIZE (USART_DMA_BUF_SIZE) #define RX_FIFO_SIZE (USART_DMA_BUF_SIZE)
#define TX_BUF_SIZE (USART_DMA_BUF_SIZE) #define TX_BUF_SIZE (USART_DMA_BUF_SIZE)
static uint32_t active_baud_rate;
/* TX double buffer */ /* TX double buffer */
static uint8_t buf_tx[TX_BUF_SIZE * 2]; static uint8_t buf_tx[TX_BUF_SIZE * 2];
/* Active buffer part idx */ /* Active buffer part idx */
@ -105,6 +105,12 @@ static void usbuart_set_led_state(uint8_t ledn, bool state)
} }
} }
static void usbuart_set_baudrate(const uint32_t baud_rate)
{
usart_set_baudrate(USBUSART, baud_rate);
active_baud_rate = baud_rate;
}
void usbuart_init(void) void usbuart_init(void)
{ {
/* Enable clocks */ /* Enable clocks */
@ -113,7 +119,7 @@ void usbuart_init(void)
/* Setup UART parameters */ /* Setup UART parameters */
UART_PIN_SETUP(); UART_PIN_SETUP();
usart_set_baudrate(USBUSART, 38400); usbuart_set_baudrate(38400);
usart_set_databits(USBUSART, 8); usart_set_databits(USBUSART, 8);
usart_set_stopbits(USBUSART, USART_STOPBITS_1); usart_set_stopbits(USBUSART, USART_STOPBITS_1);
usart_set_mode(USBUSART, USART_MODE_TX_RX); usart_set_mode(USBUSART, USART_MODE_TX_RX);
@ -206,42 +212,80 @@ void usbuart_send_stdout(const uint8_t *data, uint32_t len)
} }
} }
void usbuart_set_line_coding(struct usb_cdc_line_coding *coding) void usbuart_set_line_coding(const usb_cdc_line_coding_s *coding)
{ {
usart_set_baudrate(USBUSART, coding->dwDTERate); usbuart_set_baudrate(coding->dwDTERate);
if (coding->bParityType) if (coding->bParityType != USB_CDC_NO_PARITY)
usart_set_databits(USBUSART, (coding->bDataBits + 1 <= 8 ? 8 : 9)); usart_set_databits(USBUSART, (coding->bDataBits + 1 <= 8 ? 8 : 9));
else else
usart_set_databits(USBUSART, (coding->bDataBits <= 8 ? 8 : 9)); usart_set_databits(USBUSART, (coding->bDataBits <= 8 ? 8 : 9));
uint32_t stop_bits = USART_STOPBITS_2;
switch (coding->bCharFormat) { switch (coding->bCharFormat) {
case 0: case USB_CDC_1_STOP_BITS:
usart_set_stopbits(USBUSART, USART_STOPBITS_1); stop_bits = USART_STOPBITS_1;
break; break;
case 1: case USB_CDC_1_5_STOP_BITS:
usart_set_stopbits(USBUSART, USART_STOPBITS_1_5); stop_bits = USART_STOPBITS_1_5;
break; break;
case 2: case USB_CDC_2_STOP_BITS:
default: default:
usart_set_stopbits(USBUSART, USART_STOPBITS_2);
break; break;
} }
usart_set_stopbits(USBUSART, stop_bits);
switch(coding->bParityType) { switch(coding->bParityType) {
case 0: case USB_CDC_NO_PARITY:
default:
usart_set_parity(USBUSART, USART_PARITY_NONE); usart_set_parity(USBUSART, USART_PARITY_NONE);
break; break;
case 1: case USB_CDC_ODD_PARITY:
usart_set_parity(USBUSART, USART_PARITY_ODD); usart_set_parity(USBUSART, USART_PARITY_ODD);
break; break;
case 2: case USB_CDC_EVEN_PARITY:
default:
usart_set_parity(USBUSART, USART_PARITY_EVEN); usart_set_parity(USBUSART, USART_PARITY_EVEN);
break; break;
} }
} }
void usbuart_get_line_coding(usb_cdc_line_coding_s *coding)
{
coding->dwDTERate = active_baud_rate;
switch (usart_get_stopbits(USBUSART)) {
case USART_STOPBITS_1:
coding->bCharFormat = USB_CDC_1_STOP_BITS;
break;
case USART_STOPBITS_1_5:
coding->bCharFormat = USB_CDC_1_5_STOP_BITS;
break;
case USART_STOPBITS_2:
default:
coding->bCharFormat = USB_CDC_2_STOP_BITS;
break;
}
switch (usart_get_parity(USBUSART)) {
case USART_PARITY_NONE:
default:
coding->bParityType = USB_CDC_NO_PARITY;
break;
case USART_PARITY_ODD:
coding->bParityType = USB_CDC_ODD_PARITY;
break;
case USART_PARITY_EVEN:
coding->bParityType = USB_CDC_EVEN_PARITY;
break;
}
const uint32_t data_bits = usart_get_databits(USBUSART);
if (coding->bParityType == USB_CDC_NO_PARITY)
coding->bDataBits = data_bits;
else
coding->bDataBits = data_bits - 1;
}
/* /*
* Copy data from fifo into continuous buffer. Return copied length. * Copy data from fifo into continuous buffer. Return copied length.
*/ */

Loading…
Cancel
Save