diff --git a/bsp/cvitek/cv18xx_aarch64/.config b/bsp/cvitek/cv18xx_aarch64/.config index 07d04d9c040..d8977c50371 100644 --- a/bsp/cvitek/cv18xx_aarch64/.config +++ b/bsp/cvitek/cv18xx_aarch64/.config @@ -2,10 +2,126 @@ # # RT-Thread Kernel # + +# +# klibc options +# + +# +# rt_vsnprintf options +# +# CONFIG_RT_KLIBC_USING_LIBC_VSNPRINTF is not set +CONFIG_RT_KLIBC_USING_VSNPRINTF_LONGLONG=y +CONFIG_RT_KLIBC_USING_VSNPRINTF_STANDARD=y +CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS=y +CONFIG_RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS=y +CONFIG_RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER=y +CONFIG_RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER=y +# CONFIG_RT_KLIBC_USING_VSNPRINTF_MSVC_STYLE_INTEGER_SPECIFIERS is not set +CONFIG_RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE=32 +CONFIG_RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE=32 +CONFIG_RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION=6 +CONFIG_RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL=9 +CONFIG_RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS=4 +# end of rt_vsnprintf options + +# +# rt_vsscanf options +# +# CONFIG_RT_KLIBC_USING_LIBC_VSSCANF is not set +# end of rt_vsscanf options + +# +# rt_memset options +# +# CONFIG_RT_KLIBC_USING_USER_MEMSET is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMSET is not set +# CONFIG_RT_KLIBC_USING_TINY_MEMSET is not set +# end of rt_memset options + +# +# rt_memcpy options +# +# CONFIG_RT_KLIBC_USING_USER_MEMCPY is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMCPY is not set +# CONFIG_RT_KLIBC_USING_TINY_MEMCPY is not set +# end of rt_memcpy options + +# +# rt_memmove options +# +# CONFIG_RT_KLIBC_USING_USER_MEMMOVE is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMMOVE is not set +# end of rt_memmove options + +# +# rt_memcmp options +# +# CONFIG_RT_KLIBC_USING_USER_MEMCMP is not set +# CONFIG_RT_KLIBC_USING_LIBC_MEMCMP is not set +# end of rt_memcmp options + +# +# rt_strstr options +# +# CONFIG_RT_KLIBC_USING_USER_STRSTR is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRSTR is not set +# end of rt_strstr options + +# +# rt_strcasecmp options +# +# CONFIG_RT_KLIBC_USING_USER_STRCASECMP is not set +# end of rt_strcasecmp options + +# +# rt_strncpy options +# +# CONFIG_RT_KLIBC_USING_USER_STRNCPY is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRNCPY is not set +# end of rt_strncpy options + +# +# rt_strcpy options +# +# CONFIG_RT_KLIBC_USING_USER_STRCPY is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRCPY is not set +# end of rt_strcpy options + +# +# rt_strncmp options +# +# CONFIG_RT_KLIBC_USING_USER_STRNCMP is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRNCMP is not set +# end of rt_strncmp options + +# +# rt_strcmp options +# +# CONFIG_RT_KLIBC_USING_USER_STRCMP is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRCMP is not set +# end of rt_strcmp options + +# +# rt_strlen options +# +# CONFIG_RT_KLIBC_USING_USER_STRLEN is not set +# CONFIG_RT_KLIBC_USING_LIBC_STRLEN is not set +# end of rt_strlen options + +# +# rt_strnlen options +# +# CONFIG_RT_KLIBC_USING_USER_STRNLEN is not set +# end of rt_strnlen options + +# CONFIG_RT_UTEST_TC_USING_KLIBC is not set +# end of klibc options + CONFIG_RT_NAME_MAX=16 # CONFIG_RT_USING_ARCH_DATA_TYPE is not set -# CONFIG_RT_USING_SMART is not set # CONFIG_RT_USING_NANO is not set +# CONFIG_RT_USING_SMART is not set # CONFIG_RT_USING_AMP is not set # CONFIG_RT_USING_SMP is not set CONFIG_RT_CPUS_NR=1 @@ -15,6 +131,7 @@ CONFIG_RT_THREAD_PRIORITY_32=y # CONFIG_RT_THREAD_PRIORITY_256 is not set CONFIG_RT_THREAD_PRIORITY_MAX=32 CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y CONFIG_RT_USING_HOOK=y CONFIG_RT_HOOK_USING_FUNC_PTR=y # CONFIG_RT_USING_HOOKLIST is not set @@ -28,18 +145,10 @@ CONFIG_RT_TIMER_THREAD_STACK_SIZE=8192 # CONFIG_RT_USING_CPU_USAGE_TRACER is not set # -# kservice optimization +# kservice options # # CONFIG_RT_USING_TINY_FFS is not set -# end of kservice optimization - -# -# klibc optimization -# -# CONFIG_RT_KLIBC_USING_STDLIB is not set -# CONFIG_RT_KLIBC_USING_TINY_SIZE is not set -CONFIG_RT_KLIBC_USING_PRINTF_LONGLONG=y -# end of klibc optimization +# end of kservice options CONFIG_RT_USING_DEBUG=y CONFIG_RT_DEBUGING_ASSERT=y @@ -47,7 +156,7 @@ CONFIG_RT_DEBUGING_COLOR=y CONFIG_RT_DEBUGING_CONTEXT=y # CONFIG_RT_DEBUGING_AUTO_INIT is not set # CONFIG_RT_DEBUGING_PAGE_LEAK is not set -CONFIG_RT_USING_OVERFLOW_CHECK=y +# CONFIG_RT_USING_CI_ACTION is not set # # Inter-Thread communication @@ -86,7 +195,6 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_DEVICE_OPS=y CONFIG_RT_USING_INTERRUPT_INFO=y # CONFIG_RT_USING_THREADSAFE_PRINTF is not set -CONFIG_RT_USING_SCHED_THREAD_CTX=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0" @@ -114,7 +222,9 @@ CONFIG_ARCH_MM_MMU=y CONFIG_ARCH_ARM=y CONFIG_ARCH_ARM_MMU=y CONFIG_ARCH_ARMV8=y +CONFIG_ARCH_USING_ASID=y CONFIG_ARCH_USING_HW_THREAD_SELF=y +CONFIG_ARCH_USING_IRQ_CTX_LIST=y # # RT-Thread Components @@ -201,10 +311,12 @@ CONFIG_RT_USING_SERIAL_V1=y # CONFIG_RT_USING_SERIAL_V2 is not set CONFIG_RT_SERIAL_USING_DMA=y CONFIG_RT_SERIAL_RB_BUFSZ=256 +# CONFIG_RT_USING_SERIAL_BYPASS is not set # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_CPUTIME is not set # CONFIG_RT_USING_I2C is not set # CONFIG_RT_USING_PHY is not set +# CONFIG_RT_USING_PHY_V2 is not set # CONFIG_RT_USING_ADC is not set # CONFIG_RT_USING_DAC is not set CONFIG_RT_USING_NULL=y @@ -231,15 +343,17 @@ CONFIG_PM_TICKLESS_THRESHOLD_TIME=2 # CONFIG_RT_USING_LCD is not set # CONFIG_RT_USING_HWCRYPTO is not set # CONFIG_RT_USING_WIFI is not set -CONFIG_RT_USING_VIRTIO=y -CONFIG_RT_USING_VIRTIO10=y -CONFIG_RT_USING_VIRTIO_MMIO_ALIGN=y -CONFIG_RT_USING_VIRTIO_BLK=y -# CONFIG_RT_USING_VIRTIO_NET is not set -CONFIG_RT_USING_VIRTIO_CONSOLE=y -CONFIG_RT_USING_VIRTIO_CONSOLE_PORT_MAX_NR=4 -CONFIG_RT_USING_VIRTIO_GPU=y -CONFIG_RT_USING_VIRTIO_INPUT=y +# CONFIG_RT_USING_LED is not set +# CONFIG_RT_USING_MBOX is not set +# CONFIG_RT_USING_PHYE is not set +# CONFIG_RT_USING_BLK is not set +# CONFIG_RT_USING_SCSI is not set +# CONFIG_RT_USING_REGULATOR is not set +# CONFIG_RT_USING_RESET is not set +# CONFIG_RT_USING_THERMAL is not set +# CONFIG_RT_USING_VIRTIO is not set +# CONFIG_RT_USING_DMA is not set +# CONFIG_RT_USING_MFD is not set CONFIG_RT_USING_OFW=y # CONFIG_RT_USING_BUILTIN_FDT is not set CONFIG_RT_FDT_EARLYCON_MSG_SIZE=128 @@ -485,6 +599,7 @@ CONFIG_RT_USING_MEMBLOCK=y # CONFIG_PKG_USING_MATTER_ADAPTATION_LAYER is not set # CONFIG_PKG_USING_LHC_MODBUS is not set # CONFIG_PKG_USING_QMODBUS is not set +# CONFIG_PKG_USING_PNET is not set # end of IoT - internet of things # @@ -617,6 +732,7 @@ CONFIG_RT_USING_MEMBLOCK=y # CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set # CONFIG_PKG_USING_VOFA_PLUS is not set # CONFIG_PKG_USING_ZDEBUG is not set +# CONFIG_PKG_USING_RVBACKTRACE is not set # end of tools packages # @@ -628,7 +744,6 @@ CONFIG_RT_USING_MEMBLOCK=y # # CONFIG_PKG_USING_RT_MEMCPY_CM is not set # CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set -# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set # end of enhanced kernel services # CONFIG_PKG_USING_AUNITY is not set @@ -706,10 +821,12 @@ CONFIG_RT_USING_MEMBLOCK=y # CONFIG_PKG_USING_FLASH_BLOB is not set # CONFIG_PKG_USING_MLIBC is not set # CONFIG_PKG_USING_TASK_MSG_BUS is not set +# CONFIG_PKG_USING_UART_FRAMEWORK is not set # CONFIG_PKG_USING_SFDB is not set # CONFIG_PKG_USING_RTP is not set # CONFIG_PKG_USING_REB is not set # CONFIG_PKG_USING_R_RHEALSTONE is not set +# CONFIG_PKG_USING_HEARTBEAT is not set # end of system packages # @@ -805,6 +922,7 @@ CONFIG_RT_USING_MEMBLOCK=y # CONFIG_PKG_USING_MLX90632 is not set # CONFIG_PKG_USING_MLX90393 is not set # CONFIG_PKG_USING_MLX90392 is not set +# CONFIG_PKG_USING_MLX90394 is not set # CONFIG_PKG_USING_MLX90397 is not set # CONFIG_PKG_USING_MS5611 is not set # CONFIG_PKG_USING_MAX31865 is not set @@ -919,6 +1037,8 @@ CONFIG_RT_USING_MEMBLOCK=y # CONFIG_PKG_USING_BT_MX01 is not set # CONFIG_PKG_USING_RGPOWER is not set # CONFIG_PKG_USING_BT_MX02 is not set +# CONFIG_PKG_USING_GC9A01 is not set +# CONFIG_PKG_USING_IK485 is not set # CONFIG_PKG_USING_SPI_TOOLS is not set # end of peripheral libraries and drivers @@ -1029,6 +1149,7 @@ CONFIG_RT_USING_MEMBLOCK=y # CONFIG_PKG_USING_ARDUINO_MSGQ_C_CPP_DEMO is not set # CONFIG_PKG_USING_ARDUINO_SKETCH_LOADER_DEMO is not set # CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set +# CONFIG_PKG_USING_ARDUINO_RTDUINO_SENSORFUSION_SHIELD is not set # CONFIG_PKG_USING_ARDUINO_NINEINONE_SENSOR_SHIELD is not set # CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set # CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set diff --git a/bsp/cvitek/cv18xx_aarch64/rtconfig.h b/bsp/cvitek/cv18xx_aarch64/rtconfig.h index 14f429b4838..58429cea3fe 100644 --- a/bsp/cvitek/cv18xx_aarch64/rtconfig.h +++ b/bsp/cvitek/cv18xx_aarch64/rtconfig.h @@ -3,12 +3,82 @@ /* RT-Thread Kernel */ +/* klibc options */ + +/* rt_vsnprintf options */ + +#define RT_KLIBC_USING_VSNPRINTF_LONGLONG +#define RT_KLIBC_USING_VSNPRINTF_STANDARD +#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_SPECIFIERS +#define RT_KLIBC_USING_VSNPRINTF_EXPONENTIAL_SPECIFIERS +#define RT_KLIBC_USING_VSNPRINTF_WRITEBACK_SPECIFIER +#define RT_KLIBC_USING_VSNPRINTF_CHECK_NUL_IN_FORMAT_SPECIFIER +#define RT_KLIBC_USING_VSNPRINTF_INTEGER_BUFFER_SIZE 32 +#define RT_KLIBC_USING_VSNPRINTF_DECIMAL_BUFFER_SIZE 32 +#define RT_KLIBC_USING_VSNPRINTF_FLOAT_PRECISION 6 +#define RT_KLIBC_USING_VSNPRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9 +#define RT_KLIBC_USING_VSNPRINTF_LOG10_TAYLOR_TERMS 4 +/* end of rt_vsnprintf options */ + +/* rt_vsscanf options */ + +/* end of rt_vsscanf options */ + +/* rt_memset options */ + +/* end of rt_memset options */ + +/* rt_memcpy options */ + +/* end of rt_memcpy options */ + +/* rt_memmove options */ + +/* end of rt_memmove options */ + +/* rt_memcmp options */ + +/* end of rt_memcmp options */ + +/* rt_strstr options */ + +/* end of rt_strstr options */ + +/* rt_strcasecmp options */ + +/* end of rt_strcasecmp options */ + +/* rt_strncpy options */ + +/* end of rt_strncpy options */ + +/* rt_strcpy options */ + +/* end of rt_strcpy options */ + +/* rt_strncmp options */ + +/* end of rt_strncmp options */ + +/* rt_strcmp options */ + +/* end of rt_strcmp options */ + +/* rt_strlen options */ + +/* end of rt_strlen options */ + +/* rt_strnlen options */ + +/* end of rt_strnlen options */ +/* end of klibc options */ #define RT_NAME_MAX 16 #define RT_CPUS_NR 1 #define RT_ALIGN_SIZE 8 #define RT_THREAD_PRIORITY_32 #define RT_THREAD_PRIORITY_MAX 32 #define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK #define RT_USING_HOOK #define RT_HOOK_USING_FUNC_PTR #define RT_USING_IDLE_HOOK @@ -18,19 +88,13 @@ #define RT_TIMER_THREAD_PRIO 4 #define RT_TIMER_THREAD_STACK_SIZE 8192 -/* kservice optimization */ +/* kservice options */ -/* end of kservice optimization */ - -/* klibc optimization */ - -#define RT_KLIBC_USING_VSNPRINTF_LONGLONG -/* end of klibc optimization */ +/* end of kservice options */ #define RT_USING_DEBUG #define RT_DEBUGING_ASSERT #define RT_DEBUGING_COLOR #define RT_DEBUGING_CONTEXT -#define RT_USING_OVERFLOW_CHECK /* Inter-Thread communication */ @@ -56,7 +120,6 @@ #define RT_USING_DEVICE #define RT_USING_DEVICE_OPS #define RT_USING_INTERRUPT_INFO -#define RT_USING_SCHED_THREAD_CTX #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 256 #define RT_CONSOLE_DEVICE_NAME "uart0" @@ -82,7 +145,9 @@ #define ARCH_ARM #define ARCH_ARM_MMU #define ARCH_ARMV8 +#define ARCH_USING_ASID #define ARCH_USING_HW_THREAD_SELF +#define ARCH_USING_IRQ_CTX_LIST /* RT-Thread Components */ @@ -150,14 +215,6 @@ #define RT_USING_RANDOM #define RT_USING_PM #define PM_TICKLESS_THRESHOLD_TIME 2 -#define RT_USING_VIRTIO -#define RT_USING_VIRTIO10 -#define RT_USING_VIRTIO_MMIO_ALIGN -#define RT_USING_VIRTIO_BLK -#define RT_USING_VIRTIO_CONSOLE -#define RT_USING_VIRTIO_CONSOLE_PORT_MAX_NR 4 -#define RT_USING_VIRTIO_GPU -#define RT_USING_VIRTIO_INPUT #define RT_USING_OFW #define RT_FDT_EARLYCON_MSG_SIZE 128 #define RT_USING_OFW_BUS_RANGES_NUMBER 8 diff --git a/bsp/stm32/stm32l496-st-nucleo/.ci/attachconfig/ci.attachconfig.yml b/bsp/stm32/stm32l496-st-nucleo/.ci/attachconfig/ci.attachconfig.yml new file mode 100644 index 00000000000..8715453924d --- /dev/null +++ b/bsp/stm32/stm32l496-st-nucleo/.ci/attachconfig/ci.attachconfig.yml @@ -0,0 +1,10 @@ +nano: + scons_arg: + - '--strict' + kconfig: + - CONFIG_RT_USING_NANO=y +devices.on_chip: + kconfig: + - CONFIG_BSP_USING_ON_CHIP_FLASH=y + - CONFIG_BSP_USING_ON_CHIP_FLASH_FATFS=y + - CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=2048 \ No newline at end of file diff --git a/bsp/stm32/stm32l496-st-nucleo/.ci/attachconfig/nano.attach b/bsp/stm32/stm32l496-st-nucleo/.ci/attachconfig/nano.attach deleted file mode 100644 index f1ad05b2391..00000000000 --- a/bsp/stm32/stm32l496-st-nucleo/.ci/attachconfig/nano.attach +++ /dev/null @@ -1,2 +0,0 @@ -# scons: --strict -CONFIG_RT_USING_NANO=y diff --git a/components/dfs/dfs_v2/src/dfs_pcache.c b/components/dfs/dfs_v2/src/dfs_pcache.c index 6868170b9cb..2a68c268a4a 100644 --- a/components/dfs/dfs_v2/src/dfs_pcache.c +++ b/components/dfs/dfs_v2/src/dfs_pcache.c @@ -16,15 +16,16 @@ #include #include #include -#include -#include -#include -#include #include #ifdef RT_USING_PAGECACHE +#include +#include +#include +#include + #ifndef RT_PAGECACHE_COUNT #define RT_PAGECACHE_COUNT 4096 #endif diff --git a/components/drivers/core/device.c b/components/drivers/core/device.c index 5dfd0c4653e..751b662d4ec 100644 --- a/components/drivers/core/device.c +++ b/components/drivers/core/device.c @@ -31,9 +31,9 @@ #include /* for wqueue_init */ #endif /* RT_USING_POSIX_DEVIO */ -#ifdef RT_USING_DFS_V2 +#if defined (RT_USING_DFS_V2) && defined (RT_USING_DFS_DEVFS) #include -#endif /* RT_USING_DFS_V2 */ +#endif /* RT_USING_DFS_V2 RT_USING_DFS_DEVFS */ #ifdef RT_USING_DEVICE @@ -84,7 +84,7 @@ rt_err_t rt_device_register(rt_device_t dev, rt_wqueue_init(&(dev->wait_queue)); #endif /* RT_USING_POSIX_DEVIO */ -#ifdef RT_USING_DFS_V2 +#if defined (RT_USING_DFS_V2) && defined (RT_USING_DFS_DEVFS) dfs_devfs_device_add(dev); #endif /* RT_USING_DFS_V2 */ diff --git a/components/drivers/include/ipc/workqueue.h b/components/drivers/include/ipc/workqueue.h index e05a7ab63f8..8d0c986b4f0 100644 --- a/components/drivers/include/ipc/workqueue.h +++ b/components/drivers/include/ipc/workqueue.h @@ -13,6 +13,7 @@ #include #include +#include "completion.h" #ifdef __cplusplus extern "C" { @@ -42,6 +43,7 @@ struct rt_workqueue struct rt_semaphore sem; rt_thread_t work_thread; struct rt_spinlock spinlock; + struct rt_completion wakeup_completion; }; struct rt_work @@ -52,7 +54,7 @@ struct rt_work void *work_data; rt_uint16_t flags; rt_uint16_t type; - struct rt_timer timer; + rt_tick_t timeout_tick; struct rt_workqueue *workqueue; }; diff --git a/components/drivers/ipc/workqueue.c b/components/drivers/ipc/workqueue.c index fb3657b1925..ebe9598fbcb 100644 --- a/components/drivers/ipc/workqueue.c +++ b/components/drivers/ipc/workqueue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2023, RT-Thread Development Team + * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -10,6 +10,7 @@ * 2021-08-14 Jackistang add comments for function interface * 2022-01-16 Meco Man add rt_work_urgent() * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable + * 2024-12-21 yuqingli delete timer, using list */ #include @@ -17,8 +18,6 @@ #ifdef RT_USING_HEAP -static void _delayed_work_timeout_handler(void *parameter); - rt_inline rt_err_t _workqueue_work_completion(struct rt_workqueue *queue) { rt_err_t result; @@ -50,38 +49,61 @@ rt_inline rt_err_t _workqueue_work_completion(struct rt_workqueue *queue) static void _workqueue_thread_entry(void *parameter) { - rt_base_t level; - struct rt_work *work; + rt_base_t level; + struct rt_work *work; struct rt_workqueue *queue; + rt_tick_t current_tick; + rt_int32_t delay_tick; + void (*work_func)(struct rt_work *work, void *work_data); + void *work_data; - queue = (struct rt_workqueue *) parameter; + queue = (struct rt_workqueue *)parameter; RT_ASSERT(queue != RT_NULL); while (1) { level = rt_spin_lock_irqsave(&(queue->spinlock)); - if (rt_list_isempty(&(queue->work_list))) + + /* timer check */ + current_tick = rt_tick_get(); + delay_tick = RT_WAITING_FOREVER; + while (!rt_list_isempty(&(queue->delayed_list))) { - /* no software timer exist, suspend self. */ - rt_thread_suspend_with_flag(rt_thread_self(), RT_UNINTERRUPTIBLE); + work = rt_list_entry(queue->delayed_list.next, struct rt_work, list); + if ((current_tick - work->timeout_tick) < RT_TICK_MAX / 2) + { + rt_list_remove(&(work->list)); + rt_list_insert_after(queue->work_list.prev, &(work->list)); + work->flags &= ~RT_WORK_STATE_SUBMITTING; + work->flags |= RT_WORK_STATE_PENDING; + } + else + { + delay_tick = work->timeout_tick - current_tick; + break; + } + } - /* release lock after suspend so we will not lost any wakeups */ + if (rt_list_isempty(&(queue->work_list))) + { rt_spin_unlock_irqrestore(&(queue->spinlock), level); - - rt_schedule(); + /* wait for work completion */ + rt_completion_wait(&(queue->wakeup_completion), delay_tick); continue; } /* we have work to do with. */ work = rt_list_entry(queue->work_list.next, struct rt_work, list); rt_list_remove(&(work->list)); - queue->work_current = work; - work->flags &= ~RT_WORK_STATE_PENDING; - work->workqueue = RT_NULL; + queue->work_current = work; + work->flags &= ~RT_WORK_STATE_PENDING; + work->workqueue = RT_NULL; + work_func = work->work_func; + work_data = work->work_data; rt_spin_unlock_irqrestore(&(queue->spinlock), level); /* do work */ - work->work_func(work, work->work_data); + work_func(work, work_data); /* clean current work */ queue->work_current = RT_NULL; @@ -93,52 +115,50 @@ static void _workqueue_thread_entry(void *parameter) static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t ticks) { - rt_base_t level; - rt_err_t err = RT_EOK; + rt_base_t level; + rt_err_t err = RT_EOK; + struct rt_work *work_tmp; + rt_list_t *list_tmp; level = rt_spin_lock_irqsave(&(queue->spinlock)); - /* remove list */ rt_list_remove(&(work->list)); - work->flags &= ~RT_WORK_STATE_PENDING; + work->flags = 0; if (ticks == 0) { rt_list_insert_after(queue->work_list.prev, &(work->list)); - work->flags |= RT_WORK_STATE_PENDING; - work->workqueue = queue; + work->flags |= RT_WORK_STATE_PENDING; + work->workqueue = queue; - /* whether the workqueue is doing work */ - if (queue->work_current == RT_NULL) - { - /* resume work thread, and do a re-schedule if succeed */ - rt_thread_resume(queue->work_thread); - } + rt_completion_done(&(queue->wakeup_completion)); + err = RT_EOK; } else if (ticks < RT_TICK_MAX / 2) { - /* Timer started */ - if (work->flags & RT_WORK_STATE_SUBMITTING) - { - rt_timer_control(&work->timer, RT_TIMER_CTRL_SET_TIME, &ticks); - } - else + /* insert delay work list */ + work->flags |= RT_WORK_STATE_SUBMITTING; + work->workqueue = queue; + work->timeout_tick = rt_tick_get() + ticks; + + list_tmp = &(queue->delayed_list); + rt_list_for_each_entry(work_tmp, &(queue->delayed_list), list) { - rt_timer_init(&(work->timer), "work", _delayed_work_timeout_handler, - work, ticks, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER); - work->flags |= RT_WORK_STATE_SUBMITTING; + if ((work_tmp->timeout_tick - work->timeout_tick) < RT_TICK_MAX / 2) + { + list_tmp = &(work_tmp->list); + break; + } } - work->workqueue = queue; - /* insert delay work list */ - rt_list_insert_after(queue->delayed_list.prev, &(work->list)); + rt_list_insert_before(list_tmp, &(work->list)); - err = rt_timer_start(&(work->timer)); + rt_completion_done(&(queue->wakeup_completion)); + err = RT_EOK; } else { - err = - RT_ERROR; + err = -RT_ERROR; } - rt_spin_unlock_irqrestore(&(queue->spinlock), level); return err; } @@ -146,61 +166,17 @@ static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue, static rt_err_t _workqueue_cancel_work(struct rt_workqueue *queue, struct rt_work *work) { rt_base_t level; - rt_err_t err; + rt_err_t err; level = rt_spin_lock_irqsave(&(queue->spinlock)); rt_list_remove(&(work->list)); - work->flags &= ~RT_WORK_STATE_PENDING; - /* Timer started */ - if (work->flags & RT_WORK_STATE_SUBMITTING) - { - if ((err = rt_timer_stop(&(work->timer))) != RT_EOK) - { - goto exit; - } - rt_timer_detach(&(work->timer)); - work->flags &= ~RT_WORK_STATE_SUBMITTING; - } - err = queue->work_current != work ? RT_EOK : -RT_EBUSY; + work->flags = 0; + err = queue->work_current != work ? RT_EOK : -RT_EBUSY; work->workqueue = RT_NULL; -exit: rt_spin_unlock_irqrestore(&(queue->spinlock), level); return err; } -static void _delayed_work_timeout_handler(void *parameter) -{ - struct rt_work *work; - struct rt_workqueue *queue; - rt_base_t level; - - work = (struct rt_work *)parameter; - queue = work->workqueue; - - RT_ASSERT(work->flags & RT_WORK_STATE_SUBMITTING); - RT_ASSERT(queue != RT_NULL); - - level = rt_spin_lock_irqsave(&(queue->spinlock)); - rt_timer_detach(&(work->timer)); - work->flags &= ~RT_WORK_STATE_SUBMITTING; - /* remove delay list */ - rt_list_remove(&(work->list)); - /* insert work queue */ - if (queue->work_current != work) - { - rt_list_insert_after(queue->work_list.prev, &(work->list)); - work->flags |= RT_WORK_STATE_PENDING; - } - /* whether the workqueue is doing work */ - if (queue->work_current == RT_NULL) - { - /* resume work thread, and do a re-schedule if succeed */ - rt_thread_resume(queue->work_thread); - } - - rt_spin_unlock_irqrestore(&(queue->spinlock), level); -} - /** * @brief Initialize a work item, binding with a callback function. * @@ -221,8 +197,8 @@ void rt_work_init(struct rt_work *work, work->work_func = work_func; work->work_data = work_data; work->workqueue = RT_NULL; - work->flags = 0; - work->type = 0; + work->flags = 0; + work->type = 0; } /** @@ -248,6 +224,7 @@ struct rt_workqueue *rt_workqueue_create(const char *name, rt_uint16_t stack_siz rt_list_init(&(queue->delayed_list)); queue->work_current = RT_NULL; rt_sem_init(&(queue->sem), "wqueue", 0, RT_IPC_FLAG_FIFO); + rt_completion_init(&(queue->wakeup_completion)); /* create the work thread */ queue->work_thread = rt_thread_create(name, _workqueue_thread_entry, queue, stack_size, priority, 10); @@ -292,7 +269,6 @@ rt_err_t rt_workqueue_destroy(struct rt_workqueue *queue) * @param work is a pointer to the work item object. * * @return RT_EOK Success. - * -RT_EBUSY This work item is executing. */ rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work) { @@ -314,7 +290,6 @@ rt_err_t rt_workqueue_dowork(struct rt_workqueue *queue, struct rt_work *work) * NOTE: The max timeout tick should be no more than (RT_TICK_MAX/2 - 1) * * @return RT_EOK Success. - * -RT_EBUSY This work item is executing. * -RT_ERROR The ticks parameter is invalid. */ rt_err_t rt_workqueue_submit_work(struct rt_workqueue *queue, struct rt_work *work, rt_tick_t ticks) @@ -346,14 +321,10 @@ rt_err_t rt_workqueue_urgent_work(struct rt_workqueue *queue, struct rt_work *wo /* NOTE: the work MUST be initialized firstly */ rt_list_remove(&(work->list)); rt_list_insert_after(&queue->work_list, &(work->list)); - /* whether the workqueue is doing work */ - if (queue->work_current == RT_NULL) - { - /* resume work thread, and do a re-schedule if succeed */ - rt_thread_resume(queue->work_thread); - } + rt_completion_done(&(queue->wakeup_completion)); rt_spin_unlock_irqrestore(&(queue->spinlock), level); + return RT_EOK; } @@ -448,7 +419,6 @@ static struct rt_workqueue *sys_workq; /* system work queue */ * NOTE: The max timeout tick should be no more than (RT_TICK_MAX/2 - 1) * * @return RT_EOK Success. - * -RT_EBUSY This work item is executing. * -RT_ERROR The ticks parameter is invalid. */ rt_err_t rt_work_submit(struct rt_work *work, rt_tick_t ticks) diff --git a/components/drivers/usb/cherryusb/CherryUSB.svg b/components/drivers/usb/cherryusb/CherryUSB.svg index c1ed4782122..91de329f8d8 100644 --- a/components/drivers/usb/cherryusb/CherryUSB.svg +++ b/components/drivers/usb/cherryusb/CherryUSB.svg @@ -1,3 +1,3 @@ -
CherryUSB
CherryUSB
Hardware
Hardware
BL
BL
DWC2
DWC2
OHCI
OHCI
EHCI
EHCI
XHCI
XHCI
MUSB
MUSB
FSDEV
FSDEV
HPM
HPM
Device Controller Driver (DCD)
Device Controller Driver (DCD)
Host Controller Driver (HCD)
Host Controller Driver (HCD)
OS Abstraction Layer (OSAL)
OS Abstraction Layer (OSAL)
USB Host
USB Host
USB Host Core
USB Host Core
HID
HID
MSC
MSC
CDC
CDC
UAC
UAC
UVC
UVC
RNDIS
RNDIS
VENDOR
VENDOR
HUB
HUB
USB Device
USB Device
USB Device Core
USB Device Core
HID
HID
MSC
MSC
CDC
CDC
UAC
UAC
UVC
UVC
RNDIS
RNDIS
VENDOR
VENDOR
DFU
DFU
optional
optional
required
required
Text is not SVG - cannot display
\ No newline at end of file +
CherryUSB
CherryUSB
Hardware
Hardware
CDNS3
CDNS3
CHIPIDEA
CHIPIDEA
XHCI
XHCI
EHCI
EHCI
OHCI
OHCI
DWC2
DWC2
MUSB
MUSB
FOTG
FOTG
Device Controller Driver (DCD)
Device Controller Driver (DCD)
Host Controller Driver (HCD)
Host Controller Driver (HCD)
OS Abstraction Layer (OSAL)
OS Abstraction Layer (OSAL)
USB Host
USB Host
USB Host Core
USB Host Core
HID
HID
MSC
MSC
CDC
CDC
UAC
UAC
UVC
UVC
RNDIS
RNDIS
VENDOR
VENDOR
HUB
HUB
USB Device
USB Device
USB Device Core
USB Device Core
HID
HID
MSC
MSC
CDC
CDC
UAC
UAC
UVC
UVC
RNDIS
RNDIS
VENDOR
VENDOR
DFU
DFU
optional
optional
required
required
\ No newline at end of file diff --git a/components/drivers/usb/cherryusb/Kconfig b/components/drivers/usb/cherryusb/Kconfig index 6f6789d0029..67c6ad543a1 100644 --- a/components/drivers/usb/cherryusb/Kconfig +++ b/components/drivers/usb/cherryusb/Kconfig @@ -38,6 +38,8 @@ if RT_USING_CHERRYUSB bool "dwc2_gd" config RT_CHERRYUSB_DEVICE_DWC2_HC bool "dwc2_hc" + config RT_CHERRYUSB_DEVICE_DWC2_KENDRYTE + bool "dwc2_kendryte" config RT_CHERRYUSB_DEVICE_DWC2_CUSTOM bool "dwc2_custom" config RT_CHERRYUSB_DEVICE_MUSB_ES @@ -182,6 +184,8 @@ if RT_USING_CHERRYUSB bool "dwc2_st" config RT_CHERRYUSB_HOST_DWC2_ESP bool "dwc2_esp" + config RT_CHERRYUSB_HOST_DWC2_KENDRYTE + bool "dwc2_kendryte" config RT_CHERRYUSB_HOST_DWC2_CUSTOM bool "dwc2_custom" config RT_CHERRYUSB_HOST_MUSB_ES diff --git a/components/drivers/usb/cherryusb/README.md b/components/drivers/usb/cherryusb/README.md index bbea73f2f46..e56946a7722 100644 --- a/components/drivers/usb/cherryusb/README.md +++ b/components/drivers/usb/cherryusb/README.md @@ -1,6 +1,16 @@ -# CherryUSB - -[中文版](./README_zh.md) +

