Added CMSIS-DAP v2 support to RP2040 port + some USB code refactoring

This commit is contained in:
Alex Taradov 2022-03-05 15:50:14 -08:00
parent 61d9fe21be
commit a62a163689
18 changed files with 619 additions and 290 deletions

View File

@ -25,8 +25,10 @@
#define F_TICK 1000000
/*- Variables ---------------------------------------------------------------*/
static uint8_t app_request_buffer[DAP_CONFIG_PACKET_SIZE];
static uint8_t app_response_buffer[DAP_CONFIG_PACKET_SIZE];
static uint8_t app_req_buf_hid[DAP_CONFIG_PACKET_SIZE];
static uint8_t app_resp_buf_hid[DAP_CONFIG_PACKET_SIZE];
static uint8_t app_req_buf_bulk[DAP_CONFIG_PACKET_SIZE];
static uint8_t app_resp_buf_bulk[DAP_CONFIG_PACKET_SIZE];
static uint8_t app_recv_buffer[USB_BUFFER_SIZE];
static uint8_t app_send_buffer[USB_BUFFER_SIZE];
static int app_recv_buffer_size = 0;
@ -124,7 +126,7 @@ static void serial_number_init(void)
//-----------------------------------------------------------------------------
static void sys_time_init(void)
{
SysTick->VAL = 0;
SysTick->VAL = 0;
SysTick->LOAD = 1000; // 1 ms
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
app_system_time = 0;
@ -222,6 +224,7 @@ static void uart_timer_task(void)
//-----------------------------------------------------------------------------
void usb_cdc_line_coding_updated(usb_cdc_line_coding_t *line_coding)
{
(void)line_coding;
uart_init(line_coding);
}
@ -277,35 +280,43 @@ void usb_cdc_recv_callback(int size)
//-----------------------------------------------------------------------------
void usb_hid_send_callback(void)
{
usb_hid_recv(app_request_buffer, DAP_CONFIG_PACKET_SIZE);
usb_hid_recv(app_req_buf_hid, DAP_CONFIG_PACKET_SIZE);
}
//-----------------------------------------------------------------------------
void usb_hid_recv_callback(int size)
{
app_dap_event = true;
dap_process_request(app_request_buffer, sizeof(app_request_buffer),
app_response_buffer, sizeof(app_response_buffer));
usb_hid_send(app_response_buffer, sizeof(app_response_buffer));
dap_process_request(app_req_buf_hid, sizeof(app_req_buf_hid),
app_resp_buf_hid, sizeof(app_resp_buf_hid));
usb_hid_send(app_resp_buf_hid, sizeof(app_resp_buf_hid));
(void)size;
}
//-----------------------------------------------------------------------------
bool usb_class_handle_request(usb_request_t *request)
static void usb_bulk_send_callback(void)
{
if (usb_cdc_handle_request(request))
return true;
else if (usb_hid_handle_request(request))
return true;
else
return false;
usb_recv(USB_BULK_EP_RECV, app_req_buf_bulk, sizeof(app_req_buf_bulk));
}
//-----------------------------------------------------------------------------
static void usb_bulk_recv_callback(int size)
{
app_dap_event = true;
size = dap_process_request(app_req_buf_bulk, size,
app_resp_buf_bulk, sizeof(app_resp_buf_bulk));
usb_send(USB_BULK_EP_SEND, app_resp_buf_bulk, size);
}
//-----------------------------------------------------------------------------
void usb_configuration_callback(int config)
{
usb_set_send_callback(USB_BULK_EP_SEND, usb_bulk_send_callback);
usb_set_recv_callback(USB_BULK_EP_RECV, usb_bulk_recv_callback);
usb_cdc_recv(app_recv_buffer, sizeof(app_recv_buffer));
usb_hid_recv(app_request_buffer, sizeof(app_request_buffer));
usb_hid_recv(app_req_buf_hid, sizeof(app_req_buf_hid));
usb_recv(USB_BULK_EP_RECV, app_req_buf_bulk, sizeof(app_req_buf_bulk));
app_send_buffer_free = true;
app_send_buffer_ptr = 0;
@ -367,5 +378,3 @@ int main(void)
return 0;
}

View File

@ -3,7 +3,7 @@ BUILD = build
BIN = free_dap_rp2040
##############################################################################
.PHONY: all directory clean size
.PHONY: all directory clean size release
CC = arm-none-eabi-gcc
OBJCOPY = arm-none-eabi-objcopy
@ -30,16 +30,18 @@ LDFLAGS += -Wl,--script=../linker/rp2040.ld
INCLUDES += \
-I../include \
-I../usb \
-I../../.. \
-I..
SRCS += \
../main.c \
../uart.c \
../usb.c \
../usb_std.c \
../usb_cdc.c \
../usb_hid.c \
../usb/usb_rp2040.c \
../usb/usb_std.c \
../usb/usb_cdc.c \
../usb/usb_hid.c \
../usb/usb_winusb.c \
../usb_descriptors.c \
../startup_rp2040.c \
../../../dap.c \
@ -50,7 +52,7 @@ CFLAGS += $(INCLUDES) $(DEFINES)
OBJS = $(addprefix $(BUILD)/, $(notdir %/$(subst .c,.o, $(SRCS))))
all: directory $(BUILD)/$(BIN).elf $(BUILD)/$(BIN).hex $(BUILD)/$(BIN).bin $(BUILD)/$(BIN).uf2 size
all: directory $(BUILD)/$(BIN).elf $(BUILD)/$(BIN).hex $(BUILD)/$(BIN).bin $(BUILD)/$(BIN).uf2 release size
$(BUILD)/$(BIN).elf: $(OBJS)
@echo LD $@
@ -72,6 +74,10 @@ $(BUILD)/$(BIN).uf2: $(BUILD)/$(BIN).bin
@echo CC $@
@$(CC) $(CFLAGS) $(filter %/$(subst .o,.c,$(notdir $@)), $(SRCS)) -c -o $@
release: $(BUILD)/$(BIN).uf2
@echo release
@cp $(BUILD)/$(BIN).uf2 ../../../bin/
directory:
@$(MKDIR) -p $(BUILD)

View File

@ -193,5 +193,3 @@ __attribute__((naked, used, noreturn, section(".boot.entry"))) void boot_entry(v
__builtin_unreachable();
}

View File

@ -9,9 +9,6 @@
#include <stdbool.h>
#include "usb_descriptors.h"
/*- Definitions -------------------------------------------------------------*/
#define USB_EP_NUM 16
/*- Prototypes --------------------------------------------------------------*/
void usb_hw_init(void);
void usb_attach(void);

View File

@ -2,10 +2,6 @@
// Copyright (c) 2017-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
/*- Includes ----------------------------------------------------------------*/
#include <stdbool.h>
#include <stdalign.h>
#include <string.h>
#include "utils.h"
#include "usb.h"
#include "usb_std.h"
#include "usb_cdc.h"
@ -17,9 +13,7 @@
/*- Prototypes --------------------------------------------------------------*/
static void usb_cdc_send_state_notify(void);
static void usb_cdc_ep_comm_callback(int size);
static void usb_cdc_ep_send_callback(int size);
static void usb_cdc_ep_recv_callback(int size);
static void usb_cdc_ep_comm_callback(void);
/*- Variables ---------------------------------------------------------------*/
static usb_cdc_line_coding_t usb_cdc_line_coding =
@ -39,9 +33,9 @@ static bool usb_cdc_comm_busy;
//-----------------------------------------------------------------------------
void usb_cdc_init(void)
{
usb_set_callback(USB_CDC_EP_COMM, usb_cdc_ep_comm_callback);
usb_set_callback(USB_CDC_EP_SEND, usb_cdc_ep_send_callback);
usb_set_callback(USB_CDC_EP_RECV, usb_cdc_ep_recv_callback);
usb_set_send_callback(USB_CDC_EP_COMM, usb_cdc_ep_comm_callback);
usb_set_send_callback(USB_CDC_EP_SEND, usb_cdc_send_callback);
usb_set_recv_callback(USB_CDC_EP_RECV, usb_cdc_recv_callback);
usb_cdc_notify_message.request.bmRequestType = USB_IN_TRANSFER |
USB_INTERFACE_RECIPIENT | USB_CLASS_REQUEST;
@ -107,25 +101,11 @@ static void usb_cdc_send_state_notify(void)
}
//-----------------------------------------------------------------------------
static void usb_cdc_ep_comm_callback(int size)
static void usb_cdc_ep_comm_callback(void)
{
usb_cdc_comm_busy = false;
usb_cdc_notify_message.value &= ~ONE_SHOT_STATES;
usb_cdc_send_state_notify();
(void)size;
}
//-----------------------------------------------------------------------------
static void usb_cdc_ep_send_callback(int size)
{
usb_cdc_send_callback();
(void)size;
}
//-----------------------------------------------------------------------------
static void usb_cdc_ep_recv_callback(int size)
{
usb_cdc_recv_callback(size);
}
//-----------------------------------------------------------------------------
@ -146,18 +126,18 @@ bool usb_cdc_handle_request(usb_request_t *request)
{
int length = request->wLength;
switch ((request->bRequest << 8) | request->bmRequestType)
switch (USB_CMD_VALUE(request))
{
case USB_CMD(OUT, INTERFACE, CLASS, CDC_SET_LINE_CODING):
{
length = LIMIT(length, sizeof(usb_cdc_line_coding_t));
length = USB_LIMIT(length, sizeof(usb_cdc_line_coding_t));
usb_control_recv(usb_cdc_set_line_coding_handler);
} break;
case USB_CMD(IN, INTERFACE, CLASS, CDC_GET_LINE_CODING):
{
length = LIMIT(length, sizeof(usb_cdc_line_coding_t));
length = USB_LIMIT(length, sizeof(usb_cdc_line_coding_t));
usb_control_send((uint8_t *)&usb_cdc_line_coding, length);
} break;
@ -182,17 +162,3 @@ bool usb_cdc_handle_request(usb_request_t *request)
return true;
}
//-----------------------------------------------------------------------------
WEAK void usb_cdc_control_line_state_update(int line_state)
{
(void)line_state;
}
//-----------------------------------------------------------------------------
WEAK void usb_cdc_send_break(int duration)
{
(void)duration;
}

View File

@ -5,12 +5,11 @@
#define _USB_CDC_H_
/*- Includes ----------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include "utils.h"
#include "usb_std.h"
/*- Definitions -------------------------------------------------------------*/
#define USB_CDC_BCD_VERSION 0x0110
enum
{
USB_CDC_SEND_ENCAPSULATED_COMMAND = 0x00,
@ -144,7 +143,7 @@ enum
#define USB_CDC_BREAK_DURATION_INFINITE 0xffff
/*- Types -------------------------------------------------------------------*/
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bFunctionalLength;
uint8_t bDescriptorType;
@ -152,7 +151,7 @@ typedef struct PACK
uint16_t bcdCDC;
} usb_cdc_header_functional_descriptor_t;
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bFunctionalLength;
uint8_t bDescriptorType;
@ -160,7 +159,7 @@ typedef struct PACK
uint8_t bmCapabilities;
} usb_cdc_abstract_control_managment_descriptor_t;
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bFunctionalLength;
uint8_t bDescriptorType;
@ -169,7 +168,7 @@ typedef struct PACK
uint8_t bDataInterface;
} usb_cdc_call_managment_functional_descriptor_t;
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bFunctionalLength;
uint8_t bDescriptorType;
@ -178,7 +177,7 @@ typedef struct PACK
uint8_t bSlaveInterface0;
} usb_cdc_union_functional_descriptor_t;
typedef struct PACK
typedef struct USB_PACK
{
uint32_t dwDTERate;
uint8_t bCharFormat;
@ -186,7 +185,7 @@ typedef struct PACK
uint8_t bDataBits;
} usb_cdc_line_coding_t;
typedef struct PACK
typedef struct USB_PACK
{
usb_request_t request;
uint16_t value;

View File

@ -2,26 +2,18 @@
// Copyright (c) 2019-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
/*- Includes ----------------------------------------------------------------*/
#include <stdbool.h>
#include <stdalign.h>
#include <string.h>
#include "utils.h"
#include "usb.h"
#include "usb_std.h"
#include "usb_hid.h"
#include "usb_descriptors.h"
/*- Prototypes --------------------------------------------------------------*/
static void usb_hid_ep_send_callback(int size);
static void usb_hid_ep_recv_callback(int size);
/*- Implementations ---------------------------------------------------------*/
//-----------------------------------------------------------------------------
void usb_hid_init(void)
{
usb_set_callback(USB_HID_EP_SEND, usb_hid_ep_send_callback);
usb_set_callback(USB_HID_EP_RECV, usb_hid_ep_recv_callback);
usb_set_send_callback(USB_HID_EP_SEND, usb_hid_send_callback);
usb_set_recv_callback(USB_HID_EP_RECV, usb_hid_recv_callback);
}
//-----------------------------------------------------------------------------
@ -36,29 +28,16 @@ void usb_hid_recv(uint8_t *data, int size)
usb_recv(USB_HID_EP_RECV, data, size);
}
//-----------------------------------------------------------------------------
static void usb_hid_ep_send_callback(int size)
{
usb_hid_send_callback();
(void)size;
}
//-----------------------------------------------------------------------------
static void usb_hid_ep_recv_callback(int size)
{
usb_hid_recv_callback(size);
}
//-----------------------------------------------------------------------------
bool usb_hid_handle_request(usb_request_t *request)
{
int length = request->wLength;
switch ((request->bRequest << 8) | request->bmRequestType)
switch (USB_CMD_VALUE(request))
{
case USB_CMD(IN, INTERFACE, STANDARD, GET_DESCRIPTOR):
{
length = LIMIT(length, sizeof(usb_hid_report_descriptor));
length = USB_LIMIT(length, sizeof(usb_hid_report_descriptor));
usb_control_send((uint8_t *)usb_hid_report_descriptor, length);
} break;
@ -69,4 +48,3 @@ bool usb_hid_handle_request(usb_request_t *request)
return true;
}

View File

@ -5,9 +5,6 @@
#define _USB_HID_H_
/*- Includes ----------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include "utils.h"
#include "usb_std.h"
/*- Definitions -------------------------------------------------------------*/
@ -24,7 +21,7 @@ enum
};
/*- Types -------------------------------------------------------------------*/
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bLength;
uint8_t bDescriptorType;
@ -45,4 +42,3 @@ void usb_hid_send_callback(void);
void usb_hid_recv_callback(int size);
#endif // _USB_HID_H_

View File

@ -2,16 +2,13 @@
// Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
/*- Includes ----------------------------------------------------------------*/
#include <string.h>
#include <stdbool.h>
#include <stdalign.h>
#include "rp2040.h"
#include "utils.h"
#include "usb.h"
#include "usb_std.h"
#include "usb_descriptors.h"
/*- Definitions -------------------------------------------------------------*/
#define USB_EP_NUM 16
#define USB_DPRAM_SIZE 4096
#define USB_DPRAM ((usb_dpram_t *)USBCTRL_DPRAM_BASE)
#define USB_DPRAM_FIXED_SIZE 0x100
@ -268,7 +265,7 @@ void usb_control_send(uint8_t *data, int size)
{
while (size)
{
int transfer_size = LIMIT(size, usb_device_descriptor.bMaxPacketSize0);
int transfer_size = USB_LIMIT(size, usb_device_descriptor.bMaxPacketSize0);
for (int i = 0; i < transfer_size; i++)
usb_ep[0].in_buf[i] = data[i];
@ -364,5 +361,3 @@ void usb_task(void)
USBCTRL_REGS->BUFF_STATUS = status;
}
}

View File

@ -2,16 +2,19 @@
// Copyright (c) 2016-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
/*- Includes ----------------------------------------------------------------*/
#include <stdbool.h>
#include <stdalign.h>
#include <string.h>
#include "utils.h"
#include "usb.h"
#include "usb_std.h"
#include "usb_descriptors.h"
/*- Definitions -------------------------------------------------------------*/
#define USB_EP_NUM 16
/*- Types -------------------------------------------------------------------*/
typedef void (*usb_ep_callback_t)(int size);
typedef struct
{
void (*send)(void);
void (*recv)(int size);
} usb_ep_callback_t;
/*- Variables ---------------------------------------------------------------*/
static usb_ep_callback_t usb_ep_callbacks[USB_EP_NUM];
@ -22,30 +25,32 @@ static usb_ep_callback_t usb_ep_callbacks[USB_EP_NUM];
void usb_init(void)
{
for (int i = 0; i < USB_EP_NUM; i++)
usb_ep_callbacks[i] = NULL;
{
usb_ep_callbacks[i].send = NULL;
usb_ep_callbacks[i].recv = NULL;
}
usb_hw_init();
}
//-----------------------------------------------------------------------------
void usb_set_callback(int ep, void (*callback)(int size))
void usb_set_send_callback(int ep, void (*callback)(void))
{
usb_ep_callbacks[ep] = callback;
usb_ep_callbacks[ep].send = callback;
}
//-----------------------------------------------------------------------------
WEAK bool usb_class_handle_request(usb_request_t *request)
void usb_set_recv_callback(int ep, void (*callback)(int size))
{
(void)request;
return false;
usb_ep_callbacks[ep].recv = callback;
}
//-----------------------------------------------------------------------------
bool usb_handle_standard_request(usb_request_t *request)
{
static int usb_config = 0;
static uint8_t usb_config = 0;
switch ((request->bRequest << 8) | request->bmRequestType)
switch (USB_CMD_VALUE(request))
{
case USB_CMD(IN, DEVICE, STANDARD, GET_DESCRIPTOR):
{
@ -55,22 +60,20 @@ bool usb_handle_standard_request(usb_request_t *request)
if (USB_DEVICE_DESCRIPTOR == type)
{
length = LIMIT(length, usb_device_descriptor.bLength);
length = USB_LIMIT(length, usb_device_descriptor.bLength);
usb_control_send((uint8_t *)&usb_device_descriptor, length);
}
else if (USB_CONFIGURATION_DESCRIPTOR == type)
{
length = LIMIT(length, usb_configuration_hierarchy.configuration.wTotalLength);
length = USB_LIMIT(length, sizeof(usb_configuration_hierarchy_t));
usb_control_send((uint8_t *)&usb_configuration_hierarchy, length);
}
else if (USB_STRING_DESCRIPTOR == type)
{
if (0 == index)
{
length = LIMIT(length, usb_string_descriptor_zero.bLength);
length = USB_LIMIT(length, usb_string_descriptor_zero.bLength);
usb_control_send((uint8_t *)&usb_string_descriptor_zero, length);
}
else if (index < USB_STR_COUNT)
@ -89,7 +92,7 @@ bool usb_handle_standard_request(usb_request_t *request)
buf[3 + i*2] = 0;
}
length = LIMIT(length, size);
length = USB_LIMIT(length, size);
usb_control_send(buf, length);
}
@ -98,6 +101,13 @@ bool usb_handle_standard_request(usb_request_t *request)
return false;
}
}
#ifdef USB_ENABLE_BOS
else if (USB_BINARY_OBJECT_STORE_DESCRIPTOR == type)
{
length = USB_LIMIT(length, sizeof(usb_bos_hierarchy_t));
usb_control_send((uint8_t *)&usb_bos_hierarchy, length);
}
#endif
else
{
return false;
@ -136,8 +146,7 @@ bool usb_handle_standard_request(usb_request_t *request)
case USB_CMD(IN, DEVICE, STANDARD, GET_CONFIGURATION):
{
uint8_t config = usb_config;
usb_control_send(&config, sizeof(config));
usb_control_send(&usb_config, sizeof(uint8_t));
} break;
case USB_CMD(IN, DEVICE, STANDARD, GET_STATUS):
@ -218,8 +227,13 @@ bool usb_handle_standard_request(usb_request_t *request)
default:
{
if (!usb_class_handle_request(request))
return false;
for (int i = 0; i < USB_ARRAY_SIZE(usb_class_handlers); i++)
{
if (usb_class_handlers[i](request))
return true;
}
return false;
} break;
}
@ -229,14 +243,13 @@ bool usb_handle_standard_request(usb_request_t *request)
//-----------------------------------------------------------------------------
void usb_send_callback(int ep)
{
if (usb_ep_callbacks[ep])
usb_ep_callbacks[ep](0);
if (usb_ep_callbacks[ep].send)
usb_ep_callbacks[ep].send();
}
//-----------------------------------------------------------------------------
void usb_recv_callback(int ep, int size)
{
if (usb_ep_callbacks[ep])
usb_ep_callbacks[ep](size);
if (usb_ep_callbacks[ep].recv)
usb_ep_callbacks[ep].recv(size);
}

View File

@ -5,9 +5,11 @@
#define _USB_STD_H_
/*- Includes ----------------------------------------------------------------*/
#include <stddef.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "utils.h"
#include <stdalign.h>
/*- Definitions -------------------------------------------------------------*/
enum
@ -91,7 +93,31 @@ enum
enum
{
USB_DEVICE_CLASS_MISCELLANEOUS = 0xef,
USB_ATTRIBUTE_REMOTE_WAKEUP = 0x20,
USB_ATTRIBUTE_SELF_POWERED = 0x40,
USB_ATTRIBUTE_BUS_POWERED = 0x80,
};
enum
{
USB_DEVICE_CAPABILITY_WIRELESS_USB = 1,
USB_DEVICE_CAPABILITY_USB_2_0_EXTENSION = 2,
USB_DEVICE_CAPABILITY_SUPERSPEED_USB = 3,
USB_DEVICE_CAPABILITY_CONTAINER_ID = 4,
USB_DEVICE_CAPABILITY_PLATFORM = 5,
USB_DEVICE_CAPABILITY_POWER_DELIVERY = 6,
USB_DEVICE_CAPABILITY_BATTERY_INFO = 7,
USB_DEVICE_CAPABILITY_PD_CONSUMER_PORT = 8,
USB_DEVICE_CAPABILITY_PD_PROVIDER_PORT = 9,
USB_DEVICE_CAPABILITY_SUPERSPEED_PLUS = 10,
USB_DEVICE_CAPABILITY_PRECISION_TIME_MEASUREMENT = 11,
USB_DEVICE_CAPABILITY_WIRELESS_USB_EXT = 12,
};
enum
{
USB_DEVICE_CLASS_MISCELLANEOUS = 0xef,
USB_DEVICE_CLASS_VENDOR_SPECIFIC = 0xff,
};
enum
@ -105,13 +131,21 @@ enum
};
#define USB_CTRL_EP_SIZE 64
#define USB_LANGID_ENGLISH 0x0409 // English (United States)
#define USB_MAX_POWER(ma) ((ma) / 2)
#define USB_PACK __attribute__((packed))
#define USB_LIMIT(a, b) (((int)(a) > (int)(b)) ? (int)(b) : (int)(a))
#define USB_ARRAY_SIZE(x) ((int)(sizeof(x) / sizeof(0[x])))
#define USB_CMD_VALUE(req) (((req)->bRequest << 8) | (req)->bmRequestType)
#define USB_CMD(dir, rcpt, type, cmd) \
((USB_##cmd << 8) | (USB_##dir##_TRANSFER << 7) | \
(USB_##type##_REQUEST << 5) | (USB_##rcpt##_RECIPIENT << 0))
/*- Types -------------------------------------------------------------------*/
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bmRequestType;
uint8_t bRequest;
@ -120,13 +154,13 @@ typedef struct PACK
uint16_t wLength;
} usb_request_t;
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bLength;
uint8_t bDescriptorType;
} usb_descriptor_header_t;
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bLength;
uint8_t bDescriptorType;
@ -144,7 +178,7 @@ typedef struct PACK
uint8_t bNumConfigurations;
} usb_device_descriptor_t;
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bLength;
uint8_t bDescriptorType;
@ -156,7 +190,7 @@ typedef struct PACK
uint8_t bMaxPower;
} usb_configuration_descriptor_t;
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bLength;
uint8_t bDescriptorType;
@ -169,7 +203,7 @@ typedef struct PACK
uint8_t iInterface;
} usb_interface_descriptor_t;
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bLength;
uint8_t bDescriptorType;
@ -179,21 +213,21 @@ typedef struct PACK
uint8_t bInterval;
} usb_endpoint_descriptor_t;
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wLANGID;
} usb_string_descriptor_zero_t;
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bString;
} usb_string_descriptor_t;
typedef struct PACK
typedef struct USB_PACK
{
uint8_t bLength;
uint8_t bDescriptorType;
@ -205,12 +239,22 @@ typedef struct PACK
uint8_t iFunction;
} usb_interface_association_descriptor_t;
typedef struct USB_PACK
{
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wTotalLength;
uint8_t bNumDeviceCaps;
} usb_binary_object_store_descriptor_t;
typedef bool (*usb_class_handler_t)(usb_request_t *request);
/*- Prototypes --------------------------------------------------------------*/
void usb_init(void);
void usb_set_callback(int ep, void (*callback)(int size));
void usb_set_send_callback(int ep, void (*callback)(void));
void usb_set_recv_callback(int ep, void (*callback)(int size));
bool usb_handle_standard_request(usb_request_t *request);
void usb_send_callback(int ep);
void usb_recv_callback(int ep, int size);
#endif // _USB_STD_H_

View File

@ -0,0 +1,37 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
/*- Includes ----------------------------------------------------------------*/
#include "usb.h"
#include "usb_std.h"
#include "usb_winusb.h"
#include "usb_descriptors.h"
/*- Implementations ---------------------------------------------------------*/
//-----------------------------------------------------------------------------
bool usb_winusb_handle_request(usb_request_t *request)
{
int length = request->wLength;
switch (USB_CMD_VALUE(request))
{
case USB_CMD(IN, DEVICE, VENDOR, WINUSB_VENDOR_CODE):
{
if (USB_WINUSB_DESCRIPTOR_INDEX == request->wIndex)
{
length = USB_LIMIT(length, sizeof(usb_msos_descriptor_set_t));
usb_control_send((uint8_t *)&usb_msos_descriptor_set, length);
}
else
{
return false;
}
} break;
default:
return false;
}
return true;
}

View File

@ -0,0 +1,153 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
#ifndef _USB_WINUSB_H_
#define _USB_WINUSB_H_
// WinUSB device information is stored in the Windows registry at:
// HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USB\<Device>\<Instance>\Device Parameters
/*- Includes ----------------------------------------------------------------*/
#include "usb_std.h"
/*- Definitions -------------------------------------------------------------*/
#define USB_WINUSB_VENDOR_CODE 0x20
#define USB_WINUSB_WINDOWS_VERSION 0x06030000 // Windows 8.1
#define USB_WINUSB_PLATFORM_CAPABILITY_ID \
{ 0xdf, 0x60, 0xdd, 0xd8, 0x89, 0x45, 0xc7, 0x4c, \
0x9c, 0xd2, 0x65, 0x9d, 0x9e, 0x64, 0x8a, 0x9f }
enum // WinUSB Microsoft OS 2.0 descriptor request codes
{
USB_WINUSB_DESCRIPTOR_INDEX = 0x07,
USB_WINUSB_SET_ALT_ENUMERATION = 0x08,
};
enum // wDescriptorType
{
USB_WINUSB_SET_HEADER_DESCRIPTOR = 0x00,
USB_WINUSB_SUBSET_HEADER_CONFIGURATION = 0x01,
USB_WINUSB_SUBSET_HEADER_FUNCTION = 0x02,
USB_WINUSB_FEATURE_COMPATBLE_ID = 0x03,
USB_WINUSB_FEATURE_REG_PROPERTY = 0x04,
USB_WINUSB_FEATURE_MIN_RESUME_TIME = 0x05,
USB_WINUSB_FEATURE_MODEL_ID = 0x06,
USB_WINUSB_FEATURE_CCGP_DEVICE = 0x07,
USB_WINUSB_FEATURE_VENDOR_REVISION = 0x08,
};
enum // wPropertyDataType
{
USB_WINUSB_PROPERTY_DATA_TYPE_SZ = 1,
USB_WINUSB_PROPERTY_DATA_TYPE_EXPAND_SZ = 2,
USB_WINUSB_PROPERTY_DATA_TYPE_BINARY = 3,
USB_WINUSB_PROPERTY_DATA_TYPE_DWORD_LITTLE_ENDIAN = 4,
USB_WINUSB_PROPERTY_DATA_TYPE_DWORD_BIG_ENDIAN = 5,
USB_WINUSB_PROPERTY_DATA_TYPE_LINK = 6,
USB_WINUSB_PROPERTY_DATA_TYPE_MULTI_SZ = 7,
};
/*- Types -------------------------------------------------------------------*/
typedef struct USB_PACK
{
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bDevCapabilityType;
uint8_t bReserved;
uint8_t PlatformCapabilityUUID[16];
uint32_t dwWindowsVersion;
uint16_t wMSOSDescriptorSetTotalLength;
uint8_t bMS_VendorCode;
uint8_t bAltEnumCode;
} usb_winusb_capability_descriptor_t;
typedef struct USB_PACK
{
uint16_t wLength;
uint16_t wDescriptorType;
uint32_t dwWindowsVersion;
uint16_t wDescriptorSetTotalLength;
} usb_winusb_set_header_descriptor_t;
typedef struct USB_PACK
{
uint16_t wLength;
uint16_t wDescriptorType;
uint8_t bConfigurationValue;
uint8_t bReserved;
uint16_t wTotalLength;
} usb_winusb_subset_header_configuration_t;
typedef struct USB_PACK
{
uint16_t wLength;
uint16_t wDescriptorType;
uint8_t bFirstInterface;
uint8_t bReserved;
uint16_t wSubsetLength;
} usb_winusb_subset_header_function_t;
typedef struct USB_PACK
{
uint16_t wLength;
uint16_t wDescriptorType;
uint8_t CompatibleID[8];
uint8_t SubCompatibleID[8];
} usb_winusb_feature_compatble_id_t;
typedef struct USB_PACK
{
uint16_t wLength;
uint16_t wDescriptorType;
uint16_t wPropertyDataType;
//uint16_t wPropertyNameLength;
//uint8_t PropertyName[...];
//uint16_t wPropertyDataLength
//uint8_t PropertyData[...];
} usb_winusb_feature_reg_property_t;
typedef struct USB_PACK
{
uint16_t wLength;
uint16_t wDescriptorType;
uint16_t wPropertyDataType;
uint16_t wPropertyNameLength;
uint8_t PropertyName[42];
uint16_t wPropertyDataLength;
uint8_t PropertyData[80];
} usb_winusb_feature_reg_property_guids_t;
typedef struct USB_PACK
{
uint16_t wLength;
uint16_t wDescriptorType;
uint8_t bResumeRecoveryTime;
uint8_t bResumeSignalingTime;
} usb_winusb_feature_min_resume_time_t;
typedef struct USB_PACK
{
uint16_t wLength;
uint16_t wDescriptorType;
uint8_t ModelID[16];
} usb_winusb_feature_model_id_t;
typedef struct USB_PACK
{
uint16_t wLength;
uint16_t wDescriptorType;
} usb_winusb_feature_ccgp_device_t;
typedef struct USB_PACK
{
uint16_t wLength;
uint16_t wDescriptorType;
uint16_t VendorRevision;
} usb_winusb_feature_vendor_revision_t;
/*- Prototypes --------------------------------------------------------------*/
bool usb_winusb_handle_request(usb_request_t *request);
#endif // _USB_WINUSB_H_

View File

@ -3,7 +3,6 @@
/*- Includes ----------------------------------------------------------------*/
#include <stdalign.h>
#include "usb.h"
#include "usb_descriptors.h"
/*- Variables ---------------------------------------------------------------*/
@ -11,14 +10,14 @@ const alignas(4) usb_device_descriptor_t usb_device_descriptor =
{
.bLength = sizeof(usb_device_descriptor_t),
.bDescriptorType = USB_DEVICE_DESCRIPTOR,
.bcdUSB = 0x0200,
.bcdUSB = USB_BCD_VERSION,
.bDeviceClass = USB_DEVICE_CLASS_MISCELLANEOUS,
.bDeviceSubClass = USB_DEVICE_SUBCLASS_COMMON,
.bDeviceProtocol = USB_DEVICE_PROTOCOL_INTERFACE_ASSOCIATION,
.bMaxPacketSize0 = USB_CTRL_EP_SIZE,
.idVendor = 0x6666,
.idProduct = 0x6600,
.bcdDevice = 0x0101,
.idProduct = 0x9930,
.bcdDevice = 0x0100,
.iManufacturer = USB_STR_MANUFACTURER,
.iProduct = USB_STR_PRODUCT,
.iSerialNumber = USB_STR_SERIAL_NUMBER,
@ -32,24 +31,25 @@ const alignas(4) usb_configuration_hierarchy_t usb_configuration_hierarchy =
.bLength = sizeof(usb_configuration_descriptor_t),
.bDescriptorType = USB_CONFIGURATION_DESCRIPTOR,
.wTotalLength = sizeof(usb_configuration_hierarchy_t),
.bNumInterfaces = 3,
.bNumInterfaces = USB_INTF_COUNT,
.bConfigurationValue = 1,
.iConfiguration = 0,
.bmAttributes = 0x80,
.bMaxPower = 250, // 500 mA
.bmAttributes = USB_ATTRIBUTE_BUS_POWERED,
.bMaxPower = USB_MAX_POWER(500),
},
// CMSIS-DAP v1
.hid_interface =
{
.bLength = sizeof(usb_interface_descriptor_t),
.bDescriptorType = USB_INTERFACE_DESCRIPTOR,
.bInterfaceNumber = 0,
.bInterfaceNumber = USB_INTF_HID,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_HID_DEVICE_CLASS,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = USB_STR_CMSIS_DAP,
.iInterface = USB_STR_CMSIS_DAP_V1,
},
.hid =
@ -83,11 +83,46 @@ const alignas(4) usb_configuration_hierarchy_t usb_configuration_hierarchy =
.bInterval = 1,
},
// CMSIS-DAP v2
.bulk_interface =
{
.bLength = sizeof(usb_interface_descriptor_t),
.bDescriptorType = USB_INTERFACE_DESCRIPTOR,
.bInterfaceNumber = USB_INTF_BULK,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_DEVICE_CLASS_VENDOR_SPECIFIC,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = USB_STR_CMSIS_DAP_V2,
},
.bulk_ep_out =
{
.bLength = sizeof(usb_endpoint_descriptor_t),
.bDescriptorType = USB_ENDPOINT_DESCRIPTOR,
.bEndpointAddress = USB_OUT_ENDPOINT | USB_BULK_EP_RECV,
.bmAttributes = USB_BULK_ENDPOINT,
.wMaxPacketSize = 64,
.bInterval = 0,
},
.bulk_ep_in =
{
.bLength = sizeof(usb_endpoint_descriptor_t),
.bDescriptorType = USB_ENDPOINT_DESCRIPTOR,
.bEndpointAddress = USB_IN_ENDPOINT | USB_BULK_EP_SEND,
.bmAttributes = USB_BULK_ENDPOINT,
.wMaxPacketSize = 64,
.bInterval = 0,
},
// VCP
.iad =
{
.bLength = sizeof(usb_interface_association_descriptor_t),
.bDescriptorType = USB_INTERFACE_ASSOCIATION_DESCRIPTOR,
.bFirstInterface = 1,
.bFirstInterface = USB_INTF_CDC_COMM,
.bInterfaceCount = 2,
.bFunctionClass = USB_CDC_COMM_CLASS,
.bFunctionSubClass = USB_CDC_ACM_SUBCLASS,
@ -99,7 +134,7 @@ const alignas(4) usb_configuration_hierarchy_t usb_configuration_hierarchy =
{
.bLength = sizeof(usb_interface_descriptor_t),
.bDescriptorType = USB_INTERFACE_DESCRIPTOR,
.bInterfaceNumber = 1,
.bInterfaceNumber = USB_INTF_CDC_COMM,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CDC_COMM_CLASS,
@ -113,7 +148,7 @@ const alignas(4) usb_configuration_hierarchy_t usb_configuration_hierarchy =
.bFunctionalLength = sizeof(usb_cdc_header_functional_descriptor_t),
.bDescriptorType = USB_CS_INTERFACE_DESCRIPTOR,
.bDescriptorSubtype = USB_CDC_HEADER_SUBTYPE,
.bcdCDC = 0x0110,
.bcdCDC = USB_CDC_BCD_VERSION,
},
.cdc_acm =
@ -130,7 +165,7 @@ const alignas(4) usb_configuration_hierarchy_t usb_configuration_hierarchy =
.bDescriptorType = USB_CS_INTERFACE_DESCRIPTOR,
.bDescriptorSubtype = USB_CDC_CALL_MGMT_SUBTYPE,
.bmCapabilities = USB_CDC_CALL_MGMT_OVER_DCI,
.bDataInterface = 2,
.bDataInterface = USB_INTF_CDC_DATA,
},
.cdc_union =
@ -138,8 +173,8 @@ const alignas(4) usb_configuration_hierarchy_t usb_configuration_hierarchy =
.bFunctionalLength = sizeof(usb_cdc_union_functional_descriptor_t),
.bDescriptorType = USB_CS_INTERFACE_DESCRIPTOR,
.bDescriptorSubtype = USB_CDC_UNION_SUBTYPE,
.bMasterInterface = 1,
.bSlaveInterface0 = 2,
.bMasterInterface = USB_INTF_CDC_COMM,
.bSlaveInterface0 = USB_INTF_CDC_DATA,
},
.ep_comm =
@ -156,7 +191,7 @@ const alignas(4) usb_configuration_hierarchy_t usb_configuration_hierarchy =
{
.bLength = sizeof(usb_interface_descriptor_t),
.bDescriptorType = USB_INTERFACE_DESCRIPTOR,
.bInterfaceNumber = 2,
.bInterfaceNumber = USB_INTF_CDC_DATA,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CDC_DATA_CLASS,
@ -186,6 +221,76 @@ const alignas(4) usb_configuration_hierarchy_t usb_configuration_hierarchy =
},
};
const alignas(4) usb_bos_hierarchy_t usb_bos_hierarchy =
{
.bos =
{
.bLength = sizeof(usb_binary_object_store_descriptor_t),
.bDescriptorType = USB_BINARY_OBJECT_STORE_DESCRIPTOR,
.wTotalLength = sizeof(usb_bos_hierarchy_t),
.bNumDeviceCaps = 1,
},
.winusb =
{
.bLength = sizeof(usb_winusb_capability_descriptor_t),
.bDescriptorType = USB_DEVICE_CAPABILITY_DESCRIPTOR,
.bDevCapabilityType = USB_DEVICE_CAPABILITY_PLATFORM,
.bReserved = 0,
.PlatformCapabilityUUID = USB_WINUSB_PLATFORM_CAPABILITY_ID,
.dwWindowsVersion = USB_WINUSB_WINDOWS_VERSION,
.wMSOSDescriptorSetTotalLength = sizeof(usb_msos_descriptor_set_t),
.bMS_VendorCode = USB_WINUSB_VENDOR_CODE,
.bAltEnumCode = 0,
},
};
const alignas(4) usb_msos_descriptor_set_t usb_msos_descriptor_set =
{
.header =
{
.wLength = sizeof(usb_winusb_set_header_descriptor_t),
.wDescriptorType = USB_WINUSB_SET_HEADER_DESCRIPTOR,
.dwWindowsVersion = USB_WINUSB_WINDOWS_VERSION,
.wDescriptorSetTotalLength = sizeof(usb_msos_descriptor_set_t),
},
.subset =
{
.header = {
.wLength = sizeof(usb_winusb_subset_header_function_t),
.wDescriptorType = USB_WINUSB_SUBSET_HEADER_FUNCTION,
.bFirstInterface = USB_INTF_BULK,
.bReserved = 0,
.wSubsetLength = sizeof(usb_msos_descriptor_subset_t),
},
.comp_id =
{
.wLength = sizeof(usb_winusb_feature_compatble_id_t),
.wDescriptorType = USB_WINUSB_FEATURE_COMPATBLE_ID,
.CompatibleID = "WINUSB\0\0",
.SubCompatibleID = { 0 },
},
.property =
{
.wLength = sizeof(usb_winusb_feature_reg_property_guids_t),
.wDescriptorType = USB_WINUSB_FEATURE_REG_PROPERTY,
.wPropertyDataType = USB_WINUSB_PROPERTY_DATA_TYPE_MULTI_SZ,
.wPropertyNameLength = sizeof(usb_msos_descriptor_set.subset.property.PropertyName),
.PropertyName = {
'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'I',0,'n',0,'t',0,'e',0,'r',0,'f',0,'a',0,'c',0,'e',0,
'G',0,'U',0,'I',0,'D',0,'s',0, 0, 0 },
.wPropertyDataLength = sizeof(usb_msos_descriptor_set.subset.property.PropertyData),
.PropertyData = {
'{',0,'C',0,'D',0,'B',0,'3',0,'B',0,'5',0,'A',0,'D',0,'-',0,'2',0,'9',0,'3',0,'B',0,'-',0,
'4',0,'6',0,'6',0,'3',0,'-',0,'A',0,'A',0,'3',0,'6',0,'-',0,'1',0,'A',0,'A',0,'E',0,'4',0,
'6',0,'4',0,'6',0,'3',0,'7',0,'7',0,'6',0,'}',0, 0, 0, 0, 0 },
},
},
};
const alignas(4) uint8_t usb_hid_report_descriptor[28] =
{
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
@ -206,20 +311,26 @@ const alignas(4) uint8_t usb_hid_report_descriptor[28] =
const alignas(4) usb_string_descriptor_zero_t usb_string_descriptor_zero =
{
.bLength = sizeof(usb_string_descriptor_zero_t),
.bDescriptorType = USB_STRING_DESCRIPTOR,
.wLANGID = 0x0409, // English (United States)
.bLength = sizeof(usb_string_descriptor_zero_t),
.bDescriptorType = USB_STRING_DESCRIPTOR,
.wLANGID = USB_LANGID_ENGLISH,
};
char usb_serial_number[16];
const char *usb_strings[] =
{
[USB_STR_MANUFACTURER] = "Alex Taradov",
[USB_STR_PRODUCT] = "Combined VCP and CMSIS-DAP Adapter",
[USB_STR_COM_PORT] = "Virtual COM-Port",
[USB_STR_CMSIS_DAP] = "CMSIS-DAP Adapter",
[USB_STR_CMSIS_DAP_V1] = "CMSIS-DAP v1 Adapter",
[USB_STR_CMSIS_DAP_V2] = "CMSIS-DAP v2 Adapter",
[USB_STR_SERIAL_NUMBER] = usb_serial_number,
};
const usb_class_handler_t usb_class_handlers[3] =
{
usb_hid_handle_request,
usb_cdc_handle_request,
usb_winusb_handle_request,
};
char usb_serial_number[16];

View File

@ -5,40 +5,61 @@
#define _USB_DESCRIPTORS_H_
/*- Includes ----------------------------------------------------------------*/
#include "usb.h"
#include "usb_std.h"
#include "usb_cdc.h"
#include "usb_hid.h"
#include "usb_winusb.h"
/*- Definitions -------------------------------------------------------------*/
#define USB_ENABLE_BOS
#define USB_BCD_VERSION 0x0210
enum
{
USB_STR_ZERO,
USB_STR_MANUFACTURER,
USB_STR_PRODUCT,
USB_STR_COM_PORT,
USB_STR_CMSIS_DAP,
USB_STR_SERIAL_NUMBER,
USB_STR_CMSIS_DAP_V1,
USB_STR_CMSIS_DAP_V2,
USB_STR_COM_PORT,
USB_STR_COUNT,
};
enum
{
USB_HID_EP_SEND = 1,
USB_HID_EP_RECV = 2,
USB_CDC_EP_COMM = 3,
USB_CDC_EP_SEND = 4,
USB_CDC_EP_RECV = 5,
USB_HID_EP_SEND = 1,
USB_HID_EP_RECV = 2,
USB_BULK_EP_RECV = 3,
USB_BULK_EP_SEND = 4,
USB_CDC_EP_COMM = 5,
USB_CDC_EP_SEND = 6,
USB_CDC_EP_RECV = 7,
};
enum
{
USB_INTF_HID,
USB_INTF_BULK,
USB_INTF_CDC_COMM,
USB_INTF_CDC_DATA,
USB_INTF_COUNT,
};
/*- Types -------------------------------------------------------------------*/
typedef struct PACK
typedef struct USB_PACK
{
usb_configuration_descriptor_t configuration;
usb_interface_descriptor_t hid_interface;
usb_hid_descriptor_t hid;
usb_endpoint_descriptor_t hid_ep_in;
usb_endpoint_descriptor_t hid_ep_out;
usb_interface_descriptor_t bulk_interface;
usb_endpoint_descriptor_t bulk_ep_out;
usb_endpoint_descriptor_t bulk_ep_in;
usb_interface_association_descriptor_t iad;
usb_interface_descriptor_t interface_comm;
usb_cdc_header_functional_descriptor_t cdc_header;
@ -51,14 +72,34 @@ typedef struct PACK
usb_endpoint_descriptor_t ep_out;
} usb_configuration_hierarchy_t;
typedef struct USB_PACK
{
usb_binary_object_store_descriptor_t bos;
usb_winusb_capability_descriptor_t winusb;
} usb_bos_hierarchy_t;
typedef struct USB_PACK
{
usb_winusb_subset_header_function_t header;
usb_winusb_feature_compatble_id_t comp_id;
usb_winusb_feature_reg_property_guids_t property;
} usb_msos_descriptor_subset_t;
typedef struct USB_PACK
{
usb_winusb_set_header_descriptor_t header;
usb_msos_descriptor_subset_t subset;
} usb_msos_descriptor_set_t;
//-----------------------------------------------------------------------------
extern const usb_device_descriptor_t usb_device_descriptor;
extern const usb_configuration_hierarchy_t usb_configuration_hierarchy;
extern const usb_bos_hierarchy_t usb_bos_hierarchy;
extern const usb_msos_descriptor_set_t usb_msos_descriptor_set;
extern const uint8_t usb_hid_report_descriptor[28];
extern const usb_string_descriptor_zero_t usb_string_descriptor_zero;
extern const char *usb_strings[];
extern const usb_class_handler_t usb_class_handlers[3];
extern char usb_serial_number[16];
#endif // _USB_DESCRIPTORS_H_

View File

@ -1,14 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2016-2022, Alex Taradov <alex@taradov.com>. All rights reserved.
#ifndef _UTILS_H_
#define _UTILS_H_
/*- Definitions -------------------------------------------------------------*/
#define PACK __attribute__((packed))
#define WEAK __attribute__((weak))
#define INLINE static inline __attribute__((always_inline))
#define LIMIT(a, b) (((int)(a) > (int)(b)) ? (int)(b) : (int)(a))
#endif // _UTILS_H_