Compare commits
33 Commits
v1.5.0-rc1
...
v1.5.0-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
537ccfd945 | ||
|
|
6973ec73d9 | ||
|
|
1feaed024e | ||
|
|
88cbed9807 | ||
|
|
1d95077161 | ||
|
|
06a0c4393b | ||
|
|
6b7d755d3a | ||
|
|
078e7d1be0 | ||
|
|
ac4e4c569d | ||
|
|
b6650bdbc6 | ||
|
|
bff8a632a9 | ||
|
|
a8bf2687bd | ||
|
|
0251e3a145 | ||
|
|
f7c354b4eb | ||
|
|
ff42a6f2ea | ||
|
|
ca71e7411e | ||
|
|
16858c105a | ||
|
|
8c5026e9cb | ||
|
|
8a81d81435 | ||
|
|
c75e62c1e9 | ||
|
|
5a6023118e | ||
|
|
51ad3717c5 | ||
|
|
0ee859d339 | ||
|
|
e6d81344c3 | ||
|
|
af6df63acb | ||
|
|
b4fb10ee98 | ||
|
|
e3c50cde10 | ||
|
|
e65b8c0614 | ||
|
|
f9189b4278 | ||
|
|
51ea604ded | ||
|
|
fe24f8d4ba | ||
|
|
5fed8b7d05 | ||
|
|
45ccc810d2 |
@@ -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)
|
||||
|
||||
5
Kconfig
5
Kconfig
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
45
README.md
45
README.md
@@ -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:
|
||||
|
||||
|
||||
43
README_zh.md
43
README_zh.md
@@ -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)` 受以下宏影响:
|
||||
|
||||
|
||||
@@ -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']):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
683
class/mtp/usb_mtp.h
Normal 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
62
class/mtp/usbd_mtp.h
Normal 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 */
|
||||
312
class/mtp/usbd_mtp_support.h
Normal file
312
class/mtp/usbd_mtp_support.h
Normal 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
|
||||
3
class/vendor/net/usbh_asix.c
vendored
3
class/vendor/net/usbh_asix.c
vendored
@@ -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);
|
||||
}
|
||||
|
||||
3
class/vendor/net/usbh_rtl8152.c
vendored
3
class/vendor/net/usbh_rtl8152.c
vendored
@@ -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);
|
||||
}
|
||||
|
||||
1
class/vendor/serial/usbh_ch34x.c
vendored
1
class/vendor/serial/usbh_ch34x.c
vendored
@@ -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);
|
||||
}
|
||||
|
||||
1
class/vendor/serial/usbh_cp210x.c
vendored
1
class/vendor/serial/usbh_cp210x.c
vendored
@@ -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);
|
||||
}
|
||||
|
||||
1
class/vendor/serial/usbh_ftdi.c
vendored
1
class/vendor/serial/usbh_ftdi.c
vendored
@@ -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);
|
||||
}
|
||||
|
||||
1
class/vendor/serial/usbh_pl2303.c
vendored
1
class/vendor/serial/usbh_pl2303.c
vendored
@@ -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);
|
||||
}
|
||||
|
||||
1
class/vendor/wifi/usbh_bl616.c
vendored
1
class/vendor/wifi/usbh_bl616.c
vendored
@@ -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);
|
||||
}
|
||||
|
||||
1
class/vendor/xbox/usbh_xbox.c
vendored
1
class/vendor/xbox/usbh_xbox.c
vendored
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
250
demo/mtp_template.c
Normal 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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 |
BIN
docs/source/show/img/usbdev_uvc_mjpeg.png
Normal file
BIN
docs/source/show/img/usbdev_uvc_mjpeg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 MiB |
BIN
docs/source/show/img/usbdev_uvc_yuv.png
Normal file
BIN
docs/source/show/img/usbdev_uvc_yuv.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 MiB |
@@ -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
|
||||
-----------------------
|
||||
|
||||
|
||||
BIN
docs/source/support/img/mtpdev.png
Normal file
BIN
docs/source/support/img/mtpdev.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 353 KiB |
@@ -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
|
||||
|
||||
@@ -97,7 +97,7 @@ v1.4.3
|
||||
- **host msc 将 scsi 初始化从枚举线程中移出,在mount阶段调用,并增加了testunity 多次尝试,兼容一部分 U 盘**
|
||||
- rp2040 主从支持
|
||||
- **nuttx fs,serial,net 组件支持**
|
||||
- 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 更新
|
||||
- cmake,kconfig 更新
|
||||
- cmake,scons,kconfig 更新
|
||||
- 使用 USB_ASSERT_MSG 对部分代码检查
|
||||
- N32H4,mm32f5 支持
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
351
platform/fatfs/usbd_fatfs_mtp.c
Normal file
351
platform/fatfs/usbd_fatfs_mtp.c
Normal 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();
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
142
platform/zephyr/usbh_msc_disk.c
Normal file
142
platform/zephyr/usbh_msc_disk.c
Normal 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);
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -12,6 +12,7 @@
|
||||
#define CHERRYUSB_CONFIG_H
|
||||
|
||||
#include "rtconfig.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
/* ================ USB common Configuration ================ */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user