CherryUSB

+

+ + + + +

+ +

+ 中文 + | + English +

CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP. @@ -103,6 +113,7 @@ CherryUSB Host Stack has the following functions: - Support USB Bluetooth class (support nimble and zephyr bluetooth stack, support **CLASS:0xE0** or vendor class like cdc acm) - Support Vendor class (serial, net, wifi) - Support USB modeswitch +- Support Android Open Accessory - Support multi host with the same USB IP 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. @@ -149,7 +160,7 @@ Only standard and commercial USB IP are listed. | IP | device | host | Support status | |:----------------:|:----------:|:--------:|:--------------:| -| OHCI(intel) | none | OHCI | × | +| OHCI(intel) | none | OHCI | √ | | EHCI(intel) | none | EHCI | √ | | XHCI(intel) | none | XHCI | √ | | UHCI(intel) | none | UHCI | × | @@ -186,6 +197,7 @@ USB basic concepts and how the CherryUSB Device stack is implemented, see [Cherr |Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term | |Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term | |NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term | +|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term | |AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb | |Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb | |Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD | @@ -212,4 +224,4 @@ CherryUSB discord: https://discord.com/invite/wFfvrSAey8. Thanks to the following companies for their support (in no particular order). - + diff --git a/components/drivers/usb/cherryusb/README_zh.md b/components/drivers/usb/cherryusb/README_zh.md index 1e8b54398ee..50d2b6f672b 100644 --- a/components/drivers/usb/cherryusb/README_zh.md +++ b/components/drivers/usb/cherryusb/README_zh.md @@ -1,6 +1,16 @@ -# CherryUSB - -[English](./README.md) +

CherryUSB

+

+ + + + +

+ +

+ 中文 + | + English +

CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB IP)的 USB 主从协议栈。 @@ -103,6 +113,7 @@ CherryUSB Host 协议栈当前实现以下功能: - 支持 USB Bluetooth (支持 nimble and zephyr bluetooth 协议栈,支持 **CLASS: 0xE0** 或者厂家自定义类,类似于 cdc acm 功能) - 支持 Vendor 类 class (serial, net, wifi) - 支持 USB modeswitch +- 支持 Android Open Accessory - 支持相同 USB IP 的多主机 同时,CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。 @@ -149,7 +160,7 @@ x 受以下宏影响: | IP | device | host | Support status | |:----------------:|:----------:|:--------:|:--------------:| -| OHCI(intel) | none | OHCI | × | +| OHCI(intel) | none | OHCI | √ | | EHCI(intel) | none | EHCI | √ | | XHCI(intel) | none | XHCI | √ | | UHCI(intel) | none | UHCI | × | @@ -187,6 +198,7 @@ CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和 |Artinchip | d12x/d13x/d21x | aic/ehci/ohci |[luban-lite](https://gitee.com/artinchip/luban-lite)|<= latest | Long-term | |Espressif | esp32s2/esp32s3/esp32p4 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|<= latest | Long-term | |NXP | mcx | kinetis/chipidea/ehci |[nxp_mcx_repo](https://github.com/CherryUSB/cherryusb_mcx)|<= latest | Long-term | +|Kendryte | k230 | dwc2 |[k230_repo](https://github.com/CherryUSB/canmv_k230)|v1.2.0 | Long-term | |AllwinnerTech | F1C100S/F1C200S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|<= latest | the same with musb | |Bekencorp | bk7256/bk7258 | musb |[bk_idk](https://github.com/CherryUSB/bk_idk)| v0.7.0 | the same with musb | |Sophgo | cv18xx | dwc2 |[cvi_alios_open](https://github.com/CherryUSB/cvi_alios_open)| v0.7.0 | TBD | @@ -214,4 +226,4 @@ CherryUSB 微信群:与我联系后邀请加入 感谢以下企业支持(顺序不分先后)。 - + diff --git a/components/drivers/usb/cherryusb/SConscript b/components/drivers/usb/cherryusb/SConscript index e8e69705b00..58d0aa01c2c 100644 --- a/components/drivers/usb/cherryusb/SConscript +++ b/components/drivers/usb/cherryusb/SConscript @@ -45,6 +45,9 @@ if GetDepend(['RT_CHERRYUSB_DEVICE']): if GetDepend(['RT_CHERRYUSB_DEVICE_DWC2_HC']): src += Glob('port/dwc2/usb_dc_dwc2.c') src += Glob('port/dwc2/usb_glue_hc.c') + if GetDepend(['RT_CHERRYUSB_DEVICE_DWC2_KENDRYTE']): + src += Glob('port/dwc2/usb_dc_dwc2.c') + src += Glob('port/dwc2/usb_glue_kendryte.c') if GetDepend(['RT_CHERRYUSB_DEVICE_DWC2_CUSTOM']): src += Glob('port/dwc2/usb_dc_dwc2.c') if GetDepend(['RT_CHERRYUSB_DEVICE_MUSB_ES']): @@ -177,6 +180,9 @@ if GetDepend(['RT_CHERRYUSB_HOST']): if GetDepend(['RT_CHERRYUSB_HOST_DWC2_ESP']): src += Glob('port/dwc2/usb_hc_dwc2.c') src += Glob('port/dwc2/usb_glue_esp.c') + if GetDepend(['RT_CHERRYUSB_HOST_DWC2_KENDRYTE']): + src += Glob('port/dwc2/usb_hc_dwc2.c') + src += Glob('port/dwc2/usb_glue_kendryte.c') if GetDepend(['RT_CHERRYUSB_HOST_DWC2_CUSTOM']): src += Glob('port/dwc2/usb_hc_dwc2.c') if GetDepend(['RT_CHERRYUSB_HOST_MUSB_STANDARD']): diff --git a/components/drivers/usb/cherryusb/VERSION b/components/drivers/usb/cherryusb/VERSION index 82894229cf1..340d4aefcd5 100644 --- a/components/drivers/usb/cherryusb/VERSION +++ b/components/drivers/usb/cherryusb/VERSION @@ -1,5 +1,5 @@ VERSION_MAJOR = 1 VERSION_MINOR = 4 -PATCHLEVEL = 1 +PATCHLEVEL = 2 VERSION_TWEAK = 0 EXTRAVERSION = 0 diff --git a/components/drivers/usb/cherryusb/cherryusb.cmake b/components/drivers/usb/cherryusb/cherryusb.cmake index 81e4f8262c0..271717008ca 100644 --- a/components/drivers/usb/cherryusb/cherryusb.cmake +++ b/components/drivers/usb/cherryusb/cherryusb.cmake @@ -40,6 +40,7 @@ ${CMAKE_CURRENT_LIST_DIR}/class/adb ${CMAKE_CURRENT_LIST_DIR}/class/vendor/net ${CMAKE_CURRENT_LIST_DIR}/class/vendor/serial ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi +${CMAKE_CURRENT_LIST_DIR}/class/aoa ) if(CONFIG_CHERRYUSB_DEVICE) @@ -218,6 +219,9 @@ if(CONFIG_CHERRYUSB_HOST) if(CONFIG_CHERRYUSB_HOST_BL616) list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/vendor/wifi/usbh_bl616.c) endif() + if(CONFIG_CHERRYUSB_HOST_AOA) + list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/class/aoa/usbh_aoa.c) + endif() if(DEFINED CONFIG_CHERRYUSB_HOST_HCD) if("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "ehci_bouffalo") @@ -294,4 +298,9 @@ endif() if(CONFIG_CHERRYMP) list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool.c) list(APPEND cherryusb_incs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp) + if("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "freertos") + list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_freertos.c) + elseif("${CONFIG_CHERRYUSB_OSAL}" STREQUAL "rtthread") + list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/third_party/cherrymp/chry_mempool_osal_rtthread.c) + endif() endif() \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/cherryusb_config_template.h b/components/drivers/usb/cherryusb/cherryusb_config_template.h index 30869b437a1..e7d5230f1c5 100644 --- a/components/drivers/usb/cherryusb/cherryusb_config_template.h +++ b/components/drivers/usb/cherryusb/cherryusb_config_template.h @@ -208,6 +208,9 @@ #define CONFIG_USBDEV_EP_NUM 8 #endif +/* When your chip hardware supports high-speed and wants to initialize it in high-speed mode, the relevant IP will configure the internal or external high-speed PHY according to CONFIG_USB_HS. */ +// #define CONFIG_USB_HS + /* ---------------- FSDEV Configuration ---------------- */ //#define CONFIG_USBDEV_FSDEV_PMA_ACCESS 2 // maybe 1 or 2, many chips may have a difference diff --git a/components/drivers/usb/cherryusb/class/aoa/usb_aoa.h b/components/drivers/usb/cherryusb/class/aoa/usb_aoa.h new file mode 100644 index 00000000000..6b6c715c2a6 --- /dev/null +++ b/components/drivers/usb/cherryusb/class/aoa/usb_aoa.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef USB_AOA_H +#define USB_AOA_H + +//AOA 1.0 +#define AOA_ACCESSORY_VENDOR_ID 0x18D1 +#define AOA_ACCESSORY_PRODUCT_ID 0x2D00 +#define AOA_ACCESSORY_ADB_PRODUCT_ID 0x2D01 + +//AOA 2.0 +#define AOA_AUDIO_PRODUCT_ID 0x2D02 +#define AOA_AUDIO_ADB_PRODUCT_ID 0x2D03 +#define AOA_ACCESSORY_AUDIO_PRODUCT_ID 0x2D04 +#define AOA_ACCESSORY_AUDIO_ADB_PRODUCT_ID 0x2D05 + +//AOA 1.0 +#define AOA_ACCESSORY_GET_PROTOCOL 51 +#define AOA_ACCESSORY_SEND_STRING 52 +#define AOA_ACCESSORY_START 53 + +//AOA 2.0 +#define AOA_ACCESSORY_REGISTER_HID 54 +#define AOA_ACCESSORY_UNREGISTER_HID 55 +#define AOA_ACCESSORY_SET_HID_REPORT_DESC 56 +#define AOA_ACCESSORY_SEND_HID_EVENT 57 +#define AOA_ACCESSORY_SET_AUDIO_MODE 58 + +#define AOA_ACCESSORY_STRING_MANUFACTURER 0 +#define AOA_ACCESSORY_STRING_MODEL 1 +#define AOA_ACCESSORY_STRING_DESCRIPTION 2 +#define AOA_ACCESSORY_STRING_VERSION 3 +#define AOA_ACCESSORY_STRING_URI 4 +#define AOA_ACCESSORY_STRING_SERIAL 5 + +struct aoa_string_info { + char acc_manufacturer[64]; + char acc_model[64]; + char acc_description[64]; + char acc_version[64]; + char acc_uri[64]; + char acc_serial[64]; +}; + +#endif /* USB_AOA_H */ \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.c b/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.c new file mode 100644 index 00000000000..20cef52cf31 --- /dev/null +++ b/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "usbh_core.h" +#include "usbh_aoa.h" + +#undef USB_DBG_TAG +#define USB_DBG_TAG "usbh_aoa" +#include "usb_log.h" + +#define DEV_FORMAT "/dev/aoa" + +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_aoa_buffer[128]; + +static struct usbh_aoa g_aoa_class; + +int usbh_aoa_switch(struct usbh_hubport *hport, struct aoa_string_info *info) +{ + struct usb_setup_packet *setup; + int ret; + + setup = hport->setup; + + if (setup == NULL) { + return -USB_ERR_INVAL; + } + + USB_LOG_INFO("Try switch into aoa mode\r\n"); + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_GET_PROTOCOL; + setup->wValue = 0; + setup->wIndex = 0; + setup->wLength = 2; + + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + USB_LOG_INFO("AOA version: v%d.%d\r\n", g_aoa_buffer[0], g_aoa_buffer[1]); + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_MANUFACTURER; + setup->wLength = strlen(info->acc_manufacturer) + 1; + + memcpy(g_aoa_buffer, info->acc_manufacturer, strlen(info->acc_manufacturer)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_MODEL; + setup->wLength = strlen(info->acc_model) + 1; + + memcpy(g_aoa_buffer, info->acc_model, strlen(info->acc_model)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_DESCRIPTION; + setup->wLength = strlen(info->acc_description) + 1; + + memcpy(g_aoa_buffer, info->acc_description, strlen(info->acc_description)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_VERSION; + setup->wLength = strlen(info->acc_version) + 1; + + memcpy(g_aoa_buffer, info->acc_version, strlen(info->acc_version)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_URI; + setup->wLength = strlen(info->acc_uri) + 1; + + memcpy(g_aoa_buffer, info->acc_uri, strlen(info->acc_uri)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_STRING; + setup->wValue = 0; + setup->wIndex = AOA_ACCESSORY_STRING_SERIAL; + setup->wLength = strlen(info->acc_serial) + 1; + + memcpy(g_aoa_buffer, info->acc_serial, strlen(info->acc_serial)); + ret = usbh_control_transfer(hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_START; + setup->wValue = 0; + setup->wIndex = 0; + setup->wLength = 0; + + ret = usbh_control_transfer(hport, setup, NULL); + if (ret < 0) { + return ret; + } + + USB_LOG_INFO("Switch into aoa mode success, wait usb device restart...\r\n"); + return 0; +} + +int usbh_aoa_register_hid(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *report, uint32_t report_len) +{ + struct usb_setup_packet *setup; + int ret; + uint8_t len; + uint32_t offset; + + if (!aoa_class || !aoa_class->hport) { + return -USB_ERR_INVAL; + } + setup = aoa_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_REGISTER_HID; + setup->wValue = id; + setup->wIndex = report_len; + setup->wLength = 0; + + ret = usbh_control_transfer(aoa_class->hport, setup, NULL); + if (ret < 0) { + return ret; + } + + offset = 0; + while (report_len > 0) { + len = report_len > 64 ? 64 : report_len; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SET_HID_REPORT_DESC; + setup->wValue = id; + setup->wIndex = offset; + setup->wLength = len; + + memcpy(g_aoa_buffer, report + offset, len); + ret = usbh_control_transfer(aoa_class->hport, setup, g_aoa_buffer); + if (ret < 0) { + return ret; + } + offset += len; + report_len -= len; + } + return ret; +} + +int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *event, uint32_t event_len) +{ + struct usb_setup_packet *setup; + int ret; + uint8_t len; + uint32_t offset; + + if (!aoa_class || !aoa_class->hport) { + return -USB_ERR_INVAL; + } + setup = aoa_class->hport->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = AOA_ACCESSORY_SEND_HID_EVENT; + setup->wValue = id; + setup->wIndex = 0; + setup->wLength = event_len; + + memcpy(g_aoa_buffer, event, event_len); + return usbh_control_transfer(aoa_class->hport, setup, event); +} + +static int usbh_aoa_connect(struct usbh_hubport *hport, uint8_t intf) +{ + struct usb_endpoint_descriptor *ep_desc; + int ret = 0; + + struct usbh_aoa *aoa_class = &g_aoa_class; + + memset(aoa_class, 0, sizeof(struct usbh_aoa)); + + aoa_class->hport = hport; + aoa_class->intf = intf; + + hport->config.intf[intf].priv = aoa_class; + + for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { + ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; + + if (ep_desc->bEndpointAddress & 0x80) { + USBH_EP_INIT(aoa_class->bulkin, ep_desc); + } else { + USBH_EP_INIT(aoa_class->bulkout, ep_desc); + } + } + + strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN); + + USB_LOG_INFO("Register AOA Class:%s\r\n", hport->config.intf[intf].devname); + + usbh_aoa_run(aoa_class); + return 0; +} + +static int usbh_aoa_disconnect(struct usbh_hubport *hport, uint8_t intf) +{ + int ret = 0; + + struct usbh_aoa *aoa_class = (struct usbh_aoa *)hport->config.intf[intf].priv; + + if (aoa_class) { + if (aoa_class->bulkin) { + usbh_kill_urb(&aoa_class->bulkin_urb); + } + + if (aoa_class->bulkout) { + usbh_kill_urb(&aoa_class->bulkout_urb); + } + + if (hport->config.intf[intf].devname[0] != '\0') { + USB_LOG_INFO("Unregister AOA Class:%s\r\n", hport->config.intf[intf].devname); + usbh_aoa_stop(aoa_class); + } + + memset(aoa_class, 0, sizeof(struct usbh_aoa)); + } + + return ret; +} + +__WEAK void usbh_aoa_run(struct usbh_aoa *aoa_class) +{ + (void)aoa_class; +} + +__WEAK void usbh_aoa_stop(struct usbh_aoa *aoa_class) +{ + (void)aoa_class; +} + +static const uint16_t aoa_id_table[][2] = { + { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_PRODUCT_ID }, + { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_ADB_PRODUCT_ID }, + { AOA_ACCESSORY_VENDOR_ID, AOA_AUDIO_PRODUCT_ID }, + { AOA_ACCESSORY_VENDOR_ID, AOA_AUDIO_ADB_PRODUCT_ID }, + { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_AUDIO_PRODUCT_ID }, + { AOA_ACCESSORY_VENDOR_ID, AOA_ACCESSORY_AUDIO_ADB_PRODUCT_ID }, + { 0, 0 }, +}; + +const struct usbh_class_driver aoa_class_driver = { + .driver_name = "aoa", + .connect = usbh_aoa_connect, + .disconnect = usbh_aoa_disconnect +}; + +CLASS_INFO_DEFINE const struct usbh_class_info aoa_intf_class_info = { + .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0x00, + .id_table = aoa_id_table, + .class_driver = &aoa_class_driver +}; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.h b/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.h new file mode 100644 index 00000000000..3b184e8b980 --- /dev/null +++ b/components/drivers/usb/cherryusb/class/aoa/usbh_aoa.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef USBH_AOA_H +#define USBH_AOA_H + +#include "usb_aoa.h" + +struct usbh_aoa { + struct usbh_hubport *hport; + struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */ + struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */ + + struct usbh_urb bulkout_urb; + struct usbh_urb bulkin_urb; + + uint8_t intf; + uint8_t minor; + + void *user_data; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int usbh_aoa_switch(struct usbh_hubport *hport, struct aoa_string_info *info); +int usbh_aoa_register_hid(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *report, uint32_t report_len); +int usbh_aoa_send_hid_event(struct usbh_aoa *aoa_class, uint16_t id, uint8_t *event, uint32_t event_len); + +void usbh_aoa_run(struct usbh_aoa *aoa_class); +void usbh_aoa_stop(struct usbh_aoa *aoa_class); + +#ifdef __cplusplus +} +#endif + +#endif /* USBH_AOA_H */ \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/audio/usb_audio.h b/components/drivers/usb/cherryusb/class/audio/usb_audio.h index 1aced20ff4f..ff7a9fe2a95 100644 --- a/components/drivers/usb/cherryusb/class/audio/usb_audio.h +++ b/components/drivers/usb/cherryusb/class/audio/usb_audio.h @@ -648,6 +648,18 @@ struct audio_cs_if_ac_feature_unit_descriptor { #define AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(ch, n) (7 + (ch + 1) * n) +struct audio_cs_if_ac_selector_unit_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bUnitID; + uint8_t bNrInPins; + uint8_t baSourceID[1]; + uint8_t iSelector; +} __PACKED; + +#define AUDIO_SIZEOF_AC_SELECTOR_UNIT_DESC(n) (6 + n) + struct audio_cs_if_as_general_descriptor { uint8_t bLength; uint8_t bDescriptorType; diff --git a/components/drivers/usb/cherryusb/class/audio/usbd_audio.c b/components/drivers/usb/cherryusb/class/audio/usbd_audio.c index 4ff3767abff..458f1c191f7 100644 --- a/components/drivers/usb/cherryusb/class/audio/usbd_audio.c +++ b/components/drivers/usb/cherryusb/class/audio/usbd_audio.c @@ -136,27 +136,26 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup memcpy(&volume, *data, *len); if (volume < 0x8000) { volume_db = volume / 256; - } else if (volume > 0x8000) { - volume_db = (0xffff - volume + 1) / -256; + } else { + volume_db = (volume - 0x10000) / 256; } - volume_db += 128; /* 0 ~ 255 */ - USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%04x\r\n", ep, ch, volume); + USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db); usbd_audio_set_volume(busid, ep, ch, volume_db); break; case AUDIO_REQUEST_GET_CUR: volume_db = usbd_audio_get_volume(busid, ep, ch); - volume_db -= 128; if (volume_db >= 0) { volume = volume_db * 256; } else { - volume = volume_db * 256 + 0xffff + 1; + volume = volume_db * 256 + 0x10000; } + USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db); memcpy(*data, &volume, 2); *len = 2; break; case AUDIO_REQUEST_GET_MIN: - (*data)[0] = 0x00; /* -2560/256 dB */ - (*data)[1] = 0xdb; + (*data)[0] = 0x00; /* -100 dB */ + (*data)[1] = 0x9c; *len = 2; break; case AUDIO_REQUEST_GET_MAX: @@ -165,7 +164,7 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup *len = 2; break; case AUDIO_REQUEST_GET_RES: - (*data)[0] = 0x00; /* -256/256 dB */ + (*data)[0] = 0x00; /* 1 dB */ (*data)[1] = 0x01; *len = 2; break; @@ -178,22 +177,31 @@ static int audio_class_interface_request_handler(uint8_t busid, struct usb_setup case AUDIO_REQUEST_CUR: if (setup->bmRequestType & USB_REQUEST_DIR_MASK) { volume_db = usbd_audio_get_volume(busid, ep, ch); - volume = volume_db; + if (volume_db >= 0) { + volume = volume_db * 256; + } else { + volume = volume_db * 256 + 0x10000; + } + USB_LOG_DBG("Get ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db); memcpy(*data, &volume, 2); *len = 2; } else { memcpy(&volume, *data, *len); - volume_db = volume; - USB_LOG_DBG("Set ep:0x%02x ch:%d volume:0x%02x\r\n", ep, ch, volume); + if (volume < 0x8000) { + volume_db = volume / 256; + } else { + volume_db = (volume - 0x10000) / 256; + } + USB_LOG_DBG("Set ep:0x%02x ch:%d vol_hex:0x%04x, vol_db:%d dB\r\n", ep, ch, volume, volume_db); usbd_audio_set_volume(busid, ep, ch, volume_db); } break; case AUDIO_REQUEST_RANGE: if (setup->bmRequestType & USB_REQUEST_DIR_MASK) { *((uint16_t *)(*data + 0)) = 1; - *((uint16_t *)(*data + 2)) = 0; - *((uint16_t *)(*data + 4)) = 100; - *((uint16_t *)(*data + 6)) = 1; + *((uint16_t *)(*data + 2)) = 0x9c00; /* MIN -100 dB */ + *((uint16_t *)(*data + 4)) = 0x0000; /* MAX 0 dB */ + *((uint16_t *)(*data + 6)) = 0x100; /* RES 1 dB */ *len = 8; } else { } @@ -312,12 +320,12 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid, return intf; } -__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume) +__WEAK void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db) { (void)busid; (void)ep; (void)ch; - (void)volume; + (void)volume_db; } __WEAK int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch) diff --git a/components/drivers/usb/cherryusb/class/audio/usbd_audio.h b/components/drivers/usb/cherryusb/class/audio/usbd_audio.h index 442405a2f97..75a0b17dcda 100644 --- a/components/drivers/usb/cherryusb/class/audio/usbd_audio.h +++ b/components/drivers/usb/cherryusb/class/audio/usbd_audio.h @@ -27,7 +27,7 @@ struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface void usbd_audio_open(uint8_t busid, uint8_t intf); void usbd_audio_close(uint8_t busid, uint8_t intf); -void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume); +void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume_db); int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch); void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute); bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch); diff --git a/components/drivers/usb/cherryusb/class/audio/usbh_audio.c b/components/drivers/usb/cherryusb/class/audio/usbh_audio.c index 9e838bbae0f..6d8b4559e10 100644 --- a/components/drivers/usb/cherryusb/class/audio/usbh_audio.c +++ b/components/drivers/usb/cherryusb/class/audio/usbh_audio.c @@ -184,18 +184,21 @@ int usbh_audio_close(struct usbh_audio *audio_class, const char *name) return ret; } -int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume) +int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db) { struct usb_setup_packet *setup; int ret; uint8_t feature_id = 0xff; + uint8_t intf; uint16_t volume_hex; + int volume_min_db; + int volume_max_db; if (!audio_class || !audio_class->hport) { return -USB_ERR_INVAL; } - if (volume > 100) { + if ((volume_db > 127) || (volume_db < -127)) { return -USB_ERR_INVAL; } @@ -204,20 +207,102 @@ int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) { if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) { feature_id = audio_class->as_msg_table[i].feature_terminal_id; + intf = audio_class->as_msg_table[i].stream_intf; } } + if (feature_id == 0xff) { + return -USB_ERR_NODEV; + } + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = AUDIO_REQUEST_GET_CUR; + setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch; + setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf; + setup->wLength = 2; + + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); + if (ret < 0) { + return ret; + } + + memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur, g_audio_buf, 2); + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = AUDIO_REQUEST_GET_MIN; + setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch; + setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf; + setup->wLength = 2; + + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); + if (ret < 0) { + return ret; + } + + memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min, g_audio_buf, 2); + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = AUDIO_REQUEST_GET_MAX; + setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch; + setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf; + setup->wLength = 2; + + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); + if (ret < 0) { + return ret; + } + memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max, g_audio_buf, 2); + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = AUDIO_REQUEST_GET_RES; + setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch; + setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf; + setup->wLength = 2; + + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); + if (ret < 0) { + return ret; + } + memcpy(&audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_res, g_audio_buf, 2); + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = AUDIO_REQUEST_SET_CUR; setup->wValue = (AUDIO_FU_CONTROL_VOLUME << 8) | ch; setup->wIndex = (feature_id << 8) | audio_class->ctrl_intf; setup->wLength = 2; - volume_hex = -0xDB00 / 100 * volume + 0xdb00; + if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min < 0x8000) { + volume_min_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min / 256; + } else { + volume_min_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min - 0x10000) / 256; + } + + if (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max < 0x8000) { + volume_max_db = audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max / 256; + } else { + volume_max_db = (audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max - 0x10000) / 256; + } - memcpy(g_audio_buf, &volume_hex, 2); - ret = usbh_control_transfer(audio_class->hport, setup, NULL); + USB_LOG_INFO("Get ch:%d dB range: %d dB ~ %d dB\r\n", volume_min_db, volume_max_db); + if (volume_db >= 0) { + volume_hex = volume_db * 256; + if (volume_hex > audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_max) { + return -USB_ERR_RANGE; + } + } else { + volume_hex = volume_db * 256 + 0x10000; + if (volume_hex < audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_min) { + return -USB_ERR_RANGE; + } + } + + memcpy(g_audio_buf, &volume_hex, 2); + ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); + if (ret < 0) { + return ret; + } + audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].volume_cur = volume_hex; return ret; } @@ -226,6 +311,7 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_ struct usb_setup_packet *setup; int ret; uint8_t feature_id = 0xff; + uint8_t intf = 0xff; if (!audio_class || !audio_class->hport) { return -USB_ERR_INVAL; @@ -235,9 +321,14 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_ for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) { if (strcmp(name, audio_class->as_msg_table[i].stream_name) == 0) { feature_id = audio_class->as_msg_table[i].feature_terminal_id; + intf = audio_class->as_msg_table[i].stream_intf; } } + if (feature_id == 0xff) { + return -USB_ERR_NODEV; + } + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; setup->bRequest = AUDIO_REQUEST_SET_CUR; setup->wValue = (AUDIO_FU_CONTROL_MUTE << 8) | ch; @@ -246,7 +337,10 @@ int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_ memcpy(g_audio_buf, &mute, 1); ret = usbh_control_transfer(audio_class->hport, setup, g_audio_buf); - + if (ret < 0) { + return ret; + } + audio_class->as_msg_table[intf - audio_class->ctrl_intf - 1].mute = mute; return ret; } @@ -286,13 +380,14 @@ void usbh_audio_list_module(struct usbh_audio *audio_class) static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) { int ret; - uint8_t cur_iface = 0xff; - uint8_t cur_iface_count = 0xff; - uint8_t cur_alt_setting = 0xff; + uint8_t cur_iface = 0; + uint8_t cur_iface_count = 0; + uint8_t cur_alt_setting = 0; uint8_t input_offset = 0; uint8_t output_offset = 0; uint8_t feature_unit_offset = 0; uint8_t *p; + struct usbh_audio_ac_msg ac_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS]; struct usbh_audio *audio_class = usbh_audio_class_alloc(); if (audio_class == NULL) { @@ -327,26 +422,24 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) case AUDIO_CONTROL_INPUT_TERMINAL: { struct audio_cs_if_ac_input_terminal_descriptor *desc = (struct audio_cs_if_ac_input_terminal_descriptor *)p; - memcpy(&audio_class->ac_msg_table[input_offset].ac_input, desc, sizeof(struct audio_cs_if_ac_input_terminal_descriptor)); + memcpy(&ac_msg_table[input_offset].ac_input, desc, sizeof(struct audio_cs_if_ac_input_terminal_descriptor)); input_offset++; } break; case AUDIO_CONTROL_OUTPUT_TERMINAL: { struct audio_cs_if_ac_output_terminal_descriptor *desc = (struct audio_cs_if_ac_output_terminal_descriptor *)p; - memcpy(&audio_class->ac_msg_table[output_offset].ac_output, desc, sizeof(struct audio_cs_if_ac_output_terminal_descriptor)); + memcpy(&ac_msg_table[output_offset].ac_output, desc, sizeof(struct audio_cs_if_ac_output_terminal_descriptor)); output_offset++; } break; case AUDIO_CONTROL_FEATURE_UNIT: { struct audio_cs_if_ac_feature_unit_descriptor *desc = (struct audio_cs_if_ac_feature_unit_descriptor *)p; - memcpy(&audio_class->ac_msg_table[feature_unit_offset].ac_feature_unit, desc, desc->bLength); + memcpy(&ac_msg_table[feature_unit_offset].ac_feature_unit, desc, desc->bLength); feature_unit_offset++; } break; - case AUDIO_CONTROL_PROCESSING_UNIT: - - break; default: - break; + USB_LOG_ERR("Do not support %02x subtype\r\n", p[DESC_bDescriptorSubType]); + return -USB_ERR_NOTSUPP; } } else if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) { switch (p[DESC_bDescriptorSubType]) { @@ -383,7 +476,12 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) } if ((input_offset != output_offset) && (input_offset != feature_unit_offset)) { - USB_LOG_ERR("Audio descriptor is invalid\r\n"); + USB_LOG_ERR("Audio control descriptor is invalid\r\n"); + return -USB_ERR_INVAL; + } + + if (cur_iface_count == 0xff) { + USB_LOG_ERR("Audio descriptor must have iad descriptor\r\n"); return -USB_ERR_INVAL; } @@ -392,21 +490,21 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) { /* Search 0x0101 in input or output desc */ for (uint8_t streamidx = 0; streamidx < audio_class->stream_intf_num; streamidx++) { - if (audio_class->as_msg_table[i].as_general.bTerminalLink == audio_class->ac_msg_table[streamidx].ac_input.bTerminalID) { + if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_input.bTerminalID) { /* INPUT --> FEATURE UNIT --> OUTPUT */ - audio_class->as_msg_table[i].input_terminal_id = audio_class->ac_msg_table[streamidx].ac_input.bTerminalID; + audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[streamidx].ac_input.bTerminalID; /* Search input terminal id in feature desc */ for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) { - if (audio_class->ac_msg_table[streamidx].ac_input.bTerminalID == audio_class->ac_msg_table[featureidx].ac_feature_unit.bSourceID) { - audio_class->as_msg_table[i].feature_terminal_id = audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID; + if (ac_msg_table[streamidx].ac_input.bTerminalID == ac_msg_table[featureidx].ac_feature_unit.bSourceID) { + audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID; /* Search feature unit id in output desc */ for (uint8_t outputid = 0; outputid < audio_class->stream_intf_num; outputid++) { - if (audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID == audio_class->ac_msg_table[outputid].ac_output.bSourceID) { - audio_class->as_msg_table[i].output_terminal_id = audio_class->ac_msg_table[outputid].ac_output.bTerminalID; + if (ac_msg_table[featureidx].ac_feature_unit.bUnitID == ac_msg_table[outputid].ac_output.bSourceID) { + audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[outputid].ac_output.bTerminalID; - switch (audio_class->ac_msg_table[outputid].ac_output.wTerminalType) { + switch (ac_msg_table[outputid].ac_output.wTerminalType) { case AUDIO_OUTTERM_SPEAKER: audio_class->as_msg_table[i].stream_name = "speaker"; break; @@ -426,21 +524,21 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) break; } } - } else if (audio_class->as_msg_table[i].as_general.bTerminalLink == audio_class->ac_msg_table[streamidx].ac_output.bTerminalID) { + } else if (audio_class->as_msg_table[i].as_general.bTerminalLink == ac_msg_table[streamidx].ac_output.bTerminalID) { /* OUTPUT --> FEATURE UNIT --> INPUT */ - audio_class->as_msg_table[i].output_terminal_id = audio_class->ac_msg_table[streamidx].ac_output.bTerminalID; + audio_class->as_msg_table[i].output_terminal_id = ac_msg_table[streamidx].ac_output.bTerminalID; /* Search output terminal id in feature desc */ for (uint8_t featureidx = 0; featureidx < audio_class->stream_intf_num; featureidx++) { - if (audio_class->ac_msg_table[streamidx].ac_output.bSourceID == audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID) { - audio_class->as_msg_table[i].feature_terminal_id = audio_class->ac_msg_table[featureidx].ac_feature_unit.bUnitID; + if (ac_msg_table[streamidx].ac_output.bSourceID == ac_msg_table[featureidx].ac_feature_unit.bUnitID) { + audio_class->as_msg_table[i].feature_terminal_id = ac_msg_table[featureidx].ac_feature_unit.bUnitID; /* Search feature unit id in input desc */ for (uint8_t inputid = 0; inputid < audio_class->stream_intf_num; inputid++) { - if (audio_class->ac_msg_table[featureidx].ac_feature_unit.bSourceID == audio_class->ac_msg_table[inputid].ac_input.bTerminalID) { - audio_class->as_msg_table[i].input_terminal_id = audio_class->ac_msg_table[inputid].ac_input.bTerminalID; + if (ac_msg_table[featureidx].ac_feature_unit.bSourceID == ac_msg_table[inputid].ac_input.bTerminalID) { + audio_class->as_msg_table[i].input_terminal_id = ac_msg_table[inputid].ac_input.bTerminalID; - switch (audio_class->ac_msg_table[inputid].ac_input.wTerminalType) { + switch (ac_msg_table[inputid].ac_input.wTerminalType) { case AUDIO_INTERM_MIC: audio_class->as_msg_table[i].stream_name = "mic"; break; @@ -458,6 +556,13 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf) } } + for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) { + if (audio_class->as_msg_table[i].stream_name == NULL) { + USB_LOG_ERR("Audio stream search fail\r\n"); + return -USB_ERR_NODEV; + } + } + for (uint8_t i = 0; i < audio_class->stream_intf_num; i++) { ret = usbh_audio_close(audio_class, audio_class->as_msg_table[i].stream_name); if (ret < 0) { @@ -537,18 +642,18 @@ const struct usbh_class_driver audio_streaming_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info audio_ctrl_intf_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS, - .class = USB_DEVICE_CLASS_AUDIO, - .subclass = AUDIO_SUBCLASS_AUDIOCONTROL, - .protocol = 0x00, + .bInterfaceClass = USB_DEVICE_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOCONTROL, + .bInterfaceProtocol = 0x00, .id_table = NULL, .class_driver = &audio_ctrl_class_driver }; CLASS_INFO_DEFINE const struct usbh_class_info audio_streaming_intf_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS, - .class = USB_DEVICE_CLASS_AUDIO, - .subclass = AUDIO_SUBCLASS_AUDIOSTREAMING, - .protocol = 0x00, + .bInterfaceClass = USB_DEVICE_CLASS_AUDIO, + .bInterfaceSubClass = AUDIO_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = 0x00, .id_table = NULL, .class_driver = &audio_streaming_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/audio/usbh_audio.h b/components/drivers/usb/cherryusb/class/audio/usbh_audio.h index d6eeeffb020..2e583ac0be5 100644 --- a/components/drivers/usb/cherryusb/class/audio/usbh_audio.h +++ b/components/drivers/usb/cherryusb/class/audio/usbh_audio.h @@ -26,6 +26,11 @@ struct usbh_audio_as_msg { uint8_t output_terminal_id; uint8_t ep_attr; uint8_t num_of_altsetting; + uint16_t volume_min; + uint16_t volume_max; + uint16_t volume_res; + uint16_t volume_cur; + bool mute; struct audio_cs_if_as_general_descriptor as_general; struct audio_cs_if_as_format_type_descriptor as_format[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS]; }; @@ -43,7 +48,6 @@ struct usbh_audio { uint16_t bcdADC; uint8_t bInCollection; uint8_t stream_intf_num; - struct usbh_audio_ac_msg ac_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS]; struct usbh_audio_as_msg as_msg_table[CONFIG_USBHOST_AUDIO_MAX_STREAMS]; void *user_data; @@ -55,7 +59,7 @@ extern "C" { int usbh_audio_open(struct usbh_audio *audio_class, const char *name, uint32_t samp_freq, uint8_t bitresolution); int usbh_audio_close(struct usbh_audio *audio_class, const char *name); -int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, uint8_t volume); +int usbh_audio_set_volume(struct usbh_audio *audio_class, const char *name, uint8_t ch, int volume_db); int usbh_audio_set_mute(struct usbh_audio *audio_class, const char *name, uint8_t ch, bool mute); void usbh_audio_run(struct usbh_audio *audio_class); diff --git a/components/drivers/usb/cherryusb/class/cdc/usb_cdc.h b/components/drivers/usb/cherryusb/class/cdc/usb_cdc.h index eb2b286269b..d1546eec575 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usb_cdc.h +++ b/components/drivers/usb/cherryusb/class/cdc/usb_cdc.h @@ -524,7 +524,7 @@ struct cdc_ncm_ndp16 { int_ep, /* bEndpointAddress */ \ 0x03, /* bmAttributes */ \ 0x08, 0x00, /* wMaxPacketSize */ \ - 0x10, /* bInterval */ \ + 0x05, /* bInterval */ \ 0x09, /* bLength */ \ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ (uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \ @@ -596,7 +596,7 @@ eth_statistics, wMaxSegmentSize, wNumberMCFilters, bNumberPowerFilters, str_idx) int_ep, /* bEndpointAddress */ \ 0x03, /* bmAttributes */ \ 0x10, 0x00, /* wMaxPacketSize */ \ - 0x10, /* bInterval */ \ + 0x05, /* bInterval */ \ 0x09, /* bLength */ \ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ (uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \ diff --git a/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c b/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c index 29e82ceeaee..5ae10a207c3 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c +++ b/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.c @@ -7,17 +7,21 @@ #include "usbd_cdc_ecm.h" #define CDC_ECM_OUT_EP_IDX 0 -#define CDC_ECM_IN_EP_IDX 1 -#define CDC_ECM_INT_EP_IDX 2 +#define CDC_ECM_IN_EP_IDX 1 +#define CDC_ECM_INT_EP_IDX 2 + +/* Ethernet Maximum Segment size, typically 1514 bytes */ +#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1536U /* Describe EndPoints configuration */ static struct usbd_endpoint cdc_ecm_ep_data[3]; +#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_rx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE]; static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_tx_buffer[CONFIG_CDC_ECM_ETH_MAX_SEGSZE]; +#endif static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_cdc_ecm_notify_buf[16]; -volatile uint8_t *g_cdc_ecm_rx_data_buffer = NULL; volatile uint32_t g_cdc_ecm_rx_data_length = 0; volatile uint32_t g_cdc_ecm_tx_data_length = 0; @@ -68,8 +72,10 @@ void usbd_cdc_ecm_send_notify(uint8_t notifycode, uint8_t value, uint32_t *speed break; } - if (bytes2send) { - usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send); + if (usb_device_is_configured(0)) { + if (bytes2send) { + usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_INT_EP_IDX].ep_addr, g_cdc_ecm_notify_buf, bytes2send); + } } } @@ -93,11 +99,11 @@ static int cdc_ecm_class_interface_request_handler(uint8_t busid, struct usb_set * bit3 Broadcast * bit4 Multicast */ - if (g_current_net_status == 0) { - g_current_net_status = 1; - usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL); - } - +#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP + g_connect_speed_table[0] = 100000000; /* 100 Mbps */ + g_connect_speed_table[1] = 100000000; /* 100 Mbps */ + usbd_cdc_ecm_set_connect(true, g_connect_speed_table); +#endif break; default: USB_LOG_WRN("Unhandled CDC ECM Class bRequest 0x%02x\r\n", setup->bRequest); @@ -117,10 +123,11 @@ void cdc_ecm_notify_handler(uint8_t busid, uint8_t event, void *arg) g_current_net_status = 0; g_cdc_ecm_rx_data_length = 0; g_cdc_ecm_tx_data_length = 0; - g_cdc_ecm_rx_data_buffer = NULL; break; case USBD_EVENT_CONFIGURED: - usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(busid, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr)); +#ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP + usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE); +#endif break; default: @@ -132,14 +139,8 @@ void cdc_ecm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) { (void)busid; - g_cdc_ecm_rx_data_length += nbytes; - - if (nbytes < usbd_get_ep_mps(0, ep)) { - g_cdc_ecm_rx_data_buffer = g_cdc_ecm_rx_buffer; - usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length); - } else { - usbd_ep_start_read(0, ep, &g_cdc_ecm_rx_buffer[g_cdc_ecm_rx_data_length], usbd_get_ep_mps(0, ep)); - } + g_cdc_ecm_rx_data_length = nbytes; + usbd_cdc_ecm_data_recv_done(g_cdc_ecm_rx_data_length); } void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) @@ -150,6 +151,7 @@ void cdc_ecm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) /* send zlp */ usbd_ep_start_write(0, ep, NULL, 0); } else { + usbd_cdc_ecm_data_send_done(g_cdc_ecm_tx_data_length); g_cdc_ecm_tx_data_length = 0; } } @@ -160,14 +162,20 @@ void cdc_ecm_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes) (void)ep; (void)nbytes; - if (g_current_net_status == 1) { - g_current_net_status = 2; - usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, g_connect_speed_table); + if (g_current_net_status == 2) { + g_current_net_status = 3; + usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_CONNECTION_SPEED_CHANGE, 0, g_connect_speed_table); + } else { + g_current_net_status = 0; } } int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len) { + if (!usb_device_is_configured(0)) { + return -USB_ERR_NODEV; + } + if (g_cdc_ecm_tx_data_length > 0) { return -USB_ERR_BUSY; } @@ -175,14 +183,17 @@ int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len) g_cdc_ecm_tx_data_length = len; USB_LOG_DBG("txlen:%d\r\n", g_cdc_ecm_tx_data_length); - return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, g_cdc_ecm_tx_data_length); + return usbd_ep_start_write(0, cdc_ecm_ep_data[CDC_ECM_IN_EP_IDX].ep_addr, buf, len); } -void usbd_cdc_ecm_start_read_next(void) +int usbd_cdc_ecm_start_read(uint8_t *buf, uint32_t len) { + if (!usb_device_is_configured(0)) { + return -USB_ERR_NODEV; + } + g_cdc_ecm_rx_data_length = 0; - g_cdc_ecm_rx_data_buffer = NULL; - usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, g_cdc_ecm_rx_buffer, usbd_get_ep_mps(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr)); + return usbd_ep_start_read(0, cdc_ecm_ep_data[CDC_ECM_OUT_EP_IDX].ep_addr, buf, len); } #ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP @@ -190,19 +201,19 @@ struct pbuf *usbd_cdc_ecm_eth_rx(void) { struct pbuf *p; - if (g_cdc_ecm_rx_data_buffer == NULL) { + if (g_cdc_ecm_rx_data_length == 0) { return NULL; } p = pbuf_alloc(PBUF_RAW, g_cdc_ecm_rx_data_length, PBUF_POOL); if (p == NULL) { - usbd_cdc_ecm_start_read_next(); + usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE); return NULL; } usb_memcpy(p->payload, (uint8_t *)g_cdc_ecm_rx_buffer, g_cdc_ecm_rx_data_length); p->len = g_cdc_ecm_rx_data_length; USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ecm_rx_data_length); - usbd_cdc_ecm_start_read_next(); + usbd_cdc_ecm_start_read(g_cdc_ecm_rx_buffer, CONFIG_CDC_ECM_ETH_MAX_SEGSZE); return p; } @@ -250,13 +261,24 @@ struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const return intf; } -void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]) +void usbd_cdc_ecm_set_connect(bool connect, uint32_t speed[2]) +{ + if (connect) { + g_current_net_status = 2; + memcpy(g_connect_speed_table, speed, 8); + usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_CONNECTED, NULL); + } else { + g_current_net_status = 1; + usbd_cdc_ecm_send_notify(CDC_ECM_NOTIFY_CODE_NETWORK_CONNECTION, CDC_ECM_NET_DISCONNECTED, NULL); + } +} + +__WEAK void usbd_cdc_ecm_data_recv_done(uint32_t len) { - memcpy(g_connect_speed_table, speed, 8); + (void)len; } -__WEAK void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len) +__WEAK void usbd_cdc_ecm_data_send_done(uint32_t len) { - (void)buf; (void)len; } diff --git a/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.h b/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.h index 8d9e5c9fe00..3e0284e3288 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.h +++ b/components/drivers/usb/cherryusb/class/cdc/usbd_cdc_ecm.h @@ -12,21 +12,15 @@ extern "C" { #endif -/* Ethernet Maximum Segment size, typically 1514 bytes */ -#define CONFIG_CDC_ECM_ETH_MAX_SEGSZE 1514U - /* Init cdc ecm interface driver */ struct usbd_interface *usbd_cdc_ecm_init_intf(struct usbd_interface *intf, const uint8_t int_ep, const uint8_t out_ep, const uint8_t in_ep); -/* Setup request command callback api */ -void usbd_cdc_ecm_set_connect_speed(uint32_t speed[2]); +void usbd_cdc_ecm_set_connect(bool connect, uint32_t speed[2]); -/* Api for eth only without any net stack */ -uint8_t *usbd_cdc_ecm_get_tx_buffer(void); -void usbd_cdc_ecm_send_done(void); +void usbd_cdc_ecm_data_recv_done(uint32_t len); +void usbd_cdc_ecm_data_send_done(uint32_t len); int usbd_cdc_ecm_start_write(uint8_t *buf, uint32_t len); -void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len); -void usbd_cdc_ecm_start_read_next(void); +int usbd_cdc_ecm_start_read(uint8_t *buf, uint32_t len); #ifdef CONFIG_USBDEV_CDC_ECM_USING_LWIP #include "lwip/netif.h" diff --git a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_acm.c b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_acm.c index ceb5ad0c2dc..53666b32f03 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_acm.c +++ b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_acm.c @@ -267,18 +267,18 @@ const struct usbh_class_driver cdc_data_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS, - .class = USB_DEVICE_CLASS_CDC, - .subclass = CDC_ABSTRACT_CONTROL_MODEL, - .protocol = 0x00, + .bInterfaceClass = USB_DEVICE_CLASS_CDC, + .bInterfaceSubClass = CDC_ABSTRACT_CONTROL_MODEL, + .bInterfaceProtocol = 0x00, .id_table = NULL, .class_driver = &cdc_acm_class_driver }; CLASS_INFO_DEFINE const struct usbh_class_info cdc_data_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS, - .class = USB_DEVICE_CLASS_CDC_DATA, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = USB_DEVICE_CLASS_CDC_DATA, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = NULL, .class_driver = &cdc_data_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c index 76cfb41aa39..c4743e56d30 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c +++ b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ecm.c @@ -323,9 +323,9 @@ const struct usbh_class_driver cdc_ecm_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info cdc_ecm_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_CDC, - .subclass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL, - .protocol = CDC_COMMON_PROTOCOL_NONE, + .bInterfaceClass = USB_DEVICE_CLASS_CDC, + .bInterfaceSubClass = CDC_ETHERNET_NETWORKING_CONTROL_MODEL, + .bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE, .id_table = NULL, .class_driver = &cdc_ecm_class_driver }; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c index 094241aab58..f9f3c533819 100644 --- a/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c +++ b/components/drivers/usb/cherryusb/class/cdc/usbh_cdc_ncm.c @@ -403,9 +403,9 @@ const struct usbh_class_driver cdc_ncm_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info cdc_ncm_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_CDC, - .subclass = CDC_NETWORK_CONTROL_MODEL, - .protocol = CDC_COMMON_PROTOCOL_NONE, + .bInterfaceClass = USB_DEVICE_CLASS_CDC, + .bInterfaceSubClass = CDC_NETWORK_CONTROL_MODEL, + .bInterfaceProtocol = CDC_COMMON_PROTOCOL_NONE, .id_table = NULL, .class_driver = &cdc_ncm_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/hid/usbh_hid.c b/components/drivers/usb/cherryusb/class/hid/usbh_hid.c index de1ddc07488..0fd58abb153 100644 --- a/components/drivers/usb/cherryusb/class/hid/usbh_hid.c +++ b/components/drivers/usb/cherryusb/class/hid/usbh_hid.c @@ -303,9 +303,9 @@ const struct usbh_class_driver hid_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info hid_custom_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS, - .class = USB_DEVICE_CLASS_HID, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = USB_DEVICE_CLASS_HID, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = NULL, .class_driver = &hid_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/hub/usbh_hub.c b/components/drivers/usb/cherryusb/class/hub/usbh_hub.c index 2bcf4ddb48d..9dae3966075 100644 --- a/components/drivers/usb/cherryusb/class/hub/usbh_hub.c +++ b/components/drivers/usb/cherryusb/class/hub/usbh_hub.c @@ -734,9 +734,9 @@ const struct usbh_class_driver hub_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS, - .class = USB_DEVICE_CLASS_HUB, - .subclass = 0, - .protocol = 0, + .bInterfaceClass = USB_DEVICE_CLASS_HUB, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, .id_table = NULL, .class_driver = &hub_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/msc/usbh_msc.c b/components/drivers/usb/cherryusb/class/msc/usbh_msc.c index 1327175fce5..96cb53d2630 100644 --- a/components/drivers/usb/cherryusb/class/msc/usbh_msc.c +++ b/components/drivers/usb/cherryusb/class/msc/usbh_msc.c @@ -443,9 +443,9 @@ const struct usbh_class_driver msc_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info msc_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_MASS_STORAGE, - .subclass = MSC_SUBCLASS_SCSI, - .protocol = MSC_PROTOCOL_BULK_ONLY, + .bInterfaceClass = USB_DEVICE_CLASS_MASS_STORAGE, + .bInterfaceSubClass = MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = MSC_PROTOCOL_BULK_ONLY, .id_table = NULL, .class_driver = &msc_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/template/usbh_xxx.c b/components/drivers/usb/cherryusb/class/template/usbh_xxx.c index 78d531fc3cf..4456b3c4a1d 100644 --- a/components/drivers/usb/cherryusb/class/template/usbh_xxx.c +++ b/components/drivers/usb/cherryusb/class/template/usbh_xxx.c @@ -89,9 +89,9 @@ static const struct usbh_class_driver xxx_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info xxx_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = 0, - .subclass = 0, - .protocol = 0, + .bInterfaceClass = 0, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, .id_table = NULL, .class_driver = &xxx_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c b/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c index e8c7eb15378..66c1f078033 100644 --- a/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c +++ b/components/drivers/usb/cherryusb/class/vendor/net/usbh_asix.c @@ -817,9 +817,9 @@ static const struct usbh_class_driver asix_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info asix_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = asix_id_table, .class_driver = &asix_class_driver }; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c b/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c index 778ab264794..10fc0483982 100644 --- a/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c +++ b/components/drivers/usb/cherryusb/class/vendor/net/usbh_rtl8152.c @@ -2272,9 +2272,9 @@ static const struct usbh_class_driver rtl8152_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info rtl8152_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = rtl_id_table, .class_driver = &rtl8152_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ch34x.c b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ch34x.c index d0de5b4cf2d..3bee462db81 100644 --- a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ch34x.c +++ b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ch34x.c @@ -370,9 +370,9 @@ const struct usbh_class_driver ch34x_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info ch34x_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = ch34x_id_table, .class_driver = &ch34x_class_driver }; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_cp210x.c b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_cp210x.c index 4cd06b95be4..6f41b41be37 100644 --- a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_cp210x.c +++ b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_cp210x.c @@ -319,9 +319,9 @@ const struct usbh_class_driver cp210x_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info cp210x_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = cp210x_id_table, .class_driver = &cp210x_class_driver }; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c index 4ed698390c3..82defaab7fd 100644 --- a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c +++ b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_ftdi.c @@ -392,9 +392,9 @@ const struct usbh_class_driver ftdi_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info ftdi_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = ftdi_id_table, .class_driver = &ftdi_class_driver }; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_pl2303.c b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_pl2303.c index 42c963db4e1..01ee700fb83 100644 --- a/components/drivers/usb/cherryusb/class/vendor/serial/usbh_pl2303.c +++ b/components/drivers/usb/cherryusb/class/vendor/serial/usbh_pl2303.c @@ -440,9 +440,9 @@ const struct usbh_class_driver pl2303_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info pl2303_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = pl2303_id_table, .class_driver = &pl2303_class_driver }; \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c b/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c index 34cbcf87e4c..9275faacc63 100644 --- a/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c +++ b/components/drivers/usb/cherryusb/class/vendor/wifi/usbh_bl616.c @@ -504,9 +504,9 @@ static const struct usbh_class_driver bl616_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info bl616_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = bl616_id_table, .class_driver = &bl616_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/vendor/xbox/usbh_xbox.c b/components/drivers/usb/cherryusb/class/vendor/xbox/usbh_xbox.c index ecfb4651901..0c3339c9fc5 100644 --- a/components/drivers/usb/cherryusb/class/vendor/xbox/usbh_xbox.c +++ b/components/drivers/usb/cherryusb/class/vendor/xbox/usbh_xbox.c @@ -220,9 +220,9 @@ static const uint16_t xbox_id_table[][2] = { CLASS_INFO_DEFINE const struct usbh_class_info xbox_custom_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_VEND_SPECIFIC, - .subclass = 0x5d, - .protocol = 0x01, + .bInterfaceClass = USB_DEVICE_CLASS_VEND_SPECIFIC, + .bInterfaceSubClass = 0x5d, + .bInterfaceProtocol = 0x01, .id_table = xbox_id_table, .class_driver = &xbox_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/video/usbd_video.c b/components/drivers/usb/cherryusb/class/video/usbd_video.c index a1a42cdcf1e..dae28eb544a 100644 --- a/components/drivers/usb/cherryusb/class/video/usbd_video.c +++ b/components/drivers/usb/cherryusb/class/video/usbd_video.c @@ -18,10 +18,20 @@ struct usbd_video_priv { uint8_t power_mode; uint8_t error_code; struct video_entity_info info[3]; - uint8_t *ep_buffer; + 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; + 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; } 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) @@ -741,6 +751,43 @@ static void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dw g_usbd_video[busid].commit.bPreferedVersion = 0; g_usbd_video[busid].commit.bMinVersion = 0; 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; } struct usbd_interface *usbd_video_init_intf(uint8_t busid, @@ -770,74 +817,68 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid, bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep) { - struct video_payload_header *header = (struct video_payload_header *)g_usbd_video[busid].ep_buffer; uint32_t remain; - uint32_t len; - bool last_packet = false; - - header->bHeaderLength = 2; - header->headerInfoUnion.headerInfoBits.endOfHeader = 1; - remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset; - - len = MIN(remain, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - header->bHeaderLength); - memcpy(&g_usbd_video[busid].ep_buffer[header->bHeaderLength], - &g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset], - len); + 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); + } else { + if (g_usbd_video[busid].stream_finish) { + return true; + } + } - g_usbd_video[busid].stream_offset += len; + 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); + } + } + } - if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) { - last_packet = true; - header->headerInfoUnion.headerInfoBits.endOfFrame = 1; + 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; + } } - usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buffer, len + header->bHeaderLength); - return last_packet; + return false; } -int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buffer, uint8_t *buf, uint32_t len) +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) { - if (usb_device_is_configured(busid) == 0) { + if ((usb_device_is_configured(busid) == 0) || (stream_len == 0)) { return -1; } - g_usbd_video[busid].ep_buffer = ep_buffer; - g_usbd_video[busid].stream_buf = buf; - g_usbd_video[busid].stream_len = len; + 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].stream_buf = stream_buf; + g_usbd_video[busid].stream_len = stream_len; g_usbd_video[busid].stream_offset = 0; - struct video_payload_header *header = (struct video_payload_header *)g_usbd_video[busid].ep_buffer; - - header->headerInfoUnion.headerInfoBits.frameIdentifier ^= 1; - header->headerInfoUnion.headerInfoBits.endOfFrame = 0; - usbd_video_stream_split_transfer(busid, ep); return 0; } - -uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len) -{ - uint32_t packets; - uint32_t last_packet_size; - uint32_t picture_pos = 0; - static uint8_t uvc_header[2] = { 0x02, 0x80 }; - - packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2)) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2); - last_packet_size = input_len - ((packets - 1) * (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2)); - - for (size_t i = 0; i < packets; i++) { - output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i] = uvc_header[0]; - output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1]; - if (i == (packets - 1)) { - memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size); - output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1); - } else { - memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2); - picture_pos += g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2; - } - } - uvc_header[1] ^= 1; - *out_len = (input_len + 2 * packets); - return packets; -} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/video/usbd_video.h b/components/drivers/usb/cherryusb/class/video/usbd_video.h index 24855c897d4..a2a98bb8c01 100644 --- a/components/drivers/usb/cherryusb/class/video/usbd_video.h +++ b/components/drivers/usb/cherryusb/class/video/usbd_video.h @@ -22,9 +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_buffer, uint8_t *buf, uint32_t len); - -uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len); +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); #ifdef __cplusplus } diff --git a/components/drivers/usb/cherryusb/class/video/usbh_video.c b/components/drivers/usb/cherryusb/class/video/usbh_video.c index 043eb1d6bde..7379151250d 100644 --- a/components/drivers/usb/cherryusb/class/video/usbh_video.c +++ b/components/drivers/usb/cherryusb/class/video/usbh_video.c @@ -531,18 +531,18 @@ const struct usbh_class_driver video_streaming_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_VIDEO, - .subclass = VIDEO_SC_VIDEOCONTROL, - .protocol = VIDEO_PC_PROTOCOL_UNDEFINED, + .bInterfaceClass = USB_DEVICE_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SC_VIDEOCONTROL, + .bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED, .id_table = NULL, .class_driver = &video_ctrl_class_driver }; CLASS_INFO_DEFINE const struct usbh_class_info video_streaming_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_VIDEO, - .subclass = VIDEO_SC_VIDEOSTREAMING, - .protocol = VIDEO_PC_PROTOCOL_UNDEFINED, + .bInterfaceClass = USB_DEVICE_CLASS_VIDEO, + .bInterfaceSubClass = VIDEO_SC_VIDEOSTREAMING, + .bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED, .id_table = NULL, .class_driver = &video_streaming_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c b/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c index 61bcd290d13..43849706ea2 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c +++ b/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.c @@ -478,7 +478,7 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes) g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t); g_rndis_rx_data_length = hdr->DataLength; - usbd_rndis_data_recv_done(); + usbd_rndis_data_recv_done(g_rndis_rx_data_length); } void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) @@ -489,6 +489,7 @@ void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes) /* send zlp */ usbd_ep_start_write(0, ep, NULL, 0); } else { + usbd_rndis_data_send_done(g_rndis_tx_data_length); g_rndis_tx_data_length = 0; } } @@ -592,3 +593,13 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf, return intf; } + +__WEAK void usbd_rndis_data_recv_done(uint32_t len) +{ + (void)len; +} + +__WEAK void usbd_rndis_data_send_done(uint32_t len) +{ + (void)len; +} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h b/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h index 8a9581f68d1..72b89eab890 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h +++ b/components/drivers/usb/cherryusb/class/wireless/usbd_rndis.h @@ -18,7 +18,8 @@ struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf, const uint8_t in_ep, const uint8_t int_ep, uint8_t mac[6]); -void usbd_rndis_data_recv_done(void); +void usbd_rndis_data_recv_done(uint32_t len); +void usbd_rndis_data_send_done(uint32_t len); #ifdef CONFIG_USBDEV_RNDIS_USING_LWIP struct pbuf *usbd_rndis_eth_rx(void); diff --git a/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c b/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c index 9f78866ab5a..991f09579b3 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c +++ b/components/drivers/usb/cherryusb/class/wireless/usbh_bluetooth.c @@ -393,18 +393,18 @@ static const uint16_t bluetooth_id_table[][2] = { CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_h4_nrf_class_info = { .match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS, - .class = 0xff, - .subclass = 0x00, - .protocol = 0x00, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, .id_table = bluetooth_id_table, .class_driver = &bluetooth_class_driver }; #else CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_WIRELESS, - .subclass = 0x01, - .protocol = 0x01, + .bInterfaceClass = USB_DEVICE_CLASS_WIRELESS, + .bInterfaceSubClass = 0x01, + .bInterfaceProtocol = 0x01, .id_table = NULL, .class_driver = &bluetooth_class_driver }; diff --git a/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c b/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c index fa53f8400b0..e9eaff0114d 100644 --- a/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c +++ b/components/drivers/usb/cherryusb/class/wireless/usbh_rndis.c @@ -600,9 +600,9 @@ static const struct usbh_class_driver rndis_class_driver = { CLASS_INFO_DEFINE const struct usbh_class_info rndis_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, - .class = USB_DEVICE_CLASS_WIRELESS, - .subclass = 0x01, - .protocol = 0x03, + .bInterfaceClass = USB_DEVICE_CLASS_WIRELESS, + .bInterfaceSubClass = 0x01, + .bInterfaceProtocol = 0x03, .id_table = NULL, .class_driver = &rndis_class_driver }; diff --git a/components/drivers/usb/cherryusb/common/usb_log.h b/components/drivers/usb/cherryusb/common/usb_log.h index 9074ed9752b..8c798c7cb44 100644 --- a/components/drivers/usb/cherryusb/common/usb_log.h +++ b/components/drivers/usb/cherryusb/common/usb_log.h @@ -88,6 +88,8 @@ static inline void usb_hexdump(const void *ptr, uint32_t buflen) unsigned char *buf = (unsigned char *)ptr; uint32_t i, j; + (void)buf; + for (i = 0; i < buflen; i += 16) { CONFIG_USB_PRINTF("%08X:", i); diff --git a/components/drivers/usb/cherryusb/common/usb_version.h b/components/drivers/usb/cherryusb/common/usb_version.h index b68b8f69790..d207af9dc23 100644 --- a/components/drivers/usb/cherryusb/common/usb_version.h +++ b/components/drivers/usb/cherryusb/common/usb_version.h @@ -15,7 +15,7 @@ #undef CHERRYUSB_VERSION_STR #endif -#define CHERRYUSB_VERSION 0x010401 -#define CHERRYUSB_VERSION_STR "v1.4.1" +#define CHERRYUSB_VERSION 0x010402 +#define CHERRYUSB_VERSION_STR "v1.4.2" #endif \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/core/usbd_core.c b/components/drivers/usb/cherryusb/core/usbd_core.c index ea471e54985..d7fb351775f 100644 --- a/components/drivers/usb/cherryusb/core/usbd_core.c +++ b/components/drivers/usb/cherryusb/core/usbd_core.c @@ -64,6 +64,7 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv { bool test_req; #endif struct usbd_interface *intf[16]; + uint8_t intf_altsetting[16]; uint8_t intf_offset; struct usbd_tx_rx_msg tx_msg[CONFIG_USBDEV_EP_NUM]; @@ -98,6 +99,7 @@ static bool is_device_configured(uint8_t busid) * This function sets endpoint configuration according to one specified in USB * endpoint descriptor and then enables it for data transfers. * + * @param [in] busid busid * @param [in] ep Endpoint descriptor byte array * * @return true if successfully configured and enabled @@ -125,6 +127,7 @@ static bool usbd_set_endpoint(uint8_t busid, const struct usb_endpoint_descripto * This function cancels transfers that are associated with endpoint and * disabled endpoint itself. * + * @param [in] busid busid * @param [in] ep Endpoint descriptor byte array * * @return true if successfully deconfigured and disabled @@ -144,6 +147,7 @@ static bool usbd_reset_endpoint(uint8_t busid, const struct usb_endpoint_descrip * This function parses the list of installed USB descriptors and attempts * to find the specified USB descriptor. * + * @param [in] busid busid * @param [in] type_index Type and index of the descriptor * @param [out] data Descriptor data * @param [out] len Descriptor length @@ -370,6 +374,7 @@ static bool usbd_get_descriptor(uint8_t busid, uint16_t type_index, uint8_t **da * index and alternate setting by parsing the installed USB descriptor list. * A configuration index of 0 unconfigures the device. * + * @param [in] busid busid * @param [in] config_index Configuration index * @param [in] alt_setting Alternate setting number * @@ -439,6 +444,7 @@ static bool usbd_set_configuration(uint8_t busid, uint8_t config_index, uint8_t /** * @brief set USB interface * + * @param [in] busid busid * @param [in] iface Interface index * @param [in] alt_setting Alternate setting number * @@ -494,7 +500,6 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting goto find_end; } else if (cur_alt_setting == alt_setting) { ret = usbd_set_endpoint(busid, ep_desc); - goto find_end; } else { } } @@ -522,6 +527,7 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting /** * @brief handle a standard device request * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -617,6 +623,7 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet * /** * @brief handle a standard interface request * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -703,11 +710,12 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe ret = false; break; case USB_REQUEST_GET_INTERFACE: - (*data)[0] = 0; + (*data)[0] = g_usbd_core[busid].intf_altsetting[intf_num]; *len = 1; break; case USB_REQUEST_SET_INTERFACE: + g_usbd_core[busid].intf_altsetting[intf_num] = LO_BYTE(setup->wValue); usbd_set_interface(busid, setup->wIndex, setup->wValue); *len = 0; break; @@ -723,6 +731,7 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe /** * @brief handle a standard endpoint request * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -787,6 +796,7 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet /** * @brief handle standard requests (list in chapter 9) * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -830,8 +840,7 @@ static int usbd_standard_request_handler(uint8_t busid, struct usb_setup_packet /** * @brief handler for class requests * - * If a custom request handler was installed, this handler is called first. - * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -863,8 +872,7 @@ static int usbd_class_request_handler(uint8_t busid, struct usb_setup_packet *se /** * @brief handler for vendor requests * - * If a custom request handler was installed, this handler is called first. - * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -1006,6 +1014,7 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s /** * @brief handle setup request( standard/class/vendor/other) * + * @param [in] busid busid * @param [in] setup The setup packet * @param [in,out] data Data buffer * @param [in,out] len Pointer to data length @@ -1167,7 +1176,7 @@ void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup) #ifdef CONFIG_USBDEV_EP0_INDATA_NO_COPY g_usbd_core[busid].ep0_data_buf = buf; #else - memcpy(g_usbd_core[busid].ep0_data_buf, buf, g_usbd_core[busid].ep0_data_buf_residue); + usb_memcpy(g_usbd_core[busid].ep0_data_buf, buf, g_usbd_core[busid].ep0_data_buf_residue); #endif } else { /* use memcpy(*data, xxx, len); has copied into ep0 buffer, we do nothing */ diff --git a/components/drivers/usb/cherryusb/core/usbh_core.c b/components/drivers/usb/cherryusb/core/usbh_core.c index d4de88e54f7..cb36f97eea8 100644 --- a/components/drivers/usb/cherryusb/core/usbh_core.c +++ b/components/drivers/usb/cherryusb/core/usbh_core.c @@ -93,19 +93,22 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin struct usbh_class_info *index = NULL; for (index = usbh_class_info_table_begin; index < usbh_class_info_table_end; index++) { - if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->class == class)) { + if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->bInterfaceClass == class)) { continue; } - if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->subclass == subclass)) { + if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->bInterfaceSubClass == subclass)) { continue; } - if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->protocol == protocol)) { + if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->bInterfaceProtocol == protocol)) { continue; } if (index->match_flags & USB_CLASS_MATCH_VID_PID && index->id_table) { /* scan id table */ uint32_t i; - for (i = 0; index->id_table[i][0] && index->id_table[i][0] != vid && index->id_table[i][1] != pid; i++) { + for (i = 0; index->id_table[i][0]; i++) { + if (index->id_table[i][0] == vid && index->id_table[i][1] == pid) { + break; + } } /* do not match, continue next */ if (!index->id_table[i][0]) { @@ -831,6 +834,37 @@ static void usbh_list_all_interface_desc(struct usbh_bus *bus, struct usbh_hub * } } +static struct usbh_hubport *usbh_list_all_hubport(struct usbh_hub *hub, uint8_t hub_index, uint8_t hub_port) +{ + struct usbh_hubport *hport; + struct usbh_hub *hub_next; + + if (hub->index == hub_index) { + hport = &hub->child[hub_port - 1]; + return hport; + } else { + for (uint8_t port = 0; port < hub->nports; port++) { + hport = &hub->child[port]; + if (hport->connected) { + for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) { + if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) { + if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) { + hub_next = hport->config.intf[itf].priv; + + if (hub_next && hub_next->connected) { + hport = usbh_list_all_hubport(hub_next, hub_index, hub_port); + if (hport) { + return hport; + } + } + } + } + } + } + } + } + return NULL; +} void *usbh_find_class_instance(const char *devname) { usb_slist_t *bus_list; @@ -855,6 +889,23 @@ void *usbh_find_class_instance(const char *devname) return NULL; } +struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t hub_port) +{ + struct usbh_hub *hub; + struct usbh_bus *bus; + struct usbh_hubport *hport; + size_t flags; + + flags = usb_osal_enter_critical_section(); + + bus = &g_usbhost_bus[busid]; + hub = &bus->hcd.roothub; + + hport = usbh_list_all_hubport(hub, hub_index, hub_port); + usb_osal_leave_critical_section(flags); + return hport; +} + int lsusb(int argc, char **argv) { usb_slist_t *bus_list; diff --git a/components/drivers/usb/cherryusb/core/usbh_core.h b/components/drivers/usb/cherryusb/core/usbh_core.h index 6674fcb4953..eaddb304329 100644 --- a/components/drivers/usb/cherryusb/core/usbh_core.h +++ b/components/drivers/usb/cherryusb/core/usbh_core.h @@ -61,9 +61,9 @@ extern "C" { struct usbh_class_info { uint8_t match_flags; /* Used for product specific matches; range is inclusive */ - uint8_t class; /* Base device class code */ - uint8_t subclass; /* Sub-class, depends on base class. Eg. */ - uint8_t protocol; /* Protocol, depends on base class. Eg. */ + uint8_t bInterfaceClass; /* Base device class code */ + uint8_t bInterfaceSubClass; /* Sub-class, depends on base class. Eg. */ + uint8_t bInterfaceProtocol; /* Protocol, depends on base class. Eg. */ const uint16_t (*id_table)[2]; /* List of Vendor/Product ID pairs */ const struct usbh_class_driver *class_driver; }; @@ -275,6 +275,7 @@ int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsett int usbh_initialize(uint8_t busid, uintptr_t reg_base); int usbh_deinitialize(uint8_t busid); void *usbh_find_class_instance(const char *devname); +struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t hub_port); int lsusb(int argc, char **argv); diff --git a/components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c b/components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c index 32bd9109a56..148f324c37a 100644 --- a/components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c +++ b/components/drivers/usb/cherryusb/demo/cdc_acm_hid_msc_template.c @@ -332,14 +332,15 @@ void cdc_acm_hid_msc_descriptor_init(uint8_t busid, uintptr_t reg_base) */ void hid_mouse_test(uint8_t busid) { + if(usb_device_is_configured(busid) == false) { + return; + } /*!< move mouse pointer */ mouse_cfg.x += 10; mouse_cfg.y = 0; - int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); - if (ret < 0) { - return; - } + hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); while (hid_state == HID_STATE_BUSY) { } } diff --git a/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c b/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c index 1d70aaa5553..9147c92320f 100644 --- a/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c +++ b/components/drivers/usb/cherryusb/demo/cdc_ecm_template.c @@ -6,6 +6,10 @@ #include "usbd_core.h" #include "usbd_cdc_ecm.h" +#ifndef CONFIG_USBDEV_CDC_ECM_USING_LWIP +#error "Please enable CONFIG_USBDEV_CDC_ECM_USING_LWIP for this demo" +#endif + /*!< endpoint address */ #define CDC_IN_EP 0x81 #define CDC_OUT_EP 0x02 @@ -222,12 +226,12 @@ void cdc_ecm_lwip_init(void) while (!netif_is_up(netif)) { } - // while (dhserv_init(&dhcp_config)) {} + while (dhserv_init(&dhcp_config)) {} - // while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {} + while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {} } -void usbd_cdc_ecm_data_recv_done(uint8_t *buf, uint32_t len) +void usbd_cdc_ecm_data_recv_done(uint32_t len) { } diff --git a/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c b/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c index 310788360c1..a83a75551aa 100644 --- a/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c +++ b/components/drivers/usb/cherryusb/demo/cdc_rndis_template.c @@ -6,6 +6,10 @@ #include "usbd_core.h" #include "usbd_rndis.h" +#ifndef CONFIG_USBDEV_RNDIS_USING_LWIP +#error "Please enable CONFIG_USBDEV_RNDIS_USING_LWIP for this demo" +#endif + /*!< endpoint address */ #define CDC_IN_EP 0x81 #define CDC_OUT_EP 0x02 @@ -170,7 +174,7 @@ rt_err_t rt_usbd_rndis_eth_tx(rt_device_t dev, struct pbuf *p) return usbd_rndis_eth_tx(p); } -void usbd_rndis_data_recv_done(void) +void usbd_rndis_data_recv_done(uint32_t len) { eth_device_ready(&rndis_dev); } @@ -258,12 +262,12 @@ void rndis_lwip_init(void) while (!netif_is_up(netif)) { } - // while (dhserv_init(&dhcp_config)) {} + while (dhserv_init(&dhcp_config)) {} - // while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {} + while (dnserv_init(&ipaddr, PORT_DNS, dns_query_proc)) {} } -void usbd_rndis_data_recv_done(void) +void usbd_rndis_data_recv_done(uint32_t len) { } diff --git a/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c b/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c index 7527f396d81..4d1afc3056d 100644 --- a/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c +++ b/components/drivers/usb/cherryusb/demo/hid_keyboard_template.c @@ -236,12 +236,13 @@ void hid_keyboard_test(uint8_t busid) { const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; - memcpy(write_buffer, sendbuffer, 8); - int ret = usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8); - if (ret < 0) { + if(usb_device_is_configured(busid) == false) { return; } + + memcpy(write_buffer, sendbuffer, 8); hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8); while (hid_state == HID_STATE_BUSY) { } } diff --git a/components/drivers/usb/cherryusb/demo/hid_mouse_template.c b/components/drivers/usb/cherryusb/demo/hid_mouse_template.c index e6d24d7cb9e..564d1718bba 100644 --- a/components/drivers/usb/cherryusb/demo/hid_mouse_template.c +++ b/components/drivers/usb/cherryusb/demo/hid_mouse_template.c @@ -304,14 +304,15 @@ void draw_circle(uint8_t *buf) /* https://cps-check.com/cn/polling-rate-check */ void hid_mouse_test(uint8_t busid) { + if(usb_device_is_configured(busid) == false) { + return; + } + int counter = 0; while (counter < 1000) { draw_circle((uint8_t *)&mouse_cfg); - int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); - if (ret < 0) { - return; - } hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); while (hid_state == HID_STATE_BUSY) { } diff --git a/components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c b/components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c index b528c4a11dd..786c3240394 100644 --- a/components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c +++ b/components/drivers/usb/cherryusb/demo/hid_remote_wakeup_template.c @@ -307,6 +307,10 @@ void hid_mouse_test(uint8_t busid) static uint32_t count = 1000; int ret; + if(usb_device_is_configured(busid) == false) { + return; + } + // if (gpio_read_pin(GPIO_PIN) == 1) { // ret = usbd_send_remote_wakeup(busid); // if (ret < 0) { @@ -317,11 +321,8 @@ void hid_mouse_test(uint8_t busid) while (count) { draw_circle((uint8_t *)&mouse_cfg); - int ret = usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); - if (ret < 0) { - return; - } hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, (uint8_t *)&mouse_cfg, 4); while (hid_state == HID_STATE_BUSY) { } diff --git a/components/drivers/usb/cherryusb/demo/usb_host.c b/components/drivers/usb/cherryusb/demo/usb_host.c index 7198418893b..817103d5c08 100644 --- a/components/drivers/usb/cherryusb/demo/usb_host.c +++ b/components/drivers/usb/cherryusb/demo/usb_host.c @@ -254,38 +254,38 @@ static void usbh_msc_thread(void *argument) } #endif +#if TEST_USBH_CDC_ACM void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class) { -#if TEST_USBH_CDC_ACM usb_osal_thread_create("usbh_cdc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_acm_thread, cdc_acm_class); -#endif } void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class) { } +#endif +#if TEST_USBH_HID void usbh_hid_run(struct usbh_hid *hid_class) { -#if TEST_USBH_HID usb_osal_thread_create("usbh_hid", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_hid_thread, hid_class); -#endif } void usbh_hid_stop(struct usbh_hid *hid_class) { } +#endif +#if TEST_USBH_MSC void usbh_msc_run(struct usbh_msc *msc_class) { -#if TEST_USBH_MSC usb_osal_thread_create("usbh_msc", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_msc_thread, msc_class); -#endif } void usbh_msc_stop(struct usbh_msc *msc_class) { } +#endif #if TEST_USBH_AUDIO #error "commercial charge" @@ -294,3 +294,26 @@ void usbh_msc_stop(struct usbh_msc *msc_class) #if TEST_USBH_VIDEO #error "commercial charge" #endif + +#if 0 +#include "usbh_aoa.h" + +static struct aoa_string_info deviceinfo = { + .acc_manufacturer = "CherryUSB", + .acc_model = "CherryUSB", + .acc_description = "Android Open Accessory CherryUSB", + .acc_version = "1.0", + .acc_uri = "http://developer.android.com/tools/adk/index.html", + .acc_serial = "CherryUSB" +}; + +int aoa_switch(int argc, char **argv) +{ + struct usbh_hubport *hport = usbh_find_hubport(0, 1, 1); + + usbh_aoa_switch(hport, &deviceinfo); + return 0; +} + +SHELL_CMD_EXPORT_ALIAS(aoa_switch, aoa_switch, aoa_switch); +#endif \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c b/components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c index 85a5146d4b3..6a4116222a0 100644 --- a/components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c +++ b/components/drivers/usb/cherryusb/demo/video_audiov1_hid_template.c @@ -9,6 +9,8 @@ #include "usbd_hid.h" #include "cherryusb_mjpeg.h" +#define MAX_PACKETS_IN_ONE_TRANSFER 1 + #define VIDEO_IN_EP 0x81 #define VIDEO_INT_EP 0x86 @@ -267,7 +269,7 @@ static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = { USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t audio_read_buffer[AUDIO_OUT_PACKET]; USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t audio_write_buffer[AUDIO_IN_PACKET]; -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t video_packet_buffer[40 * 1024]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t video_packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE]; volatile bool video_tx_flag = 0; volatile bool audio_tx_flag = 0; @@ -331,8 +333,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf) void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) { - //USB_LOG_RAW("actual in len:%d\r\n", nbytes); - video_iso_tx_busy = false; + if (usbd_video_stream_split_transfer(busid, ep)) { + /* one frame has done */ + video_iso_tx_busy = false; + } } static struct usbd_endpoint video_in_ep = { @@ -458,56 +462,30 @@ void hid_keyboard_test(uint8_t busid) { const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; - memcpy(hid_write_buffer, sendbuffer, 8); - int ret = usbd_ep_start_write(busid, HID_INT_EP, hid_write_buffer, 8); - if (ret < 0) { + if(usb_device_is_configured(busid) == false) { return; } + + memcpy(hid_write_buffer, sendbuffer, 8); hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, hid_write_buffer, 8); while (hid_state == HID_STATE_BUSY) { } } void video_test(uint8_t busid) { - uint32_t out_len; - uint32_t packets; + memset(video_packet_buffer, 0, sizeof(video_packet_buffer)); - (void)packets; - memset(video_packet_buffer, 0, 40 * 1024); while (1) { if (video_tx_flag) { - packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg), video_packet_buffer, &out_len); -#if 1 video_iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, video_packet_buffer, out_len); + usbd_video_stream_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[0][0], &video_packet_buffer[1][0], MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg)); while (video_iso_tx_busy) { if (video_tx_flag == 0) { break; } } -#else - /* dwc2 must use this method */ - for (uint32_t i = 0; i < packets; i++) { - if (i == (packets - 1)) { - video_iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE); - while (video_iso_tx_busy) { - if (video_tx_flag == 0) { - break; - } - } - } else { - video_iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &video_packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE); - while (video_iso_tx_busy) { - if (video_tx_flag == 0) { - break; - } - } - } - } -#endif } } } \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/demo/video_static_h264_template.c b/components/drivers/usb/cherryusb/demo/video_static_h264_template.c index 376068edac8..e325964a2fd 100644 --- a/components/drivers/usb/cherryusb/demo/video_static_h264_template.c +++ b/components/drivers/usb/cherryusb/demo/video_static_h264_template.c @@ -7,6 +7,8 @@ #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 @@ -180,8 +182,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf) void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) { - //USB_LOG_RAW("actual in len:%d\r\n", nbytes); - iso_tx_busy = false; + if (usbd_video_stream_split_transfer(busid, ep)) { + /* one frame has done */ + iso_tx_busy = false; + } } static struct usbd_endpoint video_in_ep = { @@ -202,7 +206,7 @@ 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[40 * 1024]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][40 * 1024]; void video_test(uint8_t busid) { @@ -210,40 +214,16 @@ void video_test(uint8_t busid) uint32_t packets; (void)packets; - memset(packet_buffer, 0, 40 * 1024); + memset(packet_buffer, 0, sizeof(packet_buffer)); while (1) { if (tx_flag) { - packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_h264, sizeof(cherryusb_h264), packet_buffer, &out_len); -#if 1 iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len); + 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)); while (iso_tx_busy) { if (tx_flag == 0) { break; } } -#else - /* dwc2 must use this method */ - for (uint32_t i = 0; i < packets; i++) { - if (i == (packets - 1)) { - iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE); - while (iso_tx_busy) { - if (tx_flag == 0) { - break; - } - } - } else { - iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE); - while (iso_tx_busy) { - if (tx_flag == 0) { - break; - } - } - } - } -#endif } } } \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c b/components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c index 51a4422613f..1d2ae01ba4b 100644 --- a/components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c +++ b/components/drivers/usb/cherryusb/demo/video_static_mjpeg_template.c @@ -7,7 +7,7 @@ #include "usbd_video.h" #include "cherryusb_mjpeg.h" -#define VIDEO_STREAM_SPLIT_ENABLE 1 +#define MAX_PACKETS_IN_ONE_TRANSFER 1 #define VIDEO_IN_EP 0x81 #define VIDEO_INT_EP 0x83 @@ -182,14 +182,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf) void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) { -#if VIDEO_STREAM_SPLIT_ENABLE if (usbd_video_stream_split_transfer(busid, ep)) { /* one frame has done */ iso_tx_busy = false; } -#else - iso_tx_busy = false; -#endif } static struct usbd_endpoint video_in_ep = { @@ -210,42 +206,21 @@ void video_init(uint8_t busid, uintptr_t reg_base) usbd_initialize(busid, reg_base, usbd_event_handler); } -#if VIDEO_STREAM_SPLIT_ENABLE -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[MAX_PAYLOAD_SIZE]; -#else -USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024]; -#endif +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE]; void video_test(uint8_t busid) { - uint32_t out_len; - uint32_t packets; - - (void)packets; - (void)out_len; memset(packet_buffer, 0, sizeof(packet_buffer)); while (1) { if (tx_flag) { -#if VIDEO_STREAM_SPLIT_ENABLE iso_tx_busy = true; - usbd_video_stream_start_write(busid, VIDEO_IN_EP, packet_buffer, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg)); + 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)); while (iso_tx_busy) { if (tx_flag == 0) { break; } } -#else - packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg), packet_buffer, &out_len); - - iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len); - while (iso_tx_busy) { - if (tx_flag == 0) { - break; - } - } -#endif } } } \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c b/components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c index f90344d17e8..4ba71701c48 100644 --- a/components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c +++ b/components/drivers/usb/cherryusb/demo/video_static_yuyv_template.c @@ -7,6 +7,8 @@ #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 @@ -182,8 +184,10 @@ void usbd_video_close(uint8_t busid, uint8_t intf) void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) { - //USB_LOG_RAW("actual in len:%d\r\n", nbytes); - iso_tx_busy = false; + if (usbd_video_stream_split_transfer(busid, ep)) { + /* one frame has done */ + iso_tx_busy = false; + } } static struct usbd_endpoint video_in_ep = { @@ -204,48 +208,21 @@ 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[40 * 1024]; +USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[2][MAX_PACKETS_IN_ONE_TRANSFER * MAX_PAYLOAD_SIZE]; void video_test(uint8_t busid) { - uint32_t out_len; - uint32_t packets; + memset(packet_buffer, 0, sizeof(packet_buffer)); - (void)packets; - memset(packet_buffer, 0, 40 * 1024); while (1) { if (tx_flag) { - packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_yuyv, sizeof(cherryusb_yuyv), packet_buffer, &out_len); -#if 1 iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len); + 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)); while (iso_tx_busy) { if (tx_flag == 0) { break; } } -#else - /* dwc2 must use this method */ - for (uint32_t i = 0; i < packets; i++) { - if (i == (packets - 1)) { - iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE); - while (iso_tx_busy) { - if (tx_flag == 0) { - break; - } - } - } else { - iso_tx_busy = true; - usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE); - while (iso_tx_busy) { - if (tx_flag == 0) { - break; - } - } - } - } -#endif } } } \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/demo/webusb_hid_template.c b/components/drivers/usb/cherryusb/demo/webusb_hid_template.c index 04ec1dd25ac..52570879974 100644 --- a/components/drivers/usb/cherryusb/demo/webusb_hid_template.c +++ b/components/drivers/usb/cherryusb/demo/webusb_hid_template.c @@ -371,12 +371,13 @@ void hid_keyboard_test(uint8_t busid) { const uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; - memcpy(write_buffer, sendbuffer, 8); - int ret = usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8); - if (ret < 0) { + if(usb_device_is_configured(busid) == false) { return; } + + memcpy(write_buffer, sendbuffer, 8); hid_state = HID_STATE_BUSY; + usbd_ep_start_write(busid, HID_INT_EP, write_buffer, 8); while (hid_state == HID_STATE_BUSY) { } } diff --git a/components/drivers/usb/cherryusb/idf_component.yml b/components/drivers/usb/cherryusb/idf_component.yml new file mode 100644 index 00000000000..a500a240473 --- /dev/null +++ b/components/drivers/usb/cherryusb/idf_component.yml @@ -0,0 +1,25 @@ +version: "1.4.2" +description: CherryUSB is a tiny and portable USB Stack (device & host) for embedded system with USB IP +tags: + - usb + - usb-device + - usb-host + - cdc_acm + - cdc_ecm + - cdc_ncm + - hid + - msc + - rndis + - uvc + - uac + - winusb +url: https://github.com/cherry-embedded/CherryUSB +repository: https://github.com/cherry-embedded/CherryUSB.git +documentation: https://cherryusb.readthedocs.io/ +issues: https://github.com/cherry-embedded/CherryUSB/issues +dependencies: + idf: ">=5.0" +targets: + - esp32s2 + - esp32s3 + - esp32p4 \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c b/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c index be16ea1495b..b20e17d8755 100644 --- a/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c +++ b/components/drivers/usb/cherryusb/platform/rtthread/usb_check.c @@ -6,10 +6,6 @@ #error must enable RT_USING_TIMER_SOFT to support timer callback in thread #endif -#if IDLE_THREAD_STACK_SIZE < 2048 -#error "IDLE_THREAD_STACK_SIZE must be >= 2048" -#endif - #if RT_TIMER_THREAD_STACK_SIZE < 2048 #error "RT_TIMER_THREAD_STACK_SIZE must be >= 2048" #endif diff --git a/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbfs.c b/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbfs.c index 4b4b72d497c..7aabd411fcd 100644 --- a/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbfs.c +++ b/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbfs.c @@ -101,6 +101,11 @@ int usbd_set_address(uint8_t busid, const uint8_t addr) return 0; } +int usbd_set_remote_wakeup(uint8_t busid) +{ + return -1; +} + uint8_t usbd_get_port_speed(uint8_t busid) { return USB_SPEED_FULL; diff --git a/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbhs.c b/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbhs.c index 758ffd77f37..a8d3036a357 100644 --- a/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbhs.c +++ b/components/drivers/usb/cherryusb/port/ch32/usb_dc_usbhs.c @@ -101,6 +101,11 @@ int usbd_set_address(uint8_t busid, const uint8_t addr) return 0; } +int usbd_set_remote_wakeup(uint8_t busid) +{ + return -1; +} + uint8_t usbd_get_port_speed(uint8_t busid) { return USB_SPEED_HIGH; diff --git a/components/drivers/usb/cherryusb/port/chipidea/usb_dc_chipidea.c b/components/drivers/usb/cherryusb/port/chipidea/usb_dc_chipidea.c index 3d1971653d6..c6b6c0fee57 100644 --- a/components/drivers/usb/cherryusb/port/chipidea/usb_dc_chipidea.c +++ b/components/drivers/usb/cherryusb/port/chipidea/usb_dc_chipidea.c @@ -1,3 +1,14 @@ +/* + * Copyright (c) 2021-2024 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "usbd_core.h" #include "usb_chipidea_reg.h" diff --git a/components/drivers/usb/cherryusb/port/chipidea/usb_glue_mcx.c b/components/drivers/usb/cherryusb/port/chipidea/usb_glue_mcx.c index 29bb2d292c0..3f9b46b6af0 100644 --- a/components/drivers/usb/cherryusb/port/chipidea/usb_glue_mcx.c +++ b/components/drivers/usb/cherryusb/port/chipidea/usb_glue_mcx.c @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "usbd_core.h" #include "fsl_common.h" diff --git a/components/drivers/usb/cherryusb/port/dwc2/README.md b/components/drivers/usb/cherryusb/port/dwc2/README.md index faf9ab5a1a9..3218b31cd56 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/README.md +++ b/components/drivers/usb/cherryusb/port/dwc2/README.md @@ -20,6 +20,11 @@ If you are using more than one port, all ip parameters must be the same(like fif ## GD32 +CONFIG_USBDEV_EP_NUM 必须为4 或者 6,并删除 usb_dc_dwc2.c 中 while(1){} + +当 CONFIG_USBDEV_EP_NUM 为4 时,fifo_num 不得大于 320 字 +当 CONFIG_USBDEV_EP_NUM 为6 时,fifo_num 不得大于 1280 字 + - GD32F30X_CL - GD32F405、GD32F407 - GD32F450 diff --git a/components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c b/components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c index 72006abd5fe..6054a334a67 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_dc_dwc2.c @@ -136,10 +136,12 @@ static inline int dwc2_reset(uint8_t busid) do { if (++count > 200000U) { - return -1; + break; } } while ((USB_OTG_GLB->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST); + USB_OTG_GLB->GRSTCTL &= ~USB_OTG_GRSTCTL_CSRST; + return 0; } @@ -478,7 +480,7 @@ static inline uint32_t dwc2_get_inep_intstatus(uint8_t busid, uint8_t epnum) msk = USB_OTG_DEV->DIEPMSK; emp = USB_OTG_DEV->DIEPEMPMSK; - msk |= ((emp >> (epnum & 0x07)) & 0x1U) << 7; + msk |= ((emp >> (epnum & 0x0F)) & 0x1U) << 7; tmpreg = USB_OTG_INEP((uint32_t)epnum)->DIEPINT; USB_OTG_INEP((uint32_t)epnum)->DIEPINT = tmpreg; @@ -790,7 +792,7 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep) } while ((USB_OTG_OUTEP(ep_idx)->DOEPINT & USB_OTG_DOEPINT_EPDISD) != USB_OTG_DOEPINT_EPDISD); /* Clear and unmask endpoint disabled interrupt */ - USB_OTG_OUTEP(ep_idx)->DOEPINT |= USB_OTG_DOEPINT_EPDISD; + USB_OTG_OUTEP(ep_idx)->DOEPINT = USB_OTG_DOEPINT_EPDISD; } USB_OTG_DEV->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep_idx & 0x07)) << 16)); @@ -810,7 +812,7 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep) } while ((USB_OTG_INEP(ep_idx)->DIEPINT & USB_OTG_DIEPINT_EPDISD) != USB_OTG_DIEPINT_EPDISD); /* Clear and unmask endpoint disabled interrupt */ - USB_OTG_INEP(ep_idx)->DIEPINT |= USB_OTG_DIEPINT_EPDISD; + USB_OTG_INEP(ep_idx)->DIEPINT = USB_OTG_DIEPINT_EPDISD; } USB_OTG_DEV->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep_idx & 0x07))); @@ -1161,17 +1163,17 @@ void USBD_IRQHandler(uint8_t busid) dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup); } if (gint_status & USB_OTG_GINTSTS_ENUMDNE) { - USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_ENUMDNE; + USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_ENUMDNE; dwc2_set_turnaroundtime(busid, SystemCoreClock, dwc2_get_devspeed(busid)); USB_OTG_DEV->DCTL |= USB_OTG_DCTL_CGINAK; } if (gint_status & USB_OTG_GINTSTS_PXFR_INCOMPISOOUT) { - USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_PXFR_INCOMPISOOUT; + USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_PXFR_INCOMPISOOUT; } if (gint_status & USB_OTG_GINTSTS_IISOIXFR) { - USB_OTG_GLB->GINTSTS |= USB_OTG_GINTSTS_IISOIXFR; + USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_IISOIXFR; } if (gint_status & USB_OTG_GINTSTS_SOF) { diff --git a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_at.c b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_at.c index 137b1d87046..8d45f651394 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_at.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_at.c @@ -7,6 +7,9 @@ #include "stdint.h" #include "usb_dwc2_reg.h" +extern unsigned int system_core_clock; + +uint32_t SystemCoreClock; /* you can find this config in function: usb_global_init, file:at32fxxx_usb.c, for example: * * usbx->gccfg_bit.pwrdown = TRUE; @@ -17,6 +20,7 @@ uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base) { + SystemCoreClock = system_core_clock; #ifdef CONFIG_USB_HS return ((1 << 16) | (1 << 21)); #else @@ -35,6 +39,7 @@ uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base) uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base) { + SystemCoreClock = system_core_clock; #ifdef CONFIG_USB_HS return ((1 << 16) | (1 << 21)); #else diff --git a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_gd.c b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_gd.c index 7121ac9dbd2..f3fa4d92f7a 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_gd.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_gd.c @@ -7,6 +7,10 @@ #include "stdint.h" #include "usb_dwc2_reg.h" +#if CONFIG_USBDEV_EP_NUM != 4 && CONFIG_USBDEV_EP_NUM != 6 +#error "gd32 only has 4 endpoints for pa11/pa12 and 6 endpoints for pb14/pb15" +#endif + /* you can find this config in function:usb_core_init, file:drv_usb_core.c, for example: * * usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; diff --git a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c index f73dc5e9528..4dff31f83f4 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_glue_st.c @@ -166,6 +166,8 @@ uint32_t usbd_get_dwc2_gccfg_conf(uint32_t reg_base) USB_OTG_GLB->GCCFG = (1 << 23); usb_hsphy_init(25000000U); return (1 << 23); /* Enable USB HS PHY USBx->GCCFG |= USB_OTG_GCCFG_PHYHSEN;*/ +#elif __has_include("stm32h7rsxx.h") + return (1 << 21); #else return 0; #endif @@ -192,6 +194,8 @@ uint32_t usbh_get_dwc2_gccfg_conf(uint32_t reg_base) USB_OTG_GLB->GCCFG = (1 << 23); usb_hsphy_init(25000000U); return (1 << 23); /* Enable USB HS PHY USBx->GCCFG |= USB_OTG_GCCFG_PHYHSEN;*/ +#elif __has_include("stm32h7rsxx.h") + return (1 << 21); #else return 0; #endif diff --git a/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c b/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c index 9b0fc66015b..09f55170a5c 100644 --- a/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c +++ b/components/drivers/usb/cherryusb/port/dwc2/usb_hc_dwc2.c @@ -215,6 +215,12 @@ static inline void dwc2_chan_char_init(struct usbh_bus *bus, uint8_t ch_num, uin regval |= USB_OTG_HCCHAR_EPDIR; } + if ((usbh_get_port_speed(bus, 0) == USB_SPEED_HIGH) && (speed != USB_SPEED_HIGH)) { + USB_LOG_ERR("Do not support LS/FS device on HS hub\r\n"); + while (1) { + } + } + /* LS device plugged to HUB */ if ((speed == USB_SPEED_LOW) && (usbh_get_port_speed(bus, 0) != USB_SPEED_LOW)) { regval |= USB_OTG_HCCHAR_LSDEV; @@ -1131,4 +1137,4 @@ void USBH_IRQHandler(uint8_t busid) USB_OTG_GLB->GINTSTS = USB_OTG_GINTSTS_HCINT; } } -} +} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/ehci/usb_glue_aic.c b/components/drivers/usb/cherryusb/port/ehci/usb_glue_aic.c index 9fc87c39b70..500bc02a40d 100644 --- a/components/drivers/usb/cherryusb/port/ehci/usb_glue_aic.c +++ b/components/drivers/usb/cherryusb/port/ehci/usb_glue_aic.c @@ -9,6 +9,19 @@ #include #include "usbh_core.h" #include "usb_hc_ehci.h" +#include "usb_hc_ohci.h" + +#if !defined(CONFIG_USB_EHCI_CONFIGFLAG) +#error "aic ehci must define CONFIG_USB_EHCI_CONFIGFLAG" +#endif + +#if !defined(CONFIG_USB_EHCI_WITH_OHCI) +#error "aic must define CONFIG_USB_EHCI_WITH_OHCI for ls/fs device" +#endif + +#if CONFIG_USB_OHCI_HCOR_OFFSET != 0x400 +#error "aic CONFIG_USB_OHCI_HCOR_OFFSET must be 0x400" +#endif extern void USBH_IRQHandler(uint8_t busid); @@ -117,21 +130,12 @@ void usb_hc_low_level_init(struct usbh_bus *bus) aicos_request_irq(config[i].irq_num + 1, (irq_handler_t)aic_ohci_isr, 0, "usb_host_ohci", bus); aicos_irq_enable(config[i].irq_num); + aicos_irq_enable(config[i].irq_num + 1); } uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port) { - /* Defined by individual manufacturers */ - uint32_t regval; - - regval = EHCI_HCOR->portsc[port-1]; - if ((regval & EHCI_PORTSC_LSTATUS_MASK) == EHCI_PORTSC_LSTATUS_KSTATE) - return USB_SPEED_LOW; - - if (regval & EHCI_PORTSC_PE) - return USB_SPEED_HIGH; - else - return USB_SPEED_FULL; + return USB_SPEED_HIGH; } void usb_ehci_dcache_clean(uintptr_t addr, uint32_t len) @@ -149,7 +153,7 @@ void usb_ehci_dcache_clean_invalidate(uintptr_t addr, uint32_t len) aicos_dcache_clean_invalid_range((size_t *)addr, len); } -int usbh_init(void) +int __usbh_init(void) { #if defined(AIC_USING_USB0_HOST) || defined(AIC_USING_USB1_HOST) int bus_id = 0; @@ -171,11 +175,5 @@ int usbh_init(void) #include #include -INIT_ENV_EXPORT(usbh_init); - -#if defined (RT_USING_FINSH) -#include - -MSH_CMD_EXPORT_ALIAS(lsusb, lsusb, list usb device); -#endif +INIT_ENV_EXPORT(__usbh_init); #endif \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/ehci/usb_glue_hpm.c b/components/drivers/usb/cherryusb/port/ehci/usb_glue_hpm.c index 17724008495..40105a94984 100644 --- a/components/drivers/usb/cherryusb/port/ehci/usb_glue_hpm.c +++ b/components/drivers/usb/cherryusb/port/ehci/usb_glue_hpm.c @@ -35,6 +35,11 @@ static void usb_host_mode_init(USB_Type *ptr) /* Set parallel transceiver width */ ptr->PORTSC1 &= ~USB_PORTSC1_PTW_MASK; +#ifdef CONFIG_USB_HOST_FORCE_FULL_SPEED + /* Set usb forced to full speed mode */ + ptr->PORTSC1 |= USB_PORTSC1_PFSC_MASK; +#endif + /* Not use interrupt threshold. */ ptr->USBCMD &= ~USB_USBCMD_ITC_MASK; } @@ -53,7 +58,7 @@ void usb_hc_low_level_init(struct usbh_bus *bus) #endif } - usb_phy_init((USB_Type *)(bus->hcd.reg_base)); + usb_phy_init((USB_Type *)(bus->hcd.reg_base), true); intc_m_enable_irq(_hcd_irqnum[bus->hcd.hcd_id]); } @@ -86,18 +91,18 @@ uint8_t usbh_get_port_speed(struct usbh_bus *bus, const uint8_t port) extern void USBH_IRQHandler(uint8_t busid); +SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbh0) void isr_usbh0(void) { USBH_IRQHandler(_hcd_busid[0]); } -SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbh0) #ifdef HPM_USB1_BASE +SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbh1) void isr_usbh1(void) { USBH_IRQHandler(_hcd_busid[1]); } -SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbh1) #endif #endif diff --git a/components/drivers/usb/cherryusb/port/ehci/usb_glue_mcx.c b/components/drivers/usb/cherryusb/port/ehci/usb_glue_mcx.c index 7f8f4bf5548..92b2c25ec85 100644 --- a/components/drivers/usb/cherryusb/port/ehci/usb_glue_mcx.c +++ b/components/drivers/usb/cherryusb/port/ehci/usb_glue_mcx.c @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "usbh_core.h" #include "fsl_common.h" #include "usb_chipidea_reg.h" diff --git a/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c b/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c index 8b9caba419b..4f61854a338 100644 --- a/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c +++ b/components/drivers/usb/cherryusb/port/ehci/usb_hc_ehci.c @@ -952,6 +952,7 @@ int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u while (!(EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_OWNER)) { } + USB_LOG_INFO("Switch port %u to OHCI\r\n", port); return ohci_roothub_control(bus, setup, buf); } #endif @@ -1063,7 +1064,9 @@ int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u while (!(EHCI_HCOR->portsc[port - 1] & EHCI_PORTSC_OWNER)) { } - return ohci_roothub_control(bus, setup, buf); + + USB_LOG_INFO("Switch port %u to OHCI\r\n", port); + return -USB_ERR_NOTSUPP; } #endif break; diff --git a/components/drivers/usb/cherryusb/port/fsdev/usb_dc_fsdev.c b/components/drivers/usb/cherryusb/port/fsdev/usb_dc_fsdev.c index b2dd9cca4da..f27e8c6993f 100644 --- a/components/drivers/usb/cherryusb/port/fsdev/usb_dc_fsdev.c +++ b/components/drivers/usb/cherryusb/port/fsdev/usb_dc_fsdev.c @@ -154,7 +154,8 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep) case USB_ENDPOINT_TYPE_ISOCHRONOUS: wEpRegVal = USB_EP_ISOCHRONOUS; - break; + USB_LOG_ERR("Do not support iso in fsdev\r\n"); + return -1; default: break; diff --git a/components/drivers/usb/cherryusb/port/hpm/usb_dc_hpm.c b/components/drivers/usb/cherryusb/port/hpm/usb_dc_hpm.c index 625c8b11fbf..b663fd9afc5 100644 --- a/components/drivers/usb/cherryusb/port/hpm/usb_dc_hpm.c +++ b/components/drivers/usb/cherryusb/port/hpm/usb_dc_hpm.c @@ -128,8 +128,6 @@ int usbd_set_remote_wakeup(uint8_t busid) } usb_force_port_resume(ptr); - while (ptr->PORTSC1 & USB_PORTSC1_FPR_MASK) { - } return 0; } @@ -362,18 +360,18 @@ void USBD_IRQHandler(uint8_t busid) #if !defined(USBD_USE_CUSTOM_ISR) || !USBD_USE_CUSTOM_ISR +SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbd0) void isr_usbd0(void) { USBD_IRQHandler(_dcd_busid[0]); } -SDK_DECLARE_EXT_ISR_M(IRQn_USB0, isr_usbd0) #ifdef HPM_USB1_BASE +SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbd1) void isr_usbd1(void) { USBD_IRQHandler(_dcd_busid[1]); } -SDK_DECLARE_EXT_ISR_M(IRQn_USB1, isr_usbd1) #endif #endif diff --git a/components/drivers/usb/cherryusb/port/ohci/README.md b/components/drivers/usb/cherryusb/port/ohci/README.md index 34e753c3125..928eb0c3fd8 100644 --- a/components/drivers/usb/cherryusb/port/ohci/README.md +++ b/components/drivers/usb/cherryusb/port/ohci/README.md @@ -1,18 +1,23 @@ # Note -This OHCI is a companion controller of EHCI. +This OHCI is a companion controller of EHCI. But you can use OHCI only without CONFIG_USB_EHCI_WITH_OHCI definition. + +**And you need to pay for using OHCI driver**. ## Support Chip List ### AllwinnerTech -- F133 +- F133(EHCI + OHCI) ### Nuvoton -- Nuvoton all series +- Nuvoton all series(EHCI + OHCI, OHCI only) ### Artinchip -- d13x, d21x +- d13x, d21x(EHCI + OHCI) + +### NXP +- LPC4X/LPC5X(OHCI only) \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/ohci/usb_glue_lpc.c b/components/drivers/usb/cherryusb/port/ohci/usb_glue_lpc.c new file mode 100644 index 00000000000..51ab7814052 --- /dev/null +++ b/components/drivers/usb/cherryusb/port/ohci/usb_glue_lpc.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024, sakumisu + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "fsl_device_registers.h" +#include "fsl_power.h" +#include "usbh_core.h" + +#if defined(CONFIG_USB_EHCI_WITH_OHCI) +#error "lpc does not have ehci" +#endif + +void usb_hc_low_level_init(struct usbh_bus *bus) +{ +#if ((defined FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT)) + SYSMPU_Enable(SYSMPU, 0); +#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */ + + NVIC_ClearPendingIRQ(USB0_IRQn); + NVIC_ClearPendingIRQ(USB0_NEEDCLK_IRQn); + + POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*< Turn on USB0 Phy */ + + RESET_PeripheralReset(kUSB0D_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSB0HSL_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSB0HMR_RST_SHIFT_RSTn); + + CLOCK_EnableUsbfs0HostClock(kCLOCK_UsbfsSrcPll1, 48000000U); + + NVIC_SetPriority(USB0_IRQn, 3); + EnableIRQ(USB0_IRQn); +} + + +void usb_hc_low_level_deinit(struct usbh_bus *bus) +{ + DisableIRQ(USB0_IRQn); +} + +void USB0_IRQHandler(void) +{ + extern void USBH_IRQHandler(uint8_t busid); + USBH_IRQHandler(0); +} \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.c b/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.c index fda180909d9..2bec2a03988 100644 --- a/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.c +++ b/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.c @@ -4,18 +4,58 @@ * SPDX-License-Identifier: Apache-2.0 */ #include "usb_hc_ohci.h" -#include "usb_hc_ehci.h" + +/* Frame Interval / Periodic Start. + * + * At 12Mbps, there are 12000 bit time in each 1Msec frame. + */ + +#define OHCI_FMINTERVAL_FI (12000 - 1) +#define OHCI_FMINTERVAL_FSMPS ((6 * (OHCI_FMINTERVAL_FI - 210)) / 7) +#define DEFAULT_FMINTERVAL ((OHCI_FMINTERVAL_FSMPS << OHCI_FMINT_FSMPS_SHIFT) | OHCI_FMINTERVAL_FI) +#define DEFAULT_PERSTART ((OHCI_FMINTERVAL_FI * 9) / 10) + +struct ohci_hcd g_ohci_hcd[CONFIG_USBHOST_MAX_BUS]; + +USB_NOCACHE_RAM_SECTION struct ohci_ed_hw g_ohci_ed_pool[CONFIG_USBHOST_MAX_BUS][CONFIG_USB_OHCI_ED_NUM]; +USB_NOCACHE_RAM_SECTION struct ohci_hcca ohci_hcca[CONFIG_USBHOST_MAX_BUS]; int ohci_init(struct usbh_bus *bus) { volatile uint32_t timeout = 0; uint32_t regval; + struct ohci_ed_hw *ed; + + memset(&g_ohci_hcd[bus->hcd.hcd_id], 0, sizeof(struct ohci_hcd)); + memset(g_ohci_ed_pool[bus->hcd.hcd_id], 0, sizeof(struct ohci_ed_hw) * CONFIG_USB_OHCI_ED_NUM); + + for (uint32_t i = 0; i < 32; i++) { + ohci_hcca[bus->hcd.hcd_id].inttbl[i] = 0; + } + + for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) { + ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index]; + if ((uint32_t)&ed->hw % 32) { + USB_LOG_ERR("struct ohci_ed_hw is not align 32\r\n"); + return -USB_ERR_INVAL; + } + for (uint8_t i = 0; i < CONFIG_USB_OHCI_TD_NUM; i++) { + if ((uint32_t)&ed->td_pool[i] % 32) { + USB_LOG_ERR("struct ohci_td_hw is not align 32\r\n"); + return -USB_ERR_INVAL; + } + } + } + + for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) { + ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index]; + ed->waitsem = usb_osal_sem_create(0); + } USB_LOG_INFO("OHCI hcrevision:0x%02x\r\n", (unsigned int)OHCI_HCOR->hcrevision); + OHCI_HCOR->hcintdis = OHCI_INT_MIE; OHCI_HCOR->hccontrol = 0; - OHCI_HCOR->hccontrolheaded = 0; - OHCI_HCOR->hcbulkheaded = 0; OHCI_HCOR->hccmdsts = OHCI_CMDST_HCR; while (OHCI_HCOR->hccmdsts & OHCI_CMDST_HCR) { @@ -26,45 +66,39 @@ int ohci_init(struct usbh_bus *bus) } } - /* Frame Interval / Periodic Start. - * - * At 12Mbps, there are 12000 bit time in each 1Msec frame. - */ - -#define BITS_PER_FRAME 12000 -#define FI (BITS_PER_FRAME - 1) -#define FSMPS ((6 * (FI - 210)) / 7) -#define DEFAULT_FMINTERVAL ((FSMPS << OHCI_FMINT_FSMPS_SHIFT) | FI) -#define DEFAULT_PERSTART (((9 * BITS_PER_FRAME) / 10) - 1) - OHCI_HCOR->hcfminterval = DEFAULT_FMINTERVAL; OHCI_HCOR->hcperiodicstart = DEFAULT_PERSTART; + OHCI_HCOR->hclsthreshold = 0x628; + + OHCI_HCOR->hccontrolheaded = 0; + OHCI_HCOR->hcbulkheaded = 0; + OHCI_HCOR->hchcca = (uintptr_t)&ohci_hcca[bus->hcd.hcd_id]; + + /* Clear pending interrupts */ + regval = OHCI_HCOR->hcintsts; + OHCI_HCOR->hcintsts = regval; /* Put HC in operational state */ regval = OHCI_HCOR->hccontrol; + regval &= ~OHCI_CTRL_CBSR; regval &= ~OHCI_CTRL_HCFS_MASK; regval |= OHCI_CTRL_HCFS_OPER; + regval |= OHCI_CTRL_CBSR; + regval |= OHCI_CTRL_CLE; OHCI_HCOR->hccontrol = regval; - /* Set global power in HcRhStatus */ - OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP; + g_ohci_hcd[bus->hcd.hcd_id].n_ports = OHCI_HCOR->hcrhdescriptora & OHCI_RHDESCA_NDP_MASK; + USB_LOG_INFO("OHCI n_ports:%d\r\n", g_ohci_hcd[bus->hcd.hcd_id].n_ports); - /* Set HCCA base address */ - OHCI_HCOR->hchcca = 0; + OHCI_HCOR->hcrhdescriptora &= ~OHCI_RHDESCA_PSM; + OHCI_HCOR->hcrhdescriptora &= ~OHCI_RHDESCA_NPS; - /* Clear pending interrupts */ - regval = OHCI_HCOR->hcintsts; - OHCI_HCOR->hcintsts = regval; - - for (uint8_t port = 0; port < g_ehci_hcd[bus->hcd.hcd_id].n_pcc; port++) { - regval = OHCI_HCOR->hcrhportsts[port]; - regval |= OHCI_RHPORTST_PPS; - OHCI_HCOR->hcrhportsts[port] = regval; - } + /* Set global power in HcRhStatus */ + OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP; + usb_osal_msleep(20); /* Enable OHCI interrupts */ - OHCI_HCOR->hcinten = OHCI_INT_SO | OHCI_INT_RD | OHCI_INT_UE | OHCI_INT_OC | - OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE; + OHCI_HCOR->hcinten = OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE; return 0; } @@ -72,15 +106,25 @@ int ohci_init(struct usbh_bus *bus) int ohci_deinit(struct usbh_bus *bus) { uint32_t regval; + struct ohci_ed_hw *ed; /* Disable OHCI interrupts */ - OHCI_HCOR->hcintdis = OHCI_INT_SO | OHCI_INT_RD | OHCI_INT_UE | OHCI_INT_OC | - OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE; + OHCI_HCOR->hcintdis = OHCI_INT_WDH | OHCI_INT_RHSC | OHCI_INT_MIE; + + /* Clear pending interrupts */ + regval = OHCI_HCOR->hcintsts; + OHCI_HCOR->hcintsts = regval; + + OHCI_HCOR->hcrhsts &= ~OHCI_RHSTATUS_SGP; + + regval = OHCI_HCOR->hccontrol; + regval &= ~OHCI_CTRL_HCFS_MASK; + regval |= OHCI_CTRL_HCFS_SUSPEND; + OHCI_HCOR->hccontrol = regval; - for (uint8_t port = 0; port < g_ehci_hcd[bus->hcd.hcd_id].n_pcc; port++) { - regval = OHCI_HCOR->hcrhportsts[port]; - regval &= ~OHCI_RHPORTST_PPS; - OHCI_HCOR->hcrhportsts[port] = regval; + for (uint8_t index = 0; index < CONFIG_USB_OHCI_ED_NUM; index++) { + ed = &g_ohci_ed_pool[bus->hcd.hcd_id][index]; + usb_osal_sem_delete(ed->waitsem); } return 0; @@ -97,7 +141,7 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u uint8_t port; uint32_t temp; - nports = g_ehci_hcd[bus->hcd.hcd_id].n_pcc; + nports = g_ohci_hcd[bus->hcd.hcd_id].n_ports; port = setup->wIndex; if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) { @@ -139,28 +183,46 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u switch (setup->wValue) { case HUB_PORT_FEATURE_ENABLE: + temp = OHCI_RHPORTST_CCS; break; case HUB_PORT_FEATURE_SUSPEND: + temp = OHCI_HCOR->hccontrol; + temp &= ~OHCI_CTRL_HCFS_MASK; + temp |= OHCI_CTRL_HCFS_RESUME; + OHCI_HCOR->hccontrol = temp; + + usb_osal_msleep(20); + temp = OHCI_HCOR->hccontrol; + temp &= ~OHCI_CTRL_HCFS_MASK; + temp |= OHCI_CTRL_HCFS_OPER; + OHCI_HCOR->hccontrol = temp; + + temp = OHCI_RHPORTST_POCI; + break; case HUB_PORT_FEATURE_C_SUSPEND: + temp = OHCI_RHPORTST_PSSC; break; case HUB_PORT_FEATURE_POWER: + OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_CGP; + temp = OHCI_RHPORTST_LSDA; break; case HUB_PORT_FEATURE_C_CONNECTION: - OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_CSC; + temp = OHCI_RHPORTST_CSC; break; case HUB_PORT_FEATURE_C_ENABLE: - OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PESC; + temp = OHCI_RHPORTST_PESC; break; case HUB_PORT_FEATURE_C_OVER_CURREN: - OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_OCIC; + temp = OHCI_RHPORTST_OCIC; break; case HUB_PORT_FEATURE_C_RESET: - OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PRSC; + temp = OHCI_RHPORTST_PRSC; break; default: return -USB_ERR_NOTSUPP; } + OHCI_HCOR->hcrhportsts[port - 1] = temp; break; case HUB_REQUEST_SET_FEATURE: if (!port || port > nports) { @@ -169,11 +231,17 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u switch (setup->wValue) { case HUB_PORT_FEATURE_SUSPEND: + temp = OHCI_HCOR->hccontrol; + temp &= ~OHCI_CTRL_HCFS_MASK; + temp |= OHCI_CTRL_HCFS_SUSPEND; + OHCI_HCOR->hccontrol = temp; + break; case HUB_PORT_FEATURE_POWER: + OHCI_HCOR->hcrhsts = OHCI_RHSTATUS_SGP; break; case HUB_PORT_FEATURE_RESET: - OHCI_HCOR->hcrhportsts[port - 1] |= OHCI_RHPORTST_PRS; + OHCI_HCOR->hcrhportsts[port - 1] = OHCI_RHPORTST_PRS; while (OHCI_HCOR->hcrhportsts[port - 1] & OHCI_RHPORTST_PRS) { } @@ -188,7 +256,6 @@ int ohci_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, u return -USB_ERR_INVAL; } temp = OHCI_HCOR->hcrhportsts[port - 1]; - memcpy(buf, &temp, 4); break; default: @@ -216,9 +283,9 @@ void OHCI_IRQHandler(uint8_t busid) bus = &g_usbhost_bus[busid]; usbsts = OHCI_HCOR->hcintsts & OHCI_HCOR->hcinten; - OHCI_HCOR->hcintsts = usbsts; if (usbsts & OHCI_INT_RHSC) { + OHCI_HCOR->hcintsts = OHCI_INT_RHSC; for (int port = 0; port < CONFIG_USBHOST_MAX_RHPORTS; port++) { uint32_t portsc = OHCI_HCOR->hcrhportsts[port]; @@ -236,5 +303,51 @@ void OHCI_IRQHandler(uint8_t busid) } } if (usbsts & OHCI_INT_WDH) { + OHCI_HCOR->hcintsts = OHCI_INT_WDH; } -} \ No newline at end of file +} + +#ifndef CONFIG_USB_EHCI_WITH_OHCI +__WEAK void usb_hc_low_level_init(struct usbh_bus *bus) +{ + (void)bus; +} + +__WEAK void usb_hc_low_level_deinit(struct usbh_bus *bus) +{ + (void)bus; +} + +int usb_hc_init(struct usbh_bus *bus) +{ + usb_hc_low_level_init(bus); + return ohci_init(bus); +} + +int usb_hc_deinit(struct usbh_bus *bus) +{ + ohci_deinit(bus); + usb_hc_low_level_deinit(bus); + return 0; +} + +int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf) +{ + return ohci_roothub_control(bus, setup, buf); +} + +int usbh_submit_urb(struct usbh_urb *urb) +{ + return ohci_submit_urb(urb); +} + +int usbh_kill_urb(struct usbh_urb *urb) +{ + return ohci_kill_urb(urb); +} + +void USBH_IRQHandler(uint8_t busid) +{ + OHCI_IRQHandler(busid); +} +#endif \ No newline at end of file diff --git a/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h b/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h index 68815d9d195..19d5190966b 100644 --- a/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h +++ b/components/drivers/usb/cherryusb/port/ohci/usb_hc_ohci.h @@ -12,6 +12,38 @@ #define OHCI_HCOR ((struct ohci_hcor *)(uintptr_t)(bus->hcd.reg_base + CONFIG_USB_OHCI_HCOR_OFFSET)) +#define OHCI_PTR2ADDR(x) ((uint32_t)(uintptr_t)(x) & ~0x0F) +#define OHCI_ADDR2ED(x) ((struct ohci_ed_hw *)(uintptr_t)((uint32_t)(x) & ~0x0F)) +#define OHCI_ADDR2TD(x) ((struct ohci_td_hw *)(uintptr_t)((uint32_t)(x) & ~0x0F)) + +#ifndef CONFIG_USB_OHCI_ED_NUM +#define CONFIG_USB_OHCI_ED_NUM CONFIG_USBHOST_PIPE_NUM +#endif +#ifndef CONFIG_USB_OHCI_TD_NUM +#define CONFIG_USB_OHCI_TD_NUM 3 +#endif + +struct ohci_ed_hw; +struct ohci_td_hw { + struct ohci_gtd hw; + struct usbh_urb *urb; + uint32_t buf_start; + uint32_t length; +} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */ + +struct ohci_ed_hw { + struct ohci_ed hw; + struct ohci_td_hw td_pool[CONFIG_USB_OHCI_TD_NUM]; + uint32_t td_count; + uint8_t ed_type; + usb_osal_sem_t waitsem; +} __attribute__((aligned(32))); /* min is 16bytes, we use 32 for cacheline */ + +struct ohci_hcd { + bool ohci_ed_used[CONFIG_USB_OHCI_ED_NUM]; + uint8_t n_ports; +}; + int ohci_init(struct usbh_bus *bus); int ohci_deinit(struct usbh_bus *bus); uint16_t ohci_get_frame_number(struct usbh_bus *bus); diff --git a/components/drivers/usb/cherryusb/port/ohci/usb_ohci_reg.h b/components/drivers/usb/cherryusb/port/ohci/usb_ohci_reg.h index 030350e5cc6..61f7f4bf9a0 100644 --- a/components/drivers/usb/cherryusb/port/ohci/usb_ohci_reg.h +++ b/components/drivers/usb/cherryusb/port/ohci/usb_ohci_reg.h @@ -95,10 +95,10 @@ /* HcControl: HC control (7.1.2) */ #define OHCI_CTRL_CBSR (3 << 0) /* Bit 0: Control/bulk service ratio */ -#define OHCI_CTRL_PLE (1 << 2) /* Bit 1: Periodic list enable */ -#define OHCI_CTRL_IE (1 << 3) /* Bit 2: Isochronous enable */ -#define OHCI_CTRL_CLE (1 << 4) /* Bit 3: Control list enable */ -#define OHCI_CTRL_BLE (1 << 5) /* Bit 4: Bulk list enable */ +#define OHCI_CTRL_PLE (1 << 2) /* Bit 2: Periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* Bit 3: Isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* Bit 4: Control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* Bit 5: Bulk list enable */ #define OHCI_CTRL_HCFS_SHIFT (6) /* Bits 6-7: Host controller functional state */ #define OHCI_CTRL_HCFS_MASK (3 << OHCI_CTRL_HCFS_SHIFT) # define OHCI_CTRL_HCFS_RESET (0 << OHCI_CTRL_HCFS_SHIFT) @@ -261,9 +261,9 @@ # define ED_CONTROL_D_IN (2 << ED_CONTROL_D_SHIFT) /* IN */ # define ED_CONTROL_D_TD2 (3 << ED_CONTROL_D_SHIFT) /* Get direction from TD */ -#define ED_CONTROL_S (1 << 13) /* Bit 13: Speed (low) */ -#define ED_CONTROL_K (1 << 14) /* Bit 14: Skip */ -#define ED_CONTROL_F (1 << 15) /* Bit 15: Format (isochronous) */ +#define ED_CONTROL_SPPED_LOW (1 << 13) /* Bit 13: Speed (low) */ +#define ED_CONTROL_SKIP (1 << 14) /* Bit 14: Skip */ +#define ED_CONTROL_FORMAT_ISO (1 << 15) /* Bit 15: Format (isochronous) */ #define ED_CONTROL_MPS_SHIFT (16) /* Bits 16-26: Maximum packet size */ #define ED_CONTROL_MPS_MASK (0x7ff << ED_CONTROL_MPS_SHIFT) @@ -406,7 +406,7 @@ struct ohci_hcor /* Endpoint Descriptor Offsets (4.2.1) */ -struct ohci_ed_s +struct ohci_ed { volatile uint32_t ctrl; /* ED status/control bits */ volatile uint32_t tailp; /* TD Queue Tail Pointer (TailP) */ @@ -416,7 +416,7 @@ struct ohci_ed_s /* General Transfer Descriptor (4.3.1) */ -struct ohci_gtd_s +struct ohci_gtd { volatile uint32_t ctrl; /* TD status/control bits */ volatile uint32_t cbp; /* Current Buffer Pointer (CBP) */ @@ -426,7 +426,7 @@ struct ohci_gtd_s /* Isochronous Transfer Descriptor Offsets (4.3.2) */ -struct ohci_itd_s +struct ohci_itd { volatile uint32_t ctrl; /* TD status/control bits */ volatile uint32_t bp0; /* Buffer page 0 (BP0 */ @@ -437,7 +437,7 @@ struct ohci_itd_s /* Host Controller Communications Area Format (4.4.1) */ -struct ohci_hcca_s +struct ohci_hcca { /* HccaInterruptTable: 32x32-bit pointers to interrupt EDs */ diff --git a/components/fal/src/fal_rtt.c b/components/fal/src/fal_rtt.c index 9ef5be14401..9ae93ea6793 100644 --- a/components/fal/src/fal_rtt.c +++ b/components/fal/src/fal_rtt.c @@ -10,6 +10,8 @@ */ #include +#include +#include #include #define DBG_TAG "FAL" @@ -50,7 +52,7 @@ static rt_err_t blk_dev_control(rt_device_t dev, rt_uint8_t cmd, void *args) return -RT_ERROR; } - memcpy(geometry, &part->geometry, sizeof(struct rt_device_blk_geometry)); + rt_memcpy(geometry, &part->geometry, sizeof(struct rt_device_blk_geometry)); } else if (cmd == RT_DEVICE_CTRL_BLK_ERASE) { diff --git a/examples/utest/configs/kernel/ipc.conf b/examples/utest/configs/kernel/ipc.conf index 8af98d607a1..5dd798c1144 100644 --- a/examples/utest/configs/kernel/ipc.conf +++ b/examples/utest/configs/kernel/ipc.conf @@ -4,6 +4,7 @@ CONFIG_UTEST_MESSAGEQUEUE_TC=y CONFIG_UTEST_SIGNAL_TC=y CONFIG_UTEST_MUTEX_TC=y CONFIG_UTEST_MAILBOX_TC=y +CONFIG_UTEST_WORKQUEUE_TC=y # dependencies CONFIG_RT_USING_SEMAPHORE=y CONFIG_RT_USING_EVENT=y diff --git a/examples/utest/testcases/drivers/ipc/Kconfig b/examples/utest/testcases/drivers/ipc/Kconfig index 0e76161225b..7131a8184f4 100644 --- a/examples/utest/testcases/drivers/ipc/Kconfig +++ b/examples/utest/testcases/drivers/ipc/Kconfig @@ -4,4 +4,8 @@ config UTEST_COMPLETION_TC bool "rt_completion testcase" default n +config UTEST_WORKQUEUE_TC + bool "rt_workqueue testcase" + default n + endmenu diff --git a/examples/utest/testcases/drivers/ipc/SConscript b/examples/utest/testcases/drivers/ipc/SConscript index c1ae9c40f1d..b6c60779b7c 100644 --- a/examples/utest/testcases/drivers/ipc/SConscript +++ b/examples/utest/testcases/drivers/ipc/SConscript @@ -8,6 +8,9 @@ CPPPATH = [cwd] if GetDepend(['UTEST_COMPLETION_TC']): src += ['completion_tc.c', 'completion_timeout_tc.c'] +if GetDepend(['UTEST_WORKQUEUE_TC']): + src += ['workqueue_tc.c'] + group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH) Return('group') diff --git a/examples/utest/testcases/drivers/ipc/workqueue_tc.c b/examples/utest/testcases/drivers/ipc/workqueue_tc.c new file mode 100644 index 00000000000..3cae6657d35 --- /dev/null +++ b/examples/utest/testcases/drivers/ipc/workqueue_tc.c @@ -0,0 +1,603 @@ +/* + * Copyright (c) 2006-2024, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-06 tyx first commit + * 2024-12-31 rbb666 Adding Test Cases + */ + +#include "rtthread.h" +#include "rtdevice.h" +#include "utest.h" + +#ifdef RT_USING_DEVICE_IPC + +static rt_uint8_t get_test_thread_priority(rt_int8_t pos) +{ + rt_int16_t priority; + + priority = RT_SCHED_PRIV(rt_thread_self()).init_priority; + if (pos == 0) + { + return priority; + } + else + { + priority += pos; + } + if (priority < 0) + { + return 0; + } + else if (priority >= RT_THREAD_PRIORITY_MAX) + { + return RT_THREAD_PRIORITY_MAX - 1; + } + else + { + return (rt_uint8_t)priority; + } +} + +static void do_work_test_fun(struct rt_work *work, void *work_data) +{ + *((int *)work_data) = 1; +} + +static void do_work_test(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work; + volatile int work_flag = 0; + rt_err_t err; + + /* 1 higher priority than the current test thread */ + curr_priority = get_test_thread_priority(-1); + queue = rt_workqueue_create("test", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + rt_work_init(&work, do_work_test_fun, (void *)&work_flag); + err = rt_workqueue_submit_work(queue, &work, 0); + uassert_int_equal(err, RT_EOK); + + /* Delay 5 ticks to ensure that the task has been executed */ + rt_thread_delay(5); + uassert_int_equal(work_flag, 1); + + rt_thread_delay(100); + rt_workqueue_destroy(queue); +} + +static void do_delay_work_test_fun(struct rt_work *work, void *work_data) +{ + *((rt_tick_t *)work_data) = rt_tick_get(); +} + +static void do_delay_work_test(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work; + volatile rt_tick_t work_start = 0; + volatile rt_tick_t work_end = 0; + rt_err_t err; + + /* 1 higher priority than the current test thread */ + curr_priority = get_test_thread_priority(-1); + queue = rt_workqueue_create("test", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + rt_work_init(&work, do_delay_work_test_fun, (void *)&work_end); + work_start = rt_tick_get(); + /* Normal delayed work submission test */ + err = rt_workqueue_submit_work(queue, &work, 10); + uassert_int_equal(err, RT_EOK); + + /* Ensure that the delayed work has been executed */ + rt_thread_delay(15); + /* Check if the delayed task is executed after 10 ticks */ + if (work_end < work_start || work_end - work_start < 10) + { + uassert_false(1); + } + rt_thread_delay(100); + rt_workqueue_destroy(queue); +} + +static void cancle_work_test01_fun(struct rt_work *work, void *work_data) +{ + *((int *)work_data) = 1; +} + +static void cancle_work_test01(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work; + volatile int work_flag = 0; + rt_err_t err; + + /* 1 lower priority than the current test thread */ + curr_priority = get_test_thread_priority(1); + queue = rt_workqueue_create("test", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + work_flag = 0; + rt_work_init(&work, cancle_work_test01_fun, (void *)&work_flag); + /* Cancel the work before it is executed */ + err = rt_workqueue_submit_work(queue, &work, 0); + uassert_int_equal(err, RT_EOK); + + /* Cancel Now */ + err = rt_workqueue_cancel_work(queue, &work); + uassert_int_equal(err, RT_EOK); + + rt_thread_delay(5); + uassert_int_equal(work_flag, 0); + + rt_thread_delay(100); + rt_workqueue_destroy(queue); +} + +static void cancle_work_test02_fun(struct rt_work *work, void *work_data) +{ + rt_thread_delay(10); +} + +static void cancle_work_test02(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work; + rt_err_t err; + + /* 1 higher priority than the current test thread */ + curr_priority = get_test_thread_priority(-1); + queue = rt_workqueue_create("test", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + rt_work_init(&work, cancle_work_test02_fun, RT_NULL); + /* Cancel the work while it is in progress */ + err = rt_workqueue_submit_work(queue, &work, 0); + uassert_int_equal(err, RT_EOK); + + rt_thread_delay(5); + err = rt_workqueue_cancel_work(queue, &work); + uassert_int_equal(err, -RT_EBUSY); + + rt_thread_delay(100); + rt_workqueue_destroy(queue); +} + +static void cancle_work_test03_fun(struct rt_work *work, void *work_data) +{ + rt_thread_delay(5); +} + +static void cancle_work_test03(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work; + rt_err_t err; + + /* 1 lower priority than the current test thread */ + curr_priority = get_test_thread_priority(1); + queue = rt_workqueue_create("test", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + rt_work_init(&work, cancle_work_test03_fun, RT_NULL); + /* Canceling a work after it has been executed */ + err = rt_workqueue_submit_work(queue, &work, 0); + uassert_int_equal(err, RT_EOK); + + rt_thread_delay(10); + err = rt_workqueue_cancel_work(queue, &work); + uassert_int_equal(err, RT_EOK); + + rt_thread_delay(100); + rt_workqueue_destroy(queue); +} + +static void cancle_work_test04_fun(struct rt_work *work, void *work_data) +{ + rt_thread_delay(10); + *((int *)work_data) = 1; +} + +static void cancle_work_test04(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work; + volatile int work_flag = 0; + rt_err_t err; + + /* 1 lower priority than the current test thread */ + curr_priority = get_test_thread_priority(1); + queue = rt_workqueue_create("test", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + rt_work_init(&work, cancle_work_test04_fun, (void *)&work_flag); + err = rt_workqueue_submit_work(queue, &work, 0); + uassert_int_equal(err, RT_EOK); + + rt_thread_delay(5); + /* Synchronized cancellation work */ + err = rt_workqueue_cancel_work_sync(queue, &work); + uassert_int_equal(err, RT_EOK); + + uassert_int_equal(work_flag, 1); + + rt_thread_delay(100); + rt_workqueue_destroy(queue); +} + +static void cancle_delay_work_test01_fun(struct rt_work *work, void *work_data) +{ + *((int *)work_data) = 1; +} + +static void cancle_delay_work_test01(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work; + volatile int work_flag = 0; + rt_err_t err; + + /* 1 lower priority than the current test thread */ + curr_priority = get_test_thread_priority(1); + queue = rt_workqueue_create("test", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + work_flag = 0; + rt_work_init(&work, cancle_delay_work_test01_fun, (void *)&work_flag); + err = rt_workqueue_submit_work(queue, &work, 20); + uassert_int_equal(err, RT_EOK); + + rt_thread_delay(10); + /* Cancel work */ + err = rt_workqueue_cancel_work(queue, &work); + uassert_int_equal(err, RT_EOK); + + rt_thread_delay(15); + uassert_int_equal(work_flag, 0); + + rt_thread_delay(100); + rt_workqueue_destroy(queue); +} + +static void repeat_work_test01_fun(struct rt_work *work, void *work_data) +{ + *((int *)work_data) += 1; +} + +static void repeat_work_test01(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work; + volatile int work_flag = 0; + rt_err_t err; + + /* 1 lower priority than the current test thread */ + curr_priority = get_test_thread_priority(1); + queue = rt_workqueue_create("test01", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + work_flag = 0; + rt_work_init(&work, repeat_work_test01_fun, (void *)&work_flag); + /* Multiple submissions of the same work */ + err = rt_workqueue_submit_work(queue, &work, 0); + uassert_int_equal(err, RT_EOK); + + /* The same work, before it is executed, can be submitted repeatedly and executed only once */ + err = rt_workqueue_submit_work(queue, &work, 0); + if (err != RT_EOK) + { + LOG_E("L:%d err. %d", __LINE__, err); + } + rt_thread_delay(10); + /* Check if it was executed only once */ + uassert_int_equal(work_flag, 1); + + rt_thread_delay(100); + rt_workqueue_destroy(queue); +} + +static void repeat_work_test02_fun(struct rt_work *work, void *work_data) +{ + rt_thread_delay(10); + *((int *)work_data) += 1; +} + +static void repeat_work_test02(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work; + volatile int work_flag = 0; + rt_err_t err; + + /* 1 priority higher than current test thread */ + curr_priority = get_test_thread_priority(-1); + queue = rt_workqueue_create("test02", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + rt_work_init(&work, repeat_work_test02_fun, (void *)&work_flag); + /* Submit work with high queue priority that will be executed immediately */ + err = rt_workqueue_submit_work(queue, &work, 0); + uassert_int_equal(err, RT_EOK); + + rt_thread_delay(5); + /* Re-submission of work in progress */ + err = rt_workqueue_submit_work(queue, &work, 0); + if (err != RT_EOK) + { + LOG_E("L:%d err. %d", __LINE__, err); + } + rt_thread_delay(10); + uassert_int_equal(work_flag, 1); + + rt_thread_delay(10); + uassert_int_equal(work_flag, 2); + + rt_workqueue_destroy(queue); +} + +static struct rt_workqueue *queue_3; + +static void repeat_work_test03_fun(struct rt_work *work, void *work_data) +{ + int *work_flag = (int *)work_data; + (*work_flag) += 1; + rt_kprintf("work_flag:%d\n", *work_flag); + if (*work_flag < 20) + { + rt_workqueue_submit_work(queue_3, work, 0); + } +} + +static void repeat_work_test03(void) +{ + rt_uint8_t curr_priority; + struct rt_work work; + volatile int work_flag = 0; + rt_err_t err; + + /* 1 priority higher than current test thread */ + curr_priority = get_test_thread_priority(-1); + queue_3 = rt_workqueue_create("test03", 2048, curr_priority); + if (queue_3 == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + rt_work_init(&work, repeat_work_test03_fun, (void *)&work_flag); + /* Submit work with high queue priority that will be executed immediately */ + err = rt_workqueue_submit_work(queue_3, &work, 0); + uassert_int_equal(err, RT_EOK); + + /* Wait for the work to be executed 20 times with a timeout */ + err = rt_workqueue_cancel_work_sync(queue_3, &work); + uassert_int_equal(err, RT_EOK); + + /* Check if the work was executed 20 times */ + uassert_int_equal(work_flag, 20); + + rt_workqueue_destroy(queue_3); +} + +static void repeat_delay_work_test01_fun(struct rt_work *work, void *work_data) +{ + *((int *)work_data) += 1; +} + +static void repeat_delay_work_test01(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work; + volatile int work_flag = 0; + rt_err_t err; + + /* 1 lower priority than the current test thread */ + curr_priority = get_test_thread_priority(1); + queue = rt_workqueue_create("test", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + work_flag = 0; + rt_work_init(&work, repeat_delay_work_test01_fun, (void *)&work_flag); + + err = rt_workqueue_submit_work(queue, &work, 20); + uassert_int_equal(err, RT_EOK); + + /* At this point the delayed work has not been executed */ + rt_thread_delay(10); + /* Re-submission of time-delayed work */ + err = rt_workqueue_submit_work(queue, &work, 20); + uassert_int_equal(err, RT_EOK); + + rt_thread_delay(15); + uassert_int_equal(work_flag, 0); + + /* Waiting for delayed task execution */ + rt_thread_delay(15); + uassert_int_equal(work_flag, 1); + + rt_thread_delay(100); + rt_workqueue_destroy(queue); +} + +static void repeat_delay_work_test02_fun(struct rt_work *work, void *work_data) +{ + rt_thread_delay(10); + *((int *)work_data) += 1; +} + +static void repeat_delay_work_test02(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work; + volatile int work_flag = 0; + rt_err_t err; + + /* 1 lower priority than the current test thread */ + curr_priority = get_test_thread_priority(1); + queue = rt_workqueue_create("test", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + work_flag = 0; + rt_work_init(&work, repeat_delay_work_test02_fun, (void *)&work_flag); + + err = rt_workqueue_submit_work(queue, &work, 20); + uassert_int_equal(err, RT_EOK); + + /* Waiting for delayed work execution */ + rt_thread_delay(25); + err = rt_workqueue_submit_work(queue, &work, 20); + uassert_int_equal(err, RT_EOK); + + /* Check if the delayed work has been run only once */ + rt_thread_delay(10); + uassert_int_equal(work_flag, 1); + + rt_thread_delay(25); + /* Check if the delayed work is executed twice */ + uassert_int_equal(work_flag, 2); + + rt_thread_delay(100); + rt_workqueue_destroy(queue); +} + +static void cancel_all_work_test_fun(struct rt_work *work, void *work_data) +{ + *((int *)work_data) += 1; +} + +static void cancel_all_work_test(void) +{ + struct rt_workqueue *queue; + rt_uint8_t curr_priority; + struct rt_work work1; + struct rt_work work2; + struct rt_work work3; + struct rt_work work4; + volatile int work_flag = 0; + rt_err_t err; + + curr_priority = get_test_thread_priority(1); + queue = rt_workqueue_create("test", 2048, curr_priority); + if (queue == RT_NULL) + { + LOG_E("queue create failed, L:%d", __LINE__); + return; + } + work_flag = 0; + rt_work_init(&work1, cancel_all_work_test_fun, (void *)&work_flag); + rt_work_init(&work2, cancel_all_work_test_fun, (void *)&work_flag); + rt_work_init(&work3, cancel_all_work_test_fun, (void *)&work_flag); + rt_work_init(&work4, cancel_all_work_test_fun, (void *)&work_flag); + + err = rt_workqueue_submit_work(queue, &work1, 0); + uassert_int_equal(err, RT_EOK); + + err = rt_workqueue_submit_work(queue, &work2, 0); + uassert_int_equal(err, RT_EOK); + + err = rt_workqueue_submit_work(queue, &work3, 10); + uassert_int_equal(err, RT_EOK); + + err = rt_workqueue_submit_work(queue, &work4, 10); + uassert_int_equal(err, RT_EOK); + + err = rt_workqueue_cancel_all_work(queue); + uassert_int_equal(err, RT_EOK); + + rt_thread_delay(20); + uassert_int_equal(work_flag, 0); + + rt_thread_delay(100); + rt_workqueue_destroy(queue); +} + +static rt_err_t utest_tc_init(void) +{ + return RT_EOK; +} + +static rt_err_t utest_tc_cleanup(void) +{ + return RT_EOK; +} + +static void testcase(void) +{ + /* General work queue test */ + UTEST_UNIT_RUN(do_work_test); + /* Delayed work queue test */ + UTEST_UNIT_RUN(do_delay_work_test); + /* Cancellation of work prior to implementation */ + UTEST_UNIT_RUN(cancle_work_test01); + /* Cancellation of work during execution */ + UTEST_UNIT_RUN(cancle_work_test02); + /* Cancellation of work after implementation */ + UTEST_UNIT_RUN(cancle_work_test03); + /* Synchronized cancellation of work during execution */ + UTEST_UNIT_RUN(cancle_work_test04); + /* Cancel delayed work before execution */ + UTEST_UNIT_RUN(cancle_delay_work_test01); + /* Multiple submissions of the same work prior to implementation */ + UTEST_UNIT_RUN(repeat_work_test01); + /* Multiple submissions of the same work during execution */ + UTEST_UNIT_RUN(repeat_work_test02); + /* Submitting the same task multiple times in a mission */ + UTEST_UNIT_RUN(repeat_work_test03); + /* Multiple submissions of the same delayed task before execution */ + UTEST_UNIT_RUN(repeat_delay_work_test01); + /* Multiple submissions of the same delayed task during execution */ + UTEST_UNIT_RUN(repeat_delay_work_test02); + /* Cancel all works */ + UTEST_UNIT_RUN(cancel_all_work_test); +} +UTEST_TC_EXPORT(testcase, "components.drivers.ipc.workqueue_tc", utest_tc_init, utest_tc_cleanup, 300); +#endif