33 Commits

Author SHA1 Message Date
sakumisu
537ccfd945 fix(osal/usb_osal_rtthread): up version to v5.2.0 to use RT_SCHED_PRIV(self).current_priority
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-04 17:48:46 +08:00
sakumisu
6973ec73d9 update(cherryusb_config_template): update align size
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-04 16:17:18 +08:00
LiPeng
1feaed024e Fix esp32-p4 cache operation adaptation issue 2025-06-04 16:11:32 +08:00
sakumisu
88cbed9807 update(platform): make msc host with fs common for dcache
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-04 15:33:49 +08:00
sakumisu
1d95077161 feat(dcache): update dcache api
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-04 15:33:42 +08:00
sakumisu
06a0c4393b feat(platform/zephyr): support msc host with disk
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-04 15:08:50 +08:00
sakumisu
6b7d755d3a update(class/hub/usbh_hub): reduce critical section range
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-04 13:08:51 +08:00
sakumisu
078e7d1be0 docs: update rst
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-03 23:11:14 +08:00
sakumisu
ac4e4c569d feat(port/dwc2): add dcache api for esp & st
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-03 22:46:48 +08:00
sakumisu
b6650bdbc6 feat(port/dwc2/usb_dc_dwc2): support dcache
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-03 22:46:39 +08:00
sakumisu
bff8a632a9 feat(class): add usb_osal_thread_schedule_other to allow the applications which use the struct usbh_xxx to exit properly before free struct usbh_xxx
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-03 22:43:35 +08:00
sakumisu
a8bf2687bd update(core/usbd_core): include dcache & osal header
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-03 22:43:35 +08:00
sakumisu
0251e3a145 update(port/dwc2): implement usbd_dwc2_delay_ms with nop delay
Signed-off-by: sakumisu <1203593632@qq.com>
2025-06-03 22:43:35 +08:00
sakumisu
f7c354b4eb docs: update image
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-30 19:00:41 +08:00
sakumisu
ff42a6f2ea update(demo): add usbd_audio_set_sampling_freq and usbd_audio_get_sampling_freq for audio demo
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-30 17:11:26 +08:00
sakumisu
ca71e7411e fix(osal/usb_osal_liteos_m): fix task delete when thread is null
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-30 14:36:02 +08:00
sakumisu
16858c105a fix(port/dwc2/usb_hc_dwc2): fix typo
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-29 20:35:44 +08:00
sakumisu
8c5026e9cb fix overflow warning
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-29 10:51:49 +08:00
sakumisu
8a81d81435 update(class/video): change headerlen to 12 for 4 byte align, fix encoding
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-29 10:47:10 +08:00
sakumisu
c75e62c1e9 fix(idf): fix p4 config
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-28 22:33:00 +08:00
sakumisu
5a6023118e fix(port/chipidea): fix qtd buffer setting
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-28 22:32:54 +08:00
sakumisu
51ad3717c5 chore(cmake): disable bluetooth
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-28 21:24:56 +08:00
sakumisu
0ee859d339 docs: update usage, disable log
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-28 21:24:39 +08:00
sakumisu
e6d81344c3 refactor(class/video/usbd_video): zero copy for video data transfer
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-28 17:34:44 +08:00
sakumisu
af6df63acb fix(port/ch32): clear intflag first, set nak before handling ep in
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-28 12:26:26 +08:00
sakumisu
b4fb10ee98 update(core/usbd_core): clear configuration in disconnect callback
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-27 20:34:18 +08:00
sakumisu
e3c50cde10 fix(platform/usbd_fatfs_mtp): DIR with dynamic
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-27 20:34:18 +08:00
sakumisu
e65b8c0614 docs: update readme
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-27 20:34:18 +08:00
sakumisu
f9189b4278 fix warning
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-26 22:10:25 +08:00
sakumisu
51ea604ded update(demo): add ep num check for some templates
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-26 21:54:47 +08:00
sakumisu
fe24f8d4ba feat(class/mtp): support mtp device
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-26 21:54:32 +08:00
sakumisu
5fed8b7d05 update: sync code from rtthread master
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-20 18:46:18 +08:00
sakumisu
45ccc810d2 fix(demo): move dhcp_start in init
Signed-off-by: sakumisu <1203593632@qq.com>
2025-05-20 18:45:51 +08:00
90 changed files with 2672 additions and 351 deletions

View File

@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.15)
if(CONFIG_CHERRYUSB)
if(CONFIG_CHERRYUSB OR ESP_PLATFORM)
if(BL_SDK_BASE)
message(STATUS "enable cherryusb in bouffalo_sdk")
@@ -19,7 +19,7 @@ if(BL_SDK_BASE)
set(CONFIG_CHERRYUSB_HOST_VIDEO 1)
set(CONFIG_CHERRYUSB_HOST_AUDIO 1)
set(CONFIG_CHERRYUSB_HOST_CDC_RNDIS 1)
set(CONFIG_CHERRYUSB_HOST_BLUETOOTH 1)
# set(CONFIG_CHERRYUSB_HOST_BLUETOOTH 1)
set(CONFIG_CHERRYUSB_HOST_ASIX 1)
set(CONFIG_CHERRYUSB_HOST_RTL8152 1)
set(CONFIG_CHERRYUSB_HOST_CH34X 1)
@@ -71,7 +71,7 @@ elseif(ESP_PLATFORM)
${cherryusb_incs}
${freertos_include}
PRIV_REQUIRES
usb
usb esp_mm
LDFRAGMENTS
${ldfragments}
)
@@ -148,6 +148,9 @@ elseif(ZEPHYR_BASE)
if (CONFIG_SHELL)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/platform/zephyr/usb_cmd.c)
endif ()
if (CONFIG_FILE_SYSTEM AND CONFIG_CHERRYUSB_HOST)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/platform/zephyr/usbh_msc_disk.c)
endif ()
zephyr_library()
if(cherryusb_incs)

View File

@@ -118,6 +118,11 @@ if CHERRYUSB
prompt "Enable usb cdc ncm device"
default n
config CHERRYUSB_DEVICE_MTP
bool
prompt "Enable usb mtp device, it is commercial charge"
default n
config CHERRYUSB_DEVICE_DFU
bool
prompt "Enable usb dfu device"

View File

@@ -120,6 +120,11 @@ if RT_USING_CHERRYUSB
prompt "Enable usb cdc ncm device"
default n
config RT_CHERRYUSB_DEVICE_MTP
bool
prompt "Enable usb mtp device, it is commercial charge"
default n
config RT_CHERRYUSB_DEVICE_DFU
bool
prompt "Enable usb dfu device"

View File

@@ -119,6 +119,11 @@ if PKG_USING_CHERRYUSB
prompt "Enable usb cdc ncm device"
default n
config PKG_CHERRYUSB_DEVICE_MTP
bool
prompt "Enable usb mtp device, it is commercial charge"
default n
config PKG_CHERRYUSB_DEVICE_DFU
bool
prompt "Enable usb dfu device"

View File

@@ -71,23 +71,26 @@ CherryUSB Device Stack has the following functions:
- Support Device Firmware Upgrade CLASS (DFU)
- Support USB MIDI CLASS (MIDI)
- Support Remote NDIS (RNDIS)
- Support Media Transfer Protocol (MTP)
- Support WINUSB1.0, WINUSB2.0, WEBUSB, BOS
- Support Vendor class
- Support UF2
- Support Android Debug Bridge (Only support shell)
- Support multi device with the same USB IP
CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
CherryUSB Device Stack resource usage (GCC 10.2 with -O2, disable log):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | ~6000 | (512(default) + 320) * bus | 0 | 0 |
|usbd_cdc_acm.c | ~400 | 0 | 0 | 0 |
|usbd_msc.c | ~3800 | (128 + 512(default)) * bus | 16 * bus | 0 |
|usbd_hid.c | ~360 | 0 | 0 | 0 |
|usbd_audio.c | ~1500 | 0 | 0 | 0 |
|usbd_video.c | ~3700 | 0 | 132 * bus | 0 |
|usbd_rndis.c | ~4000 | 2 * 1580(default)+156+8 | 80 | 0 |
|usbd_core.c | ~4500 | (512(default) + 320) * bus | 0 | 0 |
|usbd_cdc_acm.c | ~900 | 0 | 0 | 0 |
|usbd_msc.c | ~5000 | (128 + 512(default)) * bus | 16 * bus | 0 |
|usbd_hid.c | ~300 | 0 | 0 | 0 |
|usbd_audio.c | ~4000 | 0 | 0 | 0 |
|usbd_video.c | ~7000 | 0 | 132 * bus | 0 |
|usbd_rndis.c | ~2500 | 2 * 1580(default)+156+8 | 80 | 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 |
## Host Stack Overview
@@ -114,21 +117,23 @@ CherryUSB Host Stack has the following functions:
The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
CherryUSB Host Stack resource usage (GCC 10.2 with -O2, disable log):
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|usbh_core.c | ~10000(enable lsusb)/ ~7500(disable lsusb) | (512(default) + 8 * (1+x) *n) * bus | sizeof(struct usbh_hub) * bus | raw_config_desc |
|usbh_hub.c | ~6000 | (32 + 4 * (1+x)) * bus | 12 + sizeof(struct usbh_hub) * x | 0 |
|usbh_cdc_acm.c | ~900 | 7 * x | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~3400 | 128 * x | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~1400 | 64 * x | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~5700 | 128 * x | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~8400 | 128 * x | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~5200 | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2200 | 2 * 1514 + 16 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_cdc_ncm.c | ~3500 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_cdc_ncm) * 1 | 0 |
|usbh_bluetooth.c | ~1000 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|usbh_core.c | ~4500 | (512(default) + 8 * (1+x) *n) * bus | sizeof(struct usbh_hub) * bus | raw_config_desc |
|usbh_hub.c | ~3500 | (32 + 4 * (1+x)) * bus | 12 + sizeof(struct usbh_hub) * x | 0 |
|usbh_cdc_acm.c | ~600 | 7 * x | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2000 | 128 * x | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~800 | 64 * x | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~5000 | 128 * x | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~4000 | 128 * x | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~3000 | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~1500 | 2 * 1514 + 16 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_cdc_ncm.c | ~2000 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_cdc_ncm) * 1| 0 |
|usbh_bluetooth.c | ~1000 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|usbh_asix.c | ~7000 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_asix) * 1 | 0 |
|usbh_rtl8152.c | ~9000 | 16K+ 2K(default) + 2 + 32 | sizeof(struct usbh_rtl8152) * 1 | 0 |
Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros:

View File

@@ -71,6 +71,7 @@ CherryUSB Device 协议栈当前实现以下功能:
- 支持 Device Firmware Upgrade CLASS (DFU)
- 支持 USB MIDI CLASS (MIDI)
- 支持 Remote NDIS (RNDIS)
- 支持 Media Transfer Protocol (MTP)
- 支持 WINUSB1.0、WINUSB2.0、WEBUSB、BOS
- 支持 Vendor 类 class
- 支持 UF2
@@ -81,13 +82,15 @@ CherryUSB Device 协议栈资源占用说明GCC 10.2 with -O2
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------:|:-------------:|:----------------:|
|usbd_core.c | ~6000 | (512(default) + 320) * bus | 0 | 0 |
|usbd_cdc_acm.c | ~400 | 0 | 0 | 0 |
|usbd_msc.c | ~3800 | (128 + 512(default)) * bus | 16 * bus | 0 |
|usbd_hid.c | ~360 | 0 | 0 | 0 |
|usbd_audio.c | ~1500 | 0 | 0 | 0 |
|usbd_video.c | ~3700 | 0 | 132 * bus | 0 |
|usbd_rndis.c | ~4000 | 2 * 1580(default)+156+8 | 80 | 0 |
|usbd_core.c | ~4500 | (512(default) + 320) * bus | 0 | 0 |
|usbd_cdc_acm.c | ~900 | 0 | 0 | 0 |
|usbd_msc.c | ~5000 | (128 + 512(default)) * bus | 16 * bus | 0 |
|usbd_hid.c | ~300 | 0 | 0 | 0 |
|usbd_audio.c | ~4000 | 0 | 0 | 0 |
|usbd_video.c | ~7000 | 0 | 132 * bus | 0 |
|usbd_rndis.c | ~2500 | 2 * 1580(default)+156+8 | 80 | 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 |
## Host 协议栈简介
@@ -114,21 +117,23 @@ CherryUSB Host 协议栈当前实现以下功能:
同时CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
CherryUSB Host 协议栈资源占用说明GCC 10.2 with -O2
CherryUSB Host 协议栈资源占用说明GCC 10.2 with -O2,关闭 log
| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:------------:|
|usbh_core.c | ~10000(enable lsusb)/ ~7500(disable lsusb) | (512(default) + 8 * (1+x) *n) * bus | sizeof(struct usbh_hub) * bus | raw_config_desc |
|usbh_hub.c | ~6000 | (32 + 4 * (1+x)) * bus | 12 + sizeof(struct usbh_hub) * x | 0 |
|usbh_cdc_acm.c | ~900 | 7 * x | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~3400 | 128 * x | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~1400 | 64 * x | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~5700 | 128 * x | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~8400 | 128 * x | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~5200 | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~2200 | 2 * 1514 + 16 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_cdc_ncm.c | ~3500 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_cdc_ncm) * 1 | 0 |
|usbh_bluetooth.c | ~1000 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|usbh_core.c | ~4500 | (512(default) + 8 * (1+x) *n) * bus | sizeof(struct usbh_hub) * bus | raw_config_desc |
|usbh_hub.c | ~3500 | (32 + 4 * (1+x)) * bus | 12 + sizeof(struct usbh_hub) * x | 0 |
|usbh_cdc_acm.c | ~600 | 7 * x | 4 + sizeof(struct usbh_cdc_acm) * x | 0 |
|usbh_msc.c | ~2000 | 128 * x | 4 + sizeof(struct usbh_msc) * x | 0 |
|usbh_hid.c | ~800 | 64 * x | 4 + sizeof(struct usbh_hid) * x | 0 |
|usbh_video.c | ~5000 | 128 * x | 4 + sizeof(struct usbh_video) * x | 0 |
|usbh_audio.c | ~4000 | 128 * x | 4 + sizeof(struct usbh_audio) * x | 0 |
|usbh_rndis.c | ~3000 | 512 + 2 * 2048(default)| sizeof(struct usbh_rndis) * 1 | 0 |
|usbh_cdc_ecm.c | ~1500 | 2 * 1514 + 16 | sizeof(struct usbh_cdc_ecm) * 1 | 0 |
|usbh_cdc_ncm.c | ~2000 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_cdc_ncm) * 1| 0 |
|usbh_bluetooth.c | ~1000 | 2 * 2048(default) | sizeof(struct usbh_bluetooth) * 1 | 0 |
|usbh_asix.c | ~7000 | 2 * 2048(default) + 16 + 32 | sizeof(struct usbh_asix) * 1 | 0 |
|usbh_rtl8152.c | ~9000 | 16K+ 2K(default) + 2 + 32 | sizeof(struct usbh_rtl8152) * 1 | 0 |
其中,`sizeof(struct usbh_hub)``sizeof(struct usbh_hubport)` 受以下宏影响:

View File

@@ -106,6 +106,8 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
if GetDepend(['ARCH_ARM_CORTEX_A']):
LIBPATH = [cwd + '/port/pusb2']
LIBS = ['libpusb2_dc_a32_softfp_neon.a']
if GetDepend(['PKG_CHERRYUSB_DEVICE_NRF5X']):
src += Glob('port/nrf5x/usb_dc_nrf5x.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_ACM']):
src += Glob('class/cdc/usbd_cdc_acm.c')
@@ -123,7 +125,7 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']):
src += Glob('class/cdc/usbd_cdc_ecm.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_NCM']):
src += Glob('class/cdc/usbd_cdc_ncm.c')
if GetDepend(['PKG_CHERRYUSB_USING_DFU']):
if GetDepend(['PKG_CHERRYUSB_DEVICE_DFU']):
src += Glob('class/dfu/usbd_dfu.c')
if GetDepend(['PKG_CHERRYUSB_DEVICE_TEMPLATE_CDC_ACM']):

View File

@@ -23,13 +23,15 @@
/* Enable print with color */
#define CONFIG_USB_PRINTF_COLOR_ENABLE
// #define CONFIG_USB_DCACHE_ENABLE
/* data align size when use dma or use dcache */
#ifndef CONFIG_USB_ALIGN_SIZE
#ifdef CONFIG_USB_DCACHE_ENABLE
#define CONFIG_USB_ALIGN_SIZE 32 // 32 or 64
#else
#define CONFIG_USB_ALIGN_SIZE 4
#endif
// #define CONFIG_USB_DCACHE_ENABLE
/* attribute data into no cache ram */
#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable")))
@@ -107,6 +109,28 @@
#define CONFIG_USBDEV_MSC_STACKSIZE 2048
#endif
#ifndef CONFIG_USBDEV_MTP_MAX_BUFSIZE
#define CONFIG_USBDEV_MTP_MAX_BUFSIZE 2048
#endif
#ifndef CONFIG_USBDEV_MTP_MAX_OBJECTS
#define CONFIG_USBDEV_MTP_MAX_OBJECTS 256
#endif
#ifndef CONFIG_USBDEV_MTP_MAX_PATHNAME
#define CONFIG_USBDEV_MTP_MAX_PATHNAME 256
#endif
#define CONFIG_USBDEV_MTP_THREAD
#ifndef CONFIG_USBDEV_MTP_PRIO
#define CONFIG_USBDEV_MTP_PRIO 4
#endif
#ifndef CONFIG_USBDEV_MTP_STACKSIZE
#define CONFIG_USBDEV_MTP_STACKSIZE 4096
#endif
#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
#endif
@@ -310,20 +334,6 @@
/* ---------------- MUSB Configuration ---------------- */
// #define CONFIG_USB_MUSB_SUNXI
/* ================ USB Dcache Configuration ==================*/
#ifdef CONFIG_USB_DCACHE_ENABLE
/* style 1*/
// void usb_dcache_clean(uintptr_t addr, uint32_t size);
// void usb_dcache_invalidate(uintptr_t addr, uint32_t size);
// void usb_dcache_flush(uintptr_t addr, uint32_t size);
/* style 2*/
// #define usb_dcache_clean(addr, size)
// #define usb_dcache_invalidate(addr, size)
// #define usb_dcache_flush(addr, size)
#endif
#ifndef usb_phyaddr2ramaddr
#define usb_phyaddr2ramaddr(addr) (addr)
#endif

View File

@@ -594,6 +594,7 @@ static int usbh_audio_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister Audio Class:%s\r\n", hport->config.intf[intf].devname);
usbh_audio_stop(audio_class);
}

View File

@@ -193,6 +193,7 @@ static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
#endif
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_acm_stop(cdc_acm_class);
}

View File

@@ -221,6 +221,7 @@ static int usbh_cdc_ecm_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister CDC ECM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_ecm_stop(cdc_ecm_class);
}

View File

@@ -52,7 +52,7 @@ static int usbh_cdc_ncm_get_ntb_parameters(struct usbh_cdc_ncm *cdc_ncm_class, s
return ret;
}
memcpy((uint8_t *)param, g_cdc_ncm_buf, ret - 8);
memcpy((uint8_t *)param, g_cdc_ncm_buf, MIN(ret - 8, sizeof(struct cdc_ncm_ntb_parameters)));
return 0;
}
@@ -239,6 +239,7 @@ static int usbh_cdc_ncm_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister CDC NCM Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cdc_ncm_stop(cdc_ncm_class);
}

View File

@@ -106,7 +106,7 @@ int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
if (ret < 8) {
return ret;
}
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
memcpy(buffer, g_hid_buf[hid_class->minor], MIN(ret - 8, 1));
return ret;
}
@@ -148,7 +148,7 @@ int usbh_hid_get_protocol(struct usbh_hid *hid_class, uint8_t *protocol)
if (ret < 8) {
return ret;
}
memcpy(protocol, g_hid_buf[hid_class->minor], ret - 8);
memcpy(protocol, g_hid_buf[hid_class->minor], MIN(ret - 8, 1));
return ret;
}
@@ -190,7 +190,7 @@ int usbh_hid_get_report(struct usbh_hid *hid_class, uint8_t report_type, uint8_t
if (ret < 8) {
return ret;
}
memcpy(buffer, g_hid_buf[hid_class->minor], ret - 8);
memcpy(buffer, g_hid_buf[hid_class->minor], MIN(ret - 8, buflen));
return ret;
}
@@ -299,6 +299,7 @@ int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister HID Class:%s\r\n", hport->config.intf[intf].devname);
usbh_hid_stop(hid_class);
}

View File

@@ -706,8 +706,6 @@ int usbh_hub_deinitialize(struct usbh_bus *bus)
struct usbh_hub *hub;
size_t flags;
flags = usb_osal_enter_critical_section();
hub = &bus->hcd.roothub;
for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
@@ -715,6 +713,8 @@ int usbh_hub_deinitialize(struct usbh_bus *bus)
usbh_hubport_release(hport);
}
flags = usb_osal_enter_critical_section();
usb_hc_deinit(bus);
usb_osal_leave_critical_section(flags);

View File

@@ -342,6 +342,7 @@ static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister MSC Class:%s\r\n", hport->config.intf[intf].devname);
usbh_msc_stop(msc_class);
}

683
class/mtp/usb_mtp.h Normal file
View File

@@ -0,0 +1,683 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USB_MTP_H
#define USB_MTP_H
// clang-format off
#define MTP_STANDARD_VERSION 100
// Container Types
#define MTP_CONTAINER_TYPE_UNDEFINED 0
#define MTP_CONTAINER_TYPE_COMMAND 1
#define MTP_CONTAINER_TYPE_DATA 2
#define MTP_CONTAINER_TYPE_RESPONSE 3
#define MTP_CONTAINER_TYPE_EVENT 4
// Container Offsets
#define MTP_CONTAINER_LENGTH_OFFSET 0
#define MTP_CONTAINER_TYPE_OFFSET 4
#define MTP_CONTAINER_CODE_OFFSET 6
#define MTP_CONTAINER_TRANSACTION_ID_OFFSET 8
#define MTP_CONTAINER_PARAMETER_OFFSET 12
#define MTP_CONTAINER_HEADER_SIZE 12
// Maximum buffer size for a MTP packet.
#define MTP_BUFFER_SIZE 16384
// MTP Data Types
#define MTP_TYPE_UNDEFINED 0x0000 // Undefined
#define MTP_TYPE_INT8 0x0001 // Signed 8-bit integer
#define MTP_TYPE_UINT8 0x0002 // Unsigned 8-bit integer
#define MTP_TYPE_INT16 0x0003 // Signed 16-bit integer
#define MTP_TYPE_UINT16 0x0004 // Unsigned 16-bit integer
#define MTP_TYPE_INT32 0x0005 // Signed 32-bit integer
#define MTP_TYPE_UINT32 0x0006 // Unsigned 32-bit integer
#define MTP_TYPE_INT64 0x0007 // Signed 64-bit integer
#define MTP_TYPE_UINT64 0x0008 // Unsigned 64-bit integer
#define MTP_TYPE_INT128 0x0009 // Signed 128-bit integer
#define MTP_TYPE_UINT128 0x000A // Unsigned 128-bit integer
#define MTP_TYPE_AINT8 0x4001 // Array of signed 8-bit integers
#define MTP_TYPE_AUINT8 0x4002 // Array of unsigned 8-bit integers
#define MTP_TYPE_AINT16 0x4003 // Array of signed 16-bit integers
#define MTP_TYPE_AUINT16 0x4004 // Array of unsigned 16-bit integers
#define MTP_TYPE_AINT32 0x4005 // Array of signed 32-bit integers
#define MTP_TYPE_AUINT32 0x4006 // Array of unsigned 32-bit integers
#define MTP_TYPE_AINT64 0x4007 // Array of signed 64-bit integers
#define MTP_TYPE_AUINT64 0x4008 // Array of unsigned 64-bit integers
#define MTP_TYPE_AINT128 0x4009 // Array of signed 128-bit integers
#define MTP_TYPE_AUINT128 0x400A // Array of unsigned 128-bit integers
#define MTP_TYPE_STR 0xFFFF // Variable-length Unicode string
// MTP Format Codes
#define MTP_FORMAT_UNDEFINED 0x3000 // Undefined object
#define MTP_FORMAT_ASSOCIATION 0x3001 // Association (for example, a folder)
#define MTP_FORMAT_SCRIPT 0x3002 // Device model-specific script
#define MTP_FORMAT_EXECUTABLE 0x3003 // Device model-specific binary executable
#define MTP_FORMAT_TEXT 0x3004 // Text file
#define MTP_FORMAT_HTML 0x3005 // Hypertext Markup Language file (text)
#define MTP_FORMAT_DPOF 0x3006 // Digital Print Order Format file (text)
#define MTP_FORMAT_AIFF 0x3007 // Audio clip
#define MTP_FORMAT_WAV 0x3008 // Audio clip
#define MTP_FORMAT_MP3 0x3009 // Audio clip
#define MTP_FORMAT_AVI 0x300A // Video clip
#define MTP_FORMAT_MPEG 0x300B // Video clip
#define MTP_FORMAT_ASF 0x300C // Microsoft Advanced Streaming Format (video)
#define MTP_FORMAT_DEFINED 0x3800 // Unknown image object
#define MTP_FORMAT_EXIF_JPEG 0x3801 // Exchangeable File Format, JEIDA standard
#define MTP_FORMAT_TIFF_EP 0x3802 // Tag Image File Format for Electronic Photography
#define MTP_FORMAT_FLASHPIX 0x3803 // Structured Storage Image Format
#define MTP_FORMAT_BMP 0x3804 // Microsoft Windows Bitmap file
#define MTP_FORMAT_CIFF 0x3805 // Canon Camera Image File Format
#define MTP_FORMAT_GIF 0x3807 // Graphics Interchange Format
#define MTP_FORMAT_JFIF 0x3808 // JPEG File Interchange Format
#define MTP_FORMAT_CD 0x3809 // PhotoCD Image Pac
#define MTP_FORMAT_PICT 0x380A // Quickdraw Image Format
#define MTP_FORMAT_PNG 0x380B // Portable Network Graphics
#define MTP_FORMAT_TIFF 0x380D // Tag Image File Format
#define MTP_FORMAT_TIFF_IT 0x380E // Tag Image File Format for Information Technology (graphic arts)
#define MTP_FORMAT_JP2 0x380F // JPEG2000 Baseline File Format
#define MTP_FORMAT_JPX 0x3810 // JPEG2000 Extended File Format
#define MTP_FORMAT_DNG 0x3811 // Digital Negative
#define MTP_FORMAT_HEIF 0x3812 // HEIF images
#define MTP_FORMAT_UNDEFINED_FIRMWARE 0xB802
#define MTP_FORMAT_WINDOWS_IMAGE_FORMAT 0xB881
#define MTP_FORMAT_UNDEFINED_AUDIO 0xB900
#define MTP_FORMAT_WMA 0xB901
#define MTP_FORMAT_OGG 0xB902
#define MTP_FORMAT_AAC 0xB903
#define MTP_FORMAT_AUDIBLE 0xB904
#define MTP_FORMAT_FLAC 0xB906
#define MTP_FORMAT_UNDEFINED_VIDEO 0xB980
#define MTP_FORMAT_WMV 0xB981
#define MTP_FORMAT_MP4_CONTAINER 0xB982 // ISO 14496-1
#define MTP_FORMAT_MP2 0xB983
#define MTP_FORMAT_3GP_CONTAINER 0xB984 // 3GPP file format. Details: http://www.3gpp.org/ftp/Specs/html-info/26244.htm (page title - \u201cTransparent end-to-end packet switched streaming service, 3GPP file format\u201d).
#define MTP_FORMAT_UNDEFINED_COLLECTION 0xBA00
#define MTP_FORMAT_ABSTRACT_MULTIMEDIA_ALBUM 0xBA01
#define MTP_FORMAT_ABSTRACT_IMAGE_ALBUM 0xBA02
#define MTP_FORMAT_ABSTRACT_AUDIO_ALBUM 0xBA03
#define MTP_FORMAT_ABSTRACT_VIDEO_ALBUM 0xBA04
#define MTP_FORMAT_ABSTRACT_AV_PLAYLIST 0xBA05
#define MTP_FORMAT_ABSTRACT_CONTACT_GROUP 0xBA06
#define MTP_FORMAT_ABSTRACT_MESSAGE_FOLDER 0xBA07
#define MTP_FORMAT_ABSTRACT_CHAPTERED_PRODUCTION 0xBA08
#define MTP_FORMAT_ABSTRACT_AUDIO_PLAYLIST 0xBA09
#define MTP_FORMAT_ABSTRACT_VIDEO_PLAYLIST 0xBA0A
#define MTP_FORMAT_ABSTRACT_MEDIACAST 0xBA0B // For use with mediacasts; references multimedia enclosures of RSS feeds or episodic content
#define MTP_FORMAT_WPL_PLAYLIST 0xBA10
#define MTP_FORMAT_M3U_PLAYLIST 0xBA11
#define MTP_FORMAT_MPL_PLAYLIST 0xBA12
#define MTP_FORMAT_ASX_PLAYLIST 0xBA13
#define MTP_FORMAT_PLS_PLAYLIST 0xBA14
#define MTP_FORMAT_UNDEFINED_DOCUMENT 0xBA80
#define MTP_FORMAT_ABSTRACT_DOCUMENT 0xBA81
#define MTP_FORMAT_XML_DOCUMENT 0xBA82
#define MTP_FORMAT_MS_WORD_DOCUMENT 0xBA83
#define MTP_FORMAT_MHT_COMPILED_HTML_DOCUMENT 0xBA84
#define MTP_FORMAT_MS_EXCEL_SPREADSHEET 0xBA85
#define MTP_FORMAT_MS_POWERPOINT_PRESENTATION 0xBA86
#define MTP_FORMAT_UNDEFINED_MESSAGE 0xBB00
#define MTP_FORMAT_ABSTRACT_MESSSAGE 0xBB01
#define MTP_FORMAT_UNDEFINED_CONTACT 0xBB80
#define MTP_FORMAT_ABSTRACT_CONTACT 0xBB81
#define MTP_FORMAT_VCARD_2 0xBB82
// MTP Object Property Codes
#define MTP_PROPERTY_STORAGE_ID 0xDC01
#define MTP_PROPERTY_OBJECT_FORMAT 0xDC02
#define MTP_PROPERTY_PROTECTION_STATUS 0xDC03
#define MTP_PROPERTY_OBJECT_SIZE 0xDC04
#define MTP_PROPERTY_ASSOCIATION_TYPE 0xDC05
#define MTP_PROPERTY_ASSOCIATION_DESC 0xDC06
#define MTP_PROPERTY_OBJECT_FILE_NAME 0xDC07
#define MTP_PROPERTY_DATE_CREATED 0xDC08
#define MTP_PROPERTY_DATE_MODIFIED 0xDC09
#define MTP_PROPERTY_KEYWORDS 0xDC0A
#define MTP_PROPERTY_PARENT_OBJECT 0xDC0B
#define MTP_PROPERTY_ALLOWED_FOLDER_CONTENTS 0xDC0C
#define MTP_PROPERTY_HIDDEN 0xDC0D
#define MTP_PROPERTY_SYSTEM_OBJECT 0xDC0E
#define MTP_PROPERTY_PERSISTENT_UID 0xDC41
#define MTP_PROPERTY_SYNC_ID 0xDC42
#define MTP_PROPERTY_PROPERTY_BAG 0xDC43
#define MTP_PROPERTY_NAME 0xDC44
#define MTP_PROPERTY_CREATED_BY 0xDC45
#define MTP_PROPERTY_ARTIST 0xDC46
#define MTP_PROPERTY_DATE_AUTHORED 0xDC47
#define MTP_PROPERTY_DESCRIPTION 0xDC48
#define MTP_PROPERTY_URL_REFERENCE 0xDC49
#define MTP_PROPERTY_LANGUAGE_LOCALE 0xDC4A
#define MTP_PROPERTY_COPYRIGHT_INFORMATION 0xDC4B
#define MTP_PROPERTY_SOURCE 0xDC4C
#define MTP_PROPERTY_ORIGIN_LOCATION 0xDC4D
#define MTP_PROPERTY_DATE_ADDED 0xDC4E
#define MTP_PROPERTY_NON_CONSUMABLE 0xDC4F
#define MTP_PROPERTY_CORRUPT_UNPLAYABLE 0xDC50
#define MTP_PROPERTY_PRODUCER_SERIAL_NUMBER 0xDC51
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_FORMAT 0xDC81
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_SIZE 0xDC82
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_HEIGHT 0xDC83
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_WIDTH 0xDC84
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DURATION 0xDC85
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DATA 0xDC86
#define MTP_PROPERTY_WIDTH 0xDC87
#define MTP_PROPERTY_HEIGHT 0xDC88
#define MTP_PROPERTY_DURATION 0xDC89
#define MTP_PROPERTY_RATING 0xDC8A
#define MTP_PROPERTY_TRACK 0xDC8B
#define MTP_PROPERTY_GENRE 0xDC8C
#define MTP_PROPERTY_CREDITS 0xDC8D
#define MTP_PROPERTY_LYRICS 0xDC8E
#define MTP_PROPERTY_SUBSCRIPTION_CONTENT_ID 0xDC8F
#define MTP_PROPERTY_PRODUCED_BY 0xDC90
#define MTP_PROPERTY_USE_COUNT 0xDC91
#define MTP_PROPERTY_SKIP_COUNT 0xDC92
#define MTP_PROPERTY_LAST_ACCESSED 0xDC93
#define MTP_PROPERTY_PARENTAL_RATING 0xDC94
#define MTP_PROPERTY_META_GENRE 0xDC95
#define MTP_PROPERTY_COMPOSER 0xDC96
#define MTP_PROPERTY_EFFECTIVE_RATING 0xDC97
#define MTP_PROPERTY_SUBTITLE 0xDC98
#define MTP_PROPERTY_ORIGINAL_RELEASE_DATE 0xDC99
#define MTP_PROPERTY_ALBUM_NAME 0xDC9A
#define MTP_PROPERTY_ALBUM_ARTIST 0xDC9B
#define MTP_PROPERTY_MOOD 0xDC9C
#define MTP_PROPERTY_DRM_STATUS 0xDC9D
#define MTP_PROPERTY_SUB_DESCRIPTION 0xDC9E
#define MTP_PROPERTY_IS_CROPPED 0xDCD1
#define MTP_PROPERTY_IS_COLOUR_CORRECTED 0xDCD2
#define MTP_PROPERTY_IMAGE_BIT_DEPTH 0xDCD3
#define MTP_PROPERTY_F_NUMBER 0xDCD4
#define MTP_PROPERTY_EXPOSURE_TIME 0xDCD5
#define MTP_PROPERTY_EXPOSURE_INDEX 0xDCD6
#define MTP_PROPERTY_TOTAL_BITRATE 0xDE91
#define MTP_PROPERTY_BITRATE_TYPE 0xDE92
#define MTP_PROPERTY_SAMPLE_RATE 0xDE93
#define MTP_PROPERTY_NUMBER_OF_CHANNELS 0xDE94
#define MTP_PROPERTY_AUDIO_BIT_DEPTH 0xDE95
#define MTP_PROPERTY_SCAN_TYPE 0xDE97
#define MTP_PROPERTY_AUDIO_WAVE_CODEC 0xDE99
#define MTP_PROPERTY_AUDIO_BITRATE 0xDE9A
#define MTP_PROPERTY_VIDEO_FOURCC_CODEC 0xDE9B
#define MTP_PROPERTY_VIDEO_BITRATE 0xDE9C
#define MTP_PROPERTY_FRAMES_PER_THOUSAND_SECONDS 0xDE9D
#define MTP_PROPERTY_KEYFRAME_DISTANCE 0xDE9E
#define MTP_PROPERTY_BUFFER_SIZE 0xDE9F
#define MTP_PROPERTY_ENCODING_QUALITY 0xDEA0
#define MTP_PROPERTY_ENCODING_PROFILE 0xDEA1
#define MTP_PROPERTY_DISPLAY_NAME 0xDCE0
#define MTP_PROPERTY_BODY_TEXT 0xDCE1
#define MTP_PROPERTY_SUBJECT 0xDCE2
#define MTP_PROPERTY_PRIORITY 0xDCE3
#define MTP_PROPERTY_GIVEN_NAME 0xDD00
#define MTP_PROPERTY_MIDDLE_NAMES 0xDD01
#define MTP_PROPERTY_FAMILY_NAME 0xDD02
#define MTP_PROPERTY_PREFIX 0xDD03
#define MTP_PROPERTY_SUFFIX 0xDD04
#define MTP_PROPERTY_PHONETIC_GIVEN_NAME 0xDD05
#define MTP_PROPERTY_PHONETIC_FAMILY_NAME 0xDD06
#define MTP_PROPERTY_EMAIL_PRIMARY 0xDD07
#define MTP_PROPERTY_EMAIL_PERSONAL_1 0xDD08
#define MTP_PROPERTY_EMAIL_PERSONAL_2 0xDD09
#define MTP_PROPERTY_EMAIL_BUSINESS_1 0xDD0A
#define MTP_PROPERTY_EMAIL_BUSINESS_2 0xDD0B
#define MTP_PROPERTY_EMAIL_OTHERS 0xDD0C
#define MTP_PROPERTY_PHONE_NUMBER_PRIMARY 0xDD0D
#define MTP_PROPERTY_PHONE_NUMBER_PERSONAL 0xDD0E
#define MTP_PROPERTY_PHONE_NUMBER_PERSONAL_2 0xDD0F
#define MTP_PROPERTY_PHONE_NUMBER_BUSINESS 0xDD10
#define MTP_PROPERTY_PHONE_NUMBER_BUSINESS_2 0xDD11
#define MTP_PROPERTY_PHONE_NUMBER_MOBILE 0xDD12
#define MTP_PROPERTY_PHONE_NUMBER_MOBILE_2 0xDD13
#define MTP_PROPERTY_FAX_NUMBER_PRIMARY 0xDD14
#define MTP_PROPERTY_FAX_NUMBER_PERSONAL 0xDD15
#define MTP_PROPERTY_FAX_NUMBER_BUSINESS 0xDD16
#define MTP_PROPERTY_PAGER_NUMBER 0xDD17
#define MTP_PROPERTY_PHONE_NUMBER_OTHERS 0xDD18
#define MTP_PROPERTY_PRIMARY_WEB_ADDRESS 0xDD19
#define MTP_PROPERTY_PERSONAL_WEB_ADDRESS 0xDD1A
#define MTP_PROPERTY_BUSINESS_WEB_ADDRESS 0xDD1B
#define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS 0xDD1C
#define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_2 0xDD1D
#define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_3 0xDD1E
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_FULL 0xDD1F
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_1 0xDD20
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_2 0xDD21
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_CITY 0xDD22
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_REGION 0xDD23
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE 0xDD24
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_COUNTRY 0xDD25
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_FULL 0xDD26
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_1 0xDD27
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_2 0xDD28
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_CITY 0xDD29
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_REGION 0xDD2A
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE 0xDD2B
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_COUNTRY 0xDD2C
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_FULL 0xDD2D
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_1 0xDD2E
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_2 0xDD2F
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_CITY 0xDD30
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_REGION 0xDD31
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_POSTAL_CODE 0xDD32
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_COUNTRY 0xDD33
#define MTP_PROPERTY_ORGANIZATION_NAME 0xDD34
#define MTP_PROPERTY_PHONETIC_ORGANIZATION_NAME 0xDD35
#define MTP_PROPERTY_ROLE 0xDD36
#define MTP_PROPERTY_BIRTHDATE 0xDD37
#define MTP_PROPERTY_MESSAGE_TO 0xDD40
#define MTP_PROPERTY_MESSAGE_CC 0xDD41
#define MTP_PROPERTY_MESSAGE_BCC 0xDD42
#define MTP_PROPERTY_MESSAGE_READ 0xDD43
#define MTP_PROPERTY_MESSAGE_RECEIVED_TIME 0xDD44
#define MTP_PROPERTY_MESSAGE_SENDER 0xDD45
#define MTP_PROPERTY_ACTIVITY_BEGIN_TIME 0xDD50
#define MTP_PROPERTY_ACTIVITY_END_TIME 0xDD51
#define MTP_PROPERTY_ACTIVITY_LOCATION 0xDD52
#define MTP_PROPERTY_ACTIVITY_REQUIRED_ATTENDEES 0xDD54
#define MTP_PROPERTY_ACTIVITY_OPTIONAL_ATTENDEES 0xDD55
#define MTP_PROPERTY_ACTIVITY_RESOURCES 0xDD56
#define MTP_PROPERTY_ACTIVITY_ACCEPTED 0xDD57
#define MTP_PROPERTY_ACTIVITY_TENTATIVE 0xDD58
#define MTP_PROPERTY_ACTIVITY_DECLINED 0xDD59
#define MTP_PROPERTY_ACTIVITY_REMAINDER_TIME 0xDD5A
#define MTP_PROPERTY_ACTIVITY_OWNER 0xDD5B
#define MTP_PROPERTY_ACTIVITY_STATUS 0xDD5C
#define MTP_PROPERTY_OWNER 0xDD5D
#define MTP_PROPERTY_EDITOR 0xDD5E
#define MTP_PROPERTY_WEBMASTER 0xDD5F
#define MTP_PROPERTY_URL_SOURCE 0xDD60
#define MTP_PROPERTY_URL_DESTINATION 0xDD61
#define MTP_PROPERTY_TIME_BOOKMARK 0xDD62
#define MTP_PROPERTY_OBJECT_BOOKMARK 0xDD63
#define MTP_PROPERTY_BYTE_BOOKMARK 0xDD64
#define MTP_PROPERTY_LAST_BUILD_DATE 0xDD70
#define MTP_PROPERTY_TIME_TO_LIVE 0xDD71
#define MTP_PROPERTY_MEDIA_GUID 0xDD72
// MTP Device Property Codes
#define MTP_DEVICE_PROPERTY_UNDEFINED 0x5000
#define MTP_DEVICE_PROPERTY_BATTERY_LEVEL 0x5001
#define MTP_DEVICE_PROPERTY_FUNCTIONAL_MODE 0x5002
#define MTP_DEVICE_PROPERTY_IMAGE_SIZE 0x5003
#define MTP_DEVICE_PROPERTY_COMPRESSION_SETTING 0x5004
#define MTP_DEVICE_PROPERTY_WHITE_BALANCE 0x5005
#define MTP_DEVICE_PROPERTY_RGB_GAIN 0x5006
#define MTP_DEVICE_PROPERTY_F_NUMBER 0x5007
#define MTP_DEVICE_PROPERTY_FOCAL_LENGTH 0x5008
#define MTP_DEVICE_PROPERTY_FOCUS_DISTANCE 0x5009
#define MTP_DEVICE_PROPERTY_FOCUS_MODE 0x500A
#define MTP_DEVICE_PROPERTY_EXPOSURE_METERING_MODE 0x500B
#define MTP_DEVICE_PROPERTY_FLASH_MODE 0x500C
#define MTP_DEVICE_PROPERTY_EXPOSURE_TIME 0x500D
#define MTP_DEVICE_PROPERTY_EXPOSURE_PROGRAM_MODE 0x500E
#define MTP_DEVICE_PROPERTY_EXPOSURE_INDEX 0x500F
#define MTP_DEVICE_PROPERTY_EXPOSURE_BIAS_COMPENSATION 0x5010
#define MTP_DEVICE_PROPERTY_DATETIME 0x5011
#define MTP_DEVICE_PROPERTY_CAPTURE_DELAY 0x5012
#define MTP_DEVICE_PROPERTY_STILL_CAPTURE_MODE 0x5013
#define MTP_DEVICE_PROPERTY_CONTRAST 0x5014
#define MTP_DEVICE_PROPERTY_SHARPNESS 0x5015
#define MTP_DEVICE_PROPERTY_DIGITAL_ZOOM 0x5016
#define MTP_DEVICE_PROPERTY_EFFECT_MODE 0x5017
#define MTP_DEVICE_PROPERTY_BURST_NUMBER 0x5018
#define MTP_DEVICE_PROPERTY_BURST_INTERVAL 0x5019
#define MTP_DEVICE_PROPERTY_TIMELAPSE_NUMBER 0x501A
#define MTP_DEVICE_PROPERTY_TIMELAPSE_INTERVAL 0x501B
#define MTP_DEVICE_PROPERTY_FOCUS_METERING_MODE 0x501C
#define MTP_DEVICE_PROPERTY_UPLOAD_URL 0x501D
#define MTP_DEVICE_PROPERTY_ARTIST 0x501E
#define MTP_DEVICE_PROPERTY_COPYRIGHT_INFO 0x501F
#define MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER 0xD401
#define MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME 0xD402
#define MTP_DEVICE_PROPERTY_VOLUME 0xD403
#define MTP_DEVICE_PROPERTY_SUPPORTED_FORMATS_ORDERED 0xD404
#define MTP_DEVICE_PROPERTY_DEVICE_ICON 0xD405
#define MTP_DEVICE_PROPERTY_PLAYBACK_RATE 0xD410
#define MTP_DEVICE_PROPERTY_PLAYBACK_OBJECT 0xD411
#define MTP_DEVICE_PROPERTY_PLAYBACK_CONTAINER_INDEX 0xD412
#define MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO 0xD406
#define MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE 0xD407
// MTP Operation Codes
#define MTP_OPERATION_GET_DEVICE_INFO 0x1001
#define MTP_OPERATION_OPEN_SESSION 0x1002
#define MTP_OPERATION_CLOSE_SESSION 0x1003
#define MTP_OPERATION_GET_STORAGE_IDS 0x1004
#define MTP_OPERATION_GET_STORAGE_INFO 0x1005
#define MTP_OPERATION_GET_NUM_OBJECTS 0x1006
#define MTP_OPERATION_GET_OBJECT_HANDLES 0x1007
#define MTP_OPERATION_GET_OBJECT_INFO 0x1008
#define MTP_OPERATION_GET_OBJECT 0x1009
#define MTP_OPERATION_GET_THUMB 0x100A
#define MTP_OPERATION_DELETE_OBJECT 0x100B
#define MTP_OPERATION_SEND_OBJECT_INFO 0x100C
#define MTP_OPERATION_SEND_OBJECT 0x100D
#define MTP_OPERATION_INITIATE_CAPTURE 0x100E
#define MTP_OPERATION_FORMAT_STORE 0x100F
#define MTP_OPERATION_RESET_DEVICE 0x1010
#define MTP_OPERATION_SELF_TEST 0x1011
#define MTP_OPERATION_SET_OBJECT_PROTECTION 0x1012
#define MTP_OPERATION_POWER_DOWN 0x1013
#define MTP_OPERATION_GET_DEVICE_PROP_DESC 0x1014
#define MTP_OPERATION_GET_DEVICE_PROP_VALUE 0x1015
#define MTP_OPERATION_SET_DEVICE_PROP_VALUE 0x1016
#define MTP_OPERATION_RESET_DEVICE_PROP_VALUE 0x1017
#define MTP_OPERATION_TERMINATE_OPEN_CAPTURE 0x1018
#define MTP_OPERATION_MOVE_OBJECT 0x1019
#define MTP_OPERATION_COPY_OBJECT 0x101A
#define MTP_OPERATION_GET_PARTIAL_OBJECT 0x101B
#define MTP_OPERATION_INITIATE_OPEN_CAPTURE 0x101C
#define MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED 0x9801
#define MTP_OPERATION_GET_OBJECT_PROP_DESC 0x9802
#define MTP_OPERATION_GET_OBJECT_PROP_VALUE 0x9803
#define MTP_OPERATION_SET_OBJECT_PROP_VALUE 0x9804
#define MTP_OPERATION_GET_OBJECT_PROP_LIST 0x9805
#define MTP_OPERATION_SET_OBJECT_PROP_LIST 0x9806
#define MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC 0x9807
#define MTP_OPERATION_SEND_OBJECT_PROP_LIST 0x9808
#define MTP_OPERATION_GET_OBJECT_REFERENCES 0x9810
#define MTP_OPERATION_SET_OBJECT_REFERENCES 0x9811
#define MTP_OPERATION_SKIP 0x9820
// Android extensions for direct file IO
// Same as GetPartialObject, but with 64 bit offset
#define MTP_OPERATION_GET_PARTIAL_OBJECT_64 0x95C1
// Same as GetPartialObject64, but copying host to device
#define MTP_OPERATION_SEND_PARTIAL_OBJECT 0x95C2
// Truncates file to 64 bit length
#define MTP_OPERATION_TRUNCATE_OBJECT 0x95C3
// Must be called before using SendPartialObject and TruncateObject
#define MTP_OPERATION_BEGIN_EDIT_OBJECT 0x95C4
// Called to commit changes made by SendPartialObject and TruncateObject
#define MTP_OPERATION_END_EDIT_OBJECT 0x95C5
// MTP Response Codes
#define MTP_RESPONSE_UNDEFINED 0x2000
#define MTP_RESPONSE_OK 0x2001
#define MTP_RESPONSE_GENERAL_ERROR 0x2002
#define MTP_RESPONSE_SESSION_NOT_OPEN 0x2003
#define MTP_RESPONSE_INVALID_TRANSACTION_ID 0x2004
#define MTP_RESPONSE_OPERATION_NOT_SUPPORTED 0x2005
#define MTP_RESPONSE_PARAMETER_NOT_SUPPORTED 0x2006
#define MTP_RESPONSE_INCOMPLETE_TRANSFER 0x2007
#define MTP_RESPONSE_INVALID_STORAGE_ID 0x2008
#define MTP_RESPONSE_INVALID_OBJECT_HANDLE 0x2009
#define MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED 0x200A
#define MTP_RESPONSE_INVALID_OBJECT_FORMAT_CODE 0x200B
#define MTP_RESPONSE_STORAGE_FULL 0x200C
#define MTP_RESPONSE_OBJECT_WRITE_PROTECTED 0x200D
#define MTP_RESPONSE_STORE_READ_ONLY 0x200E
#define MTP_RESPONSE_ACCESS_DENIED 0x200F
#define MTP_RESPONSE_NO_THUMBNAIL_PRESENT 0x2010
#define MTP_RESPONSE_SELF_TEST_FAILED 0x2011
#define MTP_RESPONSE_PARTIAL_DELETION 0x2012
#define MTP_RESPONSE_STORE_NOT_AVAILABLE 0x2013
#define MTP_RESPONSE_SPECIFICATION_BY_FORMAT_UNSUPPORTED 0x2014
#define MTP_RESPONSE_NO_VALID_OBJECT_INFO 0x2015
#define MTP_RESPONSE_INVALID_CODE_FORMAT 0x2016
#define MTP_RESPONSE_UNKNOWN_VENDOR_CODE 0x2017
#define MTP_RESPONSE_CAPTURE_ALREADY_TERMINATED 0x2018
#define MTP_RESPONSE_DEVICE_BUSY 0x2019
#define MTP_RESPONSE_INVALID_PARENT_OBJECT 0x201A
#define MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT 0x201B
#define MTP_RESPONSE_INVALID_DEVICE_PROP_VALUE 0x201C
#define MTP_RESPONSE_INVALID_PARAMETER 0x201D
#define MTP_RESPONSE_SESSION_ALREADY_OPEN 0x201E
#define MTP_RESPONSE_TRANSACTION_CANCELLED 0x201F
#define MTP_RESPONSE_SPECIFICATION_OF_DESTINATION_UNSUPPORTED 0x2020
#define MTP_RESPONSE_INVALID_OBJECT_PROP_CODE 0xA801
#define MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT 0xA802
#define MTP_RESPONSE_INVALID_OBJECT_PROP_VALUE 0xA803
#define MTP_RESPONSE_INVALID_OBJECT_REFERENCE 0xA804
#define MTP_RESPONSE_GROUP_NOT_SUPPORTED 0xA805
#define MTP_RESPONSE_INVALID_DATASET 0xA806
#define MTP_RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED 0xA807
#define MTP_RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED 0xA808
#define MTP_RESPONSE_OBJECT_TOO_LARGE 0xA809
#define MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED 0xA80A
#define MTP_RESPONSE_NO_RESPONSE 0xFFFF
// MTP Event Codes
#define MTP_EVENT_UNDEFINED 0x4000
#define MTP_EVENT_CANCEL_TRANSACTION 0x4001
#define MTP_EVENT_OBJECT_ADDED 0x4002
#define MTP_EVENT_OBJECT_REMOVED 0x4003
#define MTP_EVENT_STORE_ADDED 0x4004
#define MTP_EVENT_STORE_REMOVED 0x4005
#define MTP_EVENT_DEVICE_PROP_CHANGED 0x4006
#define MTP_EVENT_OBJECT_INFO_CHANGED 0x4007
#define MTP_EVENT_DEVICE_INFO_CHANGED 0x4008
#define MTP_EVENT_REQUEST_OBJECT_TRANSFER 0x4009
#define MTP_EVENT_STORE_FULL 0x400A
#define MTP_EVENT_DEVICE_RESET 0x400B
#define MTP_EVENT_STORAGE_INFO_CHANGED 0x400C
#define MTP_EVENT_CAPTURE_COMPLETE 0x400D
#define MTP_EVENT_UNREPORTED_STATUS 0x400E
#define MTP_EVENT_OBJECT_PROP_CHANGED 0xC801
#define MTP_EVENT_OBJECT_PROP_DESC_CHANGED 0xC802
#define MTP_EVENT_OBJECT_REFERENCES_CHANGED 0xC803
// Storage Type
#define MTP_STORAGE_FIXED_ROM 0x0001
#define MTP_STORAGE_REMOVABLE_ROM 0x0002
#define MTP_STORAGE_FIXED_RAM 0x0003
#define MTP_STORAGE_REMOVABLE_RAM 0x0004
// Storage File System
#define MTP_STORAGE_FILESYSTEM_FLAT 0x0001
#define MTP_STORAGE_FILESYSTEM_HIERARCHICAL 0x0002
#define MTP_STORAGE_FILESYSTEM_DCF 0x0003
// Storage Access Capability
#define MTP_STORAGE_READ_WRITE 0x0000
#define MTP_STORAGE_READ_ONLY_WITHOUT_DELETE 0x0001
#define MTP_STORAGE_READ_ONLY_WITH_DELETE 0x0002
// Association Type
#define MTP_ASSOCIATION_TYPE_UNDEFINED 0x0000
#define MTP_ASSOCIATION_TYPE_GENERIC_FOLDER 0x0001
// MTP class reqeusts
#define MTP_REQUEST_CANCEL 0x64
#define MTP_REQUEST_GET_EXT_EVENT_DATA 0x65
#define MTP_REQUEST_RESET 0x66
#define MTP_REQUEST_GET_DEVICE_STATUS 0x67
// clang-format on
#define USB_MTP_CLASS 0x06
#define USB_MTP_SUB_CLASS 0x01U
#define USB_MTP_PROTOCOL 0x01U
struct mtp_header {
uint32_t conlen;
uint16_t contype;
uint16_t code;
uint32_t trans_id;
uint32_t param[];
};
struct mtp_string {
uint8_t len;
uint16_t string[255];
};
struct mtp_device_info {
uint16_t StandardVersion;
uint32_t VendorExtensionID;
uint16_t VendorExtensionVersion;
uint8_t VendorExtensionDesc_len;
uint16_t VendorExtensionDesc[255];
uint16_t FunctionalMode;
uint32_t OperationsSupported_len;
uint16_t OperationsSupported[255];
uint32_t EventsSupported_len;
uint16_t EventsSupported[255];
uint32_t DevicePropertiesSupported_len;
uint16_t DevicePropertiesSupported[255];
uint32_t CaptureFormats_len;
uint16_t CaptureFormats[255];
uint32_t ImageFormats_len;
uint16_t ImageFormats[255];
uint8_t Manufacturer_len;
uint16_t Manufacturer[255];
uint8_t Model_len;
uint16_t Model[255];
uint8_t DeviceVersion_len;
uint16_t DeviceVersion[255];
uint8_t SerialNumber_len;
uint16_t SerialNumber[255];
} __PACKED;
struct mtp_object_props_support {
uint32_t ObjectPropCode_len;
uint16_t ObjectPropCode[255];
} __PACKED;
struct mtp_device_prop_desc {
uint16_t DevicePropertyCode;
uint16_t DataType;
uint8_t GetSet;
uint16_t DefaultValue[1];
uint16_t CurrentValue[1];
uint8_t FormFlag;
} __PACKED;
struct mtp_storage_id {
uint32_t StorageIDS_len;
uint32_t StorageIDS[255];
} __PACKED;
struct mtp_storage_info {
uint16_t StorageType;
uint16_t FilesystemType;
uint16_t AccessCapability;
uint64_t MaxCapability;
uint64_t FreeSpaceInBytes;
uint32_t FreeSpaceInObjects;
uint8_t StorageDescription_len;
uint8_t StorageDescription[255];
uint8_t VolumeIdentifier_len;
uint8_t VolumeIdentifier[255];
} __PACKED;
struct mtp_object_handles {
uint32_t ObjectHandle_len;
uint32_t ObjectHandle[255];
} __PACKED;
struct mtp_object_prop_desc {
uint16_t ObjectPropertyCode;
uint16_t DataType;
uint8_t GetSet;
uint8_t DefValue[16];
uint32_t GroupCode;
uint8_t FormFlag;
} __PACKED;
struct mtp_object_prop_element {
uint32_t ObjectHandle;
uint16_t PropertyCode;
uint16_t Datatype;
uint8_t value[8];
} __PACKED;
struct mtp_object_prop_list {
uint32_t element_len;
struct mtp_object_prop_element element[1];
} __PACKED;
struct mtp_object_info {
uint32_t StorageId;
uint16_t ObjectFormat;
uint16_t ProtectionStatus;
uint32_t ObjectCompressedSize;
uint16_t ThumbFormat;
uint32_t ThumbCompressedSize;
uint32_t ThumbPixWidth;
uint32_t ThumbPixHeight;
uint32_t ImagePixWidth;
uint32_t ImagePixHeight;
uint32_t ImageBitDepth;
uint32_t ParentObject;
uint16_t AssociationType;
uint32_t AssociationDesc;
uint32_t SequenceNumber;
uint8_t Filename_len;
uint16_t Filename[CONFIG_USBDEV_MTP_MAX_PATHNAME];
uint8_t CaptureDate[6];
uint8_t ModificationDate[6];
} __PACKED;
struct mtp_object {
uint32_t storage_id;
uint32_t handle;
uint32_t parent_handle;
uint16_t format;
bool is_dir;
bool is_readonly;
bool is_hidden;
uint32_t file_size;
uint32_t file_full_name_length;
char file_full_name[CONFIG_USBDEV_MTP_MAX_PATHNAME];
bool in_use;
};
/*Length of template descriptor: 23 bytes*/
#define MTP_DESCRIPTOR_LEN (9 + 7 + 7 + 7)
// clang-format off
#define MTP_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep, int_ep, wMaxPacketSize, str_idx) \
/* Interface */ \
0x09, /* bLength */ \
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
bFirstInterface, /* bInterfaceNumber */ \
0x00, /* bAlternateSetting */ \
0x03, /* bNumEndpoints */ \
USB_DEVICE_CLASS_IMAGE, /* bInterfaceClass */ \
USB_MTP_SUB_CLASS, /* bInterfaceSubClass */ \
USB_MTP_PROTOCOL, /* bInterfaceProtocol */ \
str_idx, /* iInterface */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
out_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
in_ep, /* bEndpointAddress */ \
0x02, /* bmAttributes */ \
WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x07, /* bLength */ \
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
int_ep, /* bEndpointAddress */ \
0x03, /* bmAttributes */ \
0x1c, /* wMaxPacketSize */ \
0x00, /* bInterval */ \
0x06 /* bLength */
// clang-format on
#endif

62
class/mtp/usbd_mtp.h Normal file
View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_MTP_H
#define USBD_MTP_H
#include "usb_mtp.h"
#include <sys/stat.h>
#include <fcntl.h>
/* gcc toolchain does not implement dirent.h, so we define our own MTP_DIR and mtp_dirent */
typedef void MTP_DIR;
struct mtp_statfs {
size_t f_bsize; /* block size */
size_t f_blocks; /* total data blocks in file system */
size_t f_bfree; /* free blocks in file system */
};
struct mtp_dirent {
uint8_t d_type; /* The type of the file */
uint8_t d_namlen; /* The length of the not including the terminating null file name */
uint16_t d_reclen; /* length of this record */
char d_name[CONFIG_USBDEV_MTP_MAX_PATHNAME]; /* The null-terminated file name */
};
#ifdef __cplusplus
extern "C" {
#endif
struct usbd_interface *usbd_mtp_init_intf(struct usbd_interface *intf,
const uint8_t out_ep,
const uint8_t in_ep,
const uint8_t int_ep);
const char *usbd_mtp_fs_root_path(void);
const char *usbd_mtp_fs_description(void);
int usbd_mtp_mkdir(const char *path);
int usbd_mtp_rmdir(const char *path);
MTP_DIR *usbd_mtp_opendir(const char *name);
int usbd_mtp_closedir(MTP_DIR *d);
struct mtp_dirent *usbd_mtp_readdir(MTP_DIR *d);
int usbd_mtp_statfs(const char *path, struct mtp_statfs *buf);
int usbd_mtp_stat(const char *file, struct stat *buf);
int usbd_mtp_open(const char *path, uint8_t mode);
int usbd_mtp_close(int fd);
int usbd_mtp_read(int fd, void *buf, size_t len);
int usbd_mtp_write(int fd, const void *buf, size_t len);
int usbd_mtp_unlink(const char *path);
#ifdef __cplusplus
}
#endif
#endif /* USBD_MTP_H */

View File

@@ -0,0 +1,312 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef USBD_MTP_SUPPORT_H
#define USBD_MTP_SUPPORT_H
#define MTP_VERSION 100
typedef struct _profile_property {
uint16_t prop_code;
uint16_t data_type;
uint8_t getset;
uint64_t default_value;
uint32_t group_code;
uint8_t form_flag;
uint16_t format_code;
} profile_property;
typedef struct _format_property {
uint16_t format_code;
uint16_t *properties;
} formats_property;
const char mtp_extension_string[] = "microsoft.com: 1.0; android.com: 1.0;";
const uint16_t supported_op[] = {
MTP_OPERATION_GET_DEVICE_INFO, //0x1001
MTP_OPERATION_OPEN_SESSION, //0x1002
MTP_OPERATION_CLOSE_SESSION, //0x1003
MTP_OPERATION_GET_STORAGE_IDS, //0x1004
MTP_OPERATION_GET_STORAGE_INFO, //0x1005
//MTP_OPERATION_GET_NUM_OBJECTS ,//0x1006
MTP_OPERATION_GET_OBJECT_HANDLES, //0x1007
MTP_OPERATION_GET_OBJECT_INFO, //0x1008
MTP_OPERATION_GET_OBJECT, //0x1009
//MTP_OPERATION_GET_THUMB ,//0x100A
MTP_OPERATION_DELETE_OBJECT, //0x100B
MTP_OPERATION_SEND_OBJECT_INFO, //0x100C
MTP_OPERATION_SEND_OBJECT, //0x100D
MTP_OPERATION_GET_DEVICE_PROP_DESC, //0x1014
// MTP_OPERATION_GET_DEVICE_PROP_VALUE ,//0x1015
// MTP_OPERATION_SET_DEVICE_PROP_VALUE ,//0x1016
//MTP_OPERATION_RESET_DEVICE_PROP_VALUE ,//0x1017
// MTP_OPERATION_GET_PARTIAL_OBJECT ,//0x101B
MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED, //0x9801
// MTP_OPERATION_GET_OBJECT_PROP_DESC, //0x9802
// MTP_OPERATION_GET_OBJECT_PROP_VALUE ,//0x9803
// MTP_OPERATION_SET_OBJECT_PROP_VALUE ,//0x9804
// MTP_OPERATION_GET_OBJECT_PROP_LIST ,//0x9805
//MTP_OPERATION_GET_OBJECT_REFERENCES ,//0x9810
//MTP_OPERATION_SET_OBJECT_REFERENCES ,//0x9811
// MTP_OPERATION_GET_PARTIAL_OBJECT_64 ,//0x95C1
// MTP_OPERATION_SEND_PARTIAL_OBJECT ,//0x95C2
// MTP_OPERATION_TRUNCATE_OBJECT ,//0x95C3
// MTP_OPERATION_BEGIN_EDIT_OBJECT ,//0x95C4
// MTP_OPERATION_END_EDIT_OBJECT //0x95C5
};
int supported_op_size = sizeof(supported_op);
const uint16_t supported_event[] = {
MTP_EVENT_OBJECT_ADDED, // 0x4002
MTP_EVENT_OBJECT_REMOVED, // 0x4003
MTP_EVENT_STORE_ADDED, // 0x4004
MTP_EVENT_STORE_REMOVED, // 0x4005
MTP_EVENT_STORAGE_INFO_CHANGED, // 0x400C
MTP_EVENT_OBJECT_INFO_CHANGED, // 0x4007
MTP_EVENT_DEVICE_PROP_CHANGED, // 0x4006
MTP_EVENT_OBJECT_PROP_CHANGED // 0xC801
};
int supported_event_size = sizeof(supported_event);
const formats_property support_format_properties[] = {
// format code prop code
{ MTP_FORMAT_UNDEFINED, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF } },
{ MTP_FORMAT_ASSOCIATION, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF } }
#if 0
{ MTP_FORMAT_TEXT , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF}
},
{ MTP_FORMAT_HTML , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF}
},
{ MTP_FORMAT_MP4_CONTAINER, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_ARTIST, MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_DURATION, MTP_PROPERTY_DESCRIPTION, MTP_PROPERTY_WIDTH, MTP_PROPERTY_HEIGHT, MTP_PROPERTY_DATE_AUTHORED,
0xFFFF}
},
{ MTP_FORMAT_3GP_CONTAINER, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_ARTIST, MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_DURATION, MTP_PROPERTY_DESCRIPTION, MTP_PROPERTY_WIDTH, MTP_PROPERTY_HEIGHT, MTP_PROPERTY_DATE_AUTHORED,
0xFFFF}
},
{ MTP_FORMAT_WAV , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,MTP_PROPERTY_ARTIST,MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_ALBUM_ARTIST, MTP_PROPERTY_TRACK, MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_PROPERTY_GENRE, MTP_PROPERTY_COMPOSER,
MTP_PROPERTY_AUDIO_WAVE_CODEC, MTP_PROPERTY_BITRATE_TYPE, MTP_PROPERTY_AUDIO_BITRATE, MTP_PROPERTY_NUMBER_OF_CHANNELS,MTP_PROPERTY_SAMPLE_RATE,
0xFFFF}
},
{ MTP_FORMAT_MP3 , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,MTP_PROPERTY_ARTIST,MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_ALBUM_ARTIST, MTP_PROPERTY_TRACK, MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_PROPERTY_GENRE, MTP_PROPERTY_COMPOSER,
MTP_PROPERTY_AUDIO_WAVE_CODEC, MTP_PROPERTY_BITRATE_TYPE, MTP_PROPERTY_AUDIO_BITRATE, MTP_PROPERTY_NUMBER_OF_CHANNELS,MTP_PROPERTY_SAMPLE_RATE,
0xFFFF}
},
{ MTP_FORMAT_MPEG , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_ARTIST, MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_DURATION, MTP_PROPERTY_DESCRIPTION, MTP_PROPERTY_WIDTH, MTP_PROPERTY_HEIGHT, MTP_PROPERTY_DATE_AUTHORED,
0xFFFF}
},
{ MTP_FORMAT_EXIF_JPEG , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_DESCRIPTION, MTP_PROPERTY_WIDTH,
MTP_PROPERTY_HEIGHT, MTP_PROPERTY_DATE_AUTHORED,
0xFFFF}
},
{ MTP_FORMAT_BMP , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_DESCRIPTION, MTP_PROPERTY_WIDTH,
MTP_PROPERTY_HEIGHT, MTP_PROPERTY_DATE_AUTHORED,
0xFFFF}
},
{ MTP_FORMAT_GIF , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_DESCRIPTION, MTP_PROPERTY_WIDTH,
MTP_PROPERTY_HEIGHT, MTP_PROPERTY_DATE_AUTHORED,
0xFFFF}
},
{ MTP_FORMAT_JFIF , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_DESCRIPTION, MTP_PROPERTY_WIDTH,
MTP_PROPERTY_HEIGHT, MTP_PROPERTY_DATE_AUTHORED,
0xFFFF}
},
{ MTP_FORMAT_WMA , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_ARTIST, MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_ALBUM_ARTIST, MTP_PROPERTY_TRACK, MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_PROPERTY_DURATION, MTP_PROPERTY_DESCRIPTION,
MTP_PROPERTY_GENRE, MTP_PROPERTY_COMPOSER, MTP_PROPERTY_AUDIO_WAVE_CODEC, MTP_PROPERTY_BITRATE_TYPE, MTP_PROPERTY_AUDIO_BITRATE,
MTP_PROPERTY_NUMBER_OF_CHANNELS, MTP_PROPERTY_SAMPLE_RATE,
0xFFFF}
},
{ MTP_FORMAT_OGG , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_ARTIST, MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_ALBUM_ARTIST, MTP_PROPERTY_TRACK, MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_PROPERTY_DURATION, MTP_PROPERTY_DESCRIPTION,
MTP_PROPERTY_GENRE, MTP_PROPERTY_COMPOSER, MTP_PROPERTY_AUDIO_WAVE_CODEC, MTP_PROPERTY_BITRATE_TYPE, MTP_PROPERTY_AUDIO_BITRATE,
MTP_PROPERTY_NUMBER_OF_CHANNELS, MTP_PROPERTY_SAMPLE_RATE,
0xFFFF}
},
{ MTP_FORMAT_AAC , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_ARTIST, MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_ALBUM_ARTIST, MTP_PROPERTY_TRACK, MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_PROPERTY_DURATION, MTP_PROPERTY_DESCRIPTION,
MTP_PROPERTY_GENRE, MTP_PROPERTY_COMPOSER, MTP_PROPERTY_AUDIO_WAVE_CODEC, MTP_PROPERTY_BITRATE_TYPE, MTP_PROPERTY_AUDIO_BITRATE,
MTP_PROPERTY_NUMBER_OF_CHANNELS, MTP_PROPERTY_SAMPLE_RATE,
0xFFFF}
},
{ MTP_FORMAT_ABSTRACT_AV_PLAYLIST, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF}
},
{ MTP_FORMAT_WPL_PLAYLIST, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF}
},
{ MTP_FORMAT_M3U_PLAYLIST, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF}
},
{ MTP_FORMAT_PLS_PLAYLIST, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF}
},
{ MTP_FORMAT_XML_DOCUMENT, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF}
},
{ MTP_FORMAT_FLAC , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF}
},
{ MTP_FORMAT_AVI , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_ARTIST, MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_DURATION, MTP_PROPERTY_DESCRIPTION, MTP_PROPERTY_WIDTH, MTP_PROPERTY_HEIGHT, MTP_PROPERTY_DATE_AUTHORED,
0xFFFF}
},
{ MTP_FORMAT_ASF , (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED, MTP_PROPERTY_ARTIST, MTP_PROPERTY_ALBUM_NAME,
MTP_PROPERTY_DURATION, MTP_PROPERTY_DESCRIPTION, MTP_PROPERTY_WIDTH, MTP_PROPERTY_HEIGHT, MTP_PROPERTY_DATE_AUTHORED,
0xFFFF}
},
{ MTP_FORMAT_MS_WORD_DOCUMENT, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF}
},
{ MTP_FORMAT_MS_EXCEL_SPREADSHEET, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF}
},
{ MTP_FORMAT_MS_POWERPOINT_PRESENTATION, (uint16_t[]){ MTP_PROPERTY_STORAGE_ID, MTP_PROPERTY_OBJECT_FORMAT, MTP_PROPERTY_PROTECTION_STATUS, MTP_PROPERTY_OBJECT_SIZE,
MTP_PROPERTY_OBJECT_FILE_NAME, MTP_PROPERTY_DATE_MODIFIED, MTP_PROPERTY_PARENT_OBJECT, MTP_PROPERTY_PERSISTENT_UID,
MTP_PROPERTY_NAME, MTP_PROPERTY_DISPLAY_NAME, MTP_PROPERTY_DATE_CREATED,
0xFFFF}
}
#endif
,
{ 0xFFFF, (uint16_t[]){ 0xFFFF } }
};
const profile_property support_object_properties[] = {
// prop_code data_type getset default_value group_code form_flag format_code
{ MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, 0x00, 0x00000000, 0x000000001, 0x00, 0xFFFF },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_UNDEFINED, 0x000000000, 0x00, MTP_FORMAT_UNDEFINED },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_ASSOCIATION, 0x000000000, 0x00, MTP_FORMAT_ASSOCIATION },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_TEXT, 0x000000000, 0x00, MTP_FORMAT_TEXT },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_HTML, 0x000000000, 0x00, MTP_FORMAT_HTML },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_WAV, 0x000000000, 0x00, MTP_FORMAT_WAV },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_MP3, 0x000000000, 0x00, MTP_FORMAT_MP3 },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_MPEG, 0x000000000, 0x00, MTP_FORMAT_MPEG },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_EXIF_JPEG, 0x000000000, 0x00, MTP_FORMAT_EXIF_JPEG },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_BMP, 0x000000000, 0x00, MTP_FORMAT_BMP },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_AIFF, 0x000000000, 0x00, MTP_FORMAT_AIFF },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_MPEG, 0x000000000, 0x00, MTP_FORMAT_MPEG },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_WMA, 0x000000000, 0x00, MTP_FORMAT_WMA },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_OGG, 0x000000000, 0x00, MTP_FORMAT_OGG },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_AAC, 0x000000000, 0x00, MTP_FORMAT_AAC },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_MP4_CONTAINER, 0x000000000, 0x00, MTP_FORMAT_MP4_CONTAINER },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_3GP_CONTAINER, 0x000000000, 0x00, MTP_FORMAT_3GP_CONTAINER },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_ABSTRACT_AV_PLAYLIST, 0x000000000, 0x00, MTP_FORMAT_ABSTRACT_AV_PLAYLIST },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_WPL_PLAYLIST, 0x000000000, 0x00, MTP_FORMAT_WPL_PLAYLIST },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_M3U_PLAYLIST, 0x000000000, 0x00, MTP_FORMAT_M3U_PLAYLIST },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_PLS_PLAYLIST, 0x000000000, 0x00, MTP_FORMAT_PLS_PLAYLIST },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_XML_DOCUMENT, 0x000000000, 0x00, MTP_FORMAT_XML_DOCUMENT },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_FLAC, 0x000000000, 0x00, MTP_FORMAT_FLAC },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_AVI, 0x000000000, 0x00, MTP_FORMAT_AVI },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_ASF, 0x000000000, 0x00, MTP_FORMAT_ASF },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_MS_WORD_DOCUMENT, 0x000000000, 0x00, MTP_FORMAT_MS_WORD_DOCUMENT },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_MS_EXCEL_SPREADSHEET, 0x000000000, 0x00, MTP_FORMAT_MS_EXCEL_SPREADSHEET },
{ MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16, 0x00, MTP_FORMAT_MS_POWERPOINT_PRESENTATION, 0x000000000, 0x00, MTP_FORMAT_MS_POWERPOINT_PRESENTATION },
{ MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64, 0x00, 0x0000000000000000, 0x000000000, 0x00, MTP_FORMAT_ASSOCIATION },
{ MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, 0x00, 0x00000000, 0x000000000, 0x00, MTP_FORMAT_ASSOCIATION },
{ MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16, 0x00, 0x0000, 0x000000000, 0x00, MTP_FORMAT_ASSOCIATION },
{ MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR, 0x00, 0x0000, 0x000000000, 0x00, MTP_FORMAT_ASSOCIATION },
{ MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR, 0x01, 0x0000, 0x000000000, 0x00, MTP_FORMAT_ASSOCIATION },
{ MTP_PROPERTY_DATE_CREATED, MTP_TYPE_STR, 0x00, 0x00, 0x000000000, 0x00, MTP_FORMAT_ASSOCIATION },
{ MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR, 0x00, 0x00, 0x000000000, 0x00, MTP_FORMAT_ASSOCIATION },
{ MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32, 0x00, 0x00000000, 0x000000000, 0x00, MTP_FORMAT_ASSOCIATION },
{ MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128, 0x00, 0x00, 0x000000000, 0x00, MTP_FORMAT_ASSOCIATION },
{ MTP_PROPERTY_NAME, MTP_TYPE_STR, 0x00, 0x00, 0x000000000, 0x00, MTP_FORMAT_ASSOCIATION },
{ MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64, 0x00, 0x0000000000000000, 0x000000000, 0x00, MTP_FORMAT_UNDEFINED },
{ MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, 0x00, 0x00000000, 0x000000000, 0x00, MTP_FORMAT_UNDEFINED },
{ MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16, 0x00, 0x0000, 0x000000000, 0x00, MTP_FORMAT_UNDEFINED },
{ MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR, 0x00, 0x0000, 0x000000000, 0x00, MTP_FORMAT_UNDEFINED },
{ MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR, 0x01, 0x0000, 0x000000000, 0x00, MTP_FORMAT_UNDEFINED },
{ MTP_PROPERTY_DATE_CREATED, MTP_TYPE_STR, 0x00, 0x00, 0x000000000, 0x00, MTP_FORMAT_UNDEFINED },
{ MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR, 0x00, 0x00, 0x000000000, 0x00, MTP_FORMAT_UNDEFINED },
{ MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32, 0x00, 0x00000000, 0x000000000, 0x00, MTP_FORMAT_UNDEFINED },
{ MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128, 0x00, 0x00, 0x000000000, 0x00, MTP_FORMAT_UNDEFINED },
{ MTP_PROPERTY_NAME, MTP_TYPE_STR, 0x00, 0x00, 0x000000000, 0x00, MTP_FORMAT_UNDEFINED },
//{MTP_PROPERTY_ASSOCIATION_TYPE, MTP_TYPE_UINT16, 0x00, 0x0001 , 0x000000000 , 0x00 , 0xFFFF },
{ MTP_PROPERTY_ASSOCIATION_DESC, MTP_TYPE_UINT32, 0x00, 0x00000000, 0x000000000, 0x00, 0xFFFF },
{ MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16, 0x00, 0x0000, 0x000000000, 0x00, 0xFFFF },
{ MTP_PROPERTY_HIDDEN, MTP_TYPE_UINT16, 0x00, 0x0000, 0x000000000, 0x00, 0xFFFF },
{ 0xFFFF, MTP_TYPE_UINT32, 0x00, 0x00000000, 0x000000000, 0x00 }
};
const profile_property support_device_properties[] = {
// prop_code data_type getset default_value group_code form_flag
//{MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_UINT32, 0x00, 0x00000000 , 0x000000000 , 0x00 },
//{MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_UINT32, 0x00, 0x00000000 , 0x000000000 , 0x00 },
{ MTP_DEVICE_PROPERTY_BATTERY_LEVEL, MTP_TYPE_UINT16, 0x00, 0x00000000, 0x000000000, 0x00 },
{ MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR, 0x00, 0x00000000, 0x000000000, 0x00 },
{ 0xFFFF, MTP_TYPE_UINT32, 0x00, 0x00000000, 0x000000000, 0x00 }
};
#endif

View File

@@ -74,7 +74,7 @@ static int usbh_asix_read_cmd(struct usbh_asix *asix_class,
if (ret < 8) {
return ret;
}
memcpy(data, g_asix_buf, ret - 8);
memcpy(data, g_asix_buf, MIN(ret - 8, size));
return ret;
}
@@ -638,6 +638,7 @@ static int usbh_asix_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister ASIX Class:%s\r\n", hport->config.intf[intf].devname);
usbh_asix_stop(asix_class);
}

View File

@@ -965,7 +965,7 @@ static int usbh_rtl8152_read_regs(struct usbh_rtl8152 *rtl8152_class,
if (ret < 8) {
return ret;
}
memcpy(data, g_rtl8152_buf, ret - 8);
memcpy(data, g_rtl8152_buf, MIN(ret - 8, size));
return ret;
}
@@ -2121,6 +2121,7 @@ static int usbh_rtl8152_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister rtl8152 Class:%s\r\n", hport->config.intf[intf].devname);
usbh_rtl8152_stop(rtl8152_class);
}

View File

@@ -311,6 +311,7 @@ static int usbh_ch34x_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister CH34X Class:%s\r\n", hport->config.intf[intf].devname);
usbh_ch34x_stop(ch34x_class);
}

View File

@@ -260,6 +260,7 @@ static int usbh_cp210x_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister CP210X Class:%s\r\n", hport->config.intf[intf].devname);
usbh_cp210x_stop(cp210x_class);
}

View File

@@ -440,6 +440,7 @@ static int usbh_ftdi_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister FTDI Class:%s\r\n", hport->config.intf[intf].devname);
usbh_ftdi_stop(ftdi_class);
}

View File

@@ -375,6 +375,7 @@ static int usbh_pl2303_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister PL2303 Class:%s\r\n", hport->config.intf[intf].devname);
usbh_pl2303_stop(pl2303_class);
}

View File

@@ -337,6 +337,7 @@ static int usbh_bl616_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister BL616 WIFI Class:%s\r\n", hport->config.intf[intf].devname);
usbh_bl616_stop(bl616_class);
}

View File

@@ -86,6 +86,7 @@ int usbh_xbox_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister XBOX Class:%s\r\n", hport->config.intf[intf].devname);
usbh_xbox_stop(xbox_class);
}

View File

@@ -1237,7 +1237,7 @@ struct video_autoexposure_mode {
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType : INTERFACE */ \
bInterfaceNumber, /* bInterfaceNumber: Index of this interface */ \
bAlternateSetting, /* bAlternateSetting: Index of this alternate setting */ \
bNumEndpoints, /* bNumEndpoints : 0 endpoints no bandwidth used*/ \
bNumEndpoints, /* bNumEndpoints : 0 endpoints, no bandwidth used*/ \
0x0e, /* bInterfaceClass : CC_VIDEO */ \
0x02, /* bInterfaceSubClass : SC_VIDEOSTREAMING */ \
0x00, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
@@ -1315,8 +1315,8 @@ struct video_autoexposure_mode {
bNumFrameDescriptors, /* bNumFrameDescriptors : One frame descriptor for this format follows. */ \
0x00, /* bmFlags : Uses fixed size samples.. */ \
0x01, /* bDefaultFrameIndex : Default frame index is 1. */ \
0x00, /* bAspectRatioX : Non-interlaced stream not required. */ \
0x00, /* bAspectRatioY : Non-interlaced stream not required. */ \
0x00, /* bAspectRatioX : Non-interlaced stream, not required. */ \
0x00, /* bAspectRatioY : Non-interlaced stream, not required. */ \
0x00, /* bmInterlaceFlags : Non-interlaced stream */ \
0x00 /* bCopyProtect : No restrictions imposed on the duplication of this video stream. */
@@ -1346,8 +1346,8 @@ struct video_autoexposure_mode {
VIDEO_GUID_H264, \
0x00, /* bmFlags : Uses fixed size samples.. */ \
0x01, /* bDefaultFrameIndex : Default frame index is 1. */ \
0x00, /* bAspectRatioX : Non-interlaced stream not required. */ \
0x00, /* bAspectRatioY : Non-interlaced stream not required. */ \
0x00, /* bAspectRatioX : Non-interlaced stream, not required. */ \
0x00, /* bAspectRatioY : Non-interlaced stream, not required. */ \
0x00, /* bmInterlaceFlags : Non-interlaced stream */ \
0x00, /* bCopyProtect : No restrictions imposed on the duplication of this video stream. */ \
0x00 /* Variable size: False */

View File

@@ -18,20 +18,14 @@ struct usbd_video_priv {
uint8_t power_mode;
uint8_t error_code;
struct video_entity_info info[3];
uint8_t *ep_buf0;
uint8_t *ep_buf1;
bool ep_buf0_ready;
bool ep_buf1_ready;
uint32_t ep_buf0_len;
uint32_t ep_buf1_len;
uint8_t ep_buf_idx;
uint8_t *ep_buf;
bool stream_finish;
uint32_t max_packets;
uint8_t *stream_buf;
uint32_t stream_len;
uint32_t stream_offset;
uint8_t stream_frameid;
uint32_t stream_headerlen;
bool do_copy;
} g_usbd_video[CONFIG_USBDEV_MAX_BUS];
static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
@@ -753,41 +747,7 @@ static void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dw
g_usbd_video[busid].commit.bMaxVersion = 0;
g_usbd_video[busid].stream_frameid = 0;
g_usbd_video[busid].stream_headerlen = 2;
}
static uint32_t usbd_video_prepare_ep_buf_data(uint8_t busid, uint32_t remain, uint8_t *ep_buf)
{
struct video_payload_header *header;
uint32_t len;
uint32_t offset;
len = MIN(remain, (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen) * g_usbd_video[busid].max_packets);
offset = 0;
while (len > 0) {
header = (struct video_payload_header *)&ep_buf[offset];
header->bHeaderLength = g_usbd_video[busid].stream_headerlen;
header->headerInfoUnion.bmheaderInfo = 0;
header->headerInfoUnion.headerInfoBits.endOfHeader = 1;
header->headerInfoUnion.headerInfoBits.endOfFrame = 0;
header->headerInfoUnion.headerInfoBits.frameIdentifier = g_usbd_video[busid].stream_frameid;
uint32_t len2 = MIN(len, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen);
usb_memcpy(&ep_buf[offset + g_usbd_video[busid].stream_headerlen],
&g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset],
len2);
g_usbd_video[busid].stream_offset += len2;
len -= len2;
offset += (len2 + g_usbd_video[busid].stream_headerlen);
if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) {
header->headerInfoUnion.headerInfoBits.endOfFrame = 1;
}
}
return offset;
g_usbd_video[busid].stream_headerlen = 12;
}
struct usbd_interface *usbd_video_init_intf(uint8_t busid,
@@ -817,69 +777,88 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid,
bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep)
{
uint32_t remain;
struct video_payload_header *header;
static uint32_t offset = 0;
static uint32_t len = 0;
if (g_usbd_video[busid].ep_buf1_ready && (g_usbd_video[busid].ep_buf_idx == 0)) { /* callback: buf1 ready and buf0 was sent */
g_usbd_video[busid].ep_buf0_ready = false;
g_usbd_video[busid].ep_buf_idx = 1;
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf1, g_usbd_video[busid].ep_buf1_len);
} else if (g_usbd_video[busid].ep_buf0_ready && (g_usbd_video[busid].ep_buf_idx == 1)) { /* callback: buf0 ready and buf1 was sent */
g_usbd_video[busid].ep_buf1_ready = false;
g_usbd_video[busid].ep_buf_idx = 0;
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
if (g_usbd_video[busid].stream_finish) {
g_usbd_video[busid].stream_finish = false;
return true;
}
offset = g_usbd_video[busid].stream_offset;
len = MIN(g_usbd_video[busid].stream_len,
g_usbd_video[busid].probe.dwMaxPayloadTransferSize -
g_usbd_video[busid].stream_headerlen);
if (g_usbd_video[busid].do_copy) {
header = (struct video_payload_header *)&g_usbd_video[busid].ep_buf[0];
usb_memcpy(&g_usbd_video[busid].ep_buf[g_usbd_video[busid].stream_headerlen], &g_usbd_video[busid].stream_buf[offset], len);
} else {
if (g_usbd_video[busid].stream_finish) {
return true;
}
header = (struct video_payload_header *)&g_usbd_video[busid].stream_buf[offset - g_usbd_video[busid].stream_headerlen];
}
if (!g_usbd_video[busid].ep_buf0_ready) {
remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
if (remain == 0) {
g_usbd_video[busid].stream_frameid ^= 1;
g_usbd_video[busid].stream_finish = true;
} else {
g_usbd_video[busid].ep_buf0_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf0);
g_usbd_video[busid].ep_buf0_ready = true;
if (!g_usbd_video[busid].ep_buf1_ready) {
g_usbd_video[busid].ep_buf_idx = 0;
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
}
}
memset(header, 0, g_usbd_video[busid].stream_headerlen);
header->bHeaderLength = g_usbd_video[busid].stream_headerlen;
header->headerInfoUnion.bmheaderInfo = 0;
header->headerInfoUnion.headerInfoBits.endOfHeader = 1;
header->headerInfoUnion.headerInfoBits.endOfFrame = 0;
header->headerInfoUnion.headerInfoBits.frameIdentifier = g_usbd_video[busid].stream_frameid;
g_usbd_video[busid].stream_offset += len;
g_usbd_video[busid].stream_len -= len;
if (g_usbd_video[busid].stream_len == 0) {
header->headerInfoUnion.headerInfoBits.endOfFrame = 1;
g_usbd_video[busid].stream_frameid ^= 1;
g_usbd_video[busid].stream_finish = true;
}
if (!g_usbd_video[busid].ep_buf1_ready) {
remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
if (remain == 0) {
g_usbd_video[busid].stream_frameid ^= 1;
g_usbd_video[busid].stream_finish = true;
} else {
g_usbd_video[busid].ep_buf1_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf1);
g_usbd_video[busid].ep_buf1_ready = true;
}
if (g_usbd_video[busid].do_copy) {
usbd_ep_start_write(busid, ep,
g_usbd_video[busid].ep_buf,
g_usbd_video[busid].stream_headerlen + len);
} else {
usbd_ep_start_write(busid, ep,
&g_usbd_video[busid].stream_buf[offset - g_usbd_video[busid].stream_headerlen],
g_usbd_video[busid].stream_headerlen + len);
}
return false;
}
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len)
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf, uint8_t *stream_buf, uint32_t stream_len, bool do_copy)
{
struct video_payload_header *header;
if ((usb_device_is_configured(busid) == 0) || (stream_len == 0)) {
return -1;
}
g_usbd_video[busid].ep_buf0 = ep_buf0;
g_usbd_video[busid].ep_buf1 = ep_buf1;
g_usbd_video[busid].ep_buf0_ready = false;
g_usbd_video[busid].ep_buf1_ready = false;
g_usbd_video[busid].ep_buf_idx = 0;
g_usbd_video[busid].stream_finish = false;
g_usbd_video[busid].max_packets = ep_bufsize / g_usbd_video[busid].probe.dwMaxPayloadTransferSize;
g_usbd_video[busid].ep_buf = ep_buf;
g_usbd_video[busid].stream_buf = stream_buf;
g_usbd_video[busid].stream_len = stream_len;
g_usbd_video[busid].stream_offset = 0;
g_usbd_video[busid].stream_finish = false;
g_usbd_video[busid].do_copy = do_copy;
usbd_video_stream_split_transfer(busid, ep);
uint32_t len = MIN(g_usbd_video[busid].stream_len,
g_usbd_video[busid].probe.dwMaxPayloadTransferSize -
g_usbd_video[busid].stream_headerlen);
header = (struct video_payload_header *)&ep_buf[0];
header->bHeaderLength = g_usbd_video[busid].stream_headerlen;
header->headerInfoUnion.bmheaderInfo = 0;
header->headerInfoUnion.headerInfoBits.endOfHeader = 1;
header->headerInfoUnion.headerInfoBits.endOfFrame = 0;
header->headerInfoUnion.headerInfoBits.frameIdentifier = g_usbd_video[busid].stream_frameid;
usb_memcpy(&ep_buf[g_usbd_video[busid].stream_headerlen], stream_buf, len);
g_usbd_video[busid].stream_offset += len;
g_usbd_video[busid].stream_len -= len;
usbd_ep_start_write(busid, ep, ep_buf, g_usbd_video[busid].stream_headerlen + len);
return 0;
}

View File

@@ -22,7 +22,7 @@ void usbd_video_open(uint8_t busid, uint8_t intf);
void usbd_video_close(uint8_t busid, uint8_t intf);
bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep);
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len);
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf, uint8_t *stream_buf, uint32_t stream_len, bool do_copy);
#ifdef __cplusplus
}

View File

@@ -483,6 +483,7 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
}
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister Video Class:%s\r\n", hport->config.intf[intf].devname);
usbh_video_stop(video_class);
}

View File

@@ -134,6 +134,7 @@ static int usbh_bluetooth_disconnect(struct usbh_hubport *hport, uint8_t intf)
// }
#endif
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister Bluetooth Class:%s\r\n", hport->config.intf[intf].devname);
usbh_bluetooth_stop(bluetooth_class);
}

View File

@@ -438,6 +438,7 @@ static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
// }
if (hport->config.intf[intf].devname[0] != '\0') {
usb_osal_thread_schedule_other();
USB_LOG_INFO("Unregister RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
usbh_rndis_stop(rndis_class);
}

View File

@@ -10,6 +10,9 @@
#if CONFIG_USB_ALIGN_SIZE % 32
#error "CONFIG_USB_ALIGN_SIZE must be multiple of 32"
#endif
void usb_dcache_clean(uintptr_t addr, size_t size);
void usb_dcache_invalidate(uintptr_t addr, size_t size);
void usb_dcache_flush(uintptr_t addr, size_t size);
#else
#define usb_dcache_clean(addr, size)
#define usb_dcache_invalidate(addr, size)

View File

@@ -42,6 +42,7 @@ struct usb_osal_timer {
*/
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args);
void usb_osal_thread_delete(usb_osal_thread_t thread);
void usb_osal_thread_schedule_other(void);
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count);
void usb_osal_sem_delete(usb_osal_sem_t sem);

View File

@@ -1123,6 +1123,7 @@ void usbd_event_connect_handler(uint8_t busid)
void usbd_event_disconnect_handler(uint8_t busid)
{
g_usbd_core[busid].configuration = 0;
g_usbd_core[busid].event_handler(busid, USBD_EVENT_DISCONNECTED);
}

View File

@@ -22,7 +22,9 @@ extern "C" {
#include "usb_list.h"
#include "usb_log.h"
#include "usb_dc.h"
#include "usb_osal.h"
#include "usb_memcpy.h"
#include "usb_dcache.h"
#include "usb_version.h"
enum usbd_event_type {

View File

@@ -220,6 +220,7 @@ const uint8_t audio_v1_descriptor[] = {
volatile bool tx_flag = 0;
volatile bool ep_tx_busy_flag = false;
volatile uint32_t s_mic_sample_rate;
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
@@ -260,6 +261,26 @@ void usbd_audio_close(uint8_t busid, uint8_t intf)
tx_flag = 0;
}
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
if (ep == AUDIO_IN_EP) {
s_mic_sample_rate = sampling_freq;
}
}
uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
{
(void)busid;
uint32_t freq = 0;
if (ep == AUDIO_IN_EP) {
freq = s_mic_sample_rate;
}
return freq;
}
void usbd_audio_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual in len:%d\r\n", (unsigned int)nbytes);

View File

@@ -258,6 +258,8 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t s_speaker_feedback_buffer[4];
volatile bool tx_flag = 0;
volatile bool rx_flag = 0;
volatile bool ep_tx_busy_flag = false;
volatile uint32_t s_mic_sample_rate;
volatile uint32_t s_speaker_sample_rate;
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
@@ -291,7 +293,7 @@ void usbd_audio_open(uint8_t busid, uint8_t intf)
/* setup first out ep read transfer */
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
#if USING_FEEDBACK == 1
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_SPEAKER_FREQ);
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(s_speaker_sample_rate);
AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value); /* uac1 can only use 10.14 */
usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
#endif
@@ -315,6 +317,30 @@ void usbd_audio_close(uint8_t busid, uint8_t intf)
}
}
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
if (ep == AUDIO_OUT_EP) {
s_speaker_sample_rate = sampling_freq;
} else if (ep == AUDIO_IN_EP) {
s_mic_sample_rate = sampling_freq;
}
}
uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
{
(void)busid;
uint32_t freq = 0;
if (ep == AUDIO_OUT_EP) {
freq = s_speaker_sample_rate;
} else if (ep == AUDIO_IN_EP) {
freq = s_mic_sample_rate;
}
return freq;
}
void usbd_audio_out_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual out len:%d\r\n", (unsigned int)nbytes);
@@ -331,7 +357,7 @@ void usbd_audio_in_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
void usbd_audio_iso_out_feedback_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
USB_LOG_RAW("actual feedback len:%d\r\n", (unsigned int)nbytes);
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_SPEAKER_FREQ);
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(s_speaker_sample_rate);
AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
}

View File

@@ -235,6 +235,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
volatile bool tx_flag = 0;
volatile bool ep_tx_busy_flag = false;
volatile uint32_t s_mic_sample_rate;
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
@@ -273,6 +274,26 @@ void usbd_audio_close(uint8_t busid, uint8_t intf)
tx_flag = 0;
}
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
if (ep == AUDIO_IN_EP) {
s_mic_sample_rate = sampling_freq;
}
}
uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
{
(void)busid;
uint32_t freq = 0;
if (ep == AUDIO_IN_EP) {
freq = s_mic_sample_rate;
}
return freq;
}
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
if (ep == AUDIO_IN_EP) {

View File

@@ -342,6 +342,8 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t write_buffer[AUDIO_IN_PACKET];
volatile bool tx_flag = 0;
volatile bool rx_flag = 0;
volatile bool ep_tx_busy_flag = false;
volatile uint32_t s_mic_sample_rate;
volatile uint32_t s_speaker_sample_rate;
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
@@ -402,6 +404,30 @@ void usbd_audio_close(uint8_t busid, uint8_t intf)
}
}
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
if (ep == AUDIO_OUT_EP) {
s_speaker_sample_rate = sampling_freq;
} else if (ep == AUDIO_IN_EP) {
s_mic_sample_rate = sampling_freq;
}
}
uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
{
(void)busid;
uint32_t freq = 0;
if (ep == AUDIO_OUT_EP) {
freq = s_speaker_sample_rate;
} else if (ep == AUDIO_IN_EP) {
freq = s_mic_sample_rate;
}
return freq;
}
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
if (ep == AUDIO_OUT_EP) {
@@ -429,10 +455,10 @@ void usbd_audio_iso_out_feedback_callback(uint8_t busid, uint8_t ep, uint32_t nb
{
USB_LOG_RAW("actual feedback len:%d\r\n", nbytes);
#ifdef CONFIG_USB_HS
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(AUDIO_FREQ);
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(s_speaker_sample_rate);
AUDIO_FEEDBACK_TO_BUF_HS(s_speaker_feedback_buffer, feedback_value);
#else
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_FREQ);
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(s_speaker_sample_rate);
AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
#endif
usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);

View File

@@ -274,6 +274,7 @@ USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t read_buffer[AUDIO_OUT_PACKET];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t s_speaker_feedback_buffer[4];
volatile bool rx_flag = 0;
volatile uint32_t s_speaker_sample_rate;
static void usbd_event_handler(uint8_t busid, uint8_t event)
{
@@ -307,10 +308,10 @@ void usbd_audio_open(uint8_t busid, uint8_t intf)
usbd_ep_start_read(busid, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET);
#if USING_FEEDBACK == 1
#ifdef CONFIG_USB_HS
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(AUDIO_FREQ);
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(s_speaker_sample_rate);
AUDIO_FEEDBACK_TO_BUF_HS(s_speaker_feedback_buffer, feedback_value);
#else
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_FREQ);
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(s_speaker_sample_rate);
AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
#endif
usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);
@@ -324,6 +325,26 @@ void usbd_audio_close(uint8_t busid, uint8_t intf)
rx_flag = 0;
}
void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq)
{
if (ep == AUDIO_OUT_EP) {
s_speaker_sample_rate = sampling_freq;
}
}
uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep)
{
(void)busid;
uint32_t freq = 0;
if (ep == AUDIO_OUT_EP) {
freq = s_speaker_sample_rate;
}
return freq;
}
void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table)
{
if (ep == AUDIO_OUT_EP) {
@@ -342,10 +363,10 @@ void usbd_audio_iso_out_feedback_callback(uint8_t busid, uint8_t ep, uint32_t nb
{
USB_LOG_RAW("actual feedback len:%d\r\n", (unsigned int)nbytes);
#ifdef CONFIG_USB_HS
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(AUDIO_FREQ);
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_HS(s_speaker_sample_rate);
AUDIO_FEEDBACK_TO_BUF_HS(s_speaker_feedback_buffer, feedback_value);
#else
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(AUDIO_FREQ);
uint32_t feedback_value = AUDIO_FREQ_TO_FEEDBACK_FS(s_speaker_sample_rate);
AUDIO_FEEDBACK_TO_BUF_FS(s_speaker_feedback_buffer, feedback_value);
#endif
usbd_ep_start_write(busid, AUDIO_OUT_FEEDBACK_EP, s_speaker_feedback_buffer, FEEDBACK_ENDP_PACKET_SIZE);

View File

@@ -8,6 +8,10 @@
#include "usbd_cdc_acm.h"
#include "usbd_hid.h"
#if CONFIG_USBDEV_EP_NUM < 7
#error endpoint number is too small for this demo, please try other chips
#endif
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x02

View File

@@ -7,6 +7,10 @@
#include "usbd_cdc_acm.h"
#include "usbd_msc.h"
#if CONFIG_USBDEV_EP_NUM < 6
#error endpoint number is too small for this demo, please try other chips
#endif
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x02

View File

@@ -6,6 +6,10 @@
#include "usbd_core.h"
#include "usbd_cdc_acm.h"
#if CONFIG_USBDEV_EP_NUM < 8
#error endpoint number is too small for this demo, please try other chips
#endif
/*!< endpoint address */
#define CDC_IN_EP 0x81
#define CDC_OUT_EP 0x01

View File

@@ -276,7 +276,8 @@ void cdc_ecm_lwip_init(void)
eth_device_init(&cdc_ecm_dev, "u0");
eth_device_linkchange(&cdc_ecm_dev, RT_FALSE);
eth_device_linkchange(&cdc_ecm_dev, RT_TRUE);
dhcpd_start("u0");
}
void usbd_cdc_ecm_data_recv_done(uint32_t len)
@@ -439,10 +440,6 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
#ifdef RT_USING_LWIP
eth_device_linkchange(&cdc_ecm_dev, RT_TRUE);
dhcpd_start("u0");
#endif
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;

View File

@@ -249,7 +249,8 @@ void rndis_lwip_init(void)
eth_device_init(&rndis_dev, "u0");
eth_device_linkchange(&rndis_dev, RT_FALSE);
eth_device_linkchange(&rndis_dev, RT_TRUE);
dhcpd_start("u0");
}
void usbd_rndis_data_recv_done(uint32_t len)
@@ -412,10 +413,6 @@ static void usbd_event_handler(uint8_t busid, uint8_t event)
case USBD_EVENT_SUSPEND:
break;
case USBD_EVENT_CONFIGURED:
#ifdef RT_USING_LWIP
eth_device_linkchange(&rndis_dev, RT_TRUE);
dhcpd_start("u0");
#endif
break;
case USBD_EVENT_SET_REMOTE_WAKEUP:
break;
@@ -439,7 +436,7 @@ void cdc_rndis_init(uint8_t busid, uintptr_t reg_base)
#else
usbd_desc_register(busid, cdc_rndis_descriptor);
#endif
usbd_add_interface(busid, usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
usbd_add_interface(busid, usbd_rndis_init_intf(&intf1, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, mac));
usbd_add_interface(busid, usbd_rndis_init_intf(&intf0, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, (uint8_t *)mac));
usbd_add_interface(busid, usbd_rndis_init_intf(&intf1, CDC_OUT_EP, CDC_IN_EP, CDC_INT_EP, (uint8_t *)mac));
usbd_initialize(busid, reg_base, usbd_event_handler);
}

250
demo/mtp_template.c Normal file
View File

@@ -0,0 +1,250 @@
/*
* Copyright (c) 2025 sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*
*/
#include "usbd_core.h"
#include "usbd_mtp.h"
#if 1
#error "commercial charge"
#endif
#ifndef CONFIG_USBDEV_MTP_THREAD
#warning mtp depends on filesystem, suggest to enable CONFIG_USBDEV_MTP_THREAD
#endif
#define WCID_VENDOR_CODE 0x01
__ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
///////////////////////////////////////
/// MS OS string descriptor
///////////////////////////////////////
0x12, /* bLength */
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
/* MSFT100 */
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, /* wcChar_7 */
'1', 0x00, '0', 0x00, '0', 0x00, /* wcChar_7 */
WCID_VENDOR_CODE, /* bVendorCode */
0x00, /* bReserved */
};
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
///////////////////////////////////////
/// WCID descriptor
///////////////////////////////////////
0x28, 0x00, 0x00, 0x00, /* dwLength */
0x00, 0x01, /* bcdVersion */
0x04, 0x00, /* wIndex */
0x01, /* bCount */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
///////////////////////////////////////
/// WCID function descriptor
///////////////////////////////////////
0x00, /* bFirstInterfaceNumber */
0x01, /* bReserved */
/* MTP */
'M', 'T', 'P', 0x00, 0x00, 0x00, 0x00, 0x00, /* cCID_8 */
/* */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
};
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
///////////////////////////////////////
/// WCID property descriptor
///////////////////////////////////////
0x8e, 0x00, 0x00, 0x00, /* dwLength */
0x00, 0x01, /* bcdVersion */
0x05, 0x00, /* wIndex */
0x01, 0x00, /* wCount */
///////////////////////////////////////
/// registry propter descriptor
///////////////////////////////////////
0x84, 0x00, 0x00, 0x00, /* dwSize */
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
0x28, 0x00, /* wPropertyNameLength */
/* DeviceInterfaceGUID */
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
/* {1D4B2365-4749-48EA-B38A-7C6FDDDD7E26} */
'{', 0x00, '1', 0x00, 'D', 0x00, '4', 0x00, /* wcData_39 */
'B', 0x00, '2', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
'5', 0x00, '-', 0x00, '4', 0x00, '7', 0x00, /* wcData_39 */
'4', 0x00, '9', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
'8', 0x00, 'E', 0x00, 'A', 0x00, '-', 0x00, /* wcData_39 */
'B', 0x00, '3', 0x00, '8', 0x00, 'A', 0x00, /* wcData_39 */
'-', 0x00, '7', 0x00, 'C', 0x00, '6', 0x00, /* wcData_39 */
'F', 0x00, 'D', 0x00, 'D', 0x00, 'D', 0x00, /* wcData_39 */
'D', 0x00, '7', 0x00, 'E', 0x00, '2', 0x00, /* wcData_39 */
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
};
const uint8_t bos_descriptor[] = {
0x05, 0x0f, 0x16, 0x00, 0x02,
0x07, 0x10, 0x02, 0x06, 0x00, 0x00, 0x00,
0x0a, 0x10, 0x03, 0x00, 0x0f, 0x00, 0x01, 0x01, 0xf4, 0x01
};
/*!< endpoint address */
#define MTP_IN_EP 0x81
#define MTP_OUT_EP 0x02
#define MTP_INT_EP 0x83
/*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + MTP_DESCRIPTOR_LEN)
static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0201, 0x01)
};
static const uint8_t config_descriptor_hs[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
MTP_DESCRIPTOR_INIT(0x00, MTP_OUT_EP, MTP_IN_EP, MTP_INT_EP, USB_BULK_EP_MPS_HS, 0x02),
};
static const uint8_t config_descriptor_fs[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
MTP_DESCRIPTOR_INIT(0x00, MTP_OUT_EP, MTP_IN_EP, MTP_INT_EP, USB_BULK_EP_MPS_FS, 0x02),
};
static const uint8_t device_quality_descriptor[] = {
USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, 0x01),
};
static const uint8_t other_speed_config_descriptor_hs[] = {
USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
MTP_DESCRIPTOR_INIT(0x00, MTP_OUT_EP, MTP_IN_EP, MTP_INT_EP, USB_BULK_EP_MPS_FS, 0x02),
};
static const uint8_t other_speed_config_descriptor_fs[] = {
USB_OTHER_SPEED_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
MTP_DESCRIPTOR_INIT(0x00, MTP_OUT_EP, MTP_IN_EP, MTP_INT_EP, USB_BULK_EP_MPS_HS, 0x02),
};
static const char *string_descriptors[] = {
(const char[]){ 0x09, 0x04 }, /* Langid */
"CherryUSB", /* Manufacturer */
"CherryUSB MTP DEMO", /* Product */
"2025053000", /* Serial Number */
};
static const uint8_t *device_descriptor_callback(uint8_t speed)
{
(void)speed;
return device_descriptor;
}
static const uint8_t *config_descriptor_callback(uint8_t speed)
{
if (speed == USB_SPEED_HIGH) {
return config_descriptor_hs;
} else if (speed == USB_SPEED_FULL) {
return config_descriptor_fs;
} else {
return NULL;
}
}
static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
{
(void)speed;
return device_quality_descriptor;
}
static const uint8_t *other_speed_config_descriptor_callback(uint8_t speed)
{
if (speed == USB_SPEED_HIGH) {
return other_speed_config_descriptor_hs;
} else if (speed == USB_SPEED_FULL) {
return other_speed_config_descriptor_fs;
} else {
return NULL;
}
}
static const char *string_descriptor_callback(uint8_t speed, uint8_t index)
{
(void)speed;
if (index >= (sizeof(string_descriptors) / sizeof(char *))) {
return NULL;
}
return string_descriptors[index];
}
const uint8_t *WINUSB_IFx_WCIDProperties[] = {
WINUSB_IF0_WCIDProperties,
};
struct usb_msosv1_descriptor msosv1_desc = {
.string = WCID_StringDescriptor_MSOS,
.vendor_code = WCID_VENDOR_CODE,
.compat_id = WINUSB_WCIDDescriptor,
.comp_id_property = WINUSB_IFx_WCIDProperties,
};
const struct usb_bos_descriptor bos_desc = {
.string = bos_descriptor,
.string_len = 22
};
const struct usb_descriptor mtp_descriptor = {
.device_descriptor_callback = device_descriptor_callback,
.config_descriptor_callback = config_descriptor_callback,
.device_quality_descriptor_callback = device_quality_descriptor_callback,
.other_speed_descriptor_callback = other_speed_config_descriptor_callback,
.string_descriptor_callback = string_descriptor_callback,
.bos_descriptor = &bos_desc,
.msosv1_descriptor = &msosv1_desc,
};
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;
}
}
static struct usbd_interface intf0;
extern void usbd_mtp_mount();
void mtp_init(uint8_t busid, uint32_t reg_base)
{
usbd_mtp_mount();
usbd_desc_register(busid, &mtp_descriptor);
usbd_add_interface(busid, usbd_mtp_init_intf(&intf0, MTP_OUT_EP, MTP_IN_EP, MTP_INT_EP));
usbd_initialize(busid, reg_base, usbd_event_handler);
}

View File

@@ -7,8 +7,6 @@
#include "usbd_video.h"
#include "cherryusb_h264.h"
#define MAX_PACKETS_IN_ONE_TRANSFER 1
#define VIDEO_IN_EP 0x81
#define VIDEO_INT_EP 0x83
@@ -282,7 +280,8 @@ void video_init(uint8_t busid, uintptr_t reg_base)
usbd_initialize(busid, reg_base, usbd_event_handler);
}
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][40 * 1024];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[MAX_PAYLOAD_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t frame_buffer[32 * 1024];
void video_test(uint8_t busid)
{
@@ -294,7 +293,8 @@ void video_test(uint8_t busid)
while (1) {
if (tx_flag) {
iso_tx_busy = true;
usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_h264, sizeof(cherryusb_h264));
memcpy(frame_buffer, cherryusb_h264, sizeof(cherryusb_h264)); // cherryusb_h264 is a static yuyv frame buffer, so we need copy it to frame_buffer
usbd_video_stream_start_write(busid, VIDEO_IN_EP, packet_buffer, (uint8_t *)frame_buffer, sizeof(cherryusb_h264), false);
while (iso_tx_busy) {
if (tx_flag == 0) {
break;

View File

@@ -7,8 +7,6 @@
#include "usbd_video.h"
#include "cherryusb_mjpeg.h"
#define MAX_PACKETS_IN_ONE_TRANSFER 1
#define VIDEO_IN_EP 0x81
#define VIDEO_INT_EP 0x83
@@ -282,7 +280,8 @@ void video_init(uint8_t busid, uintptr_t reg_base)
usbd_initialize(busid, reg_base, usbd_event_handler);
}
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[MAX_PAYLOAD_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t frame_buffer[32 * 1024];
void video_test(uint8_t busid)
{
@@ -291,7 +290,8 @@ void video_test(uint8_t busid)
while (1) {
if (tx_flag) {
iso_tx_busy = true;
usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg));
memcpy(frame_buffer, cherryusb_mjpeg, sizeof(cherryusb_mjpeg)); // cherryusb_mjpeg is a static MJPEG frame buffer, so we need copy it to frame_buffer
usbd_video_stream_start_write(busid, VIDEO_IN_EP, packet_buffer, (uint8_t *)frame_buffer, sizeof(cherryusb_mjpeg), false);
while (iso_tx_busy) {
if (tx_flag == 0) {
break;

View File

@@ -7,8 +7,6 @@
#include "usbd_video.h"
#include "cherryusb_yuyv.h"
#define MAX_PACKETS_IN_ONE_TRANSFER 1
#define VIDEO_IN_EP 0x81
#define VIDEO_INT_EP 0x83
@@ -286,7 +284,8 @@ void video_init(uint8_t busid, uintptr_t reg_base)
usbd_initialize(busid, reg_base, usbd_event_handler);
}
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[MAX_PAYLOAD_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t frame_buffer[32 * 1024];
void video_test(uint8_t busid)
{
@@ -295,7 +294,8 @@ void video_test(uint8_t busid)
while (1) {
if (tx_flag) {
iso_tx_busy = true;
usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_yuyv, sizeof(cherryusb_yuyv));
memcpy(frame_buffer, cherryusb_yuyv, sizeof(cherryusb_yuyv)); // cherryusb_yuyv is a static yuyv frame buffer, so we need copy it to frame_buffer
usbd_video_stream_start_write(busid, VIDEO_IN_EP, packet_buffer, (uint8_t *)frame_buffer, sizeof(cherryusb_yuyv), false);
while (iso_tx_busy) {
if (tx_flag == 0) {
break;

View File

@@ -6,6 +6,10 @@
#include "usbd_core.h"
#include "usbd_cdc_acm.h"
#if CONFIG_USBDEV_EP_NUM < 6
#error endpoint number is too small for this demo, please try other chips
#endif
#define WINUSB_IN_EP 0x81
#define WINUSB_OUT_EP 0x02

View File

@@ -6,6 +6,10 @@
#include "usbd_core.h"
#include "usbd_hid.h"
#if CONFIG_USBDEV_EP_NUM < 4
#error endpoint number is too small for this demo, please try other chips
#endif
#define WINUSB_IN_EP 0x81
#define WINUSB_OUT_EP 0x02

View File

@@ -45,13 +45,11 @@ demo 包含 **video_static_yuyv_template**, **video_static_mjpeg_template**, **v
USB_ENDPOINT_DESCRIPTOR_INIT(VIDEO_IN_EP, 0x05, VIDEO_PACKET_SIZE, 0x01),
- 使用 `usbd_video_stream_start_write` 传输数据
- 使用 `usbd_video_stream_start_write` 传输数据, 最后 **do_copy** 选项表示是否将数据 copy 到 packet_buffer,
如果不选择 copy 则会直接在原图像数据中填充头部信息,并直接发送,达到 zero copy 功能。
1传输采用双缓冲的形式 **MAX_PACKETS_IN_ONE_TRANSFER** 表示一次传输可以携带多少个 **MAX_PAYLOAD_SIZE**,通常 IP 只能为 1
- 因为提供的是静态数据,不能被修改,因此需要重新给一个 frame_buffer 用于图像传输,在实际对接 camera 场景中是动态数据,直接使用 camera 的数据缓冲区即可
2在中断完成中调用 `usbd_video_stream_split_transfer` 继续下一次传输,直到返回为 true 表示传输完成。这边的分裂传输只是表示将图片数据拆成 **MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE** 份传输。
3通常 IP 不支持一次传输非常大的数据,比如传输 1MB因此需要做分裂传输但是会增加中断次数。并且一次传输非常大数据也是需要足够的 RAM。
.. code-block:: C
@@ -63,7 +61,8 @@ demo 包含 **video_static_yuyv_template**, **video_static_mjpeg_template**, **v
}
}
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[MAX_PAYLOAD_SIZE];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t frame_buffer[32 * 1024];
void video_test(uint8_t busid)
{
@@ -72,7 +71,8 @@ demo 包含 **video_static_yuyv_template**, **video_static_mjpeg_template**, **v
while (1) {
if (tx_flag) {
iso_tx_busy = true;
usbd_video_stream_start_write(busid, VIDEO_IN_EP, &packet_buffer[0][0], &packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg));
memcpy(frame_buffer, cherryusb_mjpeg, sizeof(cherryusb_mjpeg)); // cherryusb_mjpeg is a static MJPEG frame buffer, so we need copy it to frame_buffer
usbd_video_stream_start_write(busid, VIDEO_IN_EP, packet_buffer, (uint8_t *)frame_buffer, sizeof(cherryusb_mjpeg), false);
while (iso_tx_busy) {
if (tx_flag == 0) {
break;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 842 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

View File

@@ -49,6 +49,14 @@ USB Device RNDIS
.. figure:: img/usbdev_rndis_win.png
.. figure:: img/usbdev_rndis_linux.png
USB Device UVC
-----------------------
演示 USB Device UVC + 摄像头传输 YUYV/MJPEG 640 * 480 图像。FPS 30。
.. figure:: img/usbdev_uvc_mjpeg.png
.. figure:: img/usbdev_uvc_yuv.png
USB Host HUB
-----------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

View File

@@ -20,7 +20,10 @@
- 主机 UVC & UAC 类 MUSB IP 中 ISO 驱动和 UAC/UVC 框架, MUSB 需要为 mentor 公司制定的标准 IP
- 从机 MTP 类驱动
- 从机 MTP 类驱动, 支持多文件和多文件夹
.. figure:: img/mtpdev.png
- USB 网卡类高性能版本优化,包含 CDC-NCM, CDC-RNDIS, 私有类驱动(支持多包发送和接收),下面举例 RNDIS
.. figure:: img/rndistx.png

View File

@@ -97,7 +97,7 @@ v1.4.3
- **host msc 将 scsi 初始化从枚举线程中移出在mount阶段调用并增加了testunity 多次尝试,兼容一部分 U 盘**
- rp2040 主从支持
- **nuttx fsserialnet 组件支持**
- dwc2、ehci、ohci 主机 dcache功能支持
- dwc2、ehci、ohci 主机 dcache功能支持v1.5.0 完善)
- t113、MCXA156、CH585 、 **stm32h7r 支持**
- 修复 v1.4.1 中 altsetting 为0时应该关闭所有端点的问题
@@ -105,17 +105,22 @@ v1.5.0
----------------------
- **协议栈内部全局 buffer 需要使用 USB_ALIGN_UP 对齐, 用于开启 dcache 并且不使能 nocache 时使用**
- **平台代码更新,平台相关转移到 platform增加 lvgl 键鼠支持blackmagic 支持, filex 支持**
- liteos-m, zephyr os 支持
- device msc 裸机读写采用变量模式而不是ringbuffer
- **完善 ehci/ohci dcache 模式下的处理** add CONFIG_USB_EHCI_DESC_DCACHE_ENABLE for qh&qtd&itd, add CONFIG_USB_OHCI_DESC_DCACHE_ENABLE for ed&td
- ehci qtd 使用 qtd alloc & free节省内存目前是 qh 携带 qtd
- **平台代码更新,平台相关转移到 platform增加 lvgl 键鼠支持blackmagic 支持filex 支持**
- **device sof callback 支持**
- **dwc2 、fsdev st 下实现底层 API 和中断,直接调用 HAL_PCD_MSP 和 HAL_HCD_MSP不需要用户复制粘贴**
- **DWC2 实现 SPLIT 功能,高速模式下支持外部高速 hub 对接 FS/LS 设备**
- liteos-m, zephyr os 支持
- device msc 裸机读写采用变量模式而不是ringbuffer
- ehci qtd 使用 qtd alloc & free节省内存目前是 qh 携带 qtd
- rndis/ECM device msc demo 更新,支持 rt-thread 下免修改
- **memcpy 全部使用 usb_memcpy 替换arm 库存在非对其访问问题**
- **重构 device mtp 驱动(收费使用)**
- **重构device video 传输,直接在图像数据中填充 uvc header达到zero memcpy**
- **增加 usb_osal_thread_schedule_other api用于在释放 class 资源之前,先释放所有 class 线程,避免释放 class 资源以后线程还在使用该 class 资源**
- **dwc2 device 增加 dcache 功能,可用于 STM32H7/H7R/ESP32P4**
- **bouffalo/hpm/esp/st/nxp dcache api 支持**
- ch32 device iso 更新
- cmakekconfig 更新
- cmakesconskconfig 更新
- 使用 USB_ASSERT_MSG 对部分代码检查
- N32H4mm32f5 支持

View File

@@ -8,6 +8,7 @@
#include "sdkconfig.h"
#include "esp_rom_sys.h"
#include "esp_attr.h"
/* ================ USB common Configuration ================ */
@@ -25,8 +26,15 @@
#define CONFIG_USB_ALIGN_SIZE 4
#endif
// #define CONFIG_USB_DCACHE_ENABLE
/* attribute data into no cache ram */
#define USB_NOCACHE_RAM_SECTION
#define USB_NOCACHE_RAM_SECTION DRAM_DMA_ALIGNED_ATTR
/* use usb_memcpy default for high performance but cost more flash memory.
* And, arm libc has a bug that memcpy() may cause data misalignment when the size is not a multiple of 4.
*/
// #define CONFIG_USB_MEMCPY_DISABLE
/* ================= USB Device Stack Configuration ================ */
@@ -49,6 +57,9 @@
/* Enable test mode */
// #define CONFIG_USBDEV_TEST_MODE
/* enable advance desc register api */
#define CONFIG_USBDEV_ADVANCE_DESC
/* move ep0 setup handler from isr to thread */
// #define CONFIG_USBDEV_EP0_THREAD
@@ -84,7 +95,7 @@
// #define CONFIG_USBDEV_MSC_POLLING
/* move msc read & write from isr to thread */
// #define CONFIG_USBDEV_MSC_THREAD
#define CONFIG_USBDEV_MSC_THREAD
#ifndef CONFIG_USBDEV_MSC_PRIO
#define CONFIG_USBDEV_MSC_PRIO 4
@@ -94,6 +105,28 @@
#define CONFIG_USBDEV_MSC_STACKSIZE 2048
#endif
#ifndef CONFIG_USBDEV_MTP_MAX_BUFSIZE
#define CONFIG_USBDEV_MTP_MAX_BUFSIZE 2048
#endif
#ifndef CONFIG_USBDEV_MTP_MAX_OBJECTS
#define CONFIG_USBDEV_MTP_MAX_OBJECTS 256
#endif
#ifndef CONFIG_USBDEV_MTP_MAX_PATHNAME
#define CONFIG_USBDEV_MTP_MAX_PATHNAME 256
#endif
#define CONFIG_USBDEV_MTP_THREAD
#ifndef CONFIG_USBDEV_MTP_PRIO
#define CONFIG_USBDEV_MTP_PRIO 4
#endif
#ifndef CONFIG_USBDEV_MTP_STACKSIZE
#define CONFIG_USBDEV_MTP_STACKSIZE 4096
#endif
#ifndef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
#endif
@@ -112,6 +145,7 @@
#endif
#define CONFIG_USBDEV_RNDIS_USING_LWIP
#define CONFIG_USBDEV_CDC_ECM_USING_LWIP
/* ================ USB HOST Stack Configuration ================== */
@@ -137,7 +171,7 @@
#define CONFIG_USBHOST_PSC_STACKSIZE 2048
#endif
// #define CONFIG_USBHOST_GET_STRING_DESC
//#define CONFIG_USBHOST_GET_STRING_DESC
// #define CONFIG_USBHOST_MSOS_ENABLE
#ifndef CONFIG_USBHOST_MSOS_VENDOR_CODE
@@ -236,11 +270,27 @@
#define CONFIG_USB_DWC2_DMA_ENABLE
#elif CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32P4
#elif CONFIG_IDF_TARGET_ESP32P4
#define ESP_USBD_BASE 0x50000000UL
#define CONFIG_USBDEV_MAX_BUS 1
#define CONFIG_USBDEV_EP_NUM 7 // 16
/* ---------------- DWC2 Configuration ---------------- */
//esp32s2/s3 can support up to 5 IN endpoints(include ep0) at the same time
#define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1024 / 4)
#define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX1_FIFO_SIZE (512 / 4)
#define CONFIG_USB_DWC2_TX2_FIFO_SIZE (512 / 4)
#define CONFIG_USB_DWC2_TX3_FIFO_SIZE (512 / 4)
#define CONFIG_USB_DWC2_TX4_FIFO_SIZE (512 / 4)
#define CONFIG_USB_DWC2_TX5_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX6_FIFO_SIZE (64 / 4)
#define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4)
#define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
#define CONFIG_USB_DWC2_DMA_ENABLE
#define CONFIG_USB_HS
#define ESP_USBD_BASE 0x60080000
// todo: check c5, p4 in later
#define CONFIG_USBDEV_EP_NUM 7
#else
#error "Unsupported SoC"
#endif
@@ -265,12 +315,32 @@
*/
#define CONFIG_USB_DWC2_RX_FIFO_SIZE ((200 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE))
#elif CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32P4
// todo: check c5, p4 in later
#define ESP_USBH_BASE 0x60080000
#define CONFIG_USBHOST_PIPE_NUM 8
#elif CONFIG_IDF_TARGET_ESP32P4
#define ESP_USBH_BASE 0x50000000UL
#define CONFIG_USBHOST_MAX_BUS 1
#define CONFIG_USBHOST_PIPE_NUM 16
/* ---------------- DWC2 Configuration ---------------- */
/* largest non-periodic USB packet used / 4 */
#define CONFIG_USB_DWC2_NPTX_FIFO_SIZE (512 / 4)
/* largest periodic USB packet used / 4 */
#define CONFIG_USB_DWC2_PTX_FIFO_SIZE (512 / 4)
/*
* (largest USB packet used / 4) + 1 for status information + 1 transfer complete +
* 1 location each for Bulk/Control endpoint for handling NAK/NYET scenario
*/
#define CONFIG_USB_DWC2_RX_FIFO_SIZE ((896 - CONFIG_USB_DWC2_NPTX_FIFO_SIZE - CONFIG_USB_DWC2_PTX_FIFO_SIZE))
#define CONFIG_USB_HS
#else
#error "Unsupported SoC"
#endif
#define CONFIG_USBDEV_ADVANCE_DESC
#if CONFIG_IDF_TARGET_ESP32P4
#define CONFIG_USB_DCACHE_ENABLE
#undef CONFIG_USB_ALIGN_SIZE
#define CONFIG_USB_ALIGN_SIZE CONFIG_CACHE_L1_CACHE_LINE_SIZE
#endif

View File

@@ -25,6 +25,18 @@ void usb_osal_thread_delete(usb_osal_thread_t thread)
vTaskDelete(thread);
}
void usb_osal_thread_schedule_other(void)
{
TaskHandle_t xCurrentTask = xTaskGetCurrentTaskHandle();
const UBaseType_t old_priority = uxTaskPriorityGet(xCurrentTask);
vTaskPrioritySet(xCurrentTask, tskIDLE_PRIORITY);
taskYIELD();
vTaskPrioritySet(xCurrentTask, old_priority);
}
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
{
return (usb_osal_sem_t)xSemaphoreCreateCounting(1, initial_count);

View File

@@ -30,6 +30,18 @@ void usb_osal_thread_delete(usb_osal_thread_t thread)
vTaskDelete(thread);
}
void usb_osal_thread_schedule_other(void)
{
TaskHandle_t xCurrentTask = xTaskGetCurrentTaskHandle();
const UBaseType_t old_priority = uxTaskPriorityGet(xCurrentTask);
vTaskPrioritySet(xCurrentTask, tskIDLE_PRIORITY);
taskYIELD();
vTaskPrioritySet(xCurrentTask, old_priority);
}
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
{
usb_osal_sem_t sem = (usb_osal_sem_t)xSemaphoreCreateCounting(1, initial_count);

View File

@@ -15,33 +15,19 @@
#include "los_memory.h"
#include "los_swtmr.h"
typedef struct _usb_osal_thread {
UINT32 task_id;
char name[128];
} _usb_osal_thread_t;
usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args)
{
_usb_osal_thread_t *t;
UINT32 task_id;
UINT32 ret;
TSK_INIT_PARAM_S task_init_param = {
.usTaskPrio = prio,
.pfnTaskEntry = (TSK_ENTRY_FUNC)entry,
.uwStackSize = stack_size,
.uwArg = (UINT32)args,
.pcName = name
};
t = usb_osal_malloc(sizeof(_usb_osal_thread_t));
if (t == NULL) {
USB_LOG_ERR("alloc thread %s failed\r\n", name);
while (1) {
}
}
strncpy(t->name, name, sizeof(t->name));
task_init_param.pcName = t->name;
ret = LOS_TaskCreate(&task_id, &task_init_param);
if (ret != LOS_OK) {
USB_LOG_ERR("Create task[%s] failed code[%u]\r\n", name, ret);
@@ -49,25 +35,36 @@ usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size,
}
}
t->task_id = task_id;
return (usb_osal_thread_t)t;
return (usb_osal_thread_t)task_id;
}
void usb_osal_thread_delete(usb_osal_thread_t thread)
{
_usb_osal_thread_t *t = (_usb_osal_thread_t *)thread;
UINT32 task_id = t->task_id;
UINT32 task_id = (UINT32)thread;
UINT32 ret;
if (thread == NULL) {
task_id = LOS_CurTaskIDGet();
}
ret = LOS_TaskDelete(task_id);
if (ret != LOS_OK) {
USB_LOG_ERR("Delete task id[%u] failed code[%u]\r\n", task_id, ret);
while (1) {
}
}
}
usb_osal_free(t);
void usb_osal_thread_schedule_other(void)
{
UINT32 task_id = LOS_CurTaskIDGet();
const UINT16 old_priority = LOS_TaskPriGet(task_id);
LOS_TaskPriSet(task_id, OS_TASK_PRIORITY_LOWEST);
LOS_TaskYield();
LOS_TaskPriSet(task_id, old_priority);
}
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
@@ -91,7 +88,7 @@ void usb_osal_sem_delete(usb_osal_sem_t sem)
ret = LOS_SemDelete(sem_handle);
if (ret != LOS_OK) {
USB_LOG_ERR("Delete sem handle[%u] failed code[%u]\r\n",\
USB_LOG_ERR("Delete sem handle[%u] failed code[%u]\r\n",
sem_handle, ret);
while (1) {
}
@@ -103,9 +100,10 @@ int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
UINT32 sem_handle = (UINT32)sem;
UINT32 ret;
ret = LOS_SemPend(sem_handle, \
timeout == USB_OSAL_WAITING_FOREVER ? \
LOS_WAIT_FOREVER : timeout);
ret = LOS_SemPend(sem_handle,
timeout == USB_OSAL_WAITING_FOREVER ?
LOS_WAIT_FOREVER :
timeout);
return ret == LOS_OK ? 0 : -USB_ERR_TIMEOUT;
}
@@ -122,7 +120,6 @@ int usb_osal_sem_give(usb_osal_sem_t sem)
void usb_osal_sem_reset(usb_osal_sem_t sem)
{
}
usb_osal_mutex_t usb_osal_mutex_create(void)
@@ -146,8 +143,8 @@ void usb_osal_mutex_delete(usb_osal_mutex_t mutex)
ret = LOS_MuxDelete(mux_handle);
if (ret != LOS_OK) {
USB_LOG_ERR("Delete mux handle[%u] failed code[%u]\r\n",\
mux_handle, ret);
USB_LOG_ERR("Delete mux handle[%u] failed code[%u]\r\n",
mux_handle, ret);
while (1) {
}
}
@@ -194,7 +191,7 @@ void usb_osal_mq_delete(usb_osal_mq_t mq)
ret = LOS_QueueDelete(queue_id);
if (ret != LOS_OK) {
USB_LOG_ERR("Delete queue id[%u] failed code[%u]\r\n",\
USB_LOG_ERR("Delete queue id[%u] failed code[%u]\r\n",
queue_id, ret);
while (1) {
}
@@ -247,12 +244,13 @@ struct usb_osal_timer *usb_osal_timer_create(const char *name, uint32_t timeout_
memset(timer_handle, 0x00, sizeof(struct usb_osal_timer));
ret = LOS_SwtmrCreate(timeout_ms,
is_period ? LOS_SWTMR_MODE_PERIOD : LOS_SWTMR_MODE_NO_SELFDELETE,
(SWTMR_PROC_FUNC)handler, &timer_id, (UINT32)argument
is_period ? LOS_SWTMR_MODE_PERIOD : LOS_SWTMR_MODE_NO_SELFDELETE,
(SWTMR_PROC_FUNC)handler, &timer_id, (UINT32)argument
#if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
,OS_SWTMR_ROUSES_IGNORE, OS_SWTMR_ALIGN_INSENSITIVE
,
OS_SWTMR_ROUSES_IGNORE, OS_SWTMR_ALIGN_INSENSITIVE
#endif
);
);
if (ret != LOS_OK) {
USB_LOG_ERR("Create software timer failed code[%u]\r\n", ret);
@@ -276,7 +274,7 @@ void usb_osal_timer_delete(struct usb_osal_timer *timer)
ret = LOS_SwtmrDelete(timer_id);
if (ret != LOS_OK) {
USB_LOG_ERR("Delete software timer id[%u] failed code[%u]\r\n",\
USB_LOG_ERR("Delete software timer id[%u] failed code[%u]\r\n",
timer_id, ret);
while (1) {
}
@@ -291,7 +289,7 @@ void usb_osal_timer_start(struct usb_osal_timer *timer)
ret = LOS_SwtmrStart(timer_id);
if (ret != LOS_OK) {
USB_LOG_ERR("Start software timer id[%u] failed code[%u]\r\n",\
USB_LOG_ERR("Start software timer id[%u] failed code[%u]\r\n",
timer_id, ret);
while (1) {
}
@@ -305,7 +303,7 @@ void usb_osal_timer_stop(struct usb_osal_timer *timer)
ret = LOS_SwtmrStop(timer_id);
if (ret != LOS_OK) {
USB_LOG_ERR("Stop software timer id[%u] failed code[%u]\r\n",\
USB_LOG_ERR("Stop software timer id[%u] failed code[%u]\r\n",
timer_id, ret);
while (1) {
}

View File

@@ -63,6 +63,18 @@ void usb_osal_thread_delete(usb_osal_thread_t thread)
kthread_delete(pid);
}
void usb_osal_thread_schedule_other(void)
{
struct tcb_s *tcb = nxsched_self();
const int old_priority = tcb->sched_priority;
nxsched_set_priority(tcb, SCHED_PRIORITY_MIN);
sched_yield();
nxsched_set_priority(tcb, old_priority);
}
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
{
int ret;

View File

@@ -34,6 +34,23 @@ void usb_osal_thread_delete(usb_osal_thread_t thread)
rt_thread_delete(thread);
}
void usb_osal_thread_schedule_other(void)
{
rt_thread_t self = rt_thread_self();
rt_uint8_t priority;
#if (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 2, 0))
const rt_uint8_t old_priority = RT_SCHED_PRIV(self).current_priority;
#else
const rt_uint8_t old_priority = self->current_priority;
#endif
priority = RT_THREAD_PRIORITY_MAX - 1;
rt_thread_control(self, RT_THREAD_CTRL_CHANGE_PRIORITY, (void *)&priority);
rt_thread_yield();
rt_thread_control(self, RT_THREAD_CTRL_CHANGE_PRIORITY, (void *)&old_priority);
}
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
{
usb_osal_sem_t sem = (usb_osal_sem_t)rt_sem_create("usbh_sem", initial_count, RT_IPC_FLAG_FIFO);

View File

@@ -69,6 +69,18 @@ void usb_osal_thread_delete(usb_osal_thread_t thread)
tx_byte_release(thread);
}
void usb_osal_thread_schedule_other(void)
{
TX_THREAD *current_thread = tx_thread_identify();
const UINT old_priority = current_thread->tx_thread_priority;
tx_thread_priority_change(current_thread, TX_MAX_PRIORITIES - 1, &old_priority);
tx_thread_relinquish();
tx_thread_priority_change(current_thread, old_priority, &old_priority);
}
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
{
TX_SEMAPHORE *sem_ptr = TX_NULL;

View File

@@ -74,6 +74,22 @@ void usb_osal_thread_delete(usb_osal_thread_t thread)
k_free(thread);
}
void usb_osal_thread_schedule_other(void)
{
#if (KERNELVERSION >= 0x3070000)
struct k_thread *current_thread = k_sched_current_thread_query();
#else
struct k_thread *current_thread = z_current_get();
#endif
const int old_priority = k_thread_priority_get(current_thread);
k_thread_priority_set(current_thread, K_LOWEST_APPLICATION_THREAD_PRIO);
k_yield();
k_thread_priority_set(current_thread, old_priority);
}
usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
{
struct k_sem *sem;

View File

@@ -5,7 +5,8 @@ This is a platform support for other opensource projects.
## Fatfs
Fatfs support with usb host msc.
- Fatfs support with usb host msc.
- Fatfs support with usb device mtp.
## lwip
@@ -34,6 +35,7 @@ lwip support with usb host net class(cdc_ecm/cdc_ncm/cdc_rndis/asix/rtl8152/bl61
## Zephyr
- shell support with lsusb
- disk support with usb host msc
## LVGL

View File

@@ -0,0 +1,351 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "ff.h"
#include "diskio.h"
#include "usbd_core.h"
#include "usb_osal.h"
#include "usbd_mtp.h"
FATFS s_sd_disk;
FIL s_file;
BYTE work[FF_MAX_SS];
const TCHAR driver_num_buf[4] = { '0', ':', '/', '\0' };
const char *show_error_string(FRESULT fresult);
static FRESULT sd_mount_fs(void)
{
FRESULT fresult = f_mount(&s_sd_disk, driver_num_buf, 1);
if (fresult == FR_OK) {
printf("SD card has been mounted successfully\n");
} else {
printf("Failed to mount SD card, cause: %s\n", show_error_string(fresult));
}
return fresult;
}
#if 0
static FRESULT sd_mkfs(void)
{
printf("Formatting the SD card, depending on the SD card capacity, the formatting process may take a long time\n");
FRESULT fresult = f_mkfs(driver_num_buf, NULL, work, sizeof(work));
if (fresult != FR_OK) {
printf("Making File system failed, cause: %s\n", show_error_string(fresult));
} else {
printf("Making file system is successful\n");
}
return fresult;
}
#endif
static FRESULT sd_write_file(void)
{
FRESULT fresult = f_open(&s_file, "0:/readme.txt", FA_WRITE | FA_CREATE_ALWAYS);
if (fresult != FR_OK) {
printf("Create new file failed, cause: %d\n", show_error_string(fresult));
} else {
printf("Create new file successfully, status=%d\n", fresult);
}
char hello_str[] = "Hello, this is SD card FATFS demo\n";
UINT byte_written;
fresult = f_write(&s_file, hello_str, sizeof(hello_str), &byte_written);
if (fresult != FR_OK) {
printf("Write file failed, cause: %s\n", show_error_string(fresult));
} else {
printf("Write file operation is successfully\n");
}
f_close(&s_file);
return fresult;
}
const char *show_error_string(FRESULT fresult)
{
const char *result_str;
switch (fresult) {
case FR_OK:
result_str = "succeeded";
break;
case FR_DISK_ERR:
result_str = "A hard error occurred in the low level disk I/O level";
break;
case FR_INT_ERR:
result_str = "Assertion failed";
break;
case FR_NOT_READY:
result_str = "The physical drive cannot work";
break;
case FR_NO_FILE:
result_str = "Could not find the file";
break;
case FR_NO_PATH:
result_str = "Could not find the path";
break;
case FR_INVALID_NAME:
result_str = "Tha path name format is invalid";
break;
case FR_DENIED:
result_str = "Access denied due to prohibited access or directory full";
break;
case FR_EXIST:
result_str = "Access denied due to prohibited access";
break;
case FR_INVALID_OBJECT:
result_str = "The file/directory object is invalid";
break;
case FR_WRITE_PROTECTED:
result_str = "The physical drive is write protected";
break;
case FR_INVALID_DRIVE:
result_str = "The logical driver number is invalid";
break;
case FR_NOT_ENABLED:
result_str = "The volume has no work area";
break;
case FR_NO_FILESYSTEM:
result_str = "There is no valid FAT volume";
break;
case FR_MKFS_ABORTED:
result_str = "THe f_mkfs() aborted due to any problem";
break;
case FR_TIMEOUT:
result_str = "Could not get a grant to access the volume within defined period";
break;
case FR_LOCKED:
result_str = "The operation is rejected according to the file sharing policy";
break;
case FR_NOT_ENOUGH_CORE:
result_str = "LFN working buffer could not be allocated";
break;
case FR_TOO_MANY_OPEN_FILES:
result_str = "Number of open files > FF_FS_LOCK";
break;
case FR_INVALID_PARAMETER:
result_str = "Given parameter is invalid";
break;
default:
result_str = "Unknown error";
break;
}
return result_str;
}
const char *usbd_mtp_fs_root_path(void)
{
return driver_num_buf;
}
const char *usbd_mtp_fs_description(void)
{
return "CherryUSB MTP";
}
int usbd_mtp_mkdir(const char *path)
{
FRESULT result = f_mkdir(path);
if (result != FR_OK) {
printf("f_mkdir failed, cause: %s\n", show_error_string(result));
return -1;
}
return 0; // Directory created successfully
}
int usbd_mtp_rmdir(const char *path)
{
FRESULT result = f_rmdir(path);
if (result != FR_OK) {
printf("f_mkdir failed, cause: %s\n", show_error_string(result));
return -1;
}
return 0; // Directory created successfully
}
MTP_DIR *usbd_mtp_opendir(const char *name)
{
FRESULT result;
DIR *dir;
dir = usb_osal_malloc(sizeof(DIR));
result = f_opendir(dir, name);
if (result != FR_OK) {
printf("f_opendir failed, cause: %s\n", show_error_string(result));
usb_osal_free(dir);
return NULL; // Failed to open directory
}
return (MTP_DIR *)dir;
}
int usbd_mtp_closedir(MTP_DIR *dir)
{
FRESULT result;
result = f_closedir((DIR *)dir);
if (result != FR_OK) {
printf("f_closedir failed, cause: %s\n", show_error_string(result));
return -1; // Failed to close directory
}
usb_osal_free(dir); // Free the directory structure
return result;
}
struct mtp_dirent *usbd_mtp_readdir(MTP_DIR *dir)
{
FILINFO fno;
FRESULT result;
result = f_readdir((DIR *)dir, &fno);
if (result != FR_OK || fno.fname[0] == 0)
return NULL;
static struct mtp_dirent dirent;
memset(&dirent, 0, sizeof(struct mtp_dirent));
strncpy(dirent.d_name, fno.fname, sizeof(dirent.d_name) - 1);
dirent.d_name[sizeof(dirent.d_name) - 1] = '\0';
dirent.d_namlen = strlen(dirent.d_name);
return &dirent;
}
#undef SS
#if FF_MAX_SS == FF_MIN_SS
#define SS(fs) ((UINT)FF_MAX_SS) /* Fixed sector size */
#else
#define SS(fs) ((fs)->ssize) /* Variable sector size */
#endif
int usbd_mtp_stat(const char *path, struct stat *buf)
{
FILINFO file_info;
FRESULT result;
FATFS *f;
f = &s_sd_disk;
result = f_stat(path, &file_info);
if (result != FR_OK) {
printf("f_stat failed, cause: %s\n", show_error_string(result));
return -1;
}
buf->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
S_IWUSR | S_IWGRP | S_IWOTH;
if (file_info.fattrib & AM_DIR) {
buf->st_mode &= ~S_IFREG;
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
}
if (file_info.fattrib & AM_RDO)
buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
buf->st_size = file_info.fsize;
buf->st_blksize = f->csize * SS(f);
if (file_info.fattrib & AM_ARC) {
buf->st_blocks = file_info.fsize ? ((file_info.fsize - 1) / SS(f) / f->csize + 1) : 0;
buf->st_blocks *= (buf->st_blksize / 512); // man say st_blocks is number of 512B blocks allocated
} else {
buf->st_blocks = f->csize;
}
return 0;
}
int usbd_mtp_statfs(const char *path, struct mtp_statfs *buf)
{
FATFS *f;
FRESULT res;
DWORD fre_clust, fre_sect, tot_sect;
f = &s_sd_disk;
res = f_getfree(path, &fre_clust, &f);
if (res != FR_OK) {
printf("f_getfree failed, cause: %s\n", show_error_string(res));
return -1;
}
tot_sect = (f->n_fatent - 2) * f->csize;
fre_sect = fre_clust * f->csize;
buf->f_blocks = tot_sect;
buf->f_bfree = fre_sect;
#if FF_MAX_SS != FF_MIN_SS
buf->f_bsize = f->ssize;
#else
buf->f_bsize = FF_MIN_SS;
#endif
return 0;
}
int usbd_mtp_open(const char *path, uint8_t mode)
{
BYTE flags;
if (mode == O_RDONLY) {
flags = FA_READ | FA_OPEN_EXISTING;
} else if (mode == O_WRONLY) {
flags = FA_WRITE | FA_OPEN_ALWAYS;
} else if (mode == O_RDWR) {
flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;
} else {
return -1; // Invalid mode
}
FRESULT result = f_open(&s_file, path, flags);
if (result != FR_OK) {
printf("f_open failed, cause: %s\n", show_error_string(result));
return -1;
}
return 0;
}
int usbd_mtp_close(int fd)
{
FRESULT result = f_close(&s_file);
if (result != FR_OK) {
printf("f_close failed, cause: %s\n", show_error_string(result));
return -1;
}
return 0;
}
int usbd_mtp_read(int fd, void *buf, size_t len)
{
UINT bytes_read;
FRESULT result = f_read(&s_file, buf, len, &bytes_read);
if (result != FR_OK) {
printf("f_read failed, cause: %s\n", show_error_string(result));
return -1;
}
return bytes_read; // Return number of bytes read
}
int usbd_mtp_write(int fd, const void *buf, size_t len)
{
UINT bytes_written;
FRESULT result = f_write(&s_file, buf, len, &bytes_written);
if (result != FR_OK) {
printf("f_write failed, cause: %s\n", show_error_string(result));
return -1;
}
return bytes_written; // Return number of bytes written
}
int usbd_mtp_unlink(const char *path)
{
FRESULT result = f_unlink(path);
if (result != FR_OK) {
printf("f_unlink failed, cause: %s\n", show_error_string(result));
return -1;
}
return 0; // File deleted successfully
}
void usbd_mtp_mount()
{
sd_mount_fs();
// write a file to test the SD card
sd_write_file();
}

View File

@@ -10,11 +10,6 @@
struct usbh_msc *active_msc_class;
int USB_disk_status(void)
{
return RES_OK;
}
int USB_disk_initialize(void)
{
active_msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
@@ -28,14 +23,69 @@ int USB_disk_initialize(void)
return RES_OK;
}
int USB_disk_status(void)
{
return RES_OK;
}
int USB_disk_read(BYTE *buff, LBA_t sector, UINT count)
{
return usbh_msc_scsi_read10(active_msc_class, sector, buff, count);
int ret;
uint8_t *align_buf;
align_buf = (uint8_t *)buff;
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
align_buf = (uint8_t *)memalign(CONFIG_USB_ALIGN_SIZE, count * active_msc_class->blocksize);
if (!align_buf) {
printf("msc get align buf failed\r\n");
return -USB_ERR_NOMEM;
}
}
#endif
ret = usbh_msc_scsi_read10(active_msc_class, sector, align_buf, count);
if (ret < 0) {
ret = RES_ERROR;
} else {
ret = RES_OK;
}
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
usb_memcpy(buff, align_buf, count * active_msc_class->blocksize);
free(align_buf);
}
#endif
return ret;
}
int USB_disk_write(const BYTE *buff, LBA_t sector, UINT count)
{
return usbh_msc_scsi_write10(active_msc_class, sector, buff, count);
int ret;
uint8_t *align_buf;
align_buf = (uint8_t *)buff;
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
align_buf = (uint8_t *)memalign(CONFIG_USB_ALIGN_SIZE, count * active_msc_class->blocksize);
if (!align_buf) {
printf("msc get align buf failed\r\n");
return -USB_ERR_NOMEM;
}
usb_memcpy(align_buf, buff, count * active_msc_class->blocksize);
}
#endif
ret = usbh_msc_scsi_write10(active_msc_class, sector, align_buf, count);
if (ret < 0) {
ret = RES_ERROR;
} else {
ret = RES_OK;
}
#ifdef CONFIG_USB_DCACHE_ENABLE
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
free(align_buf);
}
#endif
return ret;
}
int USB_disk_ioctl(BYTE cmd, void *buff)

View File

@@ -29,20 +29,11 @@
#endif
#endif
#if defined(BSP_USING_BL61X)
#include "bflb_l1c.h"
void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
{
if (ops == RT_HW_CACHE_FLUSH) {
bflb_l1c_dcache_clean_range(addr, size);
} else {
bflb_l1c_dcache_invalidate_range(addr, size);
}
}
#ifdef RT_USING_CACHE
#ifndef CONFIG_USB_DCACHE_ENABLE
#error CONFIG_USB_DCACHE_ENABLE must be enabled to use msc disk
#endif
#endif
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t msc_sector[512];
static rt_err_t rt_udisk_init(rt_device_t dev)
{
@@ -60,36 +51,29 @@ static ssize_t rt_udisk_read(rt_device_t dev, rt_off_t pos, void *buffer,
{
struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
int ret;
rt_uint8_t *align_buf;
align_buf = (rt_uint8_t *)buffer;
#ifdef RT_USING_CACHE
rt_uint32_t *align_buf;
if ((uint32_t)buffer & (RT_ALIGN_SIZE - 1)) {
align_buf = rt_malloc_align(size * msc_class->blocksize, RT_ALIGN_SIZE);
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE);
if (!align_buf) {
rt_kprintf("msc get align buf failed\n");
return 0;
}
} else {
align_buf = (rt_uint32_t *)buffer;
}
#endif
ret = usbh_msc_scsi_read10(msc_class, pos, (uint8_t *)align_buf, size);
if (ret < 0) {
rt_kprintf("usb mass_storage read failed\n");
return 0;
}
rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, align_buf, size * msc_class->blocksize);
if ((uint32_t)buffer & (RT_ALIGN_SIZE - 1)) {
rt_memcpy(buffer, align_buf, size * msc_class->blocksize);
#ifdef RT_USING_CACHE
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
usb_memcpy(buffer, align_buf, size * msc_class->blocksize);
rt_free_align(align_buf);
}
#else
ret = usbh_msc_scsi_read10(msc_class, pos, buffer, size);
if (ret < 0) {
rt_kprintf("usb mass_storage read failed\n");
return 0;
}
#endif
return size;
}
@@ -99,37 +83,29 @@ static ssize_t rt_udisk_write(rt_device_t dev, rt_off_t pos, const void *buffer,
{
struct usbh_msc *msc_class = (struct usbh_msc *)dev->user_data;
int ret;
rt_uint8_t *align_buf;
align_buf = (rt_uint8_t *)buffer;
#ifdef RT_USING_CACHE
rt_uint32_t *align_buf;
if ((uint32_t)buffer & (RT_ALIGN_SIZE - 1)) {
align_buf = rt_malloc_align(size * msc_class->blocksize, RT_ALIGN_SIZE);
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
align_buf = rt_malloc_align(size * msc_class->blocksize, CONFIG_USB_ALIGN_SIZE);
if (!align_buf) {
rt_kprintf("msc get align buf failed\n");
return 0;
}
rt_memcpy(align_buf, buffer, size * msc_class->blocksize);
} else {
align_buf = (rt_uint32_t *)buffer;
usb_memcpy(align_buf, buffer, size * msc_class->blocksize);
}
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, align_buf, size * msc_class->blocksize);
#endif
ret = usbh_msc_scsi_write10(msc_class, pos, (uint8_t *)align_buf, size);
if (ret < 0) {
rt_kprintf("usb mass_storage write failed\n");
return 0;
}
if ((uint32_t)buffer & (RT_ALIGN_SIZE - 1)) {
#ifdef RT_USING_CACHE
if ((uint32_t)buffer & (CONFIG_USB_ALIGN_SIZE - 1)) {
rt_free_align(align_buf);
}
#else
ret = usbh_msc_scsi_write10(msc_class, pos, buffer, size);
if (ret < 0) {
rt_kprintf("usb mass_storage write failed\n");
return 0;
}
#endif
return size;

View File

@@ -0,0 +1,142 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/disk.h>
#include "usbh_core.h"
#include "usbh_msc.h"
#ifdef CONFIG_DCACHE
#ifndef CONFIG_USB_DCACHE_ENABLE
#error CONFIG_USB_DCACHE_ENABLE must be enabled to use msc disk
#endif
#endif
struct usbh_msc *active_msc_class;
static int disk_msc_access_init(struct disk_info *disk)
{
active_msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
if (active_msc_class == NULL) {
printf("do not find /dev/sda\r\n");
return -ENODEV;
}
if (usbh_msc_scsi_init(active_msc_class) < 0) {
return -EIO;
}
return 0;
}
static int disk_msc_access_status(struct disk_info *disk)
{
return DISK_STATUS_OK;
}
static int disk_msc_access_read(struct disk_info *disk, uint8_t *buff,
uint32_t sector, uint32_t count)
{
int ret;
uint8_t *align_buf;
align_buf = (uint8_t *)buff;
#ifdef CONFIG_DCACHE
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
align_buf = (uint8_t *)k_aligned_alloc(CONFIG_USB_ALIGN_SIZE, count * active_msc_class->blocksize);
if (!align_buf) {
printf("msc get align buf failed\r\n");
return -ENOMEM;
}
}
#endif
if (usbh_msc_scsi_read10(active_msc_class, sector, align_buf, count) < 0) {
ret = -EIO;
} else {
ret = 0;
}
#ifdef CONFIG_DCACHE
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
usb_memcpy(buff, align_buf, count * active_msc_class->blocksize);
k_free(align_buf);
}
#endif
return ret;
}
static int disk_msc_access_write(struct disk_info *disk, const uint8_t *buff,
uint32_t sector, uint32_t count)
{
int ret;
uint8_t *align_buf;
align_buf = (uint8_t *)buff;
#ifdef CONFIG_DCACHE
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
align_buf = (uint8_t *)k_aligned_alloc(CONFIG_USB_ALIGN_SIZE, count * active_msc_class->blocksize);
if (!align_buf) {
printf("msc get align buf failed\r\n");
return -ENOMEM;
}
usb_memcpy(align_buf, buff, count * active_msc_class->blocksize);
}
#endif
if (usbh_msc_scsi_write10(active_msc_class, sector, align_buf, count) < 0) {
ret = -EIO;
} else {
ret = 0;
}
#ifdef CONFIG_DCACHE
if ((uint32_t)buff & (CONFIG_USB_ALIGN_SIZE - 1)) {
k_free(align_buf);
}
#endif
return ret;
}
static int disk_msc_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff)
{
switch (cmd) {
case DISK_IOCTL_CTRL_SYNC:
break;
case DISK_IOCTL_GET_SECTOR_COUNT:
*(uint32_t *)buff = active_msc_class->blocknum;
break;
case DISK_IOCTL_GET_SECTOR_SIZE:
*(uint32_t *)buff = active_msc_class->blocksize;
break;
case DISK_IOCTL_GET_ERASE_BLOCK_SZ:
*(uint32_t *)buff = 1U;
break;
case DISK_IOCTL_CTRL_INIT:
return disk_msc_access_init(disk);
case DISK_IOCTL_CTRL_DEINIT:
break;
default:
return -EINVAL;
}
return 0;
}
static const struct disk_operations msc_disk_ops = {
.init = disk_msc_access_init,
.status = disk_msc_access_status,
.read = disk_msc_access_read,
.write = disk_msc_access_write,
.ioctl = disk_msc_access_ioctl,
};
static struct disk_info usbh_msc_disk = {
.name = "USB",
.ops = &msc_disk_ops,
};
void usbh_msc_run(struct usbh_msc *msc_class)
{
disk_access_register(&usbh_msc_disk);
}
void usbh_msc_stop(struct usbh_msc *msc_class)
{
disk_access_unregister(&usbh_msc_disk);
}

View File

@@ -266,6 +266,9 @@ void USBD_IRQHandler(uint8_t busid)
if (intflag & USBFS_UIF_TRANSFER) {
token = USBFS_DEVICE->INT_ST & USBFS_UIS_TOKEN_MASK;
ep_idx = USBFS_DEVICE->INT_ST & USBFS_UIS_ENDP_MASK;
USBFS_DEVICE->INT_FG = USBFS_UIF_TRANSFER;
switch (token) {
case USBFS_UIS_TOKEN_SETUP:
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_NAK);
@@ -371,8 +374,9 @@ void USBD_IRQHandler(uint8_t busid)
break;
}
USBFS_DEVICE->INT_FG = USBFS_UIF_TRANSFER;
} else if (intflag & USBFS_UIF_BUS_RST) {
USBFS_DEVICE->INT_FG = USBFS_UIF_BUS_RST;
USBFS_DEVICE->UEP0_TX_LEN = 0;
USBFS_DEVICE->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
USBFS_DEVICE->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK;
@@ -390,8 +394,6 @@ void USBD_IRQHandler(uint8_t busid)
usbd_event_reset_handler(0);
USB_SET_DMA(ep_idx, (uint32_t)&g_ch32_usbfs_udc.setup);
USB_SET_RX_CTRL(ep_idx, USBFS_UEP_R_RES_ACK);
USBFS_DEVICE->INT_FG |= USBFS_UIF_BUS_RST;
} else if (intflag & USBFS_UIF_SUSPEND) {
if (USBFS_DEVICE->MIS_ST & USBFS_UMS_SUSPEND) {
} else {

View File

@@ -110,7 +110,7 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
g_ch32_usbhs_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
g_ch32_usbhs_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_ch32_usbhs_udc.out_ep[ep_idx].ep_enable = true;
if(g_ch32_usbhs_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
if (g_ch32_usbhs_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
USBHS_DEVICE->ENDP_TYPE |= (1 << (ep_idx + 16));
} else {
USBHS_DEVICE->ENDP_TYPE &= ~(1 << (ep_idx + 16));
@@ -122,11 +122,11 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
g_ch32_usbhs_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes);
g_ch32_usbhs_udc.in_ep[ep_idx].ep_enable = true;
if (g_ch32_usbhs_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
USBHS_DEVICE->ENDP_TYPE |= (1 << (ep_idx));
USB_SET_TX_CTRL(ep_idx, USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0);
USBHS_DEVICE->ENDP_TYPE |= (1 << (ep_idx));
USB_SET_TX_CTRL(ep_idx, USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0);
} else {
USBHS_DEVICE->ENDP_TYPE &= ~(1 << (ep_idx));
USB_SET_TX_CTRL(ep_idx, USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0 | USBHS_EP_T_AUTOTOG);
USBHS_DEVICE->ENDP_TYPE &= ~(1 << (ep_idx));
USB_SET_TX_CTRL(ep_idx, USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0 | USBHS_EP_T_AUTOTOG);
}
USBHS_DEVICE->ENDP_CONFIG |= (1 << (ep_idx));
}
@@ -141,7 +141,7 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep)
USBHS_DEVICE->ENDP_CONFIG &= ~(1 << (ep_idx + 16));
} else {
USBHS_DEVICE->ENDP_CONFIG &= ~(1 << (ep_idx));
}
}
return 0;
}
@@ -230,7 +230,11 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
tmp = USB_GET_TX_CTRL(ep_idx);
tmp &= ~(USBHS_EP_T_RES_MASK | USBHS_EP_T_TOG_MASK);
tmp |= USBHS_EP_T_RES_ACK;
tmp |= (epx_tx_data_toggle[ep_idx - 1] ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0);
if (g_ch32_usbhs_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
tmp |= USBHS_EP_T_TOG_0;
} else {
tmp |= (epx_tx_data_toggle[ep_idx - 1] ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0);
}
USB_SET_TX_CTRL(ep_idx, tmp);
}
return 0;
@@ -264,10 +268,10 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
return 0;
} else {
USB_SET_RX_DMA(ep_idx, (uint32_t)data);
if(g_ch32_usbhs_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS ) {
if (g_ch32_usbhs_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~(USBHS_EP_R_RES_MASK | USBHS_EP_R_TOG_MASK)) | USBHS_EP_R_RES_ACK | USBHS_EP_R_TOG_0);
} else {
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_EP_R_RES_MASK) | USBHS_EP_R_RES_ACK );
} else {
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_EP_R_RES_MASK) | USBHS_EP_R_RES_ACK);
}
}
@@ -285,7 +289,10 @@ void USBD_IRQHandler(uint8_t busid)
ep_idx = (USBHS_DEVICE->INT_ST) & MASK_UIS_ENDP;
token = (((USBHS_DEVICE->INT_ST) & MASK_UIS_TOKEN) >> 4) & 0x03;
USBHS_DEVICE->INT_FG = USBHS_TRANSFER_FLAG;
if (token == PID_IN) {
USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~(USBHS_EP_T_RES_MASK | USBHS_EP_T_TOG_MASK)) | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0);
if (ep_idx == 0x00) {
if (g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len >= g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps) {
g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len -= g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps;
@@ -317,8 +324,6 @@ void USBD_IRQHandler(uint8_t busid)
ep0_tx_data_toggle = true;
}
} else {
USB_SET_TX_CTRL(ep_idx, (USB_GET_TX_CTRL(ep_idx) & ~(USBHS_EP_T_RES_MASK | USBHS_EP_T_TOG_MASK)) | USBHS_EP_T_RES_NAK | USBHS_EP_T_TOG_0);
if (g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len > g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps) {
g_ch32_usbhs_udc.in_ep[ep_idx].xfer_buf += g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps;
g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len -= g_ch32_usbhs_udc.in_ep[ep_idx].ep_mps;
@@ -332,7 +337,13 @@ void USBD_IRQHandler(uint8_t busid)
uint32_t tmp = USB_GET_TX_CTRL(ep_idx);
tmp &= ~(USBHS_EP_T_RES_MASK | USBHS_EP_T_TOG_MASK);
tmp |= USBHS_EP_T_RES_ACK;
tmp |= (epx_tx_data_toggle[ep_idx - 1] ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0);
if (g_ch32_usbhs_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
tmp |= USBHS_EP_T_TOG_0;
} else {
tmp |= (epx_tx_data_toggle[ep_idx - 1] ? USBHS_EP_T_TOG_1 : USBHS_EP_T_TOG_0);
}
USB_SET_TX_CTRL(ep_idx, tmp);
} else {
g_ch32_usbhs_udc.in_ep[ep_idx].actual_xfer_len += g_ch32_usbhs_udc.in_ep[ep_idx].xfer_len;
@@ -342,6 +353,7 @@ void USBD_IRQHandler(uint8_t busid)
}
}
} else if (token == PID_OUT) {
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_EP_R_RES_MASK) | USBHS_EP_R_RES_NAK);
if (ep_idx == 0x00) {
read_count = USBHS_DEVICE->RX_LEN;
@@ -361,7 +373,6 @@ void USBD_IRQHandler(uint8_t busid)
}
} else {
if (USBHS_DEVICE->INT_ST & USBHS_DEV_UIS_TOG_OK) {
USB_SET_RX_CTRL(ep_idx, (USB_GET_RX_CTRL(ep_idx) & ~USBHS_EP_R_RES_MASK) | USBHS_EP_R_RES_NAK);
read_count = USBHS_DEVICE->RX_LEN;
g_ch32_usbhs_udc.out_ep[ep_idx].xfer_buf += read_count;
@@ -377,11 +388,16 @@ void USBD_IRQHandler(uint8_t busid)
}
}
}
USBHS_DEVICE->INT_FG = USBHS_TRANSFER_FLAG;
} else if (intflag & USBHS_SETUP_FLAG) {
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_ch32_usbhs_udc.setup);
}
if (intflag & USBHS_SETUP_FLAG) {
USBHS_DEVICE->INT_FG = USBHS_SETUP_FLAG;
} else if (intflag & USBHS_DETECT_FLAG) {
usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_ch32_usbhs_udc.setup);
}
if (intflag & USBHS_DETECT_FLAG) {
USBHS_DEVICE->INT_FG = USBHS_DETECT_FLAG;
USBHS_DEVICE->ENDP_CONFIG = USBHS_EP0_T_EN | USBHS_EP0_R_EN;
USBHS_DEVICE->UEP0_TX_LEN = 0;
@@ -401,7 +417,6 @@ void USBD_IRQHandler(uint8_t busid)
usbd_event_reset_handler(0);
USBHS_DEVICE->UEP0_DMA = (uint32_t)&g_ch32_usbhs_udc.setup;
USBHS_DEVICE->UEP0_RX_CTRL = USBHS_EP_R_RES_ACK;
USBHS_DEVICE->INT_FG = USBHS_DETECT_FLAG;
}
}

View File

@@ -304,7 +304,7 @@ static void usb_qtd_init(dcd_qtd_t *p_qtd, void *data_ptr, uint16_t total_bytes)
if (data_ptr != NULL) {
p_qtd->buffer[0] = (uint32_t)data_ptr;
for (uint8_t i = 1; i < 5; i++) {
p_qtd->buffer[i] |= ((p_qtd->buffer[i - 1]) & 0xFFFFF000UL) + 4096U;
p_qtd->buffer[i] = ((p_qtd->buffer[i - 1]) & 0xFFFFF000UL) + 4096U;
}
}
}

View File

@@ -114,8 +114,8 @@ struct dwc2_ep_state {
/* Driver state */
USB_NOCACHE_RAM_SECTION struct dwc2_udc {
uint32_t GSNPSID;
__attribute__((aligned(32))) struct usb_setup_packet setup;
USB_MEM_ALIGNX struct usb_setup_packet setup;
USB_MEM_ALIGNX uint32_t GSNPSID;
struct dwc2_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
struct dwc2_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
} g_dwc2_udc[CONFIG_USBDEV_MAX_BUS];
@@ -884,6 +884,10 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
USB_ASSERT_MSG(!((uint32_t)data % 0x04), "dwc2 data must be 4-byte aligned");
#ifdef CONFIG_USB_DCACHE_ENABLE
USB_ASSERT_MSG(!((uint32_t)data % CONFIG_USB_ALIGN_SIZE), "dwc2 data must be %d-byte aligned", CONFIG_USB_ALIGN_SIZE);
#endif
if (!data && data_len) {
return -1;
}
@@ -932,6 +936,7 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
}
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
usb_dcache_clean((uintptr_t)data, USB_ALIGN_UP(data_len, CONFIG_USB_ALIGN_SIZE));
USB_OTG_INEP(ep_idx)->DIEPDMA = (uint32_t)data;
USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
@@ -952,6 +957,10 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
USB_ASSERT_MSG(!((uint32_t)data % 0x04), "dwc2 data must be 4-byte aligned");
#ifdef CONFIG_USB_DCACHE_ENABLE
USB_ASSERT_MSG(!((uint32_t)data % CONFIG_USB_ALIGN_SIZE), "dwc2 data must be %d-byte aligned", CONFIG_USB_ALIGN_SIZE);
#endif
if (!data && data_len) {
return -1;
}
@@ -1008,6 +1017,8 @@ void USBD_IRQHandler(uint8_t busid)
uint32_t gint_status, temp, ep_idx, ep_intr, epint, read_count;
gint_status = dwc2_get_glb_intstatus(busid);
(void)read_count;
if ((USB_OTG_GLB->GINTSTS & 0x1U) == USB_OTG_MODE_DEVICE) {
/* Avoid spurious interrupt */
if (gint_status == 0) {
@@ -1052,16 +1063,19 @@ void USBD_IRQHandler(uint8_t busid)
} else {
g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len = g_dwc2_udc[busid].out_ep[ep_idx].xfer_len - ((USB_OTG_OUTEP(ep_idx)->DOEPTSIZ) & USB_OTG_DOEPTSIZ_XFRSIZ);
g_dwc2_udc[busid].out_ep[ep_idx].xfer_len = 0;
usb_dcache_invalidate((uintptr_t)g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf, USB_ALIGN_UP(g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len, CONFIG_USB_ALIGN_SIZE));
usbd_event_ep_out_complete_handler(busid, 0x00, g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len);
}
} else {
g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len = g_dwc2_udc[busid].out_ep[ep_idx].xfer_len - ((USB_OTG_OUTEP(ep_idx)->DOEPTSIZ) & USB_OTG_DOEPTSIZ_XFRSIZ);
g_dwc2_udc[busid].out_ep[ep_idx].xfer_len = 0;
usb_dcache_invalidate((uintptr_t)g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf, USB_ALIGN_UP(g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len, CONFIG_USB_ALIGN_SIZE));
usbd_event_ep_out_complete_handler(busid, ep_idx, g_dwc2_udc[busid].out_ep[ep_idx].actual_xfer_len);
}
}
if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) {
usb_dcache_invalidate((uintptr_t)&g_dwc2_udc[busid].setup, USB_ALIGN_UP(8, CONFIG_USB_ALIGN_SIZE));
usbd_event_ep0_setup_complete_handler(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
}
}

View File

@@ -56,7 +56,12 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
#endif
}
extern uint32_t SystemCoreClock;
void usbd_dwc2_delay_ms(uint8_t ms)
{
/* implement later */
}
uint32_t count = SystemCoreClock / 1000 * ms;
while (count--) {
__asm volatile("nop");
}
}

View File

@@ -14,13 +14,13 @@
#include "usbh_core.h"
#ifdef CONFIG_IDF_TARGET_ESP32S2
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_USB_INTR_SOURCE ETS_USB_INTR_SOURCE
#elif CONFIG_IDF_TARGET_ESP32S3
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_USB_INTR_SOURCE ETS_USB_INTR_SOURCE
#elif CONFIG_IDF_TARGET_ESP32P4
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ
#define DEFAULT_USB_INTR_SOURCE ETS_USB_OTG_INTR_SOURCE
#else
#define DEFAULT_CPU_FREQ_MHZ 160
@@ -56,7 +56,7 @@ void usb_dc_low_level_init(uint8_t busid)
USB_LOG_ERR("USB Interrupt Init Failed!\r\n");
return;
}
USB_LOG_INFO("cherryusb, version: "CHERRYUSB_VERSION_STR"\r\n");
USB_LOG_INFO("cherryusb, version: " CHERRYUSB_VERSION_STR "\r\n");
}
void usb_dc_low_level_deinit(uint8_t busid)
@@ -106,7 +106,7 @@ void usb_hc_low_level_init(struct usbh_bus *bus)
USB_LOG_ERR("USB Interrupt Init Failed!\r\n");
return;
}
USB_LOG_INFO("cherryusb, version: "CHERRYUSB_VERSION_STR"\r\n");
USB_LOG_INFO("cherryusb, version: " CHERRYUSB_VERSION_STR "\r\n");
}
void usb_hc_low_level_deinit(struct usbh_bus *bus)
@@ -129,4 +129,23 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
void usbd_dwc2_delay_ms(uint8_t ms)
{
vTaskDelay(pdMS_TO_TICKS(ms));
}
}
#ifdef CONFIG_USB_DCACHE_ENABLE
#include "esp_cache.h"
void usb_dcache_clean(uintptr_t addr, size_t size)
{
esp_cache_msync((void *)addr, size, ESP_CACHE_MSYNC_FLAG_TYPE_DATA | ESP_CACHE_MSYNC_FLAG_DIR_C2M);
}
void usb_dcache_invalidate(uintptr_t addr, size_t size)
{
esp_cache_msync((void *)addr, size, ESP_CACHE_MSYNC_FLAG_TYPE_DATA | ESP_CACHE_MSYNC_FLAG_DIR_M2C);
}
void usb_dcache_flush(uintptr_t addr, size_t size)
{
esp_cache_msync((void *)addr, size, ESP_CACHE_MSYNC_FLAG_TYPE_DATA | ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_DIR_M2C);
}
#endif

View File

@@ -35,7 +35,12 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
#endif
}
extern uint32_t SystemCoreClock;
void usbd_dwc2_delay_ms(uint8_t ms)
{
/* implement later */
}
uint32_t count = SystemCoreClock / 1000 * ms;
while (count--) {
__asm volatile("nop");
}
}

View File

@@ -25,7 +25,12 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
return 0;
}
extern uint32_t SystemCoreClock;
void usbd_dwc2_delay_ms(uint8_t ms)
{
/* implement later */
}
uint32_t count = SystemCoreClock / 1000 * ms;
while (count--) {
__asm volatile("nop");
}
}

View File

@@ -180,8 +180,14 @@ void USB_HS_IRQHandler(void)
g_usb_dwc2_irq(g_usb_dwc2_busid);
}
extern uint32_t SystemCoreClock;
void usbd_dwc2_delay_ms(uint8_t ms)
{
uint32_t count = SystemCoreClock / 1000 * ms;
while (count--) {
__asm volatile("nop");
}
}
#endif

View File

@@ -217,9 +217,14 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base)
#endif
}
extern uint32_t SystemCoreClock;
void usbd_dwc2_delay_ms(uint8_t ms)
{
HAL_Delay(ms);
uint32_t count = SystemCoreClock / 1000 * ms;
while (count--) {
__asm volatile("nop");
}
}
void OTG_FS_IRQHandler(void)
@@ -230,4 +235,21 @@ void OTG_FS_IRQHandler(void)
void OTG_HS_IRQHandler(void)
{
g_usb_dwc2_irq[1](g_usb_dwc2_busid[1]);
}
}
#ifdef CONFIG_USB_DCACHE_ENABLE
void usb_dcache_clean(uintptr_t addr, size_t size)
{
SCB_CleanDCache_by_Addr((void *)addr, size);
}
void usb_dcache_invalidate(uintptr_t addr, size_t size)
{
SCB_InvalidateDCache_by_Addr((void *)addr, size);
}
void usb_dcache_flush(uintptr_t addr, size_t size)
{
SCB_CleanInvalidateDCache_by_Addr((void *)addr, size);
}
#endif

View File

@@ -1207,7 +1207,7 @@ static void dwc2_outchan_irq_handler(struct usbh_bus *bus, uint8_t ch_num)
} else if (USB_GET_ENDPOINT_TYPE(urb->ep->bmAttributes) == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
} else {
if (chan->do_ssplit && urb->transfer_buffer_length > 0) {
dwc2_control_urb_init(bus, ch_num, urb, urb->setup, urb->transfer_buffer + urb->actual_length - 8, urb->transfer_buffer_length);
dwc2_bulk_intr_urb_init(bus, ch_num, urb, urb->transfer_buffer + urb->actual_length, urb->transfer_buffer_length);
} else {
dwc2_urb_waitup(urb);
}

View File

@@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "bflb_core.h"
#include "bflb_l1c.h"
#include "usbh_core.h"
#include "hardware/usb_v2_reg.h"
@@ -141,3 +142,20 @@ uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
}
return USB_SPEED_HIGH;
}
#ifdef CONFIG_USB_DCACHE_ENABLE
void usb_dcache_clean(uintptr_t addr, size_t size)
{
bflb_l1c_dcache_clean_range((void *)addr, size);
}
void usb_dcache_invalidate(uintptr_t addr, size_t size)
{
bflb_l1c_dcache_invalidate_range((void *)addr, size);
}
void usb_dcache_flush(uintptr_t addr, size_t size)
{
bflb_l1c_dcache_clean_invalidate_range((void *)addr, size);
}
#endif

View File

@@ -58,6 +58,8 @@ static void ehci_qtd_free(struct usbh_bus *bus, struct ehci_qtd_hw *qtd)
{
size_t flags;
(void)bus;
flags = usb_osal_enter_critical_section();
qtd->inuse = false;
qtd->urb = NULL;

View File

@@ -6,6 +6,8 @@
*/
#include "hpm_common.h"
#include "hpm_soc.h"
#include "hpm_l1c_drv.h"
#include "usb_config.h"
void (*g_usb_hpm_irq[2])(uint8_t busid);
uint8_t g_usb_hpm_busid[2];
@@ -13,7 +15,7 @@ uint8_t g_usb_hpm_busid[2];
ATTR_WEAK void hpm_usb_isr_enable(uint32_t base)
{
if (base == HPM_USB0_BASE) {
intc_m_enable_irq(IRQn_USB0);
intc_m_enable_irq(IRQn_USB0);
} else {
#ifdef HPM_USB1_BASE
intc_m_enable_irq(IRQn_USB1);
@@ -24,7 +26,7 @@ ATTR_WEAK void hpm_usb_isr_enable(uint32_t base)
ATTR_WEAK void hpm_usb_isr_disable(uint32_t base)
{
if (base == HPM_USB0_BASE) {
intc_m_disable_irq(IRQn_USB0);
intc_m_disable_irq(IRQn_USB0);
} else {
#ifdef HPM_USB1_BASE
intc_m_disable_irq(IRQn_USB1);
@@ -48,4 +50,21 @@ void hpm_isr_usb1(void)
{
g_usb_hpm_irq[1](g_usb_hpm_busid[1]);
}
#endif
#ifdef CONFIG_USB_DCACHE_ENABLE
void usb_dcache_clean(uintptr_t addr, size_t size)
{
l1c_dc_writeback(addr, size);
}
void usb_dcache_invalidate(uintptr_t addr, size_t size)
{
l1c_dc_invalidate(addr, size);
}
void usb_dcache_flush(uintptr_t addr, size_t size)
{
l1c_dc_flush(addr, size);
}
#endif

View File

@@ -6,6 +6,7 @@
#include "usbd_core.h"
#include "usbh_core.h"
#include "fsl_common.h"
#include "fsl_cache.h"
#include "usb_chipidea_reg.h"
__WEAK void USBD_IRQHandler(uint8_t busid)
@@ -428,4 +429,21 @@ uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port)
void USB1_HS_IRQHandler(void)
{
g_usb_nxp_irq(0);
}
}
#ifdef CONFIG_USB_DCACHE_ENABLE
void usb_dcache_clean(uintptr_t addr, size_t size)
{
DCACHE_CleanByRange(addr, size);
}
void usb_dcache_invalidate(uintptr_t addr, size_t size)
{
DCACHE_InvalidateByRange(addr, size);
}
void usb_dcache_flush(uintptr_t addr, size_t size)
{
DCACHE_CleanInvalidateByRange(addr, size);
}
#endif

View File

@@ -12,6 +12,7 @@
#define CHERRYUSB_CONFIG_H
#include "rtconfig.h"
#include <rtthread.h>
/* ================ USB common Configuration ================ */

View File

@@ -86,4 +86,9 @@ void *usb_sys_malloc_align(size_t align, size_t size)
}
return buf;
}
int usbd_set_remote_wakeup(uint8_t busid)
{
return -1;
}