7 Commits

Author SHA1 Message Date
sakumisu
859db28964 feat(class/display): add usb vendor display device driver
Signed-off-by: sakumisu <1203593632@qq.com>
2026-02-05 20:52:55 +08:00
sakumisu
6b0ec0e16f refactor(class/dfu): refactor dfu device driver
Signed-off-by: sakumisu <1203593632@qq.com>
2026-02-05 20:39:38 +08:00
sakumisu
1a5bc9d150 fix(cherrymp): fix block size check
Signed-off-by: sakumisu <1203593632@qq.com>
2026-02-05 20:38:06 +08:00
sakumisu
08d1ce4ab5 style(class): remove device warning logs for memory
Signed-off-by: sakumisu <1203593632@qq.com>
2026-02-03 21:04:14 +08:00
sakumisu
0cac0ab34c fix typo
Signed-off-by: sakumisu <1203593632@qq.com>
2026-02-03 20:52:35 +08:00
sakumisu
5f47d1a6b6 fix(port/musb/usb_hc_musb): fix stall to stalled
Signed-off-by: sakumisu <1203593632@qq.com>
2026-02-03 20:50:01 +08:00
sakumisu
64dced8ec7 fix(port/dwc2/usb_dc_dwc2): fix typo for disable global isr
Signed-off-by: sakumisu <1203593632@qq.com>
2026-02-03 20:48:35 +08:00
30 changed files with 813 additions and 915 deletions

13
Kconfig
View File

@@ -138,6 +138,11 @@ if CHERRYUSB
prompt "Enable usb dfu device" prompt "Enable usb dfu device"
default n default n
config CHERRYUSB_DEVICE_DISPLAY
bool
prompt "Enable usb display device"
default n
config USBDEV_REQUEST_BUFFER_LEN config USBDEV_REQUEST_BUFFER_LEN
int int
prompt "Set device control transfer max buffer size" prompt "Set device control transfer max buffer size"
@@ -211,6 +216,10 @@ if CHERRYUSB
bool bool
prompt "cdc_ncm" prompt "cdc_ncm"
depends on CHERRYUSB_DEVICE_CDC_NCM depends on CHERRYUSB_DEVICE_CDC_NCM
config CHERRYUSB_DEVICE_TEMPLATE_DFU
bool
prompt "dfu"
depends on CHERRYUSB_DEVICE_DFU
config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC config CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
bool bool
prompt "cdc_acm_msc" prompt "cdc_acm_msc"
@@ -233,6 +242,10 @@ if CHERRYUSB
bool bool
prompt "webusb_hid" prompt "webusb_hid"
depends on CHERRYUSB_DEVICE_HID depends on CHERRYUSB_DEVICE_HID
config CHERRYUSB_DEVICE_TEMPLATE_DISPLAY
bool
prompt "display"
depends on CHERRYUSB_DEVICE_DISPLAY
endchoice endchoice
endif endif

View File

@@ -139,6 +139,11 @@ if RT_USING_CHERRYUSB
prompt "Enable usb dfu device" prompt "Enable usb dfu device"
default n default n
config RT_CHERRYUSB_DEVICE_DISPLAY
bool
prompt "Enable usb display device"
default n
config RT_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV config RT_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV
bool bool
prompt "Enable chardev for cdc acm device" prompt "Enable chardev for cdc acm device"
@@ -221,6 +226,10 @@ if RT_USING_CHERRYUSB
bool bool
prompt "cdc_ncm" prompt "cdc_ncm"
depends on RT_CHERRYUSB_DEVICE_CDC_NCM depends on RT_CHERRYUSB_DEVICE_CDC_NCM
config RT_CHERRYUSB_DEVICE_TEMPLATE_DFU
bool
prompt "dfu"
depends on RT_CHERRYUSB_DEVICE_DFU
config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC config RT_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
bool bool
prompt "cdc_acm_msc" prompt "cdc_acm_msc"
@@ -243,6 +252,10 @@ if RT_USING_CHERRYUSB
bool bool
prompt "webusb_hid" prompt "webusb_hid"
depends on RT_CHERRYUSB_DEVICE_HID depends on RT_CHERRYUSB_DEVICE_HID
config RT_CHERRYUSB_DEVICE_TEMPLATE_DISPLAY
bool
prompt "display"
depends on RT_CHERRYUSB_DEVICE_DISPLAY
config RT_CHERRYUSB_DEVICE_TEMPLATE_ADB config RT_CHERRYUSB_DEVICE_TEMPLATE_ADB
bool bool
prompt "adb" prompt "adb"

View File

@@ -138,6 +138,11 @@ if PKG_USING_CHERRYUSB
prompt "Enable usb dfu device" prompt "Enable usb dfu device"
default n default n
config PKG_CHERRYUSB_DEVICE_DISPLAY
bool
prompt "Enable usb display device"
default n
config PKG_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV config PKG_CHERRYUSB_DEVICE_CDC_ACM_CHARDEV
bool bool
prompt "Enable chardev for cdc acm device" prompt "Enable chardev for cdc acm device"
@@ -220,6 +225,10 @@ if PKG_USING_CHERRYUSB
bool bool
prompt "cdc_ncm" prompt "cdc_ncm"
depends on PKG_CHERRYUSB_DEVICE_CDC_NCM depends on PKG_CHERRYUSB_DEVICE_CDC_NCM
config PKG_CHERRYUSB_DEVICE_TEMPLATE_DFU
bool
prompt "dfu"
depends on PKG_CHERRYUSB_DEVICE_DFU
config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC config PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC
bool bool
prompt "cdc_acm_msc" prompt "cdc_acm_msc"
@@ -242,6 +251,10 @@ if PKG_USING_CHERRYUSB
bool bool
prompt "webusb_hid" prompt "webusb_hid"
depends on PKG_CHERRYUSB_DEVICE_HID depends on PKG_CHERRYUSB_DEVICE_HID
config PKG_CHERRYUSB_DEVICE_TEMPLATE_DISPLAY
bool
prompt "display"
depends on PKG_CHERRYUSB_DEVICE_DISPLAY
config PKG_CHERRYUSB_DEVICE_TEMPLATE_ADB config PKG_CHERRYUSB_DEVICE_TEMPLATE_ADB
bool bool
prompt "adb" prompt "adb"

View File

@@ -75,6 +75,7 @@ CherryUSB Device Stack has the following functions:
- Support Remote NDIS (RNDIS) - Support Remote NDIS (RNDIS)
- Support Media Transfer Protocol (MTP) - Support Media Transfer Protocol (MTP)
- Support WINUSB1.0, WINUSB2.0, WEBUSB, BOS - Support WINUSB1.0, WINUSB2.0, WEBUSB, BOS
- Support Vendor display ([xfz1986_usb_graphic_driver](https://github.com/chuanjinpang/win10_idd_xfz1986_usb_graphic_driver_display))
- Support Vendor class - Support Vendor class
- Support UF2 - Support UF2
- Support Android Debug Bridge (Only support shell) - Support Android Debug Bridge (Only support shell)
@@ -93,6 +94,7 @@ CherryUSB Device Stack resource usage (GCC 10.2 with -O2, disable log):
|usbd_rndis.c | ~2500 | 2 * 1580(default)+156+8 | 80 | 0 | |usbd_rndis.c | ~2500 | 2 * 1580(default)+156+8 | 80 | 0 |
|usbd_cdc_ecm.c | ~900 | 2 * 1514(default)+16 | 42 | 0 | |usbd_cdc_ecm.c | ~900 | 2 * 1514(default)+16 | 42 | 0 |
|usbd_mtp.c | ~9000 | 2048(default)+128 | sizeof(struct mtp_object) * n| 0 | |usbd_mtp.c | ~9000 | 2048(default)+128 | sizeof(struct mtp_object) * n| 0 |
|usbd_dfu.c | ~2200 | 0 | 45 | 0 |
## Host Stack Overview ## Host Stack Overview

View File

@@ -75,6 +75,7 @@ CherryUSB Device 协议栈当前实现以下功能:
- 支持 Remote NDIS (RNDIS) - 支持 Remote NDIS (RNDIS)
- 支持 Media Transfer Protocol (MTP) - 支持 Media Transfer Protocol (MTP)
- 支持 WINUSB1.0、WINUSB2.0、WEBUSB、BOS - 支持 WINUSB1.0、WINUSB2.0、WEBUSB、BOS
- 支持 Vendor display ([xfz1986_usb_graphic_driver](https://github.com/chuanjinpang/win10_idd_xfz1986_usb_graphic_driver_display))
- 支持 Vendor 类 class - 支持 Vendor 类 class
- 支持 UF2 - 支持 UF2
- 支持 Android Debug Bridge (Only support shell) - 支持 Android Debug Bridge (Only support shell)
@@ -93,6 +94,7 @@ CherryUSB Device 协议栈资源占用说明GCC 10.2 with -O2
|usbd_rndis.c | ~2500 | 2 * 1580(default)+156+8 | 80 | 0 | |usbd_rndis.c | ~2500 | 2 * 1580(default)+156+8 | 80 | 0 |
|usbd_cdc_ecm.c | ~900 | 2 * 1514(default)+16 | 42 | 0 | |usbd_cdc_ecm.c | ~900 | 2 * 1514(default)+16 | 42 | 0 |
|usbd_mtp.c | ~9000 | 2048(default)+128 | sizeof(struct mtp_object) * n| 0 | |usbd_mtp.c | ~9000 | 2048(default)+128 | sizeof(struct mtp_object) * n| 0 |
|usbd_dfu.c | ~2200 | 0 | 45 | 0 |
## Host 协议栈简介 ## Host 协议栈简介

View File

@@ -17,6 +17,7 @@ path += [cwd + '/class/dfu']
path += [cwd + '/class/serial'] path += [cwd + '/class/serial']
path += [cwd + '/class/vendor/net'] path += [cwd + '/class/vendor/net']
path += [cwd + '/class/vendor/wifi'] path += [cwd + '/class/vendor/wifi']
path += [cwd + '/class/vendor/display']
src = [] src = []
LIBS = [] LIBS = []
@@ -136,6 +137,11 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('class/cdc/usbd_cdc_ncm.c') src += Glob('class/cdc/usbd_cdc_ncm.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DFU']): if GetDepend(['PKG_CHERRYUSB_DEVICE_DFU']):
src += Glob('class/dfu/usbd_dfu.c') src += Glob('class/dfu/usbd_dfu.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_DISPLAY']):
src += Glob('class/vendor/display/usbd_display.c')
src += Glob('third_party/cherrymp/chry_mempool.c')
src += Glob('third_party/cherrymp/chry_mempool_osal_rtthread.c')
path += [cwd + '/third_party/cherrymp']
if GetDepend(['PKG_CHERRYUSB_DEVICE_ADB']): if GetDepend(['PKG_CHERRYUSB_DEVICE_ADB']):
src += Glob('class/adb/usbd_adb.c') src += Glob('class/adb/usbd_adb.c')
src += Glob('platform/rtthread/usbd_adb_shell.c') src += Glob('platform/rtthread/usbd_adb_shell.c')
@@ -165,6 +171,8 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('demo/cdc_ecm_template.c') src += Glob('demo/cdc_ecm_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM']): if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_NCM']):
src += Glob('demo/cdc_ncm_template.c') src += Glob('demo/cdc_ncm_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_DFU']):
src += Glob('demo/dfu_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC']): if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC']):
src += Glob('demo/cdc_acm_msc_template.c') src += Glob('demo/cdc_acm_msc_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID']): if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_MSC_HID']):
@@ -177,6 +185,8 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('demo/winusb2.0_cdc_template.c') src += Glob('demo/winusb2.0_cdc_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WEBUSB_HID']): if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_WEBUSB_HID']):
src += Glob('demo/webusb_hid_template.c') src += Glob('demo/webusb_hid_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_DISPLAY']):
src += Glob('demo/display/usbdisplay_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_ADB']): if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_ADB']):
src += Glob('demo/adb/usbd_adb_template.c') src += Glob('demo/adb/usbd_adb_template.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_CHARDEV']): if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM_CHARDEV']):

View File

@@ -50,6 +50,7 @@ list(
${CMAKE_CURRENT_LIST_DIR}/class/serial ${CMAKE_CURRENT_LIST_DIR}/class/serial
${CMAKE_CURRENT_LIST_DIR}/class/vendor/net ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net
${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi
${CMAKE_CURRENT_LIST_DIR}/class/vendor/display
${CMAKE_CURRENT_LIST_DIR}/class/aoa ${CMAKE_CURRENT_LIST_DIR}/class/aoa
${CMAKE_CURRENT_LIST_DIR}/class/gamepad ${CMAKE_CURRENT_LIST_DIR}/class/gamepad
) )
@@ -89,6 +90,9 @@ if(CONFIG_CHERRYUSB_DEVICE)
if(CONFIG_CHERRYUSB_DEVICE_GAMEPAD) if(CONFIG_CHERRYUSB_DEVICE_GAMEPAD)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/gamepad/usbd_gamepad.c) list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/gamepad/usbd_gamepad.c)
endif() endif()
if(CONFIG_CHERRYUSB_DEVICE_DISPLAY)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/display/usbd_display.c)
endif()
if(CONFIG_CHERRYUSB_DEVICE_FSDEV_ST) if(CONFIG_CHERRYUSB_DEVICE_FSDEV_ST)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/fsdev/usb_dc_fsdev.c) list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/fsdev/usb_dc_fsdev.c)

View File

@@ -49,7 +49,6 @@ static int audio_class_endpoint_request_handler(uint8_t busid, struct usb_setup_
break; break;
default: default:
USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
return -1; return -1;
} }
return 0; return 0;
@@ -109,7 +108,6 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
*len = 1; *len = 1;
break; break;
default: default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1; return -1;
} }
} else { } else {
@@ -124,7 +122,6 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
} }
break; break;
default: default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1; return -1;
} }
} }
@@ -169,7 +166,6 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
*len = 2; *len = 2;
break; break;
default: default:
USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1; return -1;
} }
} else { } else {
@@ -207,14 +203,12 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
} }
break; break;
default: default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1; return -1;
} }
} }
break; break;
default: default:
USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
return -1; return -1;
} }
break; break;
@@ -247,7 +241,6 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
} }
break; break;
default: default:
//USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x in cs 0x%02x\r\n", setup->bRequest, control_selector);
return -1; return -1;
} }
break; break;
@@ -261,7 +254,6 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup
break; break;
default: default:
//USB_LOG_WRN("Unhandled Audio Class cs 0x%02x \r\n", control_selector);
return -1; return -1;
} }
break; break;

View File

@@ -76,7 +76,6 @@ static int cdc_acm_class_interface_request_handler(uint8_t busid, struct usb_set
usbd_cdc_acm_send_break(busid, intf_num); usbd_cdc_acm_send_break(busid, intf_num);
break; break;
default: default:
USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }

View File

@@ -106,7 +106,6 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set
#endif #endif
break; break;
default: default:
USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }

View File

@@ -23,7 +23,7 @@
#define DFU_PROTOCOL_RUNTIME 0x01 #define DFU_PROTOCOL_RUNTIME 0x01
/** DFU Class DFU mode Protocol */ /** DFU Class DFU mode Protocol */
#define DFU_PROTOCOL_MODE 0x02 #define DFU_PROTOCOL_DFU 0x02
/** /**
* @brief DFU Class Specific Requests * @brief DFU Class Specific Requests
@@ -76,21 +76,23 @@
#define DFU_STATE_DFU_UPLOAD_IDLE 9U #define DFU_STATE_DFU_UPLOAD_IDLE 9U
#define DFU_STATE_DFU_ERROR 10U #define DFU_STATE_DFU_ERROR 10U
/** DFU Manifestation State */ /* Define DFU application notification signals. */
#define DFU_MANIFEST_COMPLETE 0U #define DFU_NOTIFICATION_BEGIN_DOWNLOAD 0x1u
#define DFU_MANIFEST_IN_PROGRESS 1U #define DFU_NOTIFICATION_END_DOWNLOAD 0x2u
#define DFU_NOTIFICATION_ABORT_DOWNLOAD 0x3u
#define DFU_NOTIFICATION_BEGIN_UPLOAD 0x5u
#define DFU_NOTIFICATION_END_UPLOAD 0x6u
#define DFU_NOTIFICATION_ABORT_UPLOAD 0x7u
/** Special Commands with Download Request */ /* Define DFU application notification signals. */
#define DFU_CMD_GETCOMMANDS 0U #define DFU_MEDIA_STATUS_OK 0
#define DFU_CMD_SETADDRESSPOINTER 0x21U #define DFU_MEDIA_STATUS_BUSY 1
#define DFU_CMD_ERASE 0x41U #define DFU_MEDIA_STATUS_ERROR 2
#define DFU_MEDIA_ERASE 0x00U
#define DFU_MEDIA_PROGRAM 0x01U
/** Other defines */ /** Special Commands with Download Request for STM32, wValue = 0 */
/* Bit Detach capable = bit 3 in bmAttributes field */ #define DFU_SPECIAL_CMD_SET_ADDRESS_POINTER 0x21U
#define DFU_DETACH_MASK (1U << 3) #define DFU_SPECIAL_CMD_ERASE 0x41U
#define DFU_MANIFEST_MASK (1U << 2) #define DFU_SPECIAL_READ_UNPROTECT 0x92U
/** Run-Time Functional Descriptor */ /** Run-Time Functional Descriptor */
struct dfu_runtime_descriptor { struct dfu_runtime_descriptor {
@@ -103,35 +105,36 @@ struct dfu_runtime_descriptor {
} __PACKED; } __PACKED;
/**\brief Payload packet to response in DFU_GETSTATUS request */ /**\brief Payload packet to response in DFU_GETSTATUS request */
struct dfu_info { struct dfu_status {
uint8_t bStatus; /**<\brief An indication of the status resulting from the uint8_t bStatus; /**<\brief An indication of the status resulting from the
* execution of the most recent request.*/ * execution of the most recent request.*/
uint8_t bPollTimeout; /**<\brief Minimum time (LSB) in ms, that the host should wait uint32_t bwPollTimeout; /**<\brief Minimum time in ms, that the host should wait
* before sending a subsequent DFU_GETSTATUS request.*/ * before sending a subsequent DFU_GETSTATUS request.*/
uint16_t wPollTimeout; /**<\brief Minimum time (MSB) in ms, that the host should wait uint8_t bState; /**<\brief An indication of the state that the device is going
* before sending a subsequent DFU_GETSTATUS request.*/
uint8_t bState; /**<\brief An indication of the state that the device is going
* to enter immediately following transmission of this response.*/ * to enter immediately following transmission of this response.*/
uint8_t iString; /**<\brief Index of the status string descriptor.*/ uint8_t iString; /**<\brief Index of the status string descriptor.*/
}; };
#define DFU_DESCRIPTOR_LEN 18
// clang-format off // clang-format off
#define DFU_DESCRIPTOR_INIT() \ #define DFU_DESCRIPTOR_INIT(str_idx) \
0x09, /* bLength */ \ 0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
0x00, /* bInterfaceNumber */ \ 0x00, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \ 0x00, /* bAlternateSetting */ \
0x00, /* bNumEndpoints Default Control Pipe only */ \ 0x00, /* bNumEndpoints Default Control Pipe only */ \
USB_DEVICE_CLASS_APP_SPECIFIC, /* bInterfaceClass */ \ USB_DEVICE_CLASS_APP_SPECIFIC, /* bInterfaceClass */ \
0x01, /* bInterfaceSubClass Device Firmware Upgrade */ \ DFU_SUBCLASS_DFU, /* bInterfaceSubClass Device Firmware Upgrade */ \
0x02, /* bInterfaceProtocol DFU mode */ \ DFU_PROTOCOL_DFU, /* bInterfaceProtocol DFU mode */ \
0x04, /* iInterface */ /*!< Device Firmware Update Functional Descriptor */ \ str_idx, /* iInterface */ \
/*!< Device Firmware Update Functional Descriptor */ \
0x09, /* bLength */ \ 0x09, /* bLength */ \
0x21, /* DFU Functional Descriptor */ \ 0x21, /* DFU Functional Descriptor */ \
0x0B, /* bmAttributes */ \ 0x0B, /* bmAttributes */ \
WBVAL(0x00ff), /* wDetachTimeOut */ \ WBVAL(0x00ff), /* wDetachTimeOut */ \
WBVAL(USBD_DFU_XFER_SIZE), /* wTransferSize */ \ WBVAL(CONFIG_USBDEV_REQUEST_BUFFER_LEN), /* wTransferSize */ \
WBVAL(0x011a) /* bcdDFUVersion */ WBVAL(DFU_VERSION) /* bcdDFUVersion */
// clang-format on // clang-format on
#endif /* USB_DFU_H */ #endif /* USB_DFU_H */

View File

@@ -1,431 +1,28 @@
/* /*
* Copyright (c) 2022, sakumisu * Copyright (c) 2022 ~ 2026, sakumisu
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include "usbd_core.h" #include "usbd_core.h"
#include "usbd_dfu.h" #include "usbd_dfu.h"
/** Modify the following three parameters according to different platforms */
#ifndef USBD_DFU_XFER_SIZE
#define USBD_DFU_XFER_SIZE 1024
#endif
#ifndef USBD_DFU_APP_DEFAULT_ADD
#define USBD_DFU_APP_DEFAULT_ADD 0x8004000
#endif
#ifndef FLASH_PROGRAM_TIME
#define FLASH_PROGRAM_TIME 50
#endif
#ifndef FLASH_ERASE_TIME
#define FLASH_ERASE_TIME 50
#endif
struct usbd_dfu_priv { struct usbd_dfu_priv {
struct dfu_info info; uint8_t dfu_state;
union {
uint32_t d32[USBD_DFU_XFER_SIZE / 4U];
uint8_t d8[USBD_DFU_XFER_SIZE];
} buffer;
uint32_t wblock_num;
uint32_t wlength;
uint32_t data_ptr;
uint32_t alt_setting;
uint8_t dev_status[6];
uint8_t ReservedForAlign[2];
uint8_t dev_state;
uint8_t manif_state;
uint8_t firmwar_flag;
} g_usbd_dfu; } g_usbd_dfu;
static void dfu_reset(void) const char *usbd_dfu_state_string[] = {
{ "APP_IDLE",
memset(&g_usbd_dfu, 0, sizeof(g_usbd_dfu)); "APP_DETACH",
"DFU_IDLE",
g_usbd_dfu.alt_setting = 0U; "DFU_DNLOAD_SYNC",
g_usbd_dfu.data_ptr = USBD_DFU_APP_DEFAULT_ADD; "DFU_DNLOAD_BUSY",
g_usbd_dfu.wblock_num = 0U; "DFU_DNLOAD_IDLE",
g_usbd_dfu.wlength = 0U; "DFU_MANIFEST_SYNC",
"DFU_MANIFEST",
g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE; "DFU_MANIFEST_WAIT_RESET",
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE; "DFU_UPLOAD_IDLE",
"DFU_ERROR"
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK; };
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[5] = 0U;
}
static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
{
switch (cmd) {
case DFU_MEDIA_PROGRAM:
buffer[1] = (uint8_t)FLASH_PROGRAM_TIME;
buffer[2] = (uint8_t)(FLASH_PROGRAM_TIME << 8);
buffer[3] = 0;
break;
case DFU_MEDIA_ERASE:
buffer[1] = (uint8_t)FLASH_ERASE_TIME;
buffer[2] = (uint8_t)(FLASH_ERASE_TIME << 8);
buffer[3] = 0;
default:
break;
}
return (0);
}
static void dfu_request_detach(void)
{
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
/* Update the state machine */
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
g_usbd_dfu.dev_status[5] = 0U; /*iString*/
g_usbd_dfu.wblock_num = 0U;
g_usbd_dfu.wlength = 0U;
}
}
static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
struct usb_setup_packet *req = setup;
uint32_t addr;
/* Data setup request */
if (req->wLength > 0U) {
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
/* Update the global length and block number */
g_usbd_dfu.wblock_num = req->wValue;
g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
/* DFU Get Command */
if (g_usbd_dfu.wblock_num == 0U) {
/* Update the state machine */
g_usbd_dfu.dev_state = (g_usbd_dfu.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/* Store the values of all supported commands */
g_usbd_dfu.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
g_usbd_dfu.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
g_usbd_dfu.buffer.d8[2] = DFU_CMD_ERASE;
/* Send the status data over EP0 */
memcpy(*data, g_usbd_dfu.buffer.d8, 3);
*len = 3;
} else if (g_usbd_dfu.wblock_num > 1U) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
/* Return the physical address where data are stored */
dfu_read_flash((uint8_t *)addr, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
/* Send the status data over EP0 */
memcpy(*data, g_usbd_dfu.buffer.d8, g_usbd_dfu.wlength);
*len = g_usbd_dfu.wlength;
} else /* unsupported g_usbd_dfu.wblock_num */
{
g_usbd_dfu.dev_state = DFU_STATUS_ERR_STALLEDPKT;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/* Call the error management function (command will be NAKed */
USB_LOG_ERR("Dfu_request_upload unsupported g_usbd_dfu.wblock_num\r\n");
}
}
/* Unsupported state */
else {
g_usbd_dfu.wlength = 0U;
g_usbd_dfu.wblock_num = 0U;
/* Call the error management function (command will be NAKed */
USB_LOG_ERR("Dfu_request_upload unsupported state\r\n");
}
}
/* No Data setup request */
else {
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
}
static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
/* Data setup request */
struct usb_setup_packet *req = setup;
if (req->wLength > 0U) {
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
/* Update the global length and block number */
g_usbd_dfu.wblock_num = req->wValue;
g_usbd_dfu.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
/* Update the state machine */
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/*!< Data has received complete */
memcpy((uint8_t *)g_usbd_dfu.buffer.d8, (uint8_t *)*data, g_usbd_dfu.wlength);
/*!< Set flag = 1 Write the firmware to the flash in the next dfu_request_getstatus */
g_usbd_dfu.firmwar_flag = 1;
}
/* Unsupported state */
else {
USB_LOG_ERR("Dfu_request_dnload unsupported state\r\n");
}
}
/* 0 Data DNLOAD request */
else {
/* End of DNLOAD operation*/
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE)) {
g_usbd_dfu.manif_state = DFU_MANIFEST_IN_PROGRESS;
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
} else {
/* Call the error management function (command will be NAKed */
USB_LOG_ERR("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", g_usbd_dfu.dev_state);
}
}
}
static int8_t dfu_getstatus_special_handler(void)
{
uint32_t addr;
if (g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
/* Decode the Special Command */
if (g_usbd_dfu.wblock_num == 0U) {
if (g_usbd_dfu.wlength == 1U) {
if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
/* Nothing to do */
}
} else if (g_usbd_dfu.wlength == 5U) {
if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
} else if (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE) {
g_usbd_dfu.data_ptr = g_usbd_dfu.buffer.d8[1];
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[2] << 8;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[3] << 16;
g_usbd_dfu.data_ptr += (uint32_t)g_usbd_dfu.buffer.d8[4] << 24;
USB_LOG_DBG("Erase start add %08x \r\n", g_usbd_dfu.data_ptr);
/*!< Erase */
dfu_erase_flash(g_usbd_dfu.data_ptr);
} else {
return -1;
}
} else {
/* Reset the global length and block number */
g_usbd_dfu.wlength = 0U;
g_usbd_dfu.wblock_num = 0U;
/* Call the error management function (command will be NAKed) */
USB_LOG_ERR("Reset the global length and block number\r\n");
}
}
/* Regular Download Command */
else {
if (g_usbd_dfu.wblock_num > 1U) {
/* Decode the required address */
addr = ((g_usbd_dfu.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + g_usbd_dfu.data_ptr;
/* Perform the write operation */
/* Write flash */
USB_LOG_DBG("Write start add %08x length %d\r\n", addr, g_usbd_dfu.wlength);
dfu_write_flash(g_usbd_dfu.buffer.d8, (uint8_t *)addr, g_usbd_dfu.wlength);
}
}
/* Reset the global length and block number */
g_usbd_dfu.wlength = 0U;
g_usbd_dfu.wblock_num = 0U;
/* Update the state machine */
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
return 0;
}
static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
/*!< Determine whether to leave DFU mode */
if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS &&
g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
g_usbd_dfu.dev_status[1] == 0U &&
g_usbd_dfu.dev_status[2] == 0U &&
g_usbd_dfu.dev_status[3] == 0U &&
g_usbd_dfu.dev_status[4] == g_usbd_dfu.dev_state) {
g_usbd_dfu.manif_state = DFU_MANIFEST_COMPLETE;
if ((0x0B & DFU_MANIFEST_MASK) != 0U) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
return;
} else {
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
/* Generate system reset to allow jumping to the user code */
dfu_leave();
}
}
switch (g_usbd_dfu.dev_state) {
case DFU_STATE_DFU_DNLOAD_SYNC:
if (g_usbd_dfu.wlength != 0U) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
if ((g_usbd_dfu.wblock_num == 0U) && (g_usbd_dfu.buffer.d8[0] == DFU_CMD_ERASE)) {
dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_ERASE, g_usbd_dfu.dev_status);
} else {
dfu_getstatus(g_usbd_dfu.data_ptr, DFU_MEDIA_PROGRAM, g_usbd_dfu.dev_status);
}
} else /* (g_usbd_dfu.wlength==0)*/
{
g_usbd_dfu.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
break;
case DFU_STATE_DFU_MANIFEST_SYNC:
if (g_usbd_dfu.manif_state == DFU_MANIFEST_IN_PROGRESS) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_MANIFEST;
g_usbd_dfu.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
} else {
if ((g_usbd_dfu.manif_state == DFU_MANIFEST_COMPLETE) &&
((0x0B & DFU_MANIFEST_MASK) != 0U)) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U;
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
}
}
break;
default:
break;
}
/* Send the status data over EP0 */
memcpy(*data, g_usbd_dfu.dev_status, 6);
*len = 6;
if (g_usbd_dfu.firmwar_flag == 1) {
if (dfu_getstatus_special_handler() != 0) {
USB_LOG_ERR("dfu_getstatus_special_handler error \r\n");
}
g_usbd_dfu.firmwar_flag = 0;
}
}
static void dfu_request_clrstatus(void)
{
if (g_usbd_dfu.dev_state == DFU_STATE_DFU_ERROR) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK; /* bStatus */
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
g_usbd_dfu.dev_status[5] = 0U; /* iString */
} else {
/* State Error */
g_usbd_dfu.dev_state = DFU_STATE_DFU_ERROR;
g_usbd_dfu.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state; /* bState */
g_usbd_dfu.dev_status[5] = 0U; /* iString */
}
}
static void dfu_request_getstate(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{
/* Return the current state of the DFU interface */
(*data)[0] = g_usbd_dfu.dev_state;
*len = 1;
}
void dfu_request_abort(void)
{
if ((g_usbd_dfu.dev_state == DFU_STATE_DFU_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
(g_usbd_dfu.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
g_usbd_dfu.dev_state = DFU_STATE_DFU_IDLE;
g_usbd_dfu.dev_status[0] = DFU_STATUS_OK;
g_usbd_dfu.dev_status[1] = 0U;
g_usbd_dfu.dev_status[2] = 0U;
g_usbd_dfu.dev_status[3] = 0U; /* bwPollTimeout=0ms */
g_usbd_dfu.dev_status[4] = g_usbd_dfu.dev_state;
g_usbd_dfu.dev_status[5] = 0U; /* iString */
g_usbd_dfu.wblock_num = 0U;
g_usbd_dfu.wlength = 0U;
}
}
static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
{ {
@@ -433,33 +30,260 @@ static int dfu_class_interface_request_handler(uint8_t busid, struct usb_setup_p
"bRequest 0x%02x\r\n", "bRequest 0x%02x\r\n",
setup->bRequest); setup->bRequest);
switch (setup->bRequest) { USB_LOG_DBG("dfu state:%s\r\n", usbd_dfu_state_string[g_usbd_dfu.dfu_state]);
case DFU_REQUEST_DETACH:
dfu_request_detach(); switch (g_usbd_dfu.dfu_state) {
case DFU_STATE_APP_IDLE:
switch (setup->bRequest) {
case DFU_REQUEST_DETACH:
break;
case DFU_REQUEST_GETSTATUS:
(*data)[0] = DFU_STATUS_OK; /* bStatus */
(*data)[1] = 0;
(*data)[2] = 0;
(*data)[3] = 0;
(*data)[4] = g_usbd_dfu.dfu_state;
(*data)[5] = 0; /* iString */
*len = 6;
break;
case DFU_REQUEST_GETSTATE:
(*data)[0] = g_usbd_dfu.dfu_state;
*len = 1;
break;
default:
return -1;
}
break; break;
case DFU_REQUEST_DNLOAD: case DFU_STATE_APP_DETACH:
dfu_request_dnload(setup, data, len); switch (setup->bRequest) {
case DFU_REQUEST_GETSTATUS:
(*data)[0] = DFU_STATUS_OK; /* bStatus */
(*data)[1] = 0;
(*data)[2] = 0;
(*data)[3] = 0;
(*data)[4] = g_usbd_dfu.dfu_state;
(*data)[5] = 0; /* iString */
*len = 6;
break;
case DFU_REQUEST_GETSTATE:
(*data)[0] = g_usbd_dfu.dfu_state;
*len = 1;
break;
default:
return -1;
}
break; break;
case DFU_REQUEST_UPLOAD: case DFU_STATE_DFU_IDLE:
dfu_request_upload(setup, data, len); switch (setup->bRequest) {
case DFU_REQUEST_DNLOAD:
/* We received a DOWNLOAD command. Check the length field of the request. If it is 0,
we are done with the transfer. */
if (setup->wLength == 0) {
usbd_dfu_end_load();
g_usbd_dfu.dfu_state = DFU_STATE_DFU_MANIFEST_SYNC;
} else {
usbd_dfu_begin_load();
if (usbd_dfu_write(setup->wValue, *data, setup->wLength) < 0) {
g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
return -1;
} else {
g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_SYNC;
}
}
break;
case DFU_REQUEST_UPLOAD:
usbd_dfu_begin_load();
uint16_t actual_length;
if (usbd_dfu_read(setup->wValue, *data, setup->wLength, &actual_length) < 0) {
g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
return -1;
} else {
g_usbd_dfu.dfu_state = DFU_STATE_DFU_UPLOAD_IDLE;
}
break;
case DFU_REQUEST_ABORT:
g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
break;
case DFU_REQUEST_GETSTATUS:
(*data)[0] = DFU_STATUS_OK; /* bStatus */
(*data)[1] = 0;
(*data)[2] = 0;
(*data)[3] = 0;
(*data)[4] = g_usbd_dfu.dfu_state;
(*data)[5] = 0; /* iString */
*len = 6;
break;
case DFU_REQUEST_GETSTATE:
(*data)[0] = g_usbd_dfu.dfu_state;
*len = 1;
break;
default:
return -1;
}
break; break;
case DFU_REQUEST_GETSTATUS: case DFU_STATE_DFU_DNLOAD_SYNC:
dfu_request_getstatus(setup, data, len); switch (setup->bRequest) {
case DFU_REQUEST_GETSTATUS:
g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_BUSY;
(*data)[0] = DFU_STATUS_OK; /* bStatus */
(*data)[1] = 0;
(*data)[2] = 0;
(*data)[3] = 0;
(*data)[4] = g_usbd_dfu.dfu_state;
(*data)[5] = 0; /* iString */
*len = 6;
break;
case DFU_REQUEST_GETSTATE:
(*data)[0] = g_usbd_dfu.dfu_state;
*len = 1;
break;
default:
return -1;
}
break; break;
case DFU_REQUEST_CLRSTATUS: case DFU_STATE_DFU_DNLOAD_BUSY:
dfu_request_clrstatus(); switch (setup->bRequest) {
case DFU_REQUEST_GETSTATUS:
g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_IDLE;
(*data)[0] = DFU_STATUS_OK; /* bStatus */
(*data)[1] = 0;
(*data)[2] = 0;
(*data)[3] = 0;
(*data)[4] = g_usbd_dfu.dfu_state;
(*data)[5] = 0; /* iString */
*len = 6;
break;
case DFU_REQUEST_GETSTATE:
(*data)[0] = g_usbd_dfu.dfu_state;
*len = 1;
break;
default:
return -1;
}
break; break;
case DFU_REQUEST_GETSTATE: case DFU_STATE_DFU_DNLOAD_IDLE:
dfu_request_getstate(setup, data, len); switch (setup->bRequest) {
case DFU_REQUEST_DNLOAD:
/* We received a DOWNLOAD command. Check the length field of the request. If it is 0,
we are done with the transfer. */
if (setup->wLength == 0) {
usbd_dfu_end_load();
g_usbd_dfu.dfu_state = DFU_STATE_DFU_MANIFEST_SYNC;
} else {
if (usbd_dfu_write(setup->wValue, *data, setup->wLength) < 0) {
g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
return -1;
} else {
g_usbd_dfu.dfu_state = DFU_STATE_DFU_DNLOAD_SYNC;
}
}
break;
case DFU_REQUEST_ABORT:
g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
break;
case DFU_REQUEST_GETSTATUS:
(*data)[0] = DFU_STATUS_OK; /* bStatus */
(*data)[1] = 0;
(*data)[2] = 0;
(*data)[3] = 0;
(*data)[4] = g_usbd_dfu.dfu_state;
(*data)[5] = 0; /* iString */
*len = 6;
break;
case DFU_REQUEST_GETSTATE:
(*data)[0] = g_usbd_dfu.dfu_state;
*len = 1;
break;
default:
return -1;
}
break; break;
case DFU_REQUEST_ABORT: case DFU_STATE_DFU_UPLOAD_IDLE:
dfu_request_abort(); switch (setup->bRequest) {
case DFU_REQUEST_UPLOAD: {
uint16_t actual_length;
if (usbd_dfu_read(setup->wValue, *data, setup->wLength, &actual_length) < 0) {
g_usbd_dfu.dfu_state = DFU_STATE_DFU_ERROR;
return -1;
} else {
if (actual_length < setup->wLength) {
usbd_dfu_end_load();
g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
} else {
g_usbd_dfu.dfu_state = DFU_STATE_DFU_UPLOAD_IDLE;
}
}
} break;
case DFU_REQUEST_ABORT:
g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
break;
case DFU_REQUEST_GETSTATUS:
(*data)[0] = DFU_STATUS_OK; /* bStatus */
(*data)[1] = 0;
(*data)[2] = 0;
(*data)[3] = 0;
(*data)[4] = g_usbd_dfu.dfu_state;
(*data)[5] = 0; /* iString */
*len = 6;
break;
case DFU_REQUEST_GETSTATE:
(*data)[0] = g_usbd_dfu.dfu_state;
*len = 1;
break;
default:
return -1;
}
break; break;
case DFU_STATE_DFU_MANIFEST_SYNC:
switch (setup->bRequest) {
case DFU_REQUEST_GETSTATUS:
g_usbd_dfu.dfu_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
(*data)[0] = DFU_STATUS_OK; /* bStatus */
(*data)[1] = 0;
(*data)[2] = 0;
(*data)[3] = 0;
(*data)[4] = g_usbd_dfu.dfu_state;
(*data)[5] = 0; /* iString */
*len = 6;
usbd_dfu_reset();
break;
case DFU_REQUEST_GETSTATE:
(*data)[0] = g_usbd_dfu.dfu_state;
*len = 1;
break;
default:
return -1;
}
break;
case DFU_STATE_DFU_ERROR:
switch (setup->bRequest) {
case DFU_REQUEST_CLRSTATUS:
g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
break;
default:
return -1;
}
break;
default: default:
USB_LOG_WRN("Unhandled DFU Class bRequest 0x%02x\r\n", setup->bRequest); USB_LOG_WRN("Invalid dfu state %s\r\n", usbd_dfu_state_string[g_usbd_dfu.dfu_state]);
return -1; return -1;
} }
return 0; return 0;
} }
@@ -467,7 +291,7 @@ static void dfu_notify_handler(uint8_t busid, uint8_t event, void *arg)
{ {
switch (event) { switch (event) {
case USBD_EVENT_RESET: case USBD_EVENT_RESET:
dfu_reset(); g_usbd_dfu.dfu_state = DFU_STATE_DFU_IDLE;
break; break;
default: default:
break; break;
@@ -484,21 +308,29 @@ struct usbd_interface *usbd_dfu_init_intf(struct usbd_interface *intf)
return intf; return intf;
} }
__WEAK uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len) uint8_t usbd_dfu_get_state(void)
{ {
return dest; return g_usbd_dfu.dfu_state;
} }
__WEAK uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len) __WEAK void usbd_dfu_begin_load(void)
{
}
__WEAK void usbd_dfu_end_load(void)
{
}
__WEAK void usbd_dfu_reset(void)
{
}
__WEAK int usbd_dfu_write(uint16_t value, const uint8_t *data, uint16_t length)
{ {
return 0; return 0;
} }
__WEAK uint16_t dfu_erase_flash(uint32_t add) __WEAK int usbd_dfu_read(uint16_t value, const uint8_t *data, uint16_t length, uint16_t *actual_length)
{ {
return 0; return 0;
} }
__WEAK void dfu_leave(void)
{
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, sakumisu * Copyright (c) 2022 ~ 2026, sakumisu
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -14,12 +14,14 @@ extern "C" {
/* Init dfu interface driver */ /* Init dfu interface driver */
struct usbd_interface *usbd_dfu_init_intf(struct usbd_interface *intf); struct usbd_interface *usbd_dfu_init_intf(struct usbd_interface *intf);
uint8_t usbd_dfu_get_state(void);
void usbd_dfu_begin_load(void);
void usbd_dfu_end_load(void);
void usbd_dfu_reset(void);
int usbd_dfu_write(uint16_t value, const uint8_t *data, uint16_t length);
int usbd_dfu_read(uint16_t value, const uint8_t *data, uint16_t length, uint16_t *actual_length);
/* Interface functions that need to be implemented by the user */
uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len);
uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len);
uint16_t dfu_erase_flash(uint32_t add);
void dfu_leave(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -41,7 +41,6 @@ static int hid_class_interface_request_handler(uint8_t busid, struct usb_setup_p
break; break;
default: default:
USB_LOG_WRN("Unhandled HID Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }

View File

@@ -89,7 +89,6 @@ static int msc_storage_class_interface_request_handler(uint8_t busid, struct usb
break; break;
default: default:
USB_LOG_WRN("Unhandled MSC Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }

View File

@@ -8,7 +8,7 @@
#include "usbh_ch34x.h" #include "usbh_ch34x.h"
#undef USB_DBG_TAG #undef USB_DBG_TAG
#define USB_DBG_TAG "usbh_ch43x" #define USB_DBG_TAG "usbh_ch34x"
#include "usb_log.h" #include "usb_log.h"
struct usbh_ch34x { struct usbh_ch34x {

184
class/vendor/display/usbd_display.c vendored Normal file
View File

@@ -0,0 +1,184 @@
/*
* Copyright (c) 2026, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_display.h"
#include "chry_mempool.h"
struct usbd_disp_frame_header {
uint16_t crc16; //payload crc16
uint8_t type; //raw rgb,yuv,jpg,other
uint8_t cmd;
uint16_t x; //32bit
uint16_t y;
uint16_t width; //32bit
uint16_t height;
uint32_t frame_id : 10;
uint32_t payload_total : 22; //payload max 4MB
} __PACKED;
struct usbd_display_priv {
struct chry_mempool pool;
struct usbd_endpoint out_ep;
struct usbd_endpoint in_ep;
struct usbd_display_frame *current_frame;
} g_usbd_display;
int usbd_display_frame_create(struct usbd_display_frame *frame, uint32_t count)
{
return chry_mempool_create(&g_usbd_display.pool, frame, sizeof(struct usbd_display_frame), count);
}
struct usbd_display_frame *usbd_display_frame_alloc(void)
{
return (struct usbd_display_frame *)chry_mempool_alloc(&g_usbd_display.pool);
}
int usbd_display_frame_free(struct usbd_display_frame *frame)
{
return chry_mempool_free(&g_usbd_display.pool, (uintptr_t *)frame);
}
int usbd_display_frame_send(struct usbd_display_frame *frame)
{
return chry_mempool_send(&g_usbd_display.pool, (uintptr_t *)frame);
}
int usbd_display_frame_recv(struct usbd_display_frame **frame, uint32_t timeout)
{
return chry_mempool_recv(&g_usbd_display.pool, (uintptr_t **)frame, timeout);
}
uint8_t usb_dispay_dummy[512];
volatile uint32_t usb_display_buf_offset;
volatile bool usb_display_ignore_frame;
static void display_notify_handler(uint8_t busid, uint8_t event, void *arg)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONFIGURED:
usb_display_buf_offset = 0;
usb_display_ignore_frame = true;
g_usbd_display.current_frame = NULL;
usbd_ep_start_read(busid, g_usbd_display.out_ep.ep_addr, usb_dispay_dummy, usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr));
break;
default:
break;
}
}
void usbd_display_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
if (usb_display_ignore_frame) {
// alloc frame for next at the end of current frame
if ((nbytes % usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr)) || (nbytes == 0)) {
if (g_usbd_display.current_frame == NULL) {
g_usbd_display.current_frame = usbd_display_frame_alloc();
if (g_usbd_display.current_frame) {
usb_display_ignore_frame = false;
usb_display_buf_offset = 0;
goto get_frame;
} else {
goto drop_frame;
}
} else {
usb_display_ignore_frame = false;
usb_display_buf_offset = 0;
goto get_frame;
}
} else {
goto drop_frame;
}
} else {
struct usbd_disp_frame_header *header = (struct usbd_disp_frame_header *)&g_usbd_display.current_frame->frame_buf[0];
struct usbd_display_frame *frame;
if (header->payload_total > g_usbd_display.current_frame->frame_bufsize) {
USB_LOG_ERR("frame overflow, drop it\r\n");
usb_display_ignore_frame = true;
goto drop_frame;
}
usb_display_buf_offset += nbytes;
if ((nbytes % usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr)) || (nbytes == 0)) {
frame = g_usbd_display.current_frame;
g_usbd_display.current_frame = NULL;
frame->frame_format = header->type;
frame->frame_size = header->payload_total;
usbd_display_frame_send(frame);
g_usbd_display.current_frame = usbd_display_frame_alloc();
if (g_usbd_display.current_frame) {
usb_display_ignore_frame = false;
usb_display_buf_offset = 0;
goto get_frame;
} else {
usb_display_ignore_frame = true;
goto drop_frame;
}
} else {
goto get_frame;
}
}
return;
drop_frame:
// drop current frame
usbd_ep_start_read(busid, g_usbd_display.out_ep.ep_addr, usb_dispay_dummy, usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr));
return;
get_frame:
usbd_ep_start_read(busid, g_usbd_display.out_ep.ep_addr, &g_usbd_display.current_frame->frame_buf[usb_display_buf_offset], 16384);
return;
}
void usbd_display_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
}
struct usbd_interface *usbd_display_init_intf(struct usbd_interface *intf,
const uint8_t out_ep,
const uint8_t in_ep,
struct usbd_display_frame *frame,
uint32_t count)
{
intf->class_interface_handler = NULL;
intf->class_endpoint_handler = NULL;
intf->vendor_handler = NULL;
intf->notify_handler = display_notify_handler;
g_usbd_display.out_ep.ep_addr = out_ep;
g_usbd_display.out_ep.ep_cb = usbd_display_bulk_out;
g_usbd_display.in_ep.ep_addr = in_ep;
g_usbd_display.in_ep.ep_cb = usbd_display_bulk_in;
usbd_add_endpoint(0, &g_usbd_display.out_ep);
usbd_add_endpoint(0, &g_usbd_display.in_ep);
for (uint32_t i = 0; i < count; i++) {
USB_ASSERT_MSG(frame[i].frame_bufsize % 16384, "frame_bufsize must be the multiple of 16384");
}
usbd_display_frame_create(frame, count);
return intf;
}
int usbd_display_dequeue(struct usbd_display_frame **frame, uint32_t timeout)
{
return usbd_display_frame_recv(frame, timeout);
}
int usbd_display_enqueue(struct usbd_display_frame *frame)
{
return usbd_display_frame_free(frame);
}

39
class/vendor/display/usbd_display.h vendored Normal file
View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2026, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_DISPLAY_H
#define USBD_DISPLAY_H
#define USBD_DISPLAY_TYPE_RGB565 0
#define USBD_DISPLAY_TYPE_RGB888 1
#define USBD_DISPLAY_TYPE_YUV420 2
#define USBD_DISPLAY_TYPE_JPG 3
struct usbd_display_frame {
uint8_t *frame_buf;
uint32_t frame_bufsize;
uint32_t frame_format;
uint32_t frame_size;
};
#ifdef __cplusplus
extern "C" {
#endif
/* Init display interface driver */
struct usbd_interface *usbd_display_init_intf(struct usbd_interface *intf,
const uint8_t out_ep,
const uint8_t in_ep,
struct usbd_display_frame *frame,
uint32_t count);
int usbd_display_dequeue(struct usbd_display_frame **frame, uint32_t timeout);
int usbd_display_enqueue(struct usbd_display_frame *frame);
#ifdef __cplusplus
}
#endif
#endif /* USBD_DISPLAY_H */

View File

@@ -44,7 +44,6 @@ static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_pa
case VIDEO_REQUEST_GET_INFO: case VIDEO_REQUEST_GET_INFO:
break; break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
@@ -58,7 +57,6 @@ static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_pa
case VIDEO_REQUEST_GET_INFO: case VIDEO_REQUEST_GET_INFO:
break; break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
@@ -91,7 +89,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 1; *len = 1;
break; break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -127,7 +124,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 4; *len = 4;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -163,7 +159,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -199,7 +194,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -235,7 +229,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -247,16 +240,13 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
default: default:
USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
return -1; return -1;
} }
} else { } else {
USB_LOG_WRN("Unhandled Video Class wTerminalType 0x%02x\r\n", entity_info->wTerminalType);
return -2; return -2;
} }
break; break;
@@ -298,7 +288,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -337,7 +326,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -373,7 +361,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -409,7 +396,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -440,7 +426,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -471,7 +456,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -502,7 +486,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -538,7 +521,6 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 2; *len = 2;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -550,13 +532,11 @@ static int usbd_video_control_unit_terminal_request_handler(uint8_t busid, struc
*len = 1; *len = 1;
} break; } break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
default: default:
g_usbd_video[busid].error_code = 0x06; g_usbd_video[busid].error_code = 0x06;
USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
return -1; return -1;
} }
break; break;
@@ -606,7 +586,6 @@ static int usbd_video_stream_request_handler(uint8_t busid, struct usb_setup_pac
break; break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -638,7 +617,6 @@ static int usbd_video_stream_request_handler(uint8_t busid, struct usb_setup_pac
break; break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;
@@ -653,7 +631,6 @@ static int usbd_video_stream_request_handler(uint8_t busid, struct usb_setup_pac
*len = 1; *len = 1;
break; break;
default: default:
USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
return -1; return -1;
} }
break; break;

View File

@@ -365,14 +365,9 @@ static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
switch (cmd->Oid) { switch (cmd->Oid) {
case OID_GEN_RNDIS_CONFIG_PARAMETER: case OID_GEN_RNDIS_CONFIG_PARAMETER:
param = (rndis_config_parameter_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
USB_LOG_WRN("RNDIS cfg param: NameOfs=%d, NameLen=%d, ValueOfs=%d, ValueLen=%d\r\n",
param->ParameterNameOffset, param->ParameterNameLength,
param->ParameterValueOffset, param->ParameterValueLength);
break; break;
case OID_GEN_CURRENT_PACKET_FILTER: case OID_GEN_CURRENT_PACKET_FILTER:
if (cmd->InformationBufferLength < sizeof(g_usbd_rndis.net_filter)) { if (cmd->InformationBufferLength < sizeof(g_usbd_rndis.net_filter)) {
USB_LOG_WRN("PACKET_FILTER!\r\n");
resp->Status = RNDIS_STATUS_INVALID_DATA; resp->Status = RNDIS_STATUS_INVALID_DATA;
} else { } else {
uint32_t *filter; uint32_t *filter;

View File

@@ -1,372 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_core.h"
#include "usb_dfu.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
PCD_HandleTypeDef hpcd_USB_FS;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USB_PCD_Init(void);
/* USER CODE BEGIN PFP */
typedef void (*pFunction)(void);
static void jump_app(void)
{
pFunction JumpToApplication;
uint32_t JumpAddress;
if (((*(__IO uint32_t *)USBD_DFU_APP_DEFAULT_ADD) & 0x2FFFB000) == 0x20000000)
{
/* Jump to user application */
/*!< Jump to app reset_handler */
JumpAddress = *(__IO uint32_t *)(USBD_DFU_APP_DEFAULT_ADD + 4);
JumpToApplication = (pFunction)JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t *)USBD_DFU_APP_DEFAULT_ADD);
JumpToApplication();
}
}
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int fputc(int ch, FILE *f)
{
while ((USART1->SR & USART_SR_TXE) == 0)
;
USART1->DR = ch;
return ch;
}
void usb_dc_low_level_init(void)
{
/* Peripheral clock enable */
__HAL_RCC_USB_CLK_ENABLE();
/* USB interrupt Init */
HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
}
uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len)
{
uint32_t i = 0;
uint8_t *psrc = src;
for (i = 0; i < len; i++)
{
dest[i] = *psrc++;
}
/* Return a valid address to avoid HardFault */
return (uint8_t *)(dest);
}
uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len)
{
HAL_FLASH_Unlock();
uint32_t i = 0;
for (i = 0; i < len; i += 4)
{
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
* be done by byte */
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (uint32_t)(dest + i),
*(uint32_t *)(src + i)) == HAL_OK)
{
/* Check the written value */
if (*(uint32_t *)(src + i) != *(uint32_t *)(dest + i))
{
/* Flash content doesn't match SRAM content */
return (1);
}
}
else
{
/* Error occurred while writing data in Flash memory */
return (2);
}
}
return 0;
}
uint16_t dfu_erase_flash(uint32_t add)
{
HAL_FLASH_Unlock();
uint32_t PageError;
/* Variable contains Flash operation status */
HAL_StatusTypeDef status;
FLASH_EraseInitTypeDef eraseinitstruct;
eraseinitstruct.TypeErase = FLASH_TYPEERASE_PAGES;
eraseinitstruct.PageAddress = add;
eraseinitstruct.NbPages = 1U;
status = HAL_FLASHEx_Erase(&eraseinitstruct, &PageError);
return 0;
}
void dfu_leave(void)
{
NVIC_SystemReset();
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
jump_app();
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
//MX_USB_PCD_Init();
/* USER CODE BEGIN 2 */
// extern void cdc_acm_msc_init(void);
// cdc_acm_msc_init();
extern void dfu_flash_init(void);
dfu_flash_init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// extern void cdc_acm_data_send_with_dtr_test(void);
// cdc_acm_data_send_with_dtr_test();
// HAL_Delay(100);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
* @brief USB Initialization Function
* @param None
* @retval None
*/
static void MX_USB_PCD_Init(void)
{
/* USER CODE BEGIN USB_Init 0 */
/* USER CODE END USB_Init 0 */
/* USER CODE BEGIN USB_Init 1 */
/* USER CODE END USB_Init 1 */
hpcd_USB_FS.Instance = USB;
hpcd_USB_FS.Init.dev_endpoints = 8;
hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_FS.Init.low_power_enable = DISABLE;
hpcd_USB_FS.Init.lpm_enable = DISABLE;
hpcd_USB_FS.Init.battery_charging_enable = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USB_Init 2 */
/* USER CODE END USB_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1) {
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2024, sakumisu * Copyright (c) 2022 ~ 2026, sakumisu
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -7,13 +7,13 @@
#include "usbd_dfu.h" #include "usbd_dfu.h"
#define USBD_VID 0x0483 #define USBD_VID 0x0483
#define USBD_PID 0xDF11 #define USBD_PID 0xdf11
#define USBD_MAX_POWER 100 #define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033 #define USBD_LANGID_STRING 1033
#define FLASH_DESC_STR "@Internal Flash /0x08000000/16*001Ka,112*01Kg" #define USB_CONFIG_SIZE (9 + DFU_DESCRIPTOR_LEN)
#define USB_CONFIG_SIZE (9 + 9 + 9) #define FLASH_DESC_STR "@Internal Flash /0x08000000/16*128Kg"
static const uint8_t device_descriptor[] = { static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01) USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01)
@@ -21,7 +21,7 @@ static const uint8_t device_descriptor[] = {
static const uint8_t config_descriptor[] = { static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
DFU_DESCRIPTOR_INIT() DFU_DESCRIPTOR_INIT(4)
}; };
static const uint8_t device_quality_descriptor[] = { static const uint8_t device_quality_descriptor[] = {
@@ -45,6 +45,7 @@ static const char *string_descriptors[] = {
"CherryUSB", /* Manufacturer */ "CherryUSB", /* Manufacturer */
"CherryUSB DFU DEMO", /* Product */ "CherryUSB DFU DEMO", /* Product */
"2022123456", /* Serial Number */ "2022123456", /* Serial Number */
FLASH_DESC_STR
}; };
static const uint8_t *device_descriptor_callback(uint8_t speed) static const uint8_t *device_descriptor_callback(uint8_t speed)
@@ -64,13 +65,14 @@ static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
static const char *string_descriptor_callback(uint8_t speed, uint8_t index) static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{ {
if (index > 3) { if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
return NULL; return NULL;
} }
return string_descriptors[index]; return string_descriptors[index];
} }
const struct usb_descriptor dfu_flash_descriptor = { const struct usb_descriptor dfu_descriptor = {
.device_descriptor_callback = device_descriptor_callback, .device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback, .config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback, .device_quality_descriptor_callback = device_quality_descriptor_callback,
@@ -104,10 +106,52 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
struct usbd_interface intf0; struct usbd_interface intf0;
void dfu_flash_init(uint8_t busid, uintptr_t reg_base) void dfu_init(uint8_t busid, uintptr_t reg_base)
{ {
usbd_desc_register(busid, &dfu_flash_descriptor); usbd_desc_register(busid, &dfu_descriptor);
usbd_add_interface(busid, usbd_dfu_init_intf(&intf0)); usbd_add_interface(busid, usbd_dfu_init_intf(&intf0));
usbd_initialize(busid, reg_base, usbd_event_handler); usbd_initialize(busid, reg_base, usbd_event_handler);
} }
volatile uint32_t flash_start_address;
void usbd_dfu_begin_load(void)
{
flash_start_address = 0x08000000;
}
void usbd_dfu_end_load(void)
{
}
void usbd_dfu_reset(void)
{
//NVIC_SystemReset();
}
int usbd_dfu_write(uint16_t value, const uint8_t *data, uint16_t length)
{
//usb_hexdump(data, length);
// patch for stm32 special command
#if 1
if (value == 0) {
if (data[0] == DFU_SPECIAL_CMD_SET_ADDRESS_POINTER) {
memcpy((uint8_t *)&flash_start_address, data, 4);
} else if (data[0] == DFU_SPECIAL_CMD_ERASE) {
memcpy((uint8_t *)&flash_start_address, data, 4);
}
} else if (value > 1) {
uint32_t addr = (value - 2) * CONFIG_USBDEV_REQUEST_BUFFER_LEN + flash_start_address;
}
#else
flash_start_address += length;
#endif
return 0;
}
int usbd_dfu_read(uint16_t value, const uint8_t *data, uint16_t length, uint16_t *actual_length)
{
return 0;
}

3
demo/display/README.md Normal file
View File

@@ -0,0 +1,3 @@
Thanks to https://github.com/chuanjinpang/win10_idd_xfz1986_usb_graphic_driver_display project.
Install tools/display/xfz1986_usb_graphic_250224_rc_sign.exe in windows before use.

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 2026, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbd_core.h"
#include "usbd_display.h"
#define DISPLAY_IN_EP 0x81
#define DISPLAY_OUT_EP 0x02
#define USBD_VID 0x303A
#define USBD_PID 0x2987
#define USBD_MAX_POWER 100
#define USBD_LANGID_STRING 1033
#define USB_CONFIG_SIZE (9 + 9 + 7 + 7)
#ifdef CONFIG_USB_HS
#define DISPLAY_EP_MPS 512
#else
#define DISPLAY_EP_MPS 64
#endif
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0101, 0x01)
};
static const uint8_t config_descriptor[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xff, 0x00, 0x00, 0x00),
USB_ENDPOINT_DESCRIPTOR_INIT(DISPLAY_IN_EP, 0x02, DISPLAY_EP_MPS, 0x00),
USB_ENDPOINT_DESCRIPTOR_INIT(DISPLAY_OUT_EP, 0x02, DISPLAY_EP_MPS, 0x00),
};
static const uint8_t device_quality_descriptor[] = {
///////////////////////////////////////
/// device qualifier descriptor
///////////////////////////////////////
0x0a,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"cherryusb_R640x480_Ergb16_Fps30_Bl128", /* Product */
// "cherryusb_R640x480_Ejpg9_Fps30_Bl128", /* Product */
"2022123456", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
return config_descriptor;
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
return device_quality_descriptor;
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
return NULL;
}
return string_descriptors[index];
}
const struct usb_descriptor usbdisplay_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback
};
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
switch (event) {
case USBD_EVENT_RESET:
break;
case USBD_EVENT_CONNECTED:
break;
case USBD_EVENT_DISCONNECTED:
break;
case USBD_EVENT_RESUME:
break;
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
case USBD_EVENT_CLR_REMOTE_WAKEUP:
break;
default:
break;
}
}
struct usbd_interface intf0;
struct usbd_display_frame frame_pool[2];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t usb_display_buffer[2][640 * 480 * 2];
void usbdisplay_init(uint8_t busid, uintptr_t reg_base)
{
frame_pool[0].frame_buf = usb_display_buffer[0];
frame_pool[0].frame_bufsize = 640 * 480 * 2;
frame_pool[1].frame_buf = usb_display_buffer[1];
frame_pool[1].frame_bufsize = 640 * 480 * 2;
usbd_desc_register(busid, &usbdisplay_descriptor);
usbd_add_interface(busid, usbd_display_init_intf(&intf0, DISPLAY_OUT_EP, DISPLAY_IN_EP, frame_pool, 2));
usbd_initialize(busid, reg_base, usbd_event_handler);
}
void usbdisplay_poll(void)
{
struct usbd_display_frame *frame;
int ret;
ret = usbd_display_dequeue(&frame, 0xffffffff); // timeout is not useful for baremental
if (ret < 0) {
return;
}
USB_LOG_INFO("frame type: %u, frame size %u\r\n", frame->frame_format, frame->frame_size);
usbd_display_enqueue(frame);
}

View File

@@ -616,7 +616,7 @@ int usb_dc_init(uint8_t busid)
int usb_dc_deinit(uint8_t busid) int usb_dc_deinit(uint8_t busid)
{ {
USB_OTG_GLB->GAHBCFG |= USB_OTG_GAHBCFG_GINT; USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS; USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS;
/* Clear Pending interrupt */ /* Clear Pending interrupt */
@@ -630,6 +630,11 @@ int usb_dc_deinit(uint8_t busid)
USB_OTG_DEV->DOEPMSK = 0U; USB_OTG_DEV->DOEPMSK = 0U;
USB_OTG_DEV->DAINTMSK = 0U; USB_OTG_DEV->DAINTMSK = 0U;
/* Disable all interrupts. */
USB_OTG_GLB->GINTMSK = 0U;
/* Clear any pending interrupts */
USB_OTG_GLB->GINTSTS = 0xBFFFFFFFU;
/* Flush the FIFO */ /* Flush the FIFO */
dwc2_flush_txfifo(busid, 0x10U); dwc2_flush_txfifo(busid, 0x10U);
dwc2_flush_rxfifo(busid); dwc2_flush_rxfifo(busid);

View File

@@ -924,13 +924,6 @@ void handle_ep0(struct usbh_bus *bus)
musb_urb_waitup(urb); musb_urb_waitup(urb);
return; return;
} }
if (ep0_status & USB_CSRL0_STALL) {
HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_CSRL0_STALL;
pipe->ep0_state = USB_EP0_STATE_SETUP;
urb->errorcode = -USB_ERR_STALL;
musb_urb_waitup(urb);
return;
}
switch (pipe->ep0_state) { switch (pipe->ep0_state) {
case USB_EP0_STATE_SETUP: case USB_EP0_STATE_SETUP:
@@ -1097,8 +1090,8 @@ void USBH_IRQHandler(uint8_t busid)
HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_TXCSRL1_NAKTO; HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_TXCSRL1_NAKTO;
urb->errorcode = -USB_ERR_NAK; urb->errorcode = -USB_ERR_NAK;
musb_urb_waitup(urb); musb_urb_waitup(urb);
} else if (ep_csrl_status & USB_TXCSRL1_STALL) { } else if (ep_csrl_status & USB_TXCSRL1_STALLED) {
HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_TXCSRL1_STALL; HWREGB(USB_TXCSRL_BASE(ep_idx)) &= ~USB_TXCSRL1_STALLED;
urb->errorcode = -USB_ERR_STALL; urb->errorcode = -USB_ERR_STALL;
musb_urb_waitup(urb); musb_urb_waitup(urb);
} else { } else {
@@ -1146,8 +1139,8 @@ void USBH_IRQHandler(uint8_t busid)
HWREGB(USB_RXCSRL_BASE(ep_idx)) &= ~USB_RXCSRL1_NAKTO; HWREGB(USB_RXCSRL_BASE(ep_idx)) &= ~USB_RXCSRL1_NAKTO;
urb->errorcode = -USB_ERR_NAK; urb->errorcode = -USB_ERR_NAK;
musb_urb_waitup(urb); musb_urb_waitup(urb);
} else if (ep_csrl_status & USB_RXCSRL1_STALL) { } else if (ep_csrl_status & USB_RXCSRL1_STALLED) {
HWREGB(USB_RXCSRL_BASE(ep_idx)) &= ~USB_RXCSRL1_STALL; HWREGB(USB_RXCSRL_BASE(ep_idx)) &= ~USB_RXCSRL1_STALLED;
urb->errorcode = -USB_ERR_STALL; urb->errorcode = -USB_ERR_STALL;
musb_urb_waitup(urb); musb_urb_waitup(urb);
} else if (ep_csrl_status & USB_RXCSRL1_RXRDY) { } else if (ep_csrl_status & USB_RXCSRL1_RXRDY) {

View File

@@ -145,7 +145,7 @@ int chry_mempool_create(struct chry_mempool *pool, void *block, uint32_t block_s
return -1; return -1;
} }
if (pool->block_size % 4) { if (block_size % 4) {
return -1; return -1;
} }
@@ -176,9 +176,9 @@ int chry_mempool_create(struct chry_mempool *pool, void *block, uint32_t block_s
void chry_mempool_delete(struct chry_mempool *pool) void chry_mempool_delete(struct chry_mempool *pool)
{ {
chry_mempool_osal_sem_delete(pool->out_sem);
__chry_ringbuffer_reset(&pool->in); __chry_ringbuffer_reset(&pool->in);
__chry_ringbuffer_reset(&pool->out); __chry_ringbuffer_reset(&pool->out);
chry_mempool_osal_sem_delete(pool->out_sem);
} }
uintptr_t *chry_mempool_alloc(struct chry_mempool *pool) uintptr_t *chry_mempool_alloc(struct chry_mempool *pool)

3
tools/dfu-util/url Normal file
View File

@@ -0,0 +1,3 @@
http://www.st.com/en/development-tools/stsw-stm32080.html
https://dfu-util.sourceforge.net/

Binary file not shown.

View File

@@ -1 +0,0 @@
http://www.st.com/en/development-tools/stsw-stm32080.html