diff --git a/README.md b/README.md
index 187b49a3a0dbd270e521b2255201acb8c71a9f0a..8f7213ff99c90f1393096e7343c746719cc784fd 100644
--- a/README.md
+++ b/README.md
@@ -130,7 +130,7 @@ D2000 是一款面向桌面应用的高性能通用 8 核处理器。每 2 个
| SDIO | E2000 | | mmc/fsdio |
| SPI | E2000 | | spi/fspim |
| ADC | E2000 | | adc |
-
+| CAN | FT2000/4
D2000
E2000 | | can |
| Third-Party | Platform Supported | Platform Developing | Component |
| ------------------------------ | -------------------------- | --------------------------- | ------------------------- |
@@ -142,7 +142,7 @@ D2000 是一款面向桌面应用的高性能通用 8 核处理器。每 2 个
| SPIFFS-0.3.7 | FT2000/4
D2000
E2000 | | spiffs-0.3.7 |
| TLSF-3.1.0 | FT2000/4
D2000
E2000 | | tlsf-3.1.0 |
| Sdmmc-1.0 | E2000 | | sdmmc-1.0 |
-
+| CherryUSB-0.6.0 | E2000 | | cherryusb-0.5.2 |
---
## 5. 参考资料
diff --git a/docs/ChangeLog.md b/docs/ChangeLog.md
index 4a7f012811f62dcdbb94925cd3eea587c9213c27..26f48142f0534ddece868e4ab670da3ef98ab80e 100644
--- a/docs/ChangeLog.md
+++ b/docs/ChangeLog.md
@@ -1,3 +1,28 @@
+
+# Phytium FreeRTOS SDK 2022-10-10 ChangeLog
+
+Change Log sinc 2022-09-23
+
+## example
+
+- add cherryusb host example
+
+## third-party
+
+- add cherryusb 0.5.2 and port to xhci
+
+# Phytium FreeRTOS SDK 2022-09-23 ChangeLog
+
+Change Log sinc 2022-09-15
+
+## driver
+
+- add can os driver
+
+## example
+
+- add can test test example
+
# Phytium FreeRTOS SDK 2022-09-07 ChangeLog
Change Log sinc 2022-08-30
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 638e5c8dc681c383c6c47795ad35c4189b295827..6496ededbb4e3e3b2ce7219b8af426c71ddacc12 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -28,6 +28,8 @@ menu "Freertos Wdt Drivers"
bool
prompt "Use Freertos wdt driver"
default n
+ select USE_WDT
+ select USE_FWDT
endmenu
menu "Freertos Eth Drivers"
@@ -77,4 +79,13 @@ menu "Freertos Adc Drivers"
default n
select USE_ADC
select USE_FADC
+endmenu
+
+menu "Freertos Can Drivers"
+ config FREERTOS_USE_CAN
+ bool
+ prompt "Use Freertos can driver"
+ default n
+ select USE_CAN
+ select USE_FCAN
endmenu
\ No newline at end of file
diff --git a/drivers/can/fcan_os.c b/drivers/can/fcan_os.c
new file mode 100644
index 0000000000000000000000000000000000000000..1bece2a4c3e8bbd2bc0c947f2e1d6dad82e8f1f8
--- /dev/null
+++ b/drivers/can/fcan_os.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: fcan_os.c
+ * Date: 2022-09-15 14:20:19
+ * LastEditTime: 2022-09-21 16:59:51
+ * Description: This file is for
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ */
+#include
+#include
+#include
+#include
+#include "task.h"
+#include "ft_types.h"
+#include "ft_assert.h"
+#include "ft_debug.h"
+#include "fcan_os.h"
+#include "fcan.h"
+#include "interrupt.h"
+#include "fcan_hw.h"
+
+#define FCAN_DEBUG_TAG "FFreeRTOSCan"
+#define FCAN_ERROR(format, ...) FT_DEBUG_PRINT_E(FCAN_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FCAN_WARN(format, ...) FT_DEBUG_PRINT_W(FCAN_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FCAN_INFO(format, ...) FT_DEBUG_PRINT_I(FCAN_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FCAN_DEBUG(format, ...) FT_DEBUG_PRINT_D(FCAN_DEBUG_TAG, format, ##__VA_ARGS__)
+
+static FFreeRTOSCan os_can[FCAN_INSTANCE_NUM] = {0};
+
+/**
+ * @name: FFreeRTOSCanInit
+ * @msg: init freeRTOS can instance, include init can and create mutex
+ * @param {u32} instance_id, can instance id
+ * @return {FFreeRTOSCan *} pointer to os can instance
+ */
+FFreeRTOSCan *FFreeRTOSCanInit(u32 instance_id)
+{
+ FASSERT(instance_id < FCAN_INSTANCE_NUM);
+ FASSERT(FT_COMPONENT_IS_READY != os_can[instance_id].can_ctrl.is_ready);
+
+ FCanConfig pconfig;
+ pconfig = *FCanLookupConfig(instance_id);
+ pconfig.irq_prority = FREERTOS_CAN_IRQ_PRIORITY;
+
+ FASSERT(FCanCfgInitialize(&os_can[instance_id].can_ctrl, &pconfig) == FT_SUCCESS);
+ FASSERT((os_can[instance_id].can_semaphore = xSemaphoreCreateMutex()) != NULL);
+
+ return (&os_can[instance_id]);
+}
+
+/**
+ * @name: FFreeRTOSCanDeinit
+ * @msg: deinit freeRTOS can instance, include stop can, deinit can and delete mutex
+ * @param {FFreeRTOSCan} *os_can_p, pointer to os can instance
+ * @return err code information, FCAN_SUCCESS indicates success,others indicates failed
+ */
+FError FFreeRTOSCanDeinit(FFreeRTOSCan *os_can_p)
+{
+ FASSERT(os_can_p);
+ FASSERT(os_can_p->can_semaphore != NULL);
+
+ FCanDeInitialize(&os_can_p->can_ctrl);
+ vSemaphoreDelete(os_can_p->can_semaphore);
+ memset(os_can_p, 0, sizeof(*os_can_p));
+
+ return FCAN_SUCCESS;
+}
+
+/**
+ * @name: FFreeRTOSCanControl
+ * @msg: control freeRTOS can instance
+ * @param {FFreeRTOSCan} *os_can_p, pointer to os can instance
+ * @param {int} cmd, control cmd
+ * @param {void} *args, pointer to control cmd arguments
+ * @return err code information, FCAN_SUCCESS indicates success,others indicates failed
+ */
+FError FFreeRTOSCanControl(FFreeRTOSCan *os_can_p, int cmd, void *arg)
+{
+ FError ret = FCAN_SUCCESS;
+ FCanBaudrateConfig *baudrate_config;
+ FCanStatus *status_p;
+ FCanIdMaskConfig *id_mask_p;
+ FCanIntrEventConfig *intr_event_p;
+ boolean use_canfd;
+
+ /* New contrl can be performed only after current one is finished */
+ if (pdFALSE == xSemaphoreTake(os_can_p->can_semaphore, portMAX_DELAY))
+ {
+ FCAN_ERROR("Can xSemaphoreTake failed\r\n");
+ /* We could not take the semaphore, exit with 0 data received */
+ return FREERTOS_CAN_SEM_ERROR;
+ }
+
+ switch (cmd)
+ {
+ case FREERTOS_CAN_CTRL_ENABLE:
+ FCanEnable(&os_can_p->can_ctrl, TRUE);
+ break;
+
+ case FREERTOS_CAN_CTRL_DISABLE:
+ FCanEnable(&os_can_p->can_ctrl, FALSE);
+ break;
+
+ case FREERTOS_CAN_CTRL_BAUDRATE_SET:
+ baudrate_config = (FCanBaudrateConfig *)arg;
+ ret = FCanBaudrateSet(&os_can_p->can_ctrl, baudrate_config);
+ break;
+
+ case FREERTOS_CAN_CTRL_STATUS_GET:
+ status_p = (FCanStatus *)arg;
+ ret = FCanStatusGet(&os_can_p->can_ctrl, status_p);
+ break;
+
+ case FREERTOS_CAN_CTRL_ID_MASK_SET:
+ id_mask_p = (FCanIdMaskConfig *)arg;
+ ret = FCanIdMaskFilterSet(&os_can_p->can_ctrl, id_mask_p);
+ break;
+
+ case FREERTOS_CAN_CTRL_ID_MASK_ENABLE:
+ FCanIdMaskFilterEnable(&os_can_p->can_ctrl);
+ break;
+
+ case FREERTOS_CAN_CTRL_INTR_SET:
+ intr_event_p = (FCanIntrEventConfig *)arg;
+ FCanRegisterInterruptHandler(&os_can_p->can_ctrl, intr_event_p);
+ FCanInterruptEnable(&os_can_p->can_ctrl, intr_event_p->type);
+ break;
+
+ case FREERTOS_CAN_CTRL_FD_ENABLE:
+ use_canfd = (boolean)(uintptr)arg;
+ FCanFdEnable(&os_can_p->can_ctrl, use_canfd);
+ break;
+ default:
+ FCAN_ERROR("invalid cmd.");
+ ret = FCAN_INVAL_PARAM;
+ break;
+ }
+
+ /* Enable next contrl. Current one is finished */
+ if (pdFALSE == xSemaphoreGive(os_can_p->can_semaphore))
+ {
+ /* We could not post the semaphore, exit with error */
+ FCAN_ERROR("Can xSemaphoreGive failed\r\n");
+ return FREERTOS_CAN_SEM_ERROR;
+ }
+
+ return ret;
+
+}
+
+/**
+ * @name: FFreeRTOSCanSend
+ * @msg: send can frame
+ * @param {FFreeRTOSCan} *os_can_p, pointer to os can instance
+ * @param {FCanFrame} *frame_p, pointer to can frame
+ * @return err code information, FCAN_SUCCESS indicates success,others indicates failed
+ */
+FError FFreeRTOSCanSend(FFreeRTOSCan *os_can_p, FCanFrame *frame_p)
+{
+ FASSERT(os_can_p);
+ FASSERT(os_can_p->can_semaphore != NULL);
+ FASSERT(frame_p);
+
+ FError ret = FCAN_SUCCESS;
+
+ /* New contrl can be performed only after current one is finished */
+ if (pdFALSE == xSemaphoreTake(os_can_p->can_semaphore, portMAX_DELAY))
+ {
+ FCAN_ERROR("Can xSemaphoreTake failed\r\n");
+ /* We could not take the semaphore, exit with 0 data received */
+ return FREERTOS_CAN_SEM_ERROR;
+ }
+
+ ret = FCanSend(&os_can_p->can_ctrl, frame_p);
+ if (ret != FCAN_SUCCESS)
+ {
+ FCAN_ERROR("Can send failed\r\n");
+ }
+
+ /* Enable next contrl. Current one is finished */
+ if (pdFALSE == xSemaphoreGive(os_can_p->can_semaphore))
+ {
+ /* We could not post the semaphore, exit with error */
+ FCAN_ERROR("Can xSemaphoreGive failed\r\n");
+ return FREERTOS_CAN_SEM_ERROR;
+ }
+
+ return ret;
+
+}
+
+/**
+ * @name: FFreeRTOSCanRecv
+ * @msg: receive can frame
+ * @param {FFreeRTOSCan} *os_can_p, pointer to os can instance
+ * @param {FCanFrame} *frame_p, pointer to can frame
+ * @return err code information, FCAN_SUCCESS indicates success,others indicates failed
+ */
+FError FFreeRTOSCanRecv(FFreeRTOSCan *os_can_p, FCanFrame *frame_p)
+{
+ FASSERT(os_can_p);
+ FASSERT(os_can_p->can_semaphore != NULL);
+ FASSERT(frame_p);
+
+ FError ret = FCAN_SUCCESS;
+
+ /* New contrl can be performed only after current one is finished */
+ if (pdFALSE == xSemaphoreTake(os_can_p->can_semaphore, portMAX_DELAY))
+ {
+ FCAN_ERROR("Can xSemaphoreTake failed\r\n");
+ /* We could not take the semaphore, exit with 0 data received */
+ return FREERTOS_CAN_SEM_ERROR;
+ }
+
+ ret = FCanRecv(&os_can_p->can_ctrl, frame_p);
+ if (ret != FCAN_SUCCESS)
+ {
+ FCAN_ERROR("Can recv failed\r\n");
+ }
+
+ /* Enable next contrl. Current one is finished */
+ if (pdFALSE == xSemaphoreGive(os_can_p->can_semaphore))
+ {
+ /* We could not post the semaphore, exit with error */
+ FCAN_ERROR("Can xSemaphoreGive failed\r\n");
+ return FREERTOS_CAN_SEM_ERROR;
+ }
+
+ return ret;
+
+}
\ No newline at end of file
diff --git a/drivers/can/fcan_os.h b/drivers/can/fcan_os.h
new file mode 100644
index 0000000000000000000000000000000000000000..5efca37a2e75142fbbcabbed537dc9b4c89bdca0
--- /dev/null
+++ b/drivers/can/fcan_os.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: fcan_os.h
+ * Date: 2022-09-16 11:40:19
+ * LastEditTime: 2022-09-21 16:59:58
+ * Description: This file is for
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ */
+
+#ifndef DRIVERS_FCAN_OS_H
+#define DRIVERS_FCAN_OS_H
+
+#include
+#include
+#include "ft_error_code.h"
+#include "fcan.h"
+#include "ft_types.h"
+
+/* freertos can error */
+#define FREERTOS_CAN_OK FT_SUCCESS
+#define FREERTOS_CAN_SEM_ERROR FT_CODE_ERR(ErrModBsp, ErrBspCan, 10)
+
+/* freertos can interrupt priority */
+#define FREERTOS_CAN_IRQ_PRIORITY IRQ_PRIORITY_VALUE_12
+
+/* can control operation */
+enum
+{
+ FREERTOS_CAN_CTRL_ENABLE = 0, /* enable can */
+ FREERTOS_CAN_CTRL_DISABLE = 1, /* disable can */
+ FREERTOS_CAN_CTRL_BAUDRATE_SET, /* set can baudrate */
+ FREERTOS_CAN_CTRL_STATUS_GET, /* get can status */
+ FREERTOS_CAN_CTRL_ID_MASK_SET, /* set can receive id mask */
+ FREERTOS_CAN_CTRL_ID_MASK_ENABLE, /* enable can receive id mask */
+ FREERTOS_CAN_CTRL_INTR_SET, /* set can interrupt handler */
+ FREERTOS_CAN_CTRL_INTR_ENABLE, /* enable can interrupt */
+ FREERTOS_CAN_CTRL_FD_ENABLE, /* set can fd enable */
+ FREERTOS_CAN_CTRL_NUM
+};
+
+typedef struct
+{
+ FCanCtrl can_ctrl; /* can object */
+ xSemaphoreHandle can_semaphore; /* can semaphore for resource sharing */
+} FFreeRTOSCan;
+
+/* init freertos can instance */
+FFreeRTOSCan *FFreeRTOSCanInit(u32 instance_id);
+
+/* deinit freertos can instance */
+FError FFreeRTOSCanDeinit(FFreeRTOSCan *os_can_p);
+
+/* can config */
+FError FFreeRTOSCanControl(FFreeRTOSCan *os_can_p, int cmd, void *arg);
+
+/* can send frame */
+FError FFreeRTOSCanSend(FFreeRTOSCan *os_can_p, FCanFrame *frame_p);
+
+/* can receive frame */
+FError FFreeRTOSCanRecv(FFreeRTOSCan *os_can_p, FCanFrame *frame_p);
+
+
+#endif // !
diff --git a/drivers/drivers.mk b/drivers/drivers.mk
index 3e7da0a8facfaa7e588806afb6802fb1878f295e..b169cfe0a90b548d111dae666db2e2fe36ee74db 100644
--- a/drivers/drivers.mk
+++ b/drivers/drivers.mk
@@ -55,3 +55,7 @@ ifdef CONFIG_FREERTOS_USE_ADC
INC_DIR += $(OS_DRIVER_CUR_DIR)/adc
endif
+ifdef CONFIG_FREERTOS_USE_CAN
+ SRC_DIR += $(OS_DRIVER_CUR_DIR)/can
+ INC_DIR += $(OS_DRIVER_CUR_DIR)/can
+endif
diff --git a/example/freertos_feature/eventgroup/configs/d2000_aarch32_eg_configs b/example/freertos_feature/eventgroup/configs/d2000_aarch32_eg_configs
index 88242621be7dacbe44c1ca7cebc38c3ea086a1f0..1f65e320b69006b78f6799dbb55fa3ddf9512eb1 100644
--- a/example/freertos_feature/eventgroup/configs/d2000_aarch32_eg_configs
+++ b/example/freertos_feature/eventgroup/configs/d2000_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/eventgroup/configs/d2000_aarch64_eg_configs b/example/freertos_feature/eventgroup/configs/d2000_aarch64_eg_configs
index f7da4f7ec0909d34aba3fd2fa416f37b1c3ba796..b6f76f4c15636aab052b117d81fad5dc35c48c6e 100644
--- a/example/freertos_feature/eventgroup/configs/d2000_aarch64_eg_configs
+++ b/example/freertos_feature/eventgroup/configs/d2000_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/eventgroup/configs/e2000d_aarch32_eg_configs b/example/freertos_feature/eventgroup/configs/e2000d_aarch32_eg_configs
index 1e787231b7b1bfef02913cb0edf2681eed950dc4..dcbfaedf6532dda1df4b1438d6013f6e731b9ed0 100644
--- a/example/freertos_feature/eventgroup/configs/e2000d_aarch32_eg_configs
+++ b/example/freertos_feature/eventgroup/configs/e2000d_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/eventgroup/configs/e2000d_aarch64_eg_configs b/example/freertos_feature/eventgroup/configs/e2000d_aarch64_eg_configs
index e1b4974ab7dc8017a1bd9444babff8e8dc0a8acb..7e45bd9490d83a614f2202447656da11d3655eef 100644
--- a/example/freertos_feature/eventgroup/configs/e2000d_aarch64_eg_configs
+++ b/example/freertos_feature/eventgroup/configs/e2000d_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/eventgroup/configs/e2000q_aarch32_eg_configs b/example/freertos_feature/eventgroup/configs/e2000q_aarch32_eg_configs
index 8e8a511b5796a9c927c31028f78ed784e564cc25..755c27f6473e3a58bb1fb889adc9896fd3de0fba 100644
--- a/example/freertos_feature/eventgroup/configs/e2000q_aarch32_eg_configs
+++ b/example/freertos_feature/eventgroup/configs/e2000q_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/eventgroup/configs/e2000q_aarch64_eg_configs b/example/freertos_feature/eventgroup/configs/e2000q_aarch64_eg_configs
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/eventgroup/configs/e2000q_aarch64_eg_configs
+++ b/example/freertos_feature/eventgroup/configs/e2000q_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/eventgroup/configs/ft2004_aarch32_eg_configs b/example/freertos_feature/eventgroup/configs/ft2004_aarch32_eg_configs
index 0138724f952e35b4c4ba87bffba05092d4f0c916..f42811a5bdbc43bc5075b6ca339f1ffd7fe53df3 100644
--- a/example/freertos_feature/eventgroup/configs/ft2004_aarch32_eg_configs
+++ b/example/freertos_feature/eventgroup/configs/ft2004_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/eventgroup/configs/ft2004_aarch64_eg_configs b/example/freertos_feature/eventgroup/configs/ft2004_aarch64_eg_configs
index c9c32f36bdb82f19e010c471b287d1bce9dcf357..e0ec68fb05bc7eebbe4490f0fa4b12cad6a30bb7 100644
--- a/example/freertos_feature/eventgroup/configs/ft2004_aarch64_eg_configs
+++ b/example/freertos_feature/eventgroup/configs/ft2004_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/eventgroup/sdkconfig b/example/freertos_feature/eventgroup/sdkconfig
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/eventgroup/sdkconfig
+++ b/example/freertos_feature/eventgroup/sdkconfig
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/eventgroup/sdkconfig.h b/example/freertos_feature/eventgroup/sdkconfig.h
index 070be66948577be34cf1ceec7e087d8a36db55cb..918ddd1ec09a52898e57bb516bba1cc9a40ec952 100644
--- a/example/freertos_feature/eventgroup/sdkconfig.h
+++ b/example/freertos_feature/eventgroup/sdkconfig.h
@@ -154,6 +154,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/freertos_feature/interrupt/configs/d2000_aarch32_eg_configs b/example/freertos_feature/interrupt/configs/d2000_aarch32_eg_configs
index 88242621be7dacbe44c1ca7cebc38c3ea086a1f0..1f65e320b69006b78f6799dbb55fa3ddf9512eb1 100644
--- a/example/freertos_feature/interrupt/configs/d2000_aarch32_eg_configs
+++ b/example/freertos_feature/interrupt/configs/d2000_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/interrupt/configs/d2000_aarch64_eg_configs b/example/freertos_feature/interrupt/configs/d2000_aarch64_eg_configs
index f7da4f7ec0909d34aba3fd2fa416f37b1c3ba796..b6f76f4c15636aab052b117d81fad5dc35c48c6e 100644
--- a/example/freertos_feature/interrupt/configs/d2000_aarch64_eg_configs
+++ b/example/freertos_feature/interrupt/configs/d2000_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/interrupt/configs/e2000d_aarch32_eg_configs b/example/freertos_feature/interrupt/configs/e2000d_aarch32_eg_configs
index 1e787231b7b1bfef02913cb0edf2681eed950dc4..dcbfaedf6532dda1df4b1438d6013f6e731b9ed0 100644
--- a/example/freertos_feature/interrupt/configs/e2000d_aarch32_eg_configs
+++ b/example/freertos_feature/interrupt/configs/e2000d_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/interrupt/configs/e2000d_aarch64_eg_configs b/example/freertos_feature/interrupt/configs/e2000d_aarch64_eg_configs
index e1b4974ab7dc8017a1bd9444babff8e8dc0a8acb..7e45bd9490d83a614f2202447656da11d3655eef 100644
--- a/example/freertos_feature/interrupt/configs/e2000d_aarch64_eg_configs
+++ b/example/freertos_feature/interrupt/configs/e2000d_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/interrupt/configs/e2000q_aarch32_eg_configs b/example/freertos_feature/interrupt/configs/e2000q_aarch32_eg_configs
index 8e8a511b5796a9c927c31028f78ed784e564cc25..755c27f6473e3a58bb1fb889adc9896fd3de0fba 100644
--- a/example/freertos_feature/interrupt/configs/e2000q_aarch32_eg_configs
+++ b/example/freertos_feature/interrupt/configs/e2000q_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/interrupt/configs/e2000q_aarch64_eg_configs b/example/freertos_feature/interrupt/configs/e2000q_aarch64_eg_configs
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/interrupt/configs/e2000q_aarch64_eg_configs
+++ b/example/freertos_feature/interrupt/configs/e2000q_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/interrupt/configs/ft2004_aarch32_eg_configs b/example/freertos_feature/interrupt/configs/ft2004_aarch32_eg_configs
index 0138724f952e35b4c4ba87bffba05092d4f0c916..f42811a5bdbc43bc5075b6ca339f1ffd7fe53df3 100644
--- a/example/freertos_feature/interrupt/configs/ft2004_aarch32_eg_configs
+++ b/example/freertos_feature/interrupt/configs/ft2004_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/interrupt/configs/ft2004_aarch64_eg_configs b/example/freertos_feature/interrupt/configs/ft2004_aarch64_eg_configs
index c9c32f36bdb82f19e010c471b287d1bce9dcf357..e0ec68fb05bc7eebbe4490f0fa4b12cad6a30bb7 100644
--- a/example/freertos_feature/interrupt/configs/ft2004_aarch64_eg_configs
+++ b/example/freertos_feature/interrupt/configs/ft2004_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/interrupt/sdkconfig b/example/freertos_feature/interrupt/sdkconfig
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/interrupt/sdkconfig
+++ b/example/freertos_feature/interrupt/sdkconfig
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/interrupt/sdkconfig.h b/example/freertos_feature/interrupt/sdkconfig.h
index 070be66948577be34cf1ceec7e087d8a36db55cb..918ddd1ec09a52898e57bb516bba1cc9a40ec952 100644
--- a/example/freertos_feature/interrupt/sdkconfig.h
+++ b/example/freertos_feature/interrupt/sdkconfig.h
@@ -154,6 +154,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/freertos_feature/queue/configs/d2000_aarch32_eg_configs b/example/freertos_feature/queue/configs/d2000_aarch32_eg_configs
index 88242621be7dacbe44c1ca7cebc38c3ea086a1f0..1f65e320b69006b78f6799dbb55fa3ddf9512eb1 100644
--- a/example/freertos_feature/queue/configs/d2000_aarch32_eg_configs
+++ b/example/freertos_feature/queue/configs/d2000_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/queue/configs/d2000_aarch64_eg_configs b/example/freertos_feature/queue/configs/d2000_aarch64_eg_configs
index f7da4f7ec0909d34aba3fd2fa416f37b1c3ba796..b6f76f4c15636aab052b117d81fad5dc35c48c6e 100644
--- a/example/freertos_feature/queue/configs/d2000_aarch64_eg_configs
+++ b/example/freertos_feature/queue/configs/d2000_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/queue/configs/e2000d_aarch32_eg_configs b/example/freertos_feature/queue/configs/e2000d_aarch32_eg_configs
index 1e787231b7b1bfef02913cb0edf2681eed950dc4..dcbfaedf6532dda1df4b1438d6013f6e731b9ed0 100644
--- a/example/freertos_feature/queue/configs/e2000d_aarch32_eg_configs
+++ b/example/freertos_feature/queue/configs/e2000d_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/queue/configs/e2000d_aarch64_eg_configs b/example/freertos_feature/queue/configs/e2000d_aarch64_eg_configs
index e1b4974ab7dc8017a1bd9444babff8e8dc0a8acb..7e45bd9490d83a614f2202447656da11d3655eef 100644
--- a/example/freertos_feature/queue/configs/e2000d_aarch64_eg_configs
+++ b/example/freertos_feature/queue/configs/e2000d_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/queue/configs/e2000q_aarch32_eg_configs b/example/freertos_feature/queue/configs/e2000q_aarch32_eg_configs
index 8e8a511b5796a9c927c31028f78ed784e564cc25..755c27f6473e3a58bb1fb889adc9896fd3de0fba 100644
--- a/example/freertos_feature/queue/configs/e2000q_aarch32_eg_configs
+++ b/example/freertos_feature/queue/configs/e2000q_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/queue/configs/e2000q_aarch64_eg_configs b/example/freertos_feature/queue/configs/e2000q_aarch64_eg_configs
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/queue/configs/e2000q_aarch64_eg_configs
+++ b/example/freertos_feature/queue/configs/e2000q_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/queue/configs/ft2004_aarch32_eg_configs b/example/freertos_feature/queue/configs/ft2004_aarch32_eg_configs
index 0138724f952e35b4c4ba87bffba05092d4f0c916..f42811a5bdbc43bc5075b6ca339f1ffd7fe53df3 100644
--- a/example/freertos_feature/queue/configs/ft2004_aarch32_eg_configs
+++ b/example/freertos_feature/queue/configs/ft2004_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/queue/configs/ft2004_aarch64_eg_configs b/example/freertos_feature/queue/configs/ft2004_aarch64_eg_configs
index c9c32f36bdb82f19e010c471b287d1bce9dcf357..e0ec68fb05bc7eebbe4490f0fa4b12cad6a30bb7 100644
--- a/example/freertos_feature/queue/configs/ft2004_aarch64_eg_configs
+++ b/example/freertos_feature/queue/configs/ft2004_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/queue/sdkconfig b/example/freertos_feature/queue/sdkconfig
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/queue/sdkconfig
+++ b/example/freertos_feature/queue/sdkconfig
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/queue/sdkconfig.h b/example/freertos_feature/queue/sdkconfig.h
index 070be66948577be34cf1ceec7e087d8a36db55cb..918ddd1ec09a52898e57bb516bba1cc9a40ec952 100644
--- a/example/freertos_feature/queue/sdkconfig.h
+++ b/example/freertos_feature/queue/sdkconfig.h
@@ -154,6 +154,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/freertos_feature/resource/configs/d2000_aarch32_eg_configs b/example/freertos_feature/resource/configs/d2000_aarch32_eg_configs
index 88242621be7dacbe44c1ca7cebc38c3ea086a1f0..1f65e320b69006b78f6799dbb55fa3ddf9512eb1 100644
--- a/example/freertos_feature/resource/configs/d2000_aarch32_eg_configs
+++ b/example/freertos_feature/resource/configs/d2000_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/resource/configs/d2000_aarch64_eg_configs b/example/freertos_feature/resource/configs/d2000_aarch64_eg_configs
index f7da4f7ec0909d34aba3fd2fa416f37b1c3ba796..b6f76f4c15636aab052b117d81fad5dc35c48c6e 100644
--- a/example/freertos_feature/resource/configs/d2000_aarch64_eg_configs
+++ b/example/freertos_feature/resource/configs/d2000_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/resource/configs/e2000d_aarch32_eg_configs b/example/freertos_feature/resource/configs/e2000d_aarch32_eg_configs
index 1e787231b7b1bfef02913cb0edf2681eed950dc4..dcbfaedf6532dda1df4b1438d6013f6e731b9ed0 100644
--- a/example/freertos_feature/resource/configs/e2000d_aarch32_eg_configs
+++ b/example/freertos_feature/resource/configs/e2000d_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/resource/configs/e2000d_aarch64_eg_configs b/example/freertos_feature/resource/configs/e2000d_aarch64_eg_configs
index e1b4974ab7dc8017a1bd9444babff8e8dc0a8acb..7e45bd9490d83a614f2202447656da11d3655eef 100644
--- a/example/freertos_feature/resource/configs/e2000d_aarch64_eg_configs
+++ b/example/freertos_feature/resource/configs/e2000d_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/resource/configs/e2000q_aarch32_eg_configs b/example/freertos_feature/resource/configs/e2000q_aarch32_eg_configs
index 8e8a511b5796a9c927c31028f78ed784e564cc25..755c27f6473e3a58bb1fb889adc9896fd3de0fba 100644
--- a/example/freertos_feature/resource/configs/e2000q_aarch32_eg_configs
+++ b/example/freertos_feature/resource/configs/e2000q_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/resource/configs/e2000q_aarch64_eg_configs b/example/freertos_feature/resource/configs/e2000q_aarch64_eg_configs
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/resource/configs/e2000q_aarch64_eg_configs
+++ b/example/freertos_feature/resource/configs/e2000q_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/resource/configs/ft2004_aarch32_eg_configs b/example/freertos_feature/resource/configs/ft2004_aarch32_eg_configs
index 0138724f952e35b4c4ba87bffba05092d4f0c916..f42811a5bdbc43bc5075b6ca339f1ffd7fe53df3 100644
--- a/example/freertos_feature/resource/configs/ft2004_aarch32_eg_configs
+++ b/example/freertos_feature/resource/configs/ft2004_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/resource/configs/ft2004_aarch64_eg_configs b/example/freertos_feature/resource/configs/ft2004_aarch64_eg_configs
index c9c32f36bdb82f19e010c471b287d1bce9dcf357..e0ec68fb05bc7eebbe4490f0fa4b12cad6a30bb7 100644
--- a/example/freertos_feature/resource/configs/ft2004_aarch64_eg_configs
+++ b/example/freertos_feature/resource/configs/ft2004_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/resource/sdkconfig b/example/freertos_feature/resource/sdkconfig
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/resource/sdkconfig
+++ b/example/freertos_feature/resource/sdkconfig
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/resource/sdkconfig.h b/example/freertos_feature/resource/sdkconfig.h
index 070be66948577be34cf1ceec7e087d8a36db55cb..918ddd1ec09a52898e57bb516bba1cc9a40ec952 100644
--- a/example/freertos_feature/resource/sdkconfig.h
+++ b/example/freertos_feature/resource/sdkconfig.h
@@ -154,6 +154,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/freertos_feature/software_timer/configs/d2000_aarch32_eg_configs b/example/freertos_feature/software_timer/configs/d2000_aarch32_eg_configs
index 88242621be7dacbe44c1ca7cebc38c3ea086a1f0..1f65e320b69006b78f6799dbb55fa3ddf9512eb1 100644
--- a/example/freertos_feature/software_timer/configs/d2000_aarch32_eg_configs
+++ b/example/freertos_feature/software_timer/configs/d2000_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/software_timer/configs/d2000_aarch64_eg_configs b/example/freertos_feature/software_timer/configs/d2000_aarch64_eg_configs
index f7da4f7ec0909d34aba3fd2fa416f37b1c3ba796..b6f76f4c15636aab052b117d81fad5dc35c48c6e 100644
--- a/example/freertos_feature/software_timer/configs/d2000_aarch64_eg_configs
+++ b/example/freertos_feature/software_timer/configs/d2000_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/software_timer/configs/e2000d_aarch32_eg_configs b/example/freertos_feature/software_timer/configs/e2000d_aarch32_eg_configs
index 1e787231b7b1bfef02913cb0edf2681eed950dc4..dcbfaedf6532dda1df4b1438d6013f6e731b9ed0 100644
--- a/example/freertos_feature/software_timer/configs/e2000d_aarch32_eg_configs
+++ b/example/freertos_feature/software_timer/configs/e2000d_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/software_timer/configs/e2000d_aarch64_eg_configs b/example/freertos_feature/software_timer/configs/e2000d_aarch64_eg_configs
index e1b4974ab7dc8017a1bd9444babff8e8dc0a8acb..7e45bd9490d83a614f2202447656da11d3655eef 100644
--- a/example/freertos_feature/software_timer/configs/e2000d_aarch64_eg_configs
+++ b/example/freertos_feature/software_timer/configs/e2000d_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/software_timer/configs/e2000q_aarch32_eg_configs b/example/freertos_feature/software_timer/configs/e2000q_aarch32_eg_configs
index 8e8a511b5796a9c927c31028f78ed784e564cc25..755c27f6473e3a58bb1fb889adc9896fd3de0fba 100644
--- a/example/freertos_feature/software_timer/configs/e2000q_aarch32_eg_configs
+++ b/example/freertos_feature/software_timer/configs/e2000q_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/software_timer/configs/e2000q_aarch64_eg_configs b/example/freertos_feature/software_timer/configs/e2000q_aarch64_eg_configs
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/software_timer/configs/e2000q_aarch64_eg_configs
+++ b/example/freertos_feature/software_timer/configs/e2000q_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/software_timer/configs/ft2004_aarch32_eg_configs b/example/freertos_feature/software_timer/configs/ft2004_aarch32_eg_configs
index 0138724f952e35b4c4ba87bffba05092d4f0c916..f42811a5bdbc43bc5075b6ca339f1ffd7fe53df3 100644
--- a/example/freertos_feature/software_timer/configs/ft2004_aarch32_eg_configs
+++ b/example/freertos_feature/software_timer/configs/ft2004_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/software_timer/configs/ft2004_aarch64_eg_configs b/example/freertos_feature/software_timer/configs/ft2004_aarch64_eg_configs
index c9c32f36bdb82f19e010c471b287d1bce9dcf357..e0ec68fb05bc7eebbe4490f0fa4b12cad6a30bb7 100644
--- a/example/freertos_feature/software_timer/configs/ft2004_aarch64_eg_configs
+++ b/example/freertos_feature/software_timer/configs/ft2004_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/software_timer/sdkconfig b/example/freertos_feature/software_timer/sdkconfig
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/software_timer/sdkconfig
+++ b/example/freertos_feature/software_timer/sdkconfig
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/software_timer/sdkconfig.h b/example/freertos_feature/software_timer/sdkconfig.h
index 070be66948577be34cf1ceec7e087d8a36db55cb..918ddd1ec09a52898e57bb516bba1cc9a40ec952 100644
--- a/example/freertos_feature/software_timer/sdkconfig.h
+++ b/example/freertos_feature/software_timer/sdkconfig.h
@@ -154,6 +154,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/freertos_feature/task/configs/d2000_aarch32_eg_configs b/example/freertos_feature/task/configs/d2000_aarch32_eg_configs
index 88242621be7dacbe44c1ca7cebc38c3ea086a1f0..1f65e320b69006b78f6799dbb55fa3ddf9512eb1 100644
--- a/example/freertos_feature/task/configs/d2000_aarch32_eg_configs
+++ b/example/freertos_feature/task/configs/d2000_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task/configs/d2000_aarch64_eg_configs b/example/freertos_feature/task/configs/d2000_aarch64_eg_configs
index f7da4f7ec0909d34aba3fd2fa416f37b1c3ba796..b6f76f4c15636aab052b117d81fad5dc35c48c6e 100644
--- a/example/freertos_feature/task/configs/d2000_aarch64_eg_configs
+++ b/example/freertos_feature/task/configs/d2000_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task/configs/e2000d_aarch32_eg_configs b/example/freertos_feature/task/configs/e2000d_aarch32_eg_configs
index 1e787231b7b1bfef02913cb0edf2681eed950dc4..dcbfaedf6532dda1df4b1438d6013f6e731b9ed0 100644
--- a/example/freertos_feature/task/configs/e2000d_aarch32_eg_configs
+++ b/example/freertos_feature/task/configs/e2000d_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task/configs/e2000d_aarch64_eg_configs b/example/freertos_feature/task/configs/e2000d_aarch64_eg_configs
index e1b4974ab7dc8017a1bd9444babff8e8dc0a8acb..7e45bd9490d83a614f2202447656da11d3655eef 100644
--- a/example/freertos_feature/task/configs/e2000d_aarch64_eg_configs
+++ b/example/freertos_feature/task/configs/e2000d_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task/configs/e2000q_aarch32_eg_configs b/example/freertos_feature/task/configs/e2000q_aarch32_eg_configs
index 5a4757000bcc5573eb200916cb2fbcef1b3b1f5c..762f633f8afa3c6078d879a5217fde4ebb007308 100644
--- a/example/freertos_feature/task/configs/e2000q_aarch32_eg_configs
+++ b/example/freertos_feature/task/configs/e2000q_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task/configs/e2000q_aarch64_eg_configs b/example/freertos_feature/task/configs/e2000q_aarch64_eg_configs
index 666dd8994dab58dbdc6b18842333fe21e81358b2..be71262a2452358ec691234aa5b17dde2dbe2594 100644
--- a/example/freertos_feature/task/configs/e2000q_aarch64_eg_configs
+++ b/example/freertos_feature/task/configs/e2000q_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task/configs/ft2004_aarch32_eg_configs b/example/freertos_feature/task/configs/ft2004_aarch32_eg_configs
index 0138724f952e35b4c4ba87bffba05092d4f0c916..f42811a5bdbc43bc5075b6ca339f1ffd7fe53df3 100644
--- a/example/freertos_feature/task/configs/ft2004_aarch32_eg_configs
+++ b/example/freertos_feature/task/configs/ft2004_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task/configs/ft2004_aarch64_eg_configs b/example/freertos_feature/task/configs/ft2004_aarch64_eg_configs
index c9c32f36bdb82f19e010c471b287d1bce9dcf357..e0ec68fb05bc7eebbe4490f0fa4b12cad6a30bb7 100644
--- a/example/freertos_feature/task/configs/ft2004_aarch64_eg_configs
+++ b/example/freertos_feature/task/configs/ft2004_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task/sdkconfig b/example/freertos_feature/task/sdkconfig
index 666dd8994dab58dbdc6b18842333fe21e81358b2..be71262a2452358ec691234aa5b17dde2dbe2594 100644
--- a/example/freertos_feature/task/sdkconfig
+++ b/example/freertos_feature/task/sdkconfig
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task/sdkconfig.h b/example/freertos_feature/task/sdkconfig.h
index 6e37ce68e24d00fe278225de450654d6575b7d51..c67c992e10fd4fdfd26abb100cb7bf3eacb79763 100644
--- a/example/freertos_feature/task/sdkconfig.h
+++ b/example/freertos_feature/task/sdkconfig.h
@@ -154,6 +154,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/freertos_feature/task_notify/configs/d2000_aarch32_eg_configs b/example/freertos_feature/task_notify/configs/d2000_aarch32_eg_configs
index 88242621be7dacbe44c1ca7cebc38c3ea086a1f0..1f65e320b69006b78f6799dbb55fa3ddf9512eb1 100644
--- a/example/freertos_feature/task_notify/configs/d2000_aarch32_eg_configs
+++ b/example/freertos_feature/task_notify/configs/d2000_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task_notify/configs/d2000_aarch64_eg_configs b/example/freertos_feature/task_notify/configs/d2000_aarch64_eg_configs
index f7da4f7ec0909d34aba3fd2fa416f37b1c3ba796..b6f76f4c15636aab052b117d81fad5dc35c48c6e 100644
--- a/example/freertos_feature/task_notify/configs/d2000_aarch64_eg_configs
+++ b/example/freertos_feature/task_notify/configs/d2000_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task_notify/configs/e2000d_aarch32_eg_configs b/example/freertos_feature/task_notify/configs/e2000d_aarch32_eg_configs
index 1e787231b7b1bfef02913cb0edf2681eed950dc4..dcbfaedf6532dda1df4b1438d6013f6e731b9ed0 100644
--- a/example/freertos_feature/task_notify/configs/e2000d_aarch32_eg_configs
+++ b/example/freertos_feature/task_notify/configs/e2000d_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task_notify/configs/e2000d_aarch64_eg_configs b/example/freertos_feature/task_notify/configs/e2000d_aarch64_eg_configs
index e1b4974ab7dc8017a1bd9444babff8e8dc0a8acb..7e45bd9490d83a614f2202447656da11d3655eef 100644
--- a/example/freertos_feature/task_notify/configs/e2000d_aarch64_eg_configs
+++ b/example/freertos_feature/task_notify/configs/e2000d_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task_notify/configs/e2000q_aarch32_eg_configs b/example/freertos_feature/task_notify/configs/e2000q_aarch32_eg_configs
index 8e8a511b5796a9c927c31028f78ed784e564cc25..755c27f6473e3a58bb1fb889adc9896fd3de0fba 100644
--- a/example/freertos_feature/task_notify/configs/e2000q_aarch32_eg_configs
+++ b/example/freertos_feature/task_notify/configs/e2000q_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task_notify/configs/e2000q_aarch64_eg_configs b/example/freertos_feature/task_notify/configs/e2000q_aarch64_eg_configs
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/task_notify/configs/e2000q_aarch64_eg_configs
+++ b/example/freertos_feature/task_notify/configs/e2000q_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task_notify/configs/ft2004_aarch32_eg_configs b/example/freertos_feature/task_notify/configs/ft2004_aarch32_eg_configs
index 0138724f952e35b4c4ba87bffba05092d4f0c916..f42811a5bdbc43bc5075b6ca339f1ffd7fe53df3 100644
--- a/example/freertos_feature/task_notify/configs/ft2004_aarch32_eg_configs
+++ b/example/freertos_feature/task_notify/configs/ft2004_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task_notify/configs/ft2004_aarch64_eg_configs b/example/freertos_feature/task_notify/configs/ft2004_aarch64_eg_configs
index c9c32f36bdb82f19e010c471b287d1bce9dcf357..e0ec68fb05bc7eebbe4490f0fa4b12cad6a30bb7 100644
--- a/example/freertos_feature/task_notify/configs/ft2004_aarch64_eg_configs
+++ b/example/freertos_feature/task_notify/configs/ft2004_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task_notify/sdkconfig b/example/freertos_feature/task_notify/sdkconfig
index 11138fc7d0a7fa7c8aaf6971d3ad2d72396ed58a..bb62840c8620a9723ca3189cb8cff1f1b5e48346 100644
--- a/example/freertos_feature/task_notify/sdkconfig
+++ b/example/freertos_feature/task_notify/sdkconfig
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/freertos_feature/task_notify/sdkconfig.h b/example/freertos_feature/task_notify/sdkconfig.h
index 070be66948577be34cf1ceec7e087d8a36db55cb..918ddd1ec09a52898e57bb516bba1cc9a40ec952 100644
--- a/example/freertos_feature/task_notify/sdkconfig.h
+++ b/example/freertos_feature/task_notify/sdkconfig.h
@@ -154,6 +154,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/network/gmac_lwip_test/configs/d2000_aarch32_eg_configs b/example/network/gmac_lwip_test/configs/d2000_aarch32_eg_configs
index dbd1b782d5cd948e4b417b440d48d6f4f8f46058..c7763e5c6e06f10149ed79643f473980a5a3ca66 100644
--- a/example/network/gmac_lwip_test/configs/d2000_aarch32_eg_configs
+++ b/example/network/gmac_lwip_test/configs/d2000_aarch32_eg_configs
@@ -195,6 +195,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/network/gmac_lwip_test/configs/d2000_aarch64_eg_configs b/example/network/gmac_lwip_test/configs/d2000_aarch64_eg_configs
index 6763461a180de6638d20146dd3874cbe3f95316e..0e6700964b290b2299df5f6cbbf08a54650c60cb 100644
--- a/example/network/gmac_lwip_test/configs/d2000_aarch64_eg_configs
+++ b/example/network/gmac_lwip_test/configs/d2000_aarch64_eg_configs
@@ -191,6 +191,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/network/gmac_lwip_test/configs/ft2004_aarch32_eg_configs b/example/network/gmac_lwip_test/configs/ft2004_aarch32_eg_configs
index d5c4b679921b9c3301a15a783d692c21fb7b05ea..7b0b40a677e3d8285e84d6b4d4d6aa3f56ba6433 100644
--- a/example/network/gmac_lwip_test/configs/ft2004_aarch32_eg_configs
+++ b/example/network/gmac_lwip_test/configs/ft2004_aarch32_eg_configs
@@ -195,6 +195,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/network/gmac_lwip_test/configs/ft2004_aarch64_eg_configs b/example/network/gmac_lwip_test/configs/ft2004_aarch64_eg_configs
index ca33cb0a2f0f2ab7a538851531fd504241a81d8f..e774beb2acd0ff6f6b9ba5028af42e131eddc826 100644
--- a/example/network/gmac_lwip_test/configs/ft2004_aarch64_eg_configs
+++ b/example/network/gmac_lwip_test/configs/ft2004_aarch64_eg_configs
@@ -191,6 +191,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/network/gmac_lwip_test/sdkconfig b/example/network/gmac_lwip_test/sdkconfig
index 6763461a180de6638d20146dd3874cbe3f95316e..0e6700964b290b2299df5f6cbbf08a54650c60cb 100644
--- a/example/network/gmac_lwip_test/sdkconfig
+++ b/example/network/gmac_lwip_test/sdkconfig
@@ -191,6 +191,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/network/gmac_lwip_test/sdkconfig.h b/example/network/gmac_lwip_test/sdkconfig.h
index ff0c1cb32d337d6ffbcf9fa7e6c7ac3ee3c40551..d487d29a86d071026f96083c1e862b16afe2fe39 100644
--- a/example/network/gmac_lwip_test/sdkconfig.h
+++ b/example/network/gmac_lwip_test/sdkconfig.h
@@ -168,6 +168,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/network/xmac_lwip_test/configs/e2000d_aarch32_eg_configs b/example/network/xmac_lwip_test/configs/e2000d_aarch32_eg_configs
index dae7ddf5e8e263f9bbd31de928ed64ede3014e63..643d20f1bf604228ec4a507ebd4006d0466583a1 100644
--- a/example/network/xmac_lwip_test/configs/e2000d_aarch32_eg_configs
+++ b/example/network/xmac_lwip_test/configs/e2000d_aarch32_eg_configs
@@ -203,6 +203,12 @@ CONFIG_FREERTOS_USE_XMAC=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/network/xmac_lwip_test/configs/e2000d_aarch64_eg_configs b/example/network/xmac_lwip_test/configs/e2000d_aarch64_eg_configs
index 25105a00ce3dd365c15032e69aa9a55108086ea2..067dff9fafc2b511a6b03afbdbe39a04fa436426 100644
--- a/example/network/xmac_lwip_test/configs/e2000d_aarch64_eg_configs
+++ b/example/network/xmac_lwip_test/configs/e2000d_aarch64_eg_configs
@@ -199,6 +199,12 @@ CONFIG_FREERTOS_USE_XMAC=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/network/xmac_lwip_test/sdkconfig b/example/network/xmac_lwip_test/sdkconfig
index 25105a00ce3dd365c15032e69aa9a55108086ea2..067dff9fafc2b511a6b03afbdbe39a04fa436426 100644
--- a/example/network/xmac_lwip_test/sdkconfig
+++ b/example/network/xmac_lwip_test/sdkconfig
@@ -199,6 +199,12 @@ CONFIG_FREERTOS_USE_XMAC=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/network/xmac_lwip_test/sdkconfig.h b/example/network/xmac_lwip_test/sdkconfig.h
index 91abb934387eee41d459e2d07516d0739039fc6d..6e435b201e7712ccb849269d99319ba99389113e 100644
--- a/example/network/xmac_lwip_test/sdkconfig.h
+++ b/example/network/xmac_lwip_test/sdkconfig.h
@@ -175,6 +175,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/peripheral/adc/README.md b/example/peripheral/adc/README.md
index 86913a3c01bf954a579b7635a05547dd2d28f25d..d6743b3fa5daf5f6f2431ff96b0dce17db51fc9d 100644
--- a/example/peripheral/adc/README.md
+++ b/example/peripheral/adc/README.md
@@ -54,7 +54,7 @@
本例程需要,
- 使能Shell
-- 使能Pwm
+- 使能Adc
对应的配置项是,
diff --git a/example/peripheral/adc/configs/e2000d_aarch32_eg_configs b/example/peripheral/adc/configs/e2000d_aarch32_eg_configs
index 6001bd71d4f9c554efa75533bc1ac117741c5d83..5a6c4745f8c2c8339ca6cb84d9dc66a4f5271a39 100644
--- a/example/peripheral/adc/configs/e2000d_aarch32_eg_configs
+++ b/example/peripheral/adc/configs/e2000d_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_UART=y
#
CONFIG_FREERTOS_USE_ADC=y
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/adc/configs/e2000d_aarch64_eg_configs b/example/peripheral/adc/configs/e2000d_aarch64_eg_configs
index 8fb80c351872437a40358f8065d01cefa6b1107b..23f034a06becff399ffca766ba9d0e0740ff84c8 100644
--- a/example/peripheral/adc/configs/e2000d_aarch64_eg_configs
+++ b/example/peripheral/adc/configs/e2000d_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_UART=y
#
CONFIG_FREERTOS_USE_ADC=y
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/adc/configs/e2000q_aarch32_eg_configs b/example/peripheral/adc/configs/e2000q_aarch32_eg_configs
index 2af361a148a6862cc24b3869747b80e453e70247..352d71aa4cb6aa8381cb40ebfa15f18212813712 100644
--- a/example/peripheral/adc/configs/e2000q_aarch32_eg_configs
+++ b/example/peripheral/adc/configs/e2000q_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_UART=y
#
CONFIG_FREERTOS_USE_ADC=y
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/adc/configs/e2000q_aarch64_eg_configs b/example/peripheral/adc/configs/e2000q_aarch64_eg_configs
index 6b48134cc1a13c989a820b8daf35c52b6d4e145d..c7f11a2c9abbf54b76ebfea1e57d909d67df5143 100644
--- a/example/peripheral/adc/configs/e2000q_aarch64_eg_configs
+++ b/example/peripheral/adc/configs/e2000q_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_UART=y
#
CONFIG_FREERTOS_USE_ADC=y
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/adc/sdkconfig b/example/peripheral/adc/sdkconfig
index 6b48134cc1a13c989a820b8daf35c52b6d4e145d..c7f11a2c9abbf54b76ebfea1e57d909d67df5143 100644
--- a/example/peripheral/adc/sdkconfig
+++ b/example/peripheral/adc/sdkconfig
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_UART=y
#
CONFIG_FREERTOS_USE_ADC=y
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/adc/sdkconfig.h b/example/peripheral/adc/sdkconfig.h
index e70bdaca591d9b5cc03301b1f3276dc3446552fe..5a939a3481b65178226857e1edfb993506195abc 100644
--- a/example/peripheral/adc/sdkconfig.h
+++ b/example/peripheral/adc/sdkconfig.h
@@ -159,6 +159,11 @@
#define CONFIG_FREERTOS_USE_ADC
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/peripheral/can/Kconfig b/example/peripheral/can/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..0277fb8553f2132f097012a78633194f6173c156
--- /dev/null
+++ b/example/peripheral/can/Kconfig
@@ -0,0 +1,19 @@
+#
+# For a description of the syntax of this configuration file,
+# see tools/kconfiglib/kconfig-language.txt.
+#
+
+
+mainmenu "Phytium Freertos Configuration"
+
+ menu "Freertos Configuration"
+ config TARGET_NAME
+ string "Build Target Name"
+ default "freertos"
+ help
+ Build Target name for the demo
+
+endmenu
+
+source "$(FREERTOS_SDK_ROOT)/Kconfig"
+
diff --git a/example/peripheral/can/README.md b/example/peripheral/can/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..db190b516cc7c84e49f4a15d0056737b8592d8ee
--- /dev/null
+++ b/example/peripheral/can/README.md
@@ -0,0 +1,150 @@
+
+
+# can base on freertos
+
+## 1. 例程介绍
+
+本例程示范了freertos环境下的can的使用,包括can的初始化、can周期发送,接收操作;
+程序启动后,创建can初始化任务,设置can波特率,中断函数、id mask等;
+创建can定时发送任务FFreeRTOSCanSendTask,用于定时发送can报文;
+创建can接收任务FFreeRTOSCanRecvTask,用于接收can报文;
+创建单次模式的软件定时器,回调函数为删除FFreeRTOSCanSendTask,删除FFreeRTOSCanRecvTask,去初始化can,删除软件定时器;
+使用B板进行测试,选择can0和can1回环;
+
+## 2. 如何使用例程
+
+本例程需要用到
+- Phytium开发板(E2000D/E2000Q)
+- [Phytium freeRTOS SDK](https://gitee.com/phytium_embedded/phytium-free-rtos-sdk)
+- [Phytium standalone SDK](https://gitee.com/phytium_embedded/phytium-standalone-sdk)
+### 2.1 硬件配置方法
+
+本例程支持的硬件平台包括
+
+- FT2000-4
+- D2000
+- E2000D
+- E2000Q
+
+对应的配置项是,
+
+- CONFIG_TARGET_F2000_4
+- CONFIG_TARGET_D2000
+- CONFIG_TARGET_E2000D
+- CONFIG_TARGET_E2000Q
+
+### 2.2 SDK配置方法
+
+本例程需要,
+
+- 使能Shell
+- 使能Can
+
+对应的配置项是,
+
+- CONFIG_USE_LETTER_SHELL
+- CONFIG_FREERTOS_USE_CAN
+- CONFIG_USE_CAN
+
+本例子已经提供好具体的编译指令,以下进行介绍:
+- make 将目录下的工程进行编译
+- make clean 将目录下的工程进行清理
+- make boot 将目录下的工程进行编译,并将生成的elf 复制到目标地址
+- make load_d2000_aarch64 将预设64bit d2000 下的配置加载至工程中
+- make load_d2000_aarch32 将预设32bit d2000 下的配置加载至工程中
+- make load_ft2004_aarch64 将预设64bit ft2004 下的配置加载至工程中
+- make load_ft2004_aarch32 将预设32bit ft2004 下的配置加载至工程中
+- make load_e2000d_aarch64 将预设64bit e2000d 下的配置加载至工程中
+- make load_e2000d_aarch32 将预设32bit e2000d 下的配置加载至工程中
+- make load_e2000q_aarch64 将预设64bit e2000q 下的配置加载至工程中
+- make load_e2000q_aarch32 将预设32bit e2000q 下的配置加载至工程中
+- make menuconfig 配置目录下的参数变量
+- make backup_kconfig 将目录下的sdkconfig 备份到./configs下
+
+具体使用方法为:
+- 在当前目录下
+- 执行以上指令
+
+### 2.3 构建和下载
+
+#### 2.3.1 构建过程
+
+- 在host侧完成配置
+配置成e2000q,对于其它平台,使用对于的默认配置,如e2000d `make load_e2000d_aarch32`
+
+- 选择目标平台
+```
+make load_e2000q_aarch32
+```
+
+- 选择例程需要的配置
+```
+make menuconfig
+```
+
+- 进行编译
+```
+make
+```
+
+- 将编译出的镜像放置到tftp目录下
+```
+make boot
+```
+
+#### 2.3.2 下载过程
+
+- host侧设置重启host侧tftp服务器
+```
+sudo service tftpd-hpa restart
+```
+
+- 开发板侧使用bootelf命令跳转
+```
+setenv ipaddr 192.168.4.20
+setenv serverip 192.168.4.50
+setenv gatewayip 192.168.4.1
+tftpboot 0x90100000 freertos.elf
+bootelf -p 0x90100000
+```
+
+### 2.4 输出与实验现象
+
+- 系统进入后,创建can初始化任务,创建定时发送任务,创建接收任务,并创建单次模式软件定时器
+
+
+
+- 定时器时间到,触发单次模式软件定时器的回调函数,删除发送和接收任务,去初始化can,删除软件定时器
+
+
+
+## 3. 如何解决问题
+
+- 使用can0和can1进行回环测试时,需要将can0和can1的H和L信号线分别进行短接
+
+## 4. 修改历史记录
+
+
+
+
diff --git a/example/peripheral/can/configs/d2000_aarch32_eg_configs b/example/peripheral/can/configs/d2000_aarch32_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..2b4275b343b6e305c1918e2cf86db97a0220cb33
--- /dev/null
+++ b/example/peripheral/can/configs/d2000_aarch32_eg_configs
@@ -0,0 +1,219 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="d2000_freertos_a32"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+CONFIG_TARGET_ARMV8_AARCH32=y
+# CONFIG_TARGET_ARMV8_AARCH64 is not set
+CONFIG_USE_CACHE=y
+CONFIG_USE_L3CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+CONFIG_USE_AARCH64_L1_TO_AARCH32=y
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+CONFIG_TARGET_D2000=y
+# CONFIG_TARGET_E2000Q is not set
+# CONFIG_TARGET_E2000D is not set
+# CONFIG_TARGET_E2000S is not set
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+# CONFIG_USE_SPI is not set
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+CONFIG_USE_CAN=y
+
+#
+# CAN Configuration
+#
+CONFIG_USE_FCAN=y
+# end of CAN Configuration
+
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+# CONFIG_LOG_DEBUG is not set
+CONFIG_LOG_INFO=y
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+# CONFIG_LOG_EXTRA_INFO is not set
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+CONFIG_AARCH32_RAM_LD=y
+# CONFIG_AARCH64_RAM_LD is not set
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_SVC_STACK_SIZE=0x1000
+CONFIG_SYS_STACK_SIZE=0x1000
+CONFIG_IRQ_STACK_SIZE=0x1000
+CONFIG_ABORT_STACK_SIZE=0x1000
+CONFIG_FIQ_STACK_SIZE=0x1000
+CONFIG_UNDEF_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+# CONFIG_FREERTOS_USE_FSPIM is not set
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+CONFIG_FREERTOS_USE_CAN=y
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+# CONFIG_USE_TLSF is not set
+# CONFIG_USE_SDMMC_CMD is not set
+# end of FreeRTOS Setting
diff --git a/example/peripheral/can/configs/d2000_aarch64_eg_configs b/example/peripheral/can/configs/d2000_aarch64_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..20bc5a75a7fc3bf185b81966c4dcf0eb19d4a491
--- /dev/null
+++ b/example/peripheral/can/configs/d2000_aarch64_eg_configs
@@ -0,0 +1,215 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="d2000_freertos_a64"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+# CONFIG_TARGET_ARMV8_AARCH32 is not set
+CONFIG_TARGET_ARMV8_AARCH64=y
+CONFIG_USE_CACHE=y
+CONFIG_USE_L3CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+# CONFIG_MMU_DEBUG_PRINTS is not set
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+CONFIG_TARGET_D2000=y
+# CONFIG_TARGET_E2000Q is not set
+# CONFIG_TARGET_E2000D is not set
+# CONFIG_TARGET_E2000S is not set
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+# CONFIG_USE_SPI is not set
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+CONFIG_USE_CAN=y
+
+#
+# CAN Configuration
+#
+CONFIG_USE_FCAN=y
+# end of CAN Configuration
+
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+# CONFIG_LOG_DEBUG is not set
+CONFIG_LOG_INFO=y
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+# CONFIG_LOG_EXTRA_INFO is not set
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+# CONFIG_AARCH32_RAM_LD is not set
+CONFIG_AARCH64_RAM_LD=y
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_STACK_SIZE=0x100000
+CONFIG_FPU_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+# CONFIG_FREERTOS_USE_FSPIM is not set
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+CONFIG_FREERTOS_USE_CAN=y
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+# CONFIG_USE_TLSF is not set
+# CONFIG_USE_SDMMC_CMD is not set
+# end of FreeRTOS Setting
diff --git a/example/peripheral/can/configs/e2000d_aarch32_eg_configs b/example/peripheral/can/configs/e2000d_aarch32_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..5380224b92728322693b7f3911ddf61440f7be7a
--- /dev/null
+++ b/example/peripheral/can/configs/e2000d_aarch32_eg_configs
@@ -0,0 +1,220 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="e2000d_freertos_a32"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+CONFIG_TARGET_ARMV8_AARCH32=y
+# CONFIG_TARGET_ARMV8_AARCH64 is not set
+CONFIG_USE_CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+CONFIG_USE_AARCH64_L1_TO_AARCH32=y
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+# CONFIG_TARGET_D2000 is not set
+# CONFIG_TARGET_E2000Q is not set
+CONFIG_TARGET_E2000D=y
+# CONFIG_TARGET_E2000S is not set
+CONFIG_TARGET_E2000=y
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+# CONFIG_USE_SPI is not set
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+CONFIG_USE_CAN=y
+
+#
+# CAN Configuration
+#
+CONFIG_USE_FCAN=y
+# CONFIG_FCAN_USE_CANFD is not set
+# end of CAN Configuration
+
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+# CONFIG_LOG_DEBUG is not set
+CONFIG_LOG_INFO=y
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+# CONFIG_LOG_EXTRA_INFO is not set
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+CONFIG_AARCH32_RAM_LD=y
+# CONFIG_AARCH64_RAM_LD is not set
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_SVC_STACK_SIZE=0x1000
+CONFIG_SYS_STACK_SIZE=0x1000
+CONFIG_IRQ_STACK_SIZE=0x1000
+CONFIG_ABORT_STACK_SIZE=0x1000
+CONFIG_FIQ_STACK_SIZE=0x1000
+CONFIG_UNDEF_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+# CONFIG_FREERTOS_USE_FSPIM is not set
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+CONFIG_FREERTOS_USE_CAN=y
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+# CONFIG_USE_TLSF is not set
+# CONFIG_USE_SDMMC_CMD is not set
+# end of FreeRTOS Setting
diff --git a/example/peripheral/can/configs/e2000d_aarch64_eg_configs b/example/peripheral/can/configs/e2000d_aarch64_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..b3de0599463e395fa224812825cb1257dffe491c
--- /dev/null
+++ b/example/peripheral/can/configs/e2000d_aarch64_eg_configs
@@ -0,0 +1,216 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="e2000d_freertos_a64"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+# CONFIG_TARGET_ARMV8_AARCH32 is not set
+CONFIG_TARGET_ARMV8_AARCH64=y
+CONFIG_USE_CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+# CONFIG_MMU_DEBUG_PRINTS is not set
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+# CONFIG_TARGET_D2000 is not set
+# CONFIG_TARGET_E2000Q is not set
+CONFIG_TARGET_E2000D=y
+# CONFIG_TARGET_E2000S is not set
+CONFIG_TARGET_E2000=y
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+# CONFIG_USE_SPI is not set
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+CONFIG_USE_CAN=y
+
+#
+# CAN Configuration
+#
+CONFIG_USE_FCAN=y
+# CONFIG_FCAN_USE_CANFD is not set
+# end of CAN Configuration
+
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+# CONFIG_LOG_DEBUG is not set
+CONFIG_LOG_INFO=y
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+# CONFIG_LOG_EXTRA_INFO is not set
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+# CONFIG_AARCH32_RAM_LD is not set
+CONFIG_AARCH64_RAM_LD=y
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_STACK_SIZE=0x100000
+CONFIG_FPU_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+# CONFIG_FREERTOS_USE_FSPIM is not set
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+CONFIG_FREERTOS_USE_CAN=y
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+# CONFIG_USE_TLSF is not set
+# CONFIG_USE_SDMMC_CMD is not set
+# end of FreeRTOS Setting
diff --git a/example/peripheral/can/configs/e2000q_aarch32_eg_configs b/example/peripheral/can/configs/e2000q_aarch32_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..b8802963115f6dca1e5feaae790ac39889814e15
--- /dev/null
+++ b/example/peripheral/can/configs/e2000q_aarch32_eg_configs
@@ -0,0 +1,220 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="e2000q_freertos_a32"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+CONFIG_TARGET_ARMV8_AARCH32=y
+# CONFIG_TARGET_ARMV8_AARCH64 is not set
+CONFIG_USE_CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+CONFIG_USE_AARCH64_L1_TO_AARCH32=y
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+# CONFIG_TARGET_D2000 is not set
+CONFIG_TARGET_E2000Q=y
+# CONFIG_TARGET_E2000D is not set
+# CONFIG_TARGET_E2000S is not set
+CONFIG_TARGET_E2000=y
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+# CONFIG_USE_SPI is not set
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+CONFIG_USE_CAN=y
+
+#
+# CAN Configuration
+#
+CONFIG_USE_FCAN=y
+# CONFIG_FCAN_USE_CANFD is not set
+# end of CAN Configuration
+
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+# CONFIG_LOG_DEBUG is not set
+CONFIG_LOG_INFO=y
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+# CONFIG_LOG_EXTRA_INFO is not set
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+CONFIG_AARCH32_RAM_LD=y
+# CONFIG_AARCH64_RAM_LD is not set
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_SVC_STACK_SIZE=0x1000
+CONFIG_SYS_STACK_SIZE=0x1000
+CONFIG_IRQ_STACK_SIZE=0x1000
+CONFIG_ABORT_STACK_SIZE=0x1000
+CONFIG_FIQ_STACK_SIZE=0x1000
+CONFIG_UNDEF_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+# CONFIG_FREERTOS_USE_FSPIM is not set
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+CONFIG_FREERTOS_USE_CAN=y
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+# CONFIG_USE_TLSF is not set
+# CONFIG_USE_SDMMC_CMD is not set
+# end of FreeRTOS Setting
diff --git a/example/peripheral/can/configs/e2000q_aarch64_eg_configs b/example/peripheral/can/configs/e2000q_aarch64_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..021f45a862e31b34f5f804ccfc639a45427398df
--- /dev/null
+++ b/example/peripheral/can/configs/e2000q_aarch64_eg_configs
@@ -0,0 +1,216 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="e2000q_freertos_a64"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+# CONFIG_TARGET_ARMV8_AARCH32 is not set
+CONFIG_TARGET_ARMV8_AARCH64=y
+CONFIG_USE_CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+# CONFIG_MMU_DEBUG_PRINTS is not set
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+# CONFIG_TARGET_D2000 is not set
+CONFIG_TARGET_E2000Q=y
+# CONFIG_TARGET_E2000D is not set
+# CONFIG_TARGET_E2000S is not set
+CONFIG_TARGET_E2000=y
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+# CONFIG_USE_SPI is not set
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+CONFIG_USE_CAN=y
+
+#
+# CAN Configuration
+#
+CONFIG_USE_FCAN=y
+# CONFIG_FCAN_USE_CANFD is not set
+# end of CAN Configuration
+
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+# CONFIG_LOG_DEBUG is not set
+CONFIG_LOG_INFO=y
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+# CONFIG_LOG_EXTRA_INFO is not set
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+# CONFIG_AARCH32_RAM_LD is not set
+CONFIG_AARCH64_RAM_LD=y
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_STACK_SIZE=0x100000
+CONFIG_FPU_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+# CONFIG_FREERTOS_USE_FSPIM is not set
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+CONFIG_FREERTOS_USE_CAN=y
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+# CONFIG_USE_TLSF is not set
+# CONFIG_USE_SDMMC_CMD is not set
+# end of FreeRTOS Setting
diff --git a/example/peripheral/can/configs/ft2004_aarch32_eg_configs b/example/peripheral/can/configs/ft2004_aarch32_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..317e341a9e8cc5a42cd6e01fdeb05efb12bec9f2
--- /dev/null
+++ b/example/peripheral/can/configs/ft2004_aarch32_eg_configs
@@ -0,0 +1,219 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="ft2004_freertos_a32"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+CONFIG_TARGET_ARMV8_AARCH32=y
+# CONFIG_TARGET_ARMV8_AARCH64 is not set
+CONFIG_USE_CACHE=y
+CONFIG_USE_L3CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+CONFIG_USE_AARCH64_L1_TO_AARCH32=y
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+CONFIG_TARGET_F2000_4=y
+# CONFIG_TARGET_D2000 is not set
+# CONFIG_TARGET_E2000Q is not set
+# CONFIG_TARGET_E2000D is not set
+# CONFIG_TARGET_E2000S is not set
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+# CONFIG_USE_SPI is not set
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+CONFIG_USE_CAN=y
+
+#
+# CAN Configuration
+#
+CONFIG_USE_FCAN=y
+# end of CAN Configuration
+
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+# CONFIG_LOG_DEBUG is not set
+CONFIG_LOG_INFO=y
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+# CONFIG_LOG_EXTRA_INFO is not set
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+CONFIG_AARCH32_RAM_LD=y
+# CONFIG_AARCH64_RAM_LD is not set
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_SVC_STACK_SIZE=0x1000
+CONFIG_SYS_STACK_SIZE=0x1000
+CONFIG_IRQ_STACK_SIZE=0x1000
+CONFIG_ABORT_STACK_SIZE=0x1000
+CONFIG_FIQ_STACK_SIZE=0x1000
+CONFIG_UNDEF_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+# CONFIG_FREERTOS_USE_FSPIM is not set
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+CONFIG_FREERTOS_USE_CAN=y
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+# CONFIG_USE_TLSF is not set
+# CONFIG_USE_SDMMC_CMD is not set
+# end of FreeRTOS Setting
diff --git a/example/peripheral/can/configs/ft2004_aarch64_eg_configs b/example/peripheral/can/configs/ft2004_aarch64_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..5111a792bf248e93728264f9979ac7b82ac4fa9e
--- /dev/null
+++ b/example/peripheral/can/configs/ft2004_aarch64_eg_configs
@@ -0,0 +1,215 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="ft2004_freertos_a64"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+# CONFIG_TARGET_ARMV8_AARCH32 is not set
+CONFIG_TARGET_ARMV8_AARCH64=y
+CONFIG_USE_CACHE=y
+CONFIG_USE_L3CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+# CONFIG_MMU_DEBUG_PRINTS is not set
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+CONFIG_TARGET_F2000_4=y
+# CONFIG_TARGET_D2000 is not set
+# CONFIG_TARGET_E2000Q is not set
+# CONFIG_TARGET_E2000D is not set
+# CONFIG_TARGET_E2000S is not set
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+# CONFIG_USE_SPI is not set
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+CONFIG_USE_CAN=y
+
+#
+# CAN Configuration
+#
+CONFIG_USE_FCAN=y
+# end of CAN Configuration
+
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+# CONFIG_LOG_DEBUG is not set
+CONFIG_LOG_INFO=y
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+# CONFIG_LOG_EXTRA_INFO is not set
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+# CONFIG_AARCH32_RAM_LD is not set
+CONFIG_AARCH64_RAM_LD=y
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_STACK_SIZE=0x100000
+CONFIG_FPU_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+# CONFIG_FREERTOS_USE_FSPIM is not set
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+CONFIG_FREERTOS_USE_CAN=y
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+# CONFIG_USE_TLSF is not set
+# CONFIG_USE_SDMMC_CMD is not set
+# end of FreeRTOS Setting
diff --git a/example/peripheral/can/figs/create.png b/example/peripheral/can/figs/create.png
new file mode 100644
index 0000000000000000000000000000000000000000..c362376d9017652502d1c5a85ed920a51a0b6feb
Binary files /dev/null and b/example/peripheral/can/figs/create.png differ
diff --git a/example/peripheral/can/figs/delete.png b/example/peripheral/can/figs/delete.png
new file mode 100644
index 0000000000000000000000000000000000000000..6e11d764447ed3a46055392f374e328dd0314ced
Binary files /dev/null and b/example/peripheral/can/figs/delete.png differ
diff --git a/example/peripheral/can/inc/can_example.h b/example/peripheral/can/inc/can_example.h
new file mode 100644
index 0000000000000000000000000000000000000000..27231abbcb0220e24841eb974220e14347a248e7
--- /dev/null
+++ b/example/peripheral/can/inc/can_example.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: can_example.h
+ * Date: 2022-08-25 16:22:40
+ * LastEditTime: 2022-08-26 15:40:40
+ * Description: This file is for
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ */
+
+
+#ifndef CAN_EXAMPLE_H
+#define CAN_EXAMPLE_H
+
+/* adc test */
+BaseType_t FFreeRTOSCanCreate(void);
+#endif // !
\ No newline at end of file
diff --git a/example/peripheral/can/main.c b/example/peripheral/can/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..0cc8fe444ba47b95a567011e12f50764c29de728
--- /dev/null
+++ b/example/peripheral/can/main.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: main.c
+ * Date: 2022-06-17 08:17:59
+ * LastEditTime: 2022-06-17 08:17:59
+ * Description: This file is for
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ */
+
+#include "shell.h"
+#include "shell_port.h"
+#include
+#include "can_example.h"
+
+int main(void)
+{
+ BaseType_t ret;
+
+ /* test can 0 and can 1, loopback */
+ ret = FFreeRTOSCanCreate();
+ if(ret != pdPASS)
+ goto FAIL_EXIT;
+
+ ret = LSUserShellTask() ;
+ if(ret != pdPASS)
+ goto FAIL_EXIT;
+
+ vTaskStartScheduler(); /* 启动任务,开启调度 */
+ while (1); /* 正常不会执行到这里 */
+
+FAIL_EXIT:
+ printf("failed 0x%x \r\n", ret);
+ return 0;
+}
diff --git a/example/peripheral/can/makefile b/example/peripheral/can/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..9a46e85a944da08b3c3a676c009e094b9eeded2f
--- /dev/null
+++ b/example/peripheral/can/makefile
@@ -0,0 +1,30 @@
+export PROJECT_DIR ?= $(shell pwd)
+
+export USR_SRC_DIR = $(PROJECT_DIR) \
+ ./src
+export USR_INC_DIR = $(PROJECT_DIR) \
+ ./inc
+
+# 用户定义的编译目标文件上传路径
+ifeq ($(OS),Windows_NT)
+ USR_BOOT_DIR ?= $(subst \,/, $(PHYTIUM_DEV_PATH))/tftp
+else
+ USR_BOOT_DIR ?= /mnt/d/tftboot
+endif
+
+# 设置启动镜像名
+BOOT_IMG_NAME ?= freertos
+
+# 指定编译freertos项目使用的makefile
+include $(FREERTOS_SDK_ROOT)/make/build_freertos.mk
+
+# 完成编译
+boot:
+ make -j
+ @cp ./$(CONFIG_TARGET_NAME).elf $(USR_BOOT_DIR)/$(BOOT_IMG_NAME).elf
+ifdef CONFIG_OUTPUT_BINARY
+ @cp ./$(CONFIG_TARGET_NAME).bin $(USR_BOOT_DIR)/$(BOOT_IMG_NAME).bin
+endif
+ @ls $(USR_BOOT_DIR)/$(BOOT_IMG_NAME).* -l
+
+
diff --git a/example/peripheral/can/sdkconfig b/example/peripheral/can/sdkconfig
new file mode 100644
index 0000000000000000000000000000000000000000..021f45a862e31b34f5f804ccfc639a45427398df
--- /dev/null
+++ b/example/peripheral/can/sdkconfig
@@ -0,0 +1,216 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="e2000q_freertos_a64"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+# CONFIG_TARGET_ARMV8_AARCH32 is not set
+CONFIG_TARGET_ARMV8_AARCH64=y
+CONFIG_USE_CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+# CONFIG_MMU_DEBUG_PRINTS is not set
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+# CONFIG_TARGET_D2000 is not set
+CONFIG_TARGET_E2000Q=y
+# CONFIG_TARGET_E2000D is not set
+# CONFIG_TARGET_E2000S is not set
+CONFIG_TARGET_E2000=y
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+# CONFIG_USE_SPI is not set
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+CONFIG_USE_CAN=y
+
+#
+# CAN Configuration
+#
+CONFIG_USE_FCAN=y
+# CONFIG_FCAN_USE_CANFD is not set
+# end of CAN Configuration
+
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+# CONFIG_LOG_DEBUG is not set
+CONFIG_LOG_INFO=y
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+# CONFIG_LOG_EXTRA_INFO is not set
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+# CONFIG_AARCH32_RAM_LD is not set
+CONFIG_AARCH64_RAM_LD=y
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_STACK_SIZE=0x100000
+CONFIG_FPU_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+# CONFIG_FREERTOS_USE_FSPIM is not set
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+CONFIG_FREERTOS_USE_CAN=y
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+# CONFIG_USE_TLSF is not set
+# CONFIG_USE_SDMMC_CMD is not set
+# end of FreeRTOS Setting
diff --git a/example/peripheral/can/sdkconfig.h b/example/peripheral/can/sdkconfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..7b78d7ba2a446bf544f798e712dd4580f742c791
--- /dev/null
+++ b/example/peripheral/can/sdkconfig.h
@@ -0,0 +1,191 @@
+#ifndef SDK_CONFIG_H__
+#define SDK_CONFIG_H__
+
+/* Freertos Configuration */
+
+#define CONFIG_TARGET_NAME "e2000q_freertos_a64"
+/* end of Freertos Configuration */
+
+/* Standalone Setting */
+
+#define CONFIG_USE_FREERTOS
+
+/* Arch Configuration */
+
+/* CONFIG_TARGET_ARMV8_AARCH32 is not set */
+#define CONFIG_TARGET_ARMV8_AARCH64
+#define CONFIG_USE_CACHE
+#define CONFIG_USE_MMU
+#define CONFIG_USE_SYS_TICK
+/* CONFIG_MMU_DEBUG_PRINTS is not set */
+/* end of Arch Configuration */
+
+/* Board Configuration */
+
+/* CONFIG_TARGET_F2000_4 is not set */
+/* CONFIG_TARGET_D2000 is not set */
+#define CONFIG_TARGET_E2000Q
+/* CONFIG_TARGET_E2000D is not set */
+/* CONFIG_TARGET_E2000S is not set */
+#define CONFIG_TARGET_E2000
+#define CONFIG_DEFAULT_DEBUG_PRINT_UART1
+/* CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set */
+/* CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set */
+/* end of Board Configuration */
+
+/* Components Configuration */
+
+/* CONFIG_USE_SPI is not set */
+/* CONFIG_USE_QSPI is not set */
+#define CONFIG_USE_GIC
+#define CONFIG_ENABLE_GICV3
+#define CONFIG_USE_SERIAL
+
+/* Usart Configuration */
+
+#define CONFIG_ENABLE_Pl011_UART
+/* end of Usart Configuration */
+/* CONFIG_USE_GPIO is not set */
+/* CONFIG_USE_ETH is not set */
+#define CONFIG_USE_CAN
+
+/* CAN Configuration */
+
+#define CONFIG_USE_FCAN
+/* CONFIG_FCAN_USE_CANFD is not set */
+/* end of CAN Configuration */
+/* CONFIG_USE_I2C is not set */
+/* CONFIG_USE_TIMER is not set */
+/* CONFIG_USE_MIO is not set */
+/* CONFIG_USE_SDMMC is not set */
+/* CONFIG_USE_PCIE is not set */
+/* CONFIG_USE_WDT is not set */
+/* CONFIG_USE_DMA is not set */
+/* CONFIG_USE_NAND is not set */
+/* CONFIG_USE_RTC is not set */
+/* CONFIG_USE_SATA is not set */
+/* CONFIG_USE_USB is not set */
+/* CONFIG_USE_ADC is not set */
+/* CONFIG_USE_PWM is not set */
+/* CONFIG_USE_IPC is not set */
+/* end of Components Configuration */
+#define CONFIG_USE_NEW_LIBC
+/* end of Standalone Setting */
+
+/* Building Option */
+
+/* CONFIG_LOG_VERBOS is not set */
+/* CONFIG_LOG_DEBUG is not set */
+#define CONFIG_LOG_INFO
+/* CONFIG_LOG_WARN is not set */
+/* CONFIG_LOG_ERROR is not set */
+/* CONFIG_LOG_NONE is not set */
+#define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG
+#define CONFIG_INTERRUPT_ROLE_MASTER
+/* CONFIG_INTERRUPT_ROLE_SLAVE is not set */
+/* CONFIG_LOG_EXTRA_INFO is not set */
+/* CONFIG_BOOTUP_DEBUG_PRINTS is not set */
+
+/* Linker Options */
+
+/* CONFIG_AARCH32_RAM_LD is not set */
+#define CONFIG_AARCH64_RAM_LD
+/* CONFIG_USER_DEFINED_LD is not set */
+#define CONFIG_LINK_SCRIPT_ROM
+#define CONFIG_ROM_START_UP_ADDR 0x80100000
+#define CONFIG_ROM_SIZE_MB 1
+#define CONFIG_LINK_SCRIPT_RAM
+#define CONFIG_RAM_START_UP_ADDR 0x81000000
+#define CONFIG_RAM_SIZE_MB 64
+#define CONFIG_HEAP_SIZE 1
+#define CONFIG_STACK_SIZE 0x100000
+#define CONFIG_FPU_STACK_SIZE 0x1000
+/* end of Linker Options */
+
+/* Compiler Options */
+
+#define CONFIG_OUTPUT_BINARY
+/* end of Compiler Options */
+/* end of Building Option */
+
+/* Component Configuration */
+
+/* Freertos Uart Drivers */
+
+#define CONFIG_FREERTOS_USE_UART
+/* end of Freertos Uart Drivers */
+
+/* Freertos Pwm Drivers */
+
+/* CONFIG_FREERTOS_USE_PWM is not set */
+/* end of Freertos Pwm Drivers */
+
+/* Freertos Qspi Drivers */
+
+/* CONFIG_FREERTOS_USE_QSPI is not set */
+/* end of Freertos Qspi Drivers */
+
+/* Freertos Wdt Drivers */
+
+/* CONFIG_FREERTOS_USE_WDT is not set */
+/* end of Freertos Wdt Drivers */
+
+/* Freertos Eth Drivers */
+
+/* CONFIG_FREERTOS_USE_XMAC is not set */
+/* end of Freertos Eth Drivers */
+
+/* Freertos Gpio Drivers */
+
+/* CONFIG_FREERTOS_USE_GPIO is not set */
+/* end of Freertos Gpio Drivers */
+
+/* Freertos Spim Drivers */
+
+/* CONFIG_FREERTOS_USE_FSPIM is not set */
+/* end of Freertos Spim Drivers */
+
+/* Freertos DMA Drivers */
+
+/* CONFIG_FREERTOS_USE_FDDMA is not set */
+/* CONFIG_FREERTOS_USE_FGDMA is not set */
+/* end of Freertos DMA Drivers */
+
+/* Freertos MMC Drivers */
+
+/* CONFIG_FREERTOS_USE_FSDIO is not set */
+/* end of Freertos MMC Drivers */
+
+/* Freertos Adc Drivers */
+
+/* CONFIG_FREERTOS_USE_ADC is not set */
+/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+#define CONFIG_FREERTOS_USE_CAN
+/* end of Freertos Can Drivers */
+/* end of Component Configuration */
+
+/* FreeRTOS Setting */
+
+/* CONFIG_USE_LWIP is not set */
+#define CONFIG_USE_BACKTRACE
+/* CONFIG_USE_FATFS is not set */
+/* CONFIG_USE_SFUD is not set */
+/* CONFIG_USE_SPIFFS is not set */
+/* CONFIG_USE_AMP is not set */
+#define CONFIG_USE_LETTER_SHELL
+
+/* Letter Shell Configuration */
+
+#define CONFIG_LS_PL011_UART
+#define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1
+/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */
+/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */
+/* end of Letter Shell Configuration */
+/* CONFIG_USE_TLSF is not set */
+/* CONFIG_USE_SDMMC_CMD is not set */
+/* end of FreeRTOS Setting */
+
+#endif
diff --git a/example/peripheral/can/src/can_example.c b/example/peripheral/can/src/can_example.c
new file mode 100644
index 0000000000000000000000000000000000000000..71bcf20275222dff99bca84e793e5c19dc9a77f5
--- /dev/null
+++ b/example/peripheral/can/src/can_example.c
@@ -0,0 +1,494 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: can_example.c
+ * Date: 2022-07-11 11:32:48
+ * LastEditTime: 2022-07-11 11:32:48
+ * Description: This file is for
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ */
+#include
+#include
+#include "FreeRTOSConfig.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "timers.h"
+#include "fcan.h"
+#include "fcan_os.h"
+#include "cpu_info.h"
+#include "fpinctrl.h"
+#include "ft_assert.h"
+#include "ft_debug.h"
+
+#define FCAN_TEST_DEBUG_TAG "FCAN_FREERTOS_TEST"
+#define FCAN_TEST_DEBUG(format, ...) FT_DEBUG_PRINT_D(FCAN_TEST_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FCAN_TEST_INFO(format, ...) FT_DEBUG_PRINT_I(FCAN_TEST_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FCAN_TEST_WARN(format, ...) FT_DEBUG_PRINT_W(FCAN_TEST_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FCAN_TEST_ERROR(format, ...) FT_DEBUG_PRINT_E(FCAN_TEST_DEBUG_TAG, format, ##__VA_ARGS__)
+
+/* The periods assigned to the one-shot timers. */
+#define ONE_SHOT_TIMER_PERIOD ( pdMS_TO_TICKS( 20000UL ))
+
+/* can send period */
+#define CAN_SEND_PERIOD ( pdMS_TO_TICKS( 1000UL ))
+
+/* can baudrate */
+#define ARB_BAUD_RATE 1000000
+#define DATA_BAUD_RATE 1000000
+
+/* test task number */
+// #define TEST_TASK_NUM 2
+
+typedef struct
+{
+ u32 count;
+ FFreeRTOSCan *os_can_p;
+} FCanQueueData;
+
+// static xSemaphoreHandle xCountingSemaphore;
+
+/* Declare a variable of type QueueHandle_t. This is used to store the queue
+that is accessed by all three tasks. */
+static QueueHandle_t xQueue;
+
+
+
+static xTaskHandle send_handle;
+static xTaskHandle recv_handle;
+
+static TimerHandle_t xOneShotTimer;
+
+static FFreeRTOSCan *os_can_ctrl_p[FCAN_INSTANCE_NUM];
+
+static FCanFrame send_frame[FCAN_INSTANCE_NUM];
+static FCanFrame recv_frame[FCAN_INSTANCE_NUM];
+
+static void FFreeRTOSCanSendTask(void *pvParameters);
+static void FFreeRTOSCanRecvTask(void *pvParameters);
+static void FFreeRTOSCanDelete(void);
+
+static void FCanTxIrqCallback(void *args)
+{
+ FFreeRTOSCan *os_can_p = (FFreeRTOSCan *)args;
+ FCAN_TEST_DEBUG("Can%d irq send frame is ok", os_can_p->can_ctrl.config.instance_id);
+}
+
+static void FCanRxIrqCallback(void *args)
+{
+ FFreeRTOSCan *os_can_p = (FFreeRTOSCan *)args;
+ FCAN_TEST_DEBUG("Can%d irq recv frame callback", os_can_p->can_ctrl.config.instance_id);
+
+ static FCanQueueData xSendStructure;
+ xSendStructure.os_can_p = os_can_p;
+
+ portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
+
+ xQueueSendToBackFromISR(xQueue, &xSendStructure, &xHigherPriorityTaskWoken);
+
+ /* never call taskYIELD() form ISR! */
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+}
+
+static FError FFreeRTOSCanIntrSet(FFreeRTOSCan *os_can_p)
+{
+ FError ret = FCAN_SUCCESS;
+
+ FCanIntrEventConfig intr_event;
+ memset(&intr_event, 0, sizeof(intr_event));
+
+ intr_event.type = FCAN_INTR_EVENT_SEND;
+ intr_event.handler = FCanTxIrqCallback;
+ intr_event.param = (void *)os_can_p;
+ ret = FFreeRTOSCanControl(os_can_p, FREERTOS_CAN_CTRL_INTR_SET, &intr_event);
+ if (FCAN_SUCCESS != ret)
+ {
+ FCAN_TEST_ERROR("FFreeRTOSCanControl FCAN_INTR_EVENT_SEND failed\n");
+ return ret;
+ }
+
+ intr_event.type = FCAN_INTR_EVENT_RECV;
+ intr_event.handler = FCanRxIrqCallback;
+ intr_event.param = (void *)os_can_p;
+ ret = FFreeRTOSCanControl(os_can_p, FREERTOS_CAN_CTRL_INTR_SET, &intr_event);
+ if (FCAN_SUCCESS != ret)
+ {
+ FCAN_TEST_ERROR("FFreeRTOSCanControl FCAN_INTR_EVENT_RECV failed\n");
+ return ret;
+ }
+
+ u32 cpu_id;
+ GetCpuId(&cpu_id);
+ FCanCtrl *instance_p = &os_can_p->can_ctrl;
+ InterruptSetTargetCpus(instance_p->config.irq_num, cpu_id);
+ InterruptSetPriority(instance_p->config.irq_num, instance_p->config.irq_prority);
+ InterruptInstall(instance_p->config.irq_num, FCanIntrHandler, instance_p, "can");
+ InterruptUmask(instance_p->config.irq_num);
+
+ return ret;
+}
+
+
+static FError FFreeRTOSCanBaudrateSet(FFreeRTOSCan *os_can_p)
+{
+ FError ret = FCAN_SUCCESS;
+
+ FCanIntrEventConfig intr_event;
+ memset(&intr_event, 0, sizeof(intr_event));
+
+ FCanBaudrateConfig arb_segment_config;
+ FCanBaudrateConfig data_segment_config;
+ memset(&arb_segment_config, 0, sizeof(arb_segment_config));
+ memset(&data_segment_config, 0, sizeof(data_segment_config));
+ arb_segment_config.baudrate = ARB_BAUD_RATE;
+ arb_segment_config.auto_calc = TRUE;
+ arb_segment_config.segment = FCAN_ARB_SEGMENT;
+
+ data_segment_config.baudrate = DATA_BAUD_RATE;
+ data_segment_config.auto_calc = TRUE;
+ data_segment_config.segment = FCAN_DATA_SEGMENT;
+
+ ret = FFreeRTOSCanControl(os_can_p, FREERTOS_CAN_CTRL_BAUDRATE_SET, &arb_segment_config);
+ if (FCAN_SUCCESS != ret)
+ {
+ FCAN_TEST_ERROR("FFreeRTOSCanControl arb_segment_config failed\n");
+ return ret;
+ }
+
+ ret = FFreeRTOSCanControl(os_can_p, FREERTOS_CAN_CTRL_BAUDRATE_SET, &data_segment_config);
+ if (FCAN_SUCCESS != ret)
+ {
+ FCAN_TEST_ERROR("FFreeRTOSCanControl data_segment_config failed\n");
+ return ret;
+ }
+ return ret;
+}
+
+
+static FError FFreeRTOSCanIdMaskSet(FFreeRTOSCan *os_can_p)
+{
+ FError ret = FCAN_SUCCESS;
+
+ FCanIdMaskConfig id_mask;
+ memset(&id_mask, 0, sizeof(id_mask));
+ for (int i = 0; i < FCAN_ACC_ID_REG_NUM; i++)
+ {
+ id_mask.filter_index = i;
+ id_mask.id = 0;
+ id_mask.mask = FCAN_ACC_IDN_MASK;
+ ret = FFreeRTOSCanControl(os_can_p, FREERTOS_CAN_CTRL_ID_MASK_SET, &id_mask);
+ if (FCAN_SUCCESS != ret)
+ {
+ FCAN_TEST_ERROR("FFreeRTOSCanControl FREERTOS_CAN_CTRL_ID_MASK_SET %d failed\n", i);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static void FFreeRTOSCanInitTask(void *pvParameters)
+{
+ FError ret = FCAN_SUCCESS;
+ BaseType_t xReturn = pdPASS;
+ FCanInstance can_id = FCAN_INSTANCE_0;
+
+ for(can_id = FCAN_INSTANCE_0; can_id < FCAN_INSTANCE_NUM; can_id++)
+ {
+ #if defined(CONFIG_TARGET_F2000_4) || defined(CONFIG_TARGET_D2000)
+ if(can_id == FCAN_INSTANCE_0)
+ {
+ FPinSetFunc(FIOCTRL_TJTAG_TDI_PAD, FPIN_FUNC1); /* can0-tx: func 1 */
+ FPinSetFunc(FIOCTRL_SWDITMS_SWJ_PAD, FPIN_FUNC1); /* can0-rx: func 1 */
+ }
+ else if(can_id == FCAN_INSTANCE_1)
+ {
+ FPinSetFunc(FIOCTRL_NTRST_SWJ_PAD, FPIN_FUNC1); /* can1-tx: func 1 */
+ FPinSetFunc(FIOCTRL_SWDO_SWJ_PAD, FPIN_FUNC1); /* can1-rx: func 1 */
+ }
+ else if(can_id == FCAN_INSTANCE_2)
+ {
+
+ }
+ else
+ {
+ FCAN_TEST_ERROR("can id is error");
+ goto can_init_exit;
+ }
+ #elif defined(CONFIG_TARGET_E2000)
+ FIOPadSetCanMux(can_id);
+ #endif
+
+ /* init can controller */
+ os_can_ctrl_p[can_id] = FFreeRTOSCanInit(can_id);
+ if(os_can_ctrl_p[can_id] == NULL)
+ {
+ printf("FFreeRTOSCanInit %d failed!!!\n", can_id);
+ goto can_init_exit;
+ }
+
+ /* set can baudrate */
+ ret = FFreeRTOSCanBaudrateSet(os_can_ctrl_p[can_id]);
+ if (FCAN_SUCCESS != ret)
+ {
+ printf("FFreeRTOSCanInit FFreeRTOSCanBaudrateSet failed!!!\n");
+ goto can_init_exit;
+ }
+
+ /* set can id mask */
+ ret = FFreeRTOSCanIdMaskSet(os_can_ctrl_p[can_id]);
+ if (FCAN_SUCCESS != ret)
+ {
+ printf("FFreeRTOSCanInit FFreeRTOSCanIdMaskSet failed!!!\n");
+ goto can_init_exit;
+ }
+
+ /* Identifier mask enable */
+ ret = FFreeRTOSCanControl(os_can_ctrl_p[can_id], FREERTOS_CAN_CTRL_ID_MASK_ENABLE, NULL);
+ if (FCAN_SUCCESS != ret)
+ {
+ FCAN_TEST_ERROR("FFreeRTOSCanControl FREERTOS_CAN_CTRL_ID_MASK_ENABLE failed\n");
+ goto can_init_exit;
+ }
+
+ /* init can interrupt handler */
+ ret = FFreeRTOSCanIntrSet(os_can_ctrl_p[can_id]);
+ if (FCAN_SUCCESS != ret)
+ {
+ FCAN_TEST_ERROR("FFreeRTOSCanInit FFreeRTOSCanIntrSet failed!!!\n");
+ goto can_init_exit;
+ }
+
+ /* enable can transfer */
+ ret = FFreeRTOSCanControl(os_can_ctrl_p[can_id], FREERTOS_CAN_CTRL_ENABLE, NULL);
+ if (FCAN_SUCCESS != ret)
+ {
+ FCAN_TEST_ERROR("FFreeRTOSCanControl FREERTOS_CAN_CTRL_ENABLE failed\n");
+ goto can_init_exit;
+ }
+ }
+
+ printf("FFreeRTOSCanInitTask execute success !!!\r\n");
+
+ /* can send task */
+ xReturn = xTaskCreate((TaskFunction_t )FFreeRTOSCanSendTask, /* 任务入口函数 */
+ (const char* )"FFreeRTOSCanSendTask",/* 任务名字 */
+ (uint16_t )1024, /* 任务栈大小 */
+ NULL,/* 任务入口函数参数 */
+ (UBaseType_t )configMAX_PRIORITIES-5, /* 任务的优先级 */
+ (TaskHandle_t* )&send_handle); /* 任务控制 */
+ if(xReturn != pdPASS)
+ {
+ printf("Create FFreeRTOSCanSendTask failed.\r\n");
+ goto can_init_exit;
+ }
+
+ /* can recv task */
+ xReturn = xTaskCreate((TaskFunction_t )FFreeRTOSCanRecvTask, /* 任务入口函数 */
+ (const char* )"FFreeRTOSCanRecvTask",/* 任务名字 */
+ (uint16_t )1024, /* 任务栈大小 */
+ NULL,/* 任务入口函数参数 */
+ (UBaseType_t )configMAX_PRIORITIES-5, /* 任务的优先级 */
+ (TaskHandle_t* )&recv_handle); /* 任务控制 */
+ if(xReturn != pdPASS)
+ {
+ printf("Create FFreeRTOSCanRecvTask failed.\r\n");
+ goto can_init_exit;
+ }
+
+can_init_exit:
+ vTaskDelete(NULL);
+}
+
+static void FFreeRTOSCanRecvTask(void *pvParameters)
+{
+ FError ret = FCAN_SUCCESS;
+ u8 count[FCAN_INSTANCE_NUM]= {0};
+ int i = 0;
+ static FCanQueueData xReceiveStructure;
+ FFreeRTOSCan *os_can_p;
+ u32 instance_id = 0;
+ /* As per most tasks, this task is implemented in an infinite loop. */
+ for (;;)
+ {
+ /* wait recv interrupt give semphore */
+ xQueueReceive(xQueue, &xReceiveStructure, portMAX_DELAY);
+ os_can_p = xReceiveStructure.os_can_p;
+ instance_id = os_can_p->can_ctrl.config.instance_id;
+ memset(&recv_frame, 0, sizeof(FCanFrame));
+ ret = FFreeRTOSCanRecv(os_can_p, &recv_frame[instance_id]);
+ if (FCAN_SUCCESS == ret)
+ {
+ printf("\r\ncan 0 recv id is %#x\r\n", recv_frame[instance_id].canid);
+ printf("can 0 recv dlc is %d\r\n", recv_frame[instance_id].candlc);
+ printf("can 0 recv data is ");
+ for (i = 0; i < recv_frame[instance_id].candlc; i++)
+ {
+ printf("%#x ", recv_frame[instance_id].data[i]);
+ if(recv_frame[instance_id].data[i] != send_frame[FCAN_INSTANCE_1-instance_id].data[i])
+ {
+ FCAN_TEST_ERROR("\ncount=%d: can %d recv is equal to can%d send!!!\r\n", count[instance_id], instance_id, FCAN_INSTANCE_1-instance_id);
+ }
+ }
+ printf("\ncount=%d: can %d recv is equal to can%d send!!!\r\n", count[instance_id], instance_id, FCAN_INSTANCE_1-instance_id);
+
+ count[instance_id]++;
+ }
+
+ }
+}
+
+static void FFreeRTOSCanSendTask(void *pvParameters)
+{
+ #define FCAN_SEND_ID 0x23
+ #define FCAN_SEND_LENGTH 8
+
+ FError ret = FCAN_SUCCESS;
+ FCanInstance can_id = FCAN_INSTANCE_0;
+
+ u8 count[FCAN_INSTANCE_NUM]= {0};
+ int i = 0;
+
+ /* As per most tasks, this task is implemented in an infinite loop. */
+ for (;;)
+ {
+ printf("\r\ncan send task running\r\n");
+ for(can_id = FCAN_INSTANCE_0; can_id <= FCAN_INSTANCE_1; can_id++)
+ {
+ send_frame[can_id].canid = FCAN_SEND_ID+(can_id<<8);
+ send_frame[can_id].canid &= CAN_SFF_MASK;
+ send_frame[can_id].candlc = FCAN_SEND_LENGTH;
+ for (i = 0; i < send_frame[can_id].candlc; i++)
+ {
+ send_frame[can_id].data[i] = i+(can_id<<4);
+ }
+ ret = FFreeRTOSCanSend(os_can_ctrl_p[can_id], &send_frame[can_id]);
+ if(ret != FCAN_SUCCESS)
+ {
+ printf("can%d send failed.\n", can_id);
+ }
+ count[can_id]++;
+ }
+ vTaskDelay(CAN_SEND_PERIOD);
+ }
+}
+
+static void prvOneShotTimerCallback( TimerHandle_t xTimer )
+{
+ /* Output a string to show the time at which the callback was executed. */
+ printf("One-shot timer callback executing, will delete FFreeRTOSCanReadTask.\r\n" );
+
+ FFreeRTOSCanDelete();
+}
+
+/* create can test, can0 and can1 loopback */
+BaseType_t FFreeRTOSCanCreate(void)
+{
+ BaseType_t xReturn = pdPASS;
+ BaseType_t timer_started = pdPASS;
+
+ /* The queue is created to hold a maximum of 32 structures of type xData. */
+ xQueue = xQueueCreate(32, sizeof(FCanQueueData));
+ if (xQueue == NULL)
+ {
+ printf("FFreeRTOSCanCreate FCanQueueData create failed.\r\n" );
+ return pdFAIL;
+ }
+
+ /* enter critical region */
+
+ /* can init task */
+ xReturn = xTaskCreate((TaskFunction_t )FFreeRTOSCanInitTask, /* 任务入口函数 */
+ (const char* )"FFreeRTOSCanInitTask",/* 任务名字 */
+ (uint16_t )1024, /* 任务栈大小 */
+ NULL,/* 任务入口函数参数 */
+ (UBaseType_t )1, /* 任务的优先级 */
+ NULL); /* 任务控制 */
+
+ /* Create the one shot software timer, storing the handle to the created
+ software timer in xOneShotTimer. */
+ xOneShotTimer = xTimerCreate( "OneShot Software Timer", /* Text name for the software timer - not used by FreeRTOS. */
+ ONE_SHOT_TIMER_PERIOD, /* The software timer's period in ticks. */
+ pdFALSE, /* Setting uxAutoRealod to pdFALSE creates a one-shot software timer. */
+ 0, /* This example use the timer id. */
+ prvOneShotTimerCallback ); /* The callback function to be used by the software timer being created. */
+
+ /* Check the timers were created. */
+ if( xOneShotTimer != NULL )
+ {
+ /* Start the software timers, using a block time of 0 (no block time).
+ The scheduler has not been started yet so any block time specified here
+ would be ignored anyway. */
+ timer_started = xTimerStart( xOneShotTimer, 0 );
+
+ /* The implementation of xTimerStart() uses the timer command queue, and
+ xTimerStart() will fail if the timer command queue gets full. The timer
+ service task does not get created until the scheduler is started, so all
+ commands sent to the command queue will stay in the queue until after
+ the scheduler has been started. Check both calls to xTimerStart()
+ passed. */
+ if(timer_started != pdPASS)
+ {
+ vPrintf("CreateSoftwareTimerTasks xTimerStart failed \r\n");
+ }
+ }
+ else
+ {
+ vPrintf("CreateSoftwareTimerTasks xTimerCreate failed \r\n");
+ }
+
+ /* exit critical region */
+ // taskEXIT_CRITICAL();
+
+ return xReturn;
+}
+
+static void FFreeRTOSCanDelete(void)
+{
+ BaseType_t xReturn = pdPASS;
+
+ if(send_handle)
+ {
+ vTaskDelete(send_handle);
+ vPrintf("Delete FFreeRTOSCanSendTask success\r\n");
+ }
+
+ if(recv_handle)
+ {
+ vTaskDelete(recv_handle);
+ vPrintf("Delete FFreeRTOSCanRecvTask success\r\n");
+ }
+
+ /* deinit can os instance */
+ FFreeRTOSCanDeinit(os_can_ctrl_p[FCAN_INSTANCE_0]);
+ FFreeRTOSCanDeinit(os_can_ctrl_p[FCAN_INSTANCE_1]);
+
+ /* delete count sem */
+ // vSemaphoreDelete(xCountingSemaphore);
+
+ /* delete queue */
+ vQueueDelete(xQueue);
+
+ /* delete timer */
+ xReturn = xTimerDelete(xOneShotTimer, 0);
+ if(xReturn != pdPASS)
+ {
+ vPrintf("Delete OneShot Software Timer failed.\r\n");
+ }
+ else
+ {
+ vPrintf("Delete OneShot Software Timer success.\r\n");
+ }
+}
\ No newline at end of file
diff --git a/example/peripheral/dma/ddma/configs/e2000d_aarch32_eg_configs b/example/peripheral/dma/ddma/configs/e2000d_aarch32_eg_configs
index 71a9998ac364b4bb2d5db41cf3e0b1c9b3157208..dcb1c97ba2ee2494e9aa62544bda41fca821afad 100644
--- a/example/peripheral/dma/ddma/configs/e2000d_aarch32_eg_configs
+++ b/example/peripheral/dma/ddma/configs/e2000d_aarch32_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_FDDMA=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/dma/ddma/configs/e2000d_aarch64_eg_configs b/example/peripheral/dma/ddma/configs/e2000d_aarch64_eg_configs
index e3f1567b08e9603ecae6063dc42eb275bde2e828..264ca1868a134a255fc2d2421cf73cffbc7302ce 100644
--- a/example/peripheral/dma/ddma/configs/e2000d_aarch64_eg_configs
+++ b/example/peripheral/dma/ddma/configs/e2000d_aarch64_eg_configs
@@ -178,6 +178,12 @@ CONFIG_FREERTOS_USE_FDDMA=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/dma/ddma/sdkconfig b/example/peripheral/dma/ddma/sdkconfig
index e3f1567b08e9603ecae6063dc42eb275bde2e828..264ca1868a134a255fc2d2421cf73cffbc7302ce 100644
--- a/example/peripheral/dma/ddma/sdkconfig
+++ b/example/peripheral/dma/ddma/sdkconfig
@@ -178,6 +178,12 @@ CONFIG_FREERTOS_USE_FDDMA=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/dma/ddma/sdkconfig.h b/example/peripheral/dma/ddma/sdkconfig.h
index 69bb4d90988e03384964f82603984ff43384c8d2..a670826664e951c92d5e979e2e34a222c40896c1 100644
--- a/example/peripheral/dma/ddma/sdkconfig.h
+++ b/example/peripheral/dma/ddma/sdkconfig.h
@@ -157,6 +157,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/peripheral/dma/gdma/configs/e2000d_aarch32_eg_configs b/example/peripheral/dma/gdma/configs/e2000d_aarch32_eg_configs
index ff35af8c4af4a3017f358f6e87d2bd2de33c13e1..95256b411ae704273e0b2a72b330808711b9d152 100644
--- a/example/peripheral/dma/gdma/configs/e2000d_aarch32_eg_configs
+++ b/example/peripheral/dma/gdma/configs/e2000d_aarch32_eg_configs
@@ -181,6 +181,12 @@ CONFIG_FREERTOS_USE_FGDMA=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/dma/gdma/configs/e2000d_aarch64_eg_configs b/example/peripheral/dma/gdma/configs/e2000d_aarch64_eg_configs
index 91a4888409fddb255acff3bd527d41be49b2ba26..6dd9ba885eb1b8187a3c52a2bf8593fa473f0464 100644
--- a/example/peripheral/dma/gdma/configs/e2000d_aarch64_eg_configs
+++ b/example/peripheral/dma/gdma/configs/e2000d_aarch64_eg_configs
@@ -177,6 +177,12 @@ CONFIG_FREERTOS_USE_FGDMA=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/dma/gdma/sdkconfig b/example/peripheral/dma/gdma/sdkconfig
index 91a4888409fddb255acff3bd527d41be49b2ba26..6dd9ba885eb1b8187a3c52a2bf8593fa473f0464 100644
--- a/example/peripheral/dma/gdma/sdkconfig
+++ b/example/peripheral/dma/gdma/sdkconfig
@@ -177,6 +177,12 @@ CONFIG_FREERTOS_USE_FGDMA=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/dma/gdma/sdkconfig.h b/example/peripheral/dma/gdma/sdkconfig.h
index ecfe045685187602270ac820c707464cfee5bb29..90bd3ebdd181944befe2fe084e1940f795b03ad4 100644
--- a/example/peripheral/dma/gdma/sdkconfig.h
+++ b/example/peripheral/dma/gdma/sdkconfig.h
@@ -156,6 +156,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/peripheral/gpio/configs/e2000d_aarch32_eg_configs b/example/peripheral/gpio/configs/e2000d_aarch32_eg_configs
index d74bd05cdd5e1daf6fe2bcd6d214953e1bb2af55..04ae2ba8ec12bbb1333ec2f8548c94f21e52728b 100644
--- a/example/peripheral/gpio/configs/e2000d_aarch32_eg_configs
+++ b/example/peripheral/gpio/configs/e2000d_aarch32_eg_configs
@@ -180,6 +180,12 @@ CONFIG_FREERTOS_USE_GPIO=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/gpio/configs/e2000d_aarch64_eg_configs b/example/peripheral/gpio/configs/e2000d_aarch64_eg_configs
index 4bafd61393f4fbba8e204d1ed6f701681d3d6211..463daeef3f0b5123914856dac4df7a8cd4d8643f 100644
--- a/example/peripheral/gpio/configs/e2000d_aarch64_eg_configs
+++ b/example/peripheral/gpio/configs/e2000d_aarch64_eg_configs
@@ -176,6 +176,12 @@ CONFIG_FREERTOS_USE_GPIO=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/gpio/sdkconfig b/example/peripheral/gpio/sdkconfig
index 4bafd61393f4fbba8e204d1ed6f701681d3d6211..463daeef3f0b5123914856dac4df7a8cd4d8643f 100644
--- a/example/peripheral/gpio/sdkconfig
+++ b/example/peripheral/gpio/sdkconfig
@@ -176,6 +176,12 @@ CONFIG_FREERTOS_USE_GPIO=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/gpio/sdkconfig.h b/example/peripheral/gpio/sdkconfig.h
index b26793157af449f333fb46bce010406cbc506129..52be9ec531a96c65d9517d1f3daad24748c9d16a 100644
--- a/example/peripheral/gpio/sdkconfig.h
+++ b/example/peripheral/gpio/sdkconfig.h
@@ -155,6 +155,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/peripheral/pwm/configs/e2000d_aarch32_eg_configs b/example/peripheral/pwm/configs/e2000d_aarch32_eg_configs
index d9bceaf19434879b450a17641ac4a6dcc25fa9b9..04e82ee22ba5b76511f5c0105d61e6abf5d457e6 100644
--- a/example/peripheral/pwm/configs/e2000d_aarch32_eg_configs
+++ b/example/peripheral/pwm/configs/e2000d_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_PWM=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/pwm/configs/e2000d_aarch64_eg_configs b/example/peripheral/pwm/configs/e2000d_aarch64_eg_configs
index c4750c46000aabd75b5eb35bbabd8b7a58a604b8..37d670dbc6b653009a6e4e704311a1af02debd92 100644
--- a/example/peripheral/pwm/configs/e2000d_aarch64_eg_configs
+++ b/example/peripheral/pwm/configs/e2000d_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_PWM=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/pwm/configs/e2000q_aarch32_eg_configs b/example/peripheral/pwm/configs/e2000q_aarch32_eg_configs
index 9f8d8eb776ec678d9a669700d203922a348ab497..9536d0e01847a2a0d9970561f728428f18cb883b 100644
--- a/example/peripheral/pwm/configs/e2000q_aarch32_eg_configs
+++ b/example/peripheral/pwm/configs/e2000q_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_PWM=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/pwm/configs/e2000q_aarch64_eg_configs b/example/peripheral/pwm/configs/e2000q_aarch64_eg_configs
index cee19e2553fd9898e84fe5104b0e72c3c258e919..1f477b024344f122f8b4184d6ecfbb962d5d540b 100644
--- a/example/peripheral/pwm/configs/e2000q_aarch64_eg_configs
+++ b/example/peripheral/pwm/configs/e2000q_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_PWM=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/pwm/sdkconfig b/example/peripheral/pwm/sdkconfig
index cee19e2553fd9898e84fe5104b0e72c3c258e919..1f477b024344f122f8b4184d6ecfbb962d5d540b 100644
--- a/example/peripheral/pwm/sdkconfig
+++ b/example/peripheral/pwm/sdkconfig
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_PWM=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/pwm/sdkconfig.h b/example/peripheral/pwm/sdkconfig.h
index 974c160e3ea9b0187d3dc339a9ab22f0dbabf466..6c10faef5846f2405fb67ad312e4215796ca6f9a 100644
--- a/example/peripheral/pwm/sdkconfig.h
+++ b/example/peripheral/pwm/sdkconfig.h
@@ -159,6 +159,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/peripheral/qspi/configs/d2000_aarch32_eg_configs b/example/peripheral/qspi/configs/d2000_aarch32_eg_configs
index 0106123ccf055d317fbed916340735c2c5b845f6..27ee8c8b3f3e3a81c18696a6ca7372ae8049fa49 100644
--- a/example/peripheral/qspi/configs/d2000_aarch32_eg_configs
+++ b/example/peripheral/qspi/configs/d2000_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/qspi/configs/d2000_aarch64_eg_configs b/example/peripheral/qspi/configs/d2000_aarch64_eg_configs
index d7f059d7c473ae4b6c669ef693452965e251d79f..ee6fa43ce020a03948ae2e1c98a1427211708340 100644
--- a/example/peripheral/qspi/configs/d2000_aarch64_eg_configs
+++ b/example/peripheral/qspi/configs/d2000_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/qspi/configs/e2000d_aarch32_eg_configs b/example/peripheral/qspi/configs/e2000d_aarch32_eg_configs
index 917cedfa80ae506ad4abe20395ee36271f43dbee..e7a5177497297a0ef252235fa9c4ae1a25e1c8d4 100644
--- a/example/peripheral/qspi/configs/e2000d_aarch32_eg_configs
+++ b/example/peripheral/qspi/configs/e2000d_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/qspi/configs/e2000d_aarch64_eg_configs b/example/peripheral/qspi/configs/e2000d_aarch64_eg_configs
index 8cb87ac1118587e9d257bf041140b42e72f74ee7..f800099a153f7df3315d33827292c5facec8d61f 100644
--- a/example/peripheral/qspi/configs/e2000d_aarch64_eg_configs
+++ b/example/peripheral/qspi/configs/e2000d_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/qspi/configs/e2000q_aarch32_eg_configs b/example/peripheral/qspi/configs/e2000q_aarch32_eg_configs
index ef1427f88b7eb879cd7a448c44eddcc14978c6bf..03fdb8bfa03c527fdd3bbd7c88f04e768dbd6faf 100644
--- a/example/peripheral/qspi/configs/e2000q_aarch32_eg_configs
+++ b/example/peripheral/qspi/configs/e2000q_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/qspi/configs/e2000q_aarch64_eg_configs b/example/peripheral/qspi/configs/e2000q_aarch64_eg_configs
index c66bfa278909fceaf8df3fdfed326ad94ef69fb7..ed58351d51acb869ecfb0f208ba9ec3d55fbdc98 100644
--- a/example/peripheral/qspi/configs/e2000q_aarch64_eg_configs
+++ b/example/peripheral/qspi/configs/e2000q_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/qspi/configs/ft2004_aarch32_eg_configs b/example/peripheral/qspi/configs/ft2004_aarch32_eg_configs
index 5c7837d81169674337dd05b30823c8672156d712..da6c977fd165c9ed714e676f8d14a89498bcbf7e 100644
--- a/example/peripheral/qspi/configs/ft2004_aarch32_eg_configs
+++ b/example/peripheral/qspi/configs/ft2004_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/qspi/configs/ft2004_aarch64_eg_configs b/example/peripheral/qspi/configs/ft2004_aarch64_eg_configs
index b0b5499d2ee4d39fb7a8d8a3645e189e9f977257..2da814a4d13ea2a3f95418635cfd1d8176201bd0 100644
--- a/example/peripheral/qspi/configs/ft2004_aarch64_eg_configs
+++ b/example/peripheral/qspi/configs/ft2004_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/qspi/sdkconfig b/example/peripheral/qspi/sdkconfig
index c66bfa278909fceaf8df3fdfed326ad94ef69fb7..ed58351d51acb869ecfb0f208ba9ec3d55fbdc98 100644
--- a/example/peripheral/qspi/sdkconfig
+++ b/example/peripheral/qspi/sdkconfig
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/qspi/sdkconfig.h b/example/peripheral/qspi/sdkconfig.h
index fd1da99957c8505d21cb20bc173a74b2e2043e8d..ea49e6e66bea8f8e657b6a07e7b98e41c4896a41 100644
--- a/example/peripheral/qspi/sdkconfig.h
+++ b/example/peripheral/qspi/sdkconfig.h
@@ -159,6 +159,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/peripheral/sdio/configs/e2000d_aarch32_eg_configs b/example/peripheral/sdio/configs/e2000d_aarch32_eg_configs
index fc2941839afce3ac8589e6f0289917ba031f4ecf..b80867fedbb73dfb0b220cc34f6b71a40f42873c 100644
--- a/example/peripheral/sdio/configs/e2000d_aarch32_eg_configs
+++ b/example/peripheral/sdio/configs/e2000d_aarch32_eg_configs
@@ -180,6 +180,12 @@ CONFIG_FREERTOS_USE_FSDIO=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/sdio/configs/e2000d_aarch64_eg_configs b/example/peripheral/sdio/configs/e2000d_aarch64_eg_configs
index e50168bb98c0d5111def92810d2d74c8b2f6a430..b55ef0572b9407f33d62cbf1ac0a769f2af94dde 100644
--- a/example/peripheral/sdio/configs/e2000d_aarch64_eg_configs
+++ b/example/peripheral/sdio/configs/e2000d_aarch64_eg_configs
@@ -176,6 +176,12 @@ CONFIG_FREERTOS_USE_FSDIO=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/sdio/sdkconfig b/example/peripheral/sdio/sdkconfig
index e50168bb98c0d5111def92810d2d74c8b2f6a430..b55ef0572b9407f33d62cbf1ac0a769f2af94dde 100644
--- a/example/peripheral/sdio/sdkconfig
+++ b/example/peripheral/sdio/sdkconfig
@@ -176,6 +176,12 @@ CONFIG_FREERTOS_USE_FSDIO=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/sdio/sdkconfig.h b/example/peripheral/sdio/sdkconfig.h
index 453e9deb02f7b454958fc9ff5ef8174aa4bddb2a..4f9d87ae3d7e9458c0cf6c4df97b77d529ad58ae 100644
--- a/example/peripheral/sdio/sdkconfig.h
+++ b/example/peripheral/sdio/sdkconfig.h
@@ -155,6 +155,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/peripheral/spi/configs/e2000d_aarch32_eg_configs b/example/peripheral/spi/configs/e2000d_aarch32_eg_configs
index 913504f719b47866612f4c41cb783d8c68cd9951..013713239d3f59eb2d3824952aee024fbfd45b5b 100644
--- a/example/peripheral/spi/configs/e2000d_aarch32_eg_configs
+++ b/example/peripheral/spi/configs/e2000d_aarch32_eg_configs
@@ -180,6 +180,12 @@ CONFIG_FREERTOS_USE_FSPIM=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/spi/configs/e2000d_aarch64_eg_configs b/example/peripheral/spi/configs/e2000d_aarch64_eg_configs
index 6ea2a56551edc9fa6c9d9b08ff9c29081b70428d..8bfa203555d5781db1db07c06a4bb7a0d38bf84a 100644
--- a/example/peripheral/spi/configs/e2000d_aarch64_eg_configs
+++ b/example/peripheral/spi/configs/e2000d_aarch64_eg_configs
@@ -176,6 +176,12 @@ CONFIG_FREERTOS_USE_FSPIM=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/spi/sdkconfig b/example/peripheral/spi/sdkconfig
index 6ea2a56551edc9fa6c9d9b08ff9c29081b70428d..8bfa203555d5781db1db07c06a4bb7a0d38bf84a 100644
--- a/example/peripheral/spi/sdkconfig
+++ b/example/peripheral/spi/sdkconfig
@@ -176,6 +176,12 @@ CONFIG_FREERTOS_USE_FSPIM=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/spi/sdkconfig.h b/example/peripheral/spi/sdkconfig.h
index 1fff15deca8417eeb0f0e84c67a265efdbe0c49e..b57efb1979d893471b15e1ef23d7bddc28300675 100644
--- a/example/peripheral/spi/sdkconfig.h
+++ b/example/peripheral/spi/sdkconfig.h
@@ -155,6 +155,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/peripheral/usb/cherryusb_host/Kconfig b/example/peripheral/usb/cherryusb_host/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..a4938ffbfaff69e6a42f44fa14f31296dfae9ddb
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/Kconfig
@@ -0,0 +1,19 @@
+#
+# For a description of the syntax of this configuration file,
+# see tools/kconfiglib/kconfig-language.txt.
+#
+
+
+mainmenu "Phytium Freertos Configuration"
+
+menu "Freertos Configuration"
+ config TARGET_NAME
+ string "Build Target Name"
+ default "freertos"
+ help
+ Build Target name for the demo
+
+endmenu
+
+source "$(FREERTOS_SDK_ROOT)/Kconfig"
+
diff --git a/example/peripheral/usb/cherryusb_host/README.md b/example/peripheral/usb/cherryusb_host/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..9902b65b66093e3931a50d9b1fd7badf5208a37e
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/README.md
@@ -0,0 +1,153 @@
+
+# CherryUSB Host 测试
+
+## 1. 例程介绍
+
+>介绍例程的用途,使用场景,相关基本概念,描述用户可以使用例程完成哪些工作
+
+CherryUSB 是一个用于嵌入式系统 USB 协议栈,支持运行在Host模式和Device模式
+
+## 2. 如何使用例程
+
+>描述开发平台准备,使用例程配置,构建和下载镜像的过程
+
+### 2.1 硬件配置方法
+
+>哪些硬件平台是支持的,需要哪些外设,例程与开发板哪些IO口相关等(建议附录开发板照片,展示哪些IO口被引出)
+
+本例程在 E2000 平台测试通过,您可以参考以下方法配置本例程所需要的硬件和软件环境,
+- E2000开发板
+- 本例程基于E2000 Demo 开发板,使用logitech键盘、Dell鼠标和Sandisk盘完成测试
+
+### 2.2 SDK配置方法
+
+>依赖哪些驱动、库和第三方组件,如何完成配置(列出需要使能的关键配置项)
+
+本例程需要的配置包括,
+- Letter Shell组件,依赖 USE_LETTER_SHELL
+- FATFS组件,依赖 USE_FATFS 和 SELECT_FATFS_FSATA_PCIE
+- PCIE组件,作为转接接口,依赖USE_PCIE
+- SATA组件,依赖 USE_SATA
+
+本例子已经提供好具体的编译指令,以下进行介绍:
+- make 将目录下的工程进行编译
+- make clean 将目录下的工程进行清理
+- make boot 将目录下的工程进行编译,并将生成的elf 复制到目标地址
+- make load_e2000d_aarch64 将预设64bit e2000d 下的配置加载至工程中
+- make load_e2000d_aarch32 将预设32bit e2000d 下的配置加载至工程中
+- make menuconfig 配置目录下的参数变量
+- make backup_kconfig 将目录下的sdkconfig 备份到./configs下
+
+- 具体使用方法为:
+ - 在当前目录下
+ - 执行以上指令
+
+### 2.3 构建和下载
+
+>描述构建、烧录下载镜像的过程,列出相关的命令
+
+使用例程的一般过程为
+
+- 选择目标平台和例程需要的配置
+```
+make load_e2000d_aarch64
+```
+
+- 进行编译
+```
+make
+```
+
+- 将编译出的镜像放置到tftp目录下
+```
+make boot
+```
+
+- host侧设置重启host侧tftp服务器
+```
+sudo service tftpd-hpa restart
+```
+
+- 开发板侧使用bootelf命令跳转
+```
+setenv ipaddr 192.168.4.20
+setenv serverip 192.168.4.50
+setenv gatewayip 192.168.4.1
+tftpboot 0x90100000 freertos.elf
+bootelf -p 0x90100000
+```
+
+### 2.4 输出与实验现象
+
+>描述输入输出情况,列出存在哪些输出,对应的输出是什么(建议附录相关现象图片)
+
+
+
+#### 2.4.1 读写 U 盘
+
+- 目前 CherryUSB 的 USB 3.0 支持尚未完成,超高速设备需要通过2.0 Hub连接进行测试
+
+```
+usb init
+usb disk
+```
+
+
+
+
+
+- 输入`usb disk`后,启动一个任务不断读写U盘
+
+#### 2.4.2 获取键盘输入
+
+- 目前 USB (xhci port) 协议栈中 hub 的支持还不够完善,低速设备需要直连板上的 USB 插槽进行测试
+
+```
+usb init
+usb input
+```
+
+- 输入`usb input`后,可以通过中断处理键盘输入
+
+
+
+
+
+#### 2.4.3 获取鼠标输入
+
+- 目前 USB (xhci port) 协议栈中 hub 的支持还不够完善,低速设备需要直连板上的 USB 插槽进行测试
+
+```
+usb init
+usb input
+```
+
+- 输入`usb input`后,可以通过中断处理鼠标输入
+
+
+
+
+
+## 3. 如何解决问题
+
+>主要记录使用例程中可能会遇到的问题,给出相应的解决方案
+
+- 目前CherryUSB(xhci port)上的hub支持不完善,主要的影响是
+1. 不支持枚举hub上的低速设备,例如鼠标、键盘等需要直接插槽
+
+- 目前CherryUSB上的USB3.0支持尚未完成,主要的影响是
+1. 不支持枚举超高速设备,例如高速U盘直接插槽枚举会失败
+2. 不支持枚举USB 3.0超高速hub
+
+- 因此,目前支持的两种连接方式是
+1. 板上USB插槽直连鼠标、键盘
+2. 通过USB 2.0全速/高速hub,连接U盘等超高速设备
+
+## 4. 修改历史记录
+
+>记录例程的重大修改记录,标明修改发生的版本号
+
+V0.3.1 首次合入
+
+
+
diff --git a/example/peripheral/usb/cherryusb_host/configs/e2000d_aarch32_eg_configs b/example/peripheral/usb/cherryusb_host/configs/e2000d_aarch32_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..6c949218c8b063d49d05f5751cf50510c2f07e66
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/configs/e2000d_aarch32_eg_configs
@@ -0,0 +1,229 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="e2000d_freertos_a32"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+CONFIG_TARGET_ARMV8_AARCH32=y
+# CONFIG_TARGET_ARMV8_AARCH64 is not set
+CONFIG_USE_CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+CONFIG_USE_AARCH64_L1_TO_AARCH32=y
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+# CONFIG_TARGET_D2000 is not set
+# CONFIG_TARGET_E2000Q is not set
+CONFIG_TARGET_E2000D=y
+# CONFIG_TARGET_E2000S is not set
+CONFIG_TARGET_E2000=y
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+CONFIG_USE_SPI=y
+CONFIG_USE_FSPIM=y
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+# CONFIG_USE_CAN is not set
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+# CONFIG_LOG_DEBUG is not set
+# CONFIG_LOG_INFO is not set
+# CONFIG_LOG_WARN is not set
+CONFIG_LOG_ERROR=y
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+CONFIG_LOG_EXTRA_INFO=y
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+CONFIG_AARCH32_RAM_LD=y
+# CONFIG_AARCH64_RAM_LD is not set
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_SVC_STACK_SIZE=0x1000
+CONFIG_SYS_STACK_SIZE=0x1000
+CONFIG_IRQ_STACK_SIZE=0x1000
+CONFIG_ABORT_STACK_SIZE=0x1000
+CONFIG_FIQ_STACK_SIZE=0x1000
+CONFIG_UNDEF_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+CONFIG_FREERTOS_USE_FSPIM=y
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+CONFIG_USE_TLSF=y
+# CONFIG_USE_SDMMC_CMD is not set
+CONFIG_USE_CHERRY_USB=y
+
+#
+# CherryUSB Configuration
+#
+CONFIG_CHERRY_USB_PORT_XHCI=y
+# CONFIG_CHERRY_USB_PORT_PHYTIUM_OTG is not set
+CONFIG_CHERRYUSB_HOST=y
+# CONFIG_CHERRYUSB_DEVICE is not set
+CONFIG_CHERRY_USB_HOST_HUB=y
+CONFIG_CHERRY_USB_HOST_MSC=y
+CONFIG_CHERRY_USB_HOST_HID=y
+CONFIG_CHERRY_USB_HOST_VEDIO=y
+CONFIG_CHERRY_USB_HOST_CDC=y
+CONFIG_CHERRY_USB_HOST_RNDIS_WIRELESS=y
+# end of CherryUSB Configuration
+# end of FreeRTOS Setting
diff --git a/example/peripheral/usb/cherryusb_host/configs/e2000d_aarch64_eg_configs b/example/peripheral/usb/cherryusb_host/configs/e2000d_aarch64_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..5ee6831fd2f1f39daf502e29b45617c5a60b20fa
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/configs/e2000d_aarch64_eg_configs
@@ -0,0 +1,225 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="e2000d_freertos_a64"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+# CONFIG_TARGET_ARMV8_AARCH32 is not set
+CONFIG_TARGET_ARMV8_AARCH64=y
+CONFIG_USE_CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+# CONFIG_MMU_DEBUG_PRINTS is not set
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+# CONFIG_TARGET_D2000 is not set
+# CONFIG_TARGET_E2000Q is not set
+CONFIG_TARGET_E2000D=y
+# CONFIG_TARGET_E2000S is not set
+CONFIG_TARGET_E2000=y
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+CONFIG_USE_SPI=y
+CONFIG_USE_FSPIM=y
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+# CONFIG_USE_CAN is not set
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+CONFIG_LOG_DEBUG=y
+# CONFIG_LOG_INFO is not set
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+CONFIG_LOG_EXTRA_INFO=y
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+# CONFIG_AARCH32_RAM_LD is not set
+CONFIG_AARCH64_RAM_LD=y
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_STACK_SIZE=0x100000
+CONFIG_FPU_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+CONFIG_FREERTOS_USE_FSPIM=y
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+CONFIG_USE_TLSF=y
+# CONFIG_USE_SDMMC_CMD is not set
+CONFIG_USE_CHERRY_USB=y
+
+#
+# CherryUSB Configuration
+#
+CONFIG_CHERRY_USB_PORT_XHCI=y
+# CONFIG_CHERRY_USB_PORT_PHYTIUM_OTG is not set
+CONFIG_CHERRYUSB_HOST=y
+# CONFIG_CHERRYUSB_DEVICE is not set
+CONFIG_CHERRY_USB_HOST_HUB=y
+CONFIG_CHERRY_USB_HOST_MSC=y
+CONFIG_CHERRY_USB_HOST_HID=y
+CONFIG_CHERRY_USB_HOST_VEDIO=y
+CONFIG_CHERRY_USB_HOST_CDC=y
+CONFIG_CHERRY_USB_HOST_RNDIS_WIRELESS=y
+# end of CherryUSB Configuration
+# end of FreeRTOS Setting
diff --git a/example/peripheral/usb/cherryusb_host/configs/e2000s_aarch32_eg_configs b/example/peripheral/usb/cherryusb_host/configs/e2000s_aarch32_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..7007137b04270e3bb37a8ec9859ec087ee3c6c41
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/configs/e2000s_aarch32_eg_configs
@@ -0,0 +1,229 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="e2000s_freertos_a32"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+CONFIG_TARGET_ARMV8_AARCH32=y
+# CONFIG_TARGET_ARMV8_AARCH64 is not set
+CONFIG_USE_CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+CONFIG_USE_AARCH64_L1_TO_AARCH32=y
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+# CONFIG_TARGET_D2000 is not set
+# CONFIG_TARGET_E2000Q is not set
+# CONFIG_TARGET_E2000D=y
+CONFIG_TARGET_E2000S=y
+CONFIG_TARGET_E2000=y
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+CONFIG_USE_SPI=y
+CONFIG_USE_FSPIM=y
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+# CONFIG_USE_CAN is not set
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+# CONFIG_LOG_DEBUG is not set
+# CONFIG_LOG_INFO is not set
+# CONFIG_LOG_WARN is not set
+CONFIG_LOG_ERROR=y
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+CONFIG_LOG_EXTRA_INFO=y
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+CONFIG_AARCH32_RAM_LD=y
+# CONFIG_AARCH64_RAM_LD is not set
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_SVC_STACK_SIZE=0x1000
+CONFIG_SYS_STACK_SIZE=0x1000
+CONFIG_IRQ_STACK_SIZE=0x1000
+CONFIG_ABORT_STACK_SIZE=0x1000
+CONFIG_FIQ_STACK_SIZE=0x1000
+CONFIG_UNDEF_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+CONFIG_FREERTOS_USE_FSPIM=y
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+CONFIG_USE_TLSF=y
+# CONFIG_USE_SDMMC_CMD is not set
+CONFIG_USE_CHERRY_USB=y
+
+#
+# CherryUSB Configuration
+#
+CONFIG_CHERRY_USB_PORT_XHCI=y
+# CONFIG_CHERRY_USB_PORT_PHYTIUM_OTG is not set
+CONFIG_CHERRYUSB_HOST=y
+# CONFIG_CHERRYUSB_DEVICE is not set
+CONFIG_CHERRY_USB_HOST_HUB=y
+CONFIG_CHERRY_USB_HOST_MSC=y
+CONFIG_CHERRY_USB_HOST_HID=y
+CONFIG_CHERRY_USB_HOST_VEDIO=y
+CONFIG_CHERRY_USB_HOST_CDC=y
+CONFIG_CHERRY_USB_HOST_RNDIS_WIRELESS=y
+# end of CherryUSB Configuration
+# end of FreeRTOS Setting
diff --git a/example/peripheral/usb/cherryusb_host/configs/e2000s_aarch64_eg_configs b/example/peripheral/usb/cherryusb_host/configs/e2000s_aarch64_eg_configs
new file mode 100644
index 0000000000000000000000000000000000000000..c650a324140e62c4385452dc152f62a812fb7ca8
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/configs/e2000s_aarch64_eg_configs
@@ -0,0 +1,225 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="e2000s_freertos_a64"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+# CONFIG_TARGET_ARMV8_AARCH32 is not set
+CONFIG_TARGET_ARMV8_AARCH64=y
+CONFIG_USE_CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+# CONFIG_MMU_DEBUG_PRINTS is not set
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+# CONFIG_TARGET_D2000 is not set
+# CONFIG_TARGET_E2000Q is not set
+# CONFIG_TARGET_E2000D=y
+CONFIG_TARGET_E2000S=y
+CONFIG_TARGET_E2000=y
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+CONFIG_USE_SPI=y
+CONFIG_USE_FSPIM=y
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+# CONFIG_USE_CAN is not set
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+CONFIG_LOG_DEBUG=y
+# CONFIG_LOG_INFO is not set
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+CONFIG_LOG_EXTRA_INFO=y
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+# CONFIG_AARCH32_RAM_LD is not set
+CONFIG_AARCH64_RAM_LD=y
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_STACK_SIZE=0x100000
+CONFIG_FPU_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+CONFIG_FREERTOS_USE_FSPIM=y
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+CONFIG_USE_TLSF=y
+# CONFIG_USE_SDMMC_CMD is not set
+CONFIG_USE_CHERRY_USB=y
+
+#
+# CherryUSB Configuration
+#
+CONFIG_CHERRY_USB_PORT_XHCI=y
+# CONFIG_CHERRY_USB_PORT_PHYTIUM_OTG is not set
+CONFIG_CHERRYUSB_HOST=y
+# CONFIG_CHERRYUSB_DEVICE is not set
+CONFIG_CHERRY_USB_HOST_HUB=y
+CONFIG_CHERRY_USB_HOST_MSC=y
+CONFIG_CHERRY_USB_HOST_HID=y
+CONFIG_CHERRY_USB_HOST_VEDIO=y
+CONFIG_CHERRY_USB_HOST_CDC=y
+CONFIG_CHERRY_USB_HOST_RNDIS_WIRELESS=y
+# end of CherryUSB Configuration
+# end of FreeRTOS Setting
diff --git a/example/peripheral/usb/cherryusb_host/figs/usb_disk_connection.png b/example/peripheral/usb/cherryusb_host/figs/usb_disk_connection.png
new file mode 100644
index 0000000000000000000000000000000000000000..dff4db139fff3cfd224f470a062b7d362118f40a
Binary files /dev/null and b/example/peripheral/usb/cherryusb_host/figs/usb_disk_connection.png differ
diff --git a/example/peripheral/usb/cherryusb_host/figs/usb_disk_init.png b/example/peripheral/usb/cherryusb_host/figs/usb_disk_init.png
new file mode 100644
index 0000000000000000000000000000000000000000..385cd0086d6f4f5c88d762e48afeb32f5c256440
Binary files /dev/null and b/example/peripheral/usb/cherryusb_host/figs/usb_disk_init.png differ
diff --git a/example/peripheral/usb/cherryusb_host/figs/usb_keyboard_connect.jpg b/example/peripheral/usb/cherryusb_host/figs/usb_keyboard_connect.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d5a0aaec61643aab9a6c1936fdde410f7b0dc8ff
Binary files /dev/null and b/example/peripheral/usb/cherryusb_host/figs/usb_keyboard_connect.jpg differ
diff --git a/example/peripheral/usb/cherryusb_host/figs/usb_keyboard_input.png b/example/peripheral/usb/cherryusb_host/figs/usb_keyboard_input.png
new file mode 100644
index 0000000000000000000000000000000000000000..e67d2daaba890bc459698a1e75f1e0f7d600ce89
Binary files /dev/null and b/example/peripheral/usb/cherryusb_host/figs/usb_keyboard_input.png differ
diff --git a/example/peripheral/usb/cherryusb_host/figs/usb_mouse_connect.jpg b/example/peripheral/usb/cherryusb_host/figs/usb_mouse_connect.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..4d960f035587a5541d4f72bffe162a4e631a3ac6
Binary files /dev/null and b/example/peripheral/usb/cherryusb_host/figs/usb_mouse_connect.jpg differ
diff --git a/example/peripheral/usb/cherryusb_host/figs/usb_mouse_input.png b/example/peripheral/usb/cherryusb_host/figs/usb_mouse_input.png
new file mode 100644
index 0000000000000000000000000000000000000000..c3a6582103e10c5fd3200f448d6dfeb6c7dd3369
Binary files /dev/null and b/example/peripheral/usb/cherryusb_host/figs/usb_mouse_input.png differ
diff --git a/example/peripheral/usb/cherryusb_host/inc/usb_host.h b/example/peripheral/usb/cherryusb_host/inc/usb_host.h
new file mode 100644
index 0000000000000000000000000000000000000000..48edc36a41ce41e69819a6f08d5aeaf082189e6b
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/inc/usb_host.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: usb_host.h
+ * Date: 2022-07-19 09:26:25
+ * LastEditTime: 2022-07-19 09:26:25
+ * Description: This files is for
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ */
+#ifndef EXAMPLE_USB_HOST_H
+#define EXAMPLE_USB_HOST_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/***************************** Include Files *********************************/
+
+/************************** Constant Definitions *****************************/
+
+/************************** Variable Definitions *****************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+BaseType_t FFreeRTOSInitUsb(void);
+BaseType_t FFreeRTOSRunUsbDisk(void);
+BaseType_t FFreeRTOSRunUsbInput(void);
+BaseType_t FFreeRTOSListUsbDev(int argc, char *argv[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/example/peripheral/usb/cherryusb_host/main.c b/example/peripheral/usb/cherryusb_host/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..c188a8dd866665419f31156fe4c347fa36d24c9d
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/main.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: main.c
+ * Date: 2022-06-17 08:17:59
+ * LastEditTime: 2022-06-17 08:17:59
+ * Description: This file is for
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ */
+
+#include "shell.h"
+#include "shell_port.h"
+#include
+
+int main(void)
+{
+ BaseType_t ret;
+
+ ret = LSUserShellTask();
+ if(ret != pdPASS)
+ goto FAIL_EXIT;
+
+ vTaskStartScheduler(); /* 启动任务,开启调度 */
+ while (1); /* 正常不会执行到这里 */
+
+FAIL_EXIT:
+ printf("failed 0x%x \r\n", ret);
+ return 0;
+}
diff --git a/example/peripheral/usb/cherryusb_host/makefile b/example/peripheral/usb/cherryusb_host/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d56227392212980c329dde7ebb09f8ec2d601317
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/makefile
@@ -0,0 +1,29 @@
+export PROJECT_DIR ?= $(shell pwd)
+
+export USR_SRC_DIR = $(PROJECT_DIR) \
+ ./src
+export USR_INC_DIR = $(PROJECT_DIR) \
+ ./inc
+
+# 用户定义的编译目标文件上传路径
+ifeq ($(OS),Windows_NT)
+ USR_BOOT_DIR ?= $(subst \,/, $(PHYTIUM_DEV_PATH))/tftp
+else
+ USR_BOOT_DIR ?= /mnt/d/tftboot
+endif
+
+
+# 设置启动镜像名
+BOOT_IMG_NAME ?= freertos
+
+# 指定编译freertos项目使用的makefile
+include $(FREERTOS_SDK_ROOT)/make/build_freertos.mk
+
+# 完成编译
+boot:
+ make -j
+ @cp ./$(CONFIG_TARGET_NAME).elf $(USR_BOOT_DIR)/$(BOOT_IMG_NAME).elf
+ @cp ./$(CONFIG_TARGET_NAME).bin $(USR_BOOT_DIR)/$(BOOT_IMG_NAME).bin
+ @ls -l $(USR_BOOT_DIR)/$(BOOT_IMG_NAME).*
+
+
diff --git a/example/peripheral/usb/cherryusb_host/sdkconfig b/example/peripheral/usb/cherryusb_host/sdkconfig
new file mode 100644
index 0000000000000000000000000000000000000000..c650a324140e62c4385452dc152f62a812fb7ca8
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/sdkconfig
@@ -0,0 +1,225 @@
+
+#
+# Freertos Configuration
+#
+CONFIG_TARGET_NAME="e2000s_freertos_a64"
+# end of Freertos Configuration
+
+#
+# Standalone Setting
+#
+CONFIG_USE_FREERTOS=y
+
+#
+# Arch Configuration
+#
+# CONFIG_TARGET_ARMV8_AARCH32 is not set
+CONFIG_TARGET_ARMV8_AARCH64=y
+CONFIG_USE_CACHE=y
+CONFIG_USE_MMU=y
+CONFIG_USE_SYS_TICK=y
+# CONFIG_MMU_DEBUG_PRINTS is not set
+# end of Arch Configuration
+
+#
+# Board Configuration
+#
+# CONFIG_TARGET_F2000_4 is not set
+# CONFIG_TARGET_D2000 is not set
+# CONFIG_TARGET_E2000Q is not set
+# CONFIG_TARGET_E2000D=y
+CONFIG_TARGET_E2000S=y
+CONFIG_TARGET_E2000=y
+CONFIG_DEFAULT_DEBUG_PRINT_UART1=y
+# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set
+# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set
+# end of Board Configuration
+
+#
+# Components Configuration
+#
+CONFIG_USE_SPI=y
+CONFIG_USE_FSPIM=y
+# CONFIG_USE_QSPI is not set
+CONFIG_USE_GIC=y
+CONFIG_ENABLE_GICV3=y
+CONFIG_USE_SERIAL=y
+
+#
+# Usart Configuration
+#
+CONFIG_ENABLE_Pl011_UART=y
+# end of Usart Configuration
+
+# CONFIG_USE_GPIO is not set
+# CONFIG_USE_ETH is not set
+# CONFIG_USE_CAN is not set
+# CONFIG_USE_I2C is not set
+# CONFIG_USE_TIMER is not set
+# CONFIG_USE_MIO is not set
+# CONFIG_USE_SDMMC is not set
+# CONFIG_USE_PCIE is not set
+# CONFIG_USE_WDT is not set
+# CONFIG_USE_DMA is not set
+# CONFIG_USE_NAND is not set
+# CONFIG_USE_RTC is not set
+# CONFIG_USE_SATA is not set
+# CONFIG_USE_USB is not set
+# CONFIG_USE_ADC is not set
+# CONFIG_USE_PWM is not set
+# CONFIG_USE_IPC is not set
+# end of Components Configuration
+
+CONFIG_USE_NEW_LIBC=y
+# end of Standalone Setting
+
+#
+# Building Option
+#
+# CONFIG_LOG_VERBOS is not set
+CONFIG_LOG_DEBUG=y
+# CONFIG_LOG_INFO is not set
+# CONFIG_LOG_WARN is not set
+# CONFIG_LOG_ERROR is not set
+# CONFIG_LOG_NONE is not set
+CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y
+CONFIG_INTERRUPT_ROLE_MASTER=y
+# CONFIG_INTERRUPT_ROLE_SLAVE is not set
+CONFIG_LOG_EXTRA_INFO=y
+# CONFIG_BOOTUP_DEBUG_PRINTS is not set
+
+#
+# Linker Options
+#
+# CONFIG_AARCH32_RAM_LD is not set
+CONFIG_AARCH64_RAM_LD=y
+# CONFIG_USER_DEFINED_LD is not set
+CONFIG_LINK_SCRIPT_ROM=y
+CONFIG_ROM_START_UP_ADDR=0x80100000
+CONFIG_ROM_SIZE_MB=1
+CONFIG_LINK_SCRIPT_RAM=y
+CONFIG_RAM_START_UP_ADDR=0x81000000
+CONFIG_RAM_SIZE_MB=64
+CONFIG_HEAP_SIZE=1
+CONFIG_STACK_SIZE=0x100000
+CONFIG_FPU_STACK_SIZE=0x1000
+# end of Linker Options
+
+#
+# Compiler Options
+#
+CONFIG_OUTPUT_BINARY=y
+# end of Compiler Options
+# end of Building Option
+
+#
+# Component Configuration
+#
+
+#
+# Freertos Uart Drivers
+#
+CONFIG_FREERTOS_USE_UART=y
+# end of Freertos Uart Drivers
+
+#
+# Freertos Pwm Drivers
+#
+# CONFIG_FREERTOS_USE_PWM is not set
+# end of Freertos Pwm Drivers
+
+#
+# Freertos Qspi Drivers
+#
+# CONFIG_FREERTOS_USE_QSPI is not set
+# end of Freertos Qspi Drivers
+
+#
+# Freertos Wdt Drivers
+#
+# CONFIG_FREERTOS_USE_WDT is not set
+# end of Freertos Wdt Drivers
+
+#
+# Freertos Eth Drivers
+#
+# CONFIG_FREERTOS_USE_XMAC is not set
+# end of Freertos Eth Drivers
+
+#
+# Freertos Gpio Drivers
+#
+# CONFIG_FREERTOS_USE_GPIO is not set
+# end of Freertos Gpio Drivers
+
+#
+# Freertos Spim Drivers
+#
+CONFIG_FREERTOS_USE_FSPIM=y
+# end of Freertos Spim Drivers
+
+#
+# Freertos DMA Drivers
+#
+# CONFIG_FREERTOS_USE_FDDMA is not set
+# CONFIG_FREERTOS_USE_FGDMA is not set
+# end of Freertos DMA Drivers
+
+#
+# Freertos MMC Drivers
+#
+# CONFIG_FREERTOS_USE_FSDIO is not set
+# end of Freertos MMC Drivers
+
+#
+# Freertos Adc Drivers
+#
+# CONFIG_FREERTOS_USE_ADC is not set
+# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
+# end of Component Configuration
+
+#
+# FreeRTOS Setting
+#
+# CONFIG_USE_LWIP is not set
+CONFIG_USE_BACKTRACE=y
+# CONFIG_USE_FATFS is not set
+# CONFIG_USE_SFUD is not set
+# CONFIG_USE_SPIFFS is not set
+# CONFIG_USE_AMP is not set
+CONFIG_USE_LETTER_SHELL=y
+
+#
+# Letter Shell Configuration
+#
+CONFIG_LS_PL011_UART=y
+CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set
+# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set
+# end of Letter Shell Configuration
+
+CONFIG_USE_TLSF=y
+# CONFIG_USE_SDMMC_CMD is not set
+CONFIG_USE_CHERRY_USB=y
+
+#
+# CherryUSB Configuration
+#
+CONFIG_CHERRY_USB_PORT_XHCI=y
+# CONFIG_CHERRY_USB_PORT_PHYTIUM_OTG is not set
+CONFIG_CHERRYUSB_HOST=y
+# CONFIG_CHERRYUSB_DEVICE is not set
+CONFIG_CHERRY_USB_HOST_HUB=y
+CONFIG_CHERRY_USB_HOST_MSC=y
+CONFIG_CHERRY_USB_HOST_HID=y
+CONFIG_CHERRY_USB_HOST_VEDIO=y
+CONFIG_CHERRY_USB_HOST_CDC=y
+CONFIG_CHERRY_USB_HOST_RNDIS_WIRELESS=y
+# end of CherryUSB Configuration
+# end of FreeRTOS Setting
diff --git a/example/peripheral/usb/cherryusb_host/sdkconfig.h b/example/peripheral/usb/cherryusb_host/sdkconfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..1493aa9b631588b6184d5e090af5cc5ef7356a73
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/sdkconfig.h
@@ -0,0 +1,201 @@
+#ifndef SDK_CONFIG_H__
+#define SDK_CONFIG_H__
+
+/* Freertos Configuration */
+
+#define CONFIG_TARGET_NAME "e2000s_freertos_a64"
+/* end of Freertos Configuration */
+
+/* Standalone Setting */
+
+#define CONFIG_USE_FREERTOS
+
+/* Arch Configuration */
+
+/* CONFIG_TARGET_ARMV8_AARCH32 is not set */
+#define CONFIG_TARGET_ARMV8_AARCH64
+#define CONFIG_USE_CACHE
+#define CONFIG_USE_MMU
+#define CONFIG_USE_SYS_TICK
+/* CONFIG_MMU_DEBUG_PRINTS is not set */
+/* end of Arch Configuration */
+
+/* Board Configuration */
+
+/* CONFIG_TARGET_F2000_4 is not set */
+/* CONFIG_TARGET_D2000 is not set */
+/* CONFIG_TARGET_E2000Q is not set */
+/* CONFIG_TARGET_E2000D=y */
+#define CONFIG_TARGET_E2000S
+#define CONFIG_TARGET_E2000
+#define CONFIG_DEFAULT_DEBUG_PRINT_UART1
+/* CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set */
+/* CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set */
+/* end of Board Configuration */
+
+/* Components Configuration */
+
+#define CONFIG_USE_SPI
+#define CONFIG_USE_FSPIM
+/* CONFIG_USE_QSPI is not set */
+#define CONFIG_USE_GIC
+#define CONFIG_ENABLE_GICV3
+#define CONFIG_USE_SERIAL
+
+/* Usart Configuration */
+
+#define CONFIG_ENABLE_Pl011_UART
+/* end of Usart Configuration */
+/* CONFIG_USE_GPIO is not set */
+/* CONFIG_USE_ETH is not set */
+/* CONFIG_USE_CAN is not set */
+/* CONFIG_USE_I2C is not set */
+/* CONFIG_USE_TIMER is not set */
+/* CONFIG_USE_MIO is not set */
+/* CONFIG_USE_SDMMC is not set */
+/* CONFIG_USE_PCIE is not set */
+/* CONFIG_USE_WDT is not set */
+/* CONFIG_USE_DMA is not set */
+/* CONFIG_USE_NAND is not set */
+/* CONFIG_USE_RTC is not set */
+/* CONFIG_USE_SATA is not set */
+/* CONFIG_USE_USB is not set */
+/* CONFIG_USE_ADC is not set */
+/* CONFIG_USE_PWM is not set */
+/* CONFIG_USE_IPC is not set */
+/* end of Components Configuration */
+#define CONFIG_USE_NEW_LIBC
+/* end of Standalone Setting */
+
+/* Building Option */
+
+/* CONFIG_LOG_VERBOS is not set */
+#define CONFIG_LOG_DEBUG
+/* CONFIG_LOG_INFO is not set */
+/* CONFIG_LOG_WARN is not set */
+/* CONFIG_LOG_ERROR is not set */
+/* CONFIG_LOG_NONE is not set */
+#define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG
+#define CONFIG_INTERRUPT_ROLE_MASTER
+/* CONFIG_INTERRUPT_ROLE_SLAVE is not set */
+#define CONFIG_LOG_EXTRA_INFO
+/* CONFIG_BOOTUP_DEBUG_PRINTS is not set */
+
+/* Linker Options */
+
+/* CONFIG_AARCH32_RAM_LD is not set */
+#define CONFIG_AARCH64_RAM_LD
+/* CONFIG_USER_DEFINED_LD is not set */
+#define CONFIG_LINK_SCRIPT_ROM
+#define CONFIG_ROM_START_UP_ADDR 0x80100000
+#define CONFIG_ROM_SIZE_MB 1
+#define CONFIG_LINK_SCRIPT_RAM
+#define CONFIG_RAM_START_UP_ADDR 0x81000000
+#define CONFIG_RAM_SIZE_MB 64
+#define CONFIG_HEAP_SIZE 1
+#define CONFIG_STACK_SIZE 0x100000
+#define CONFIG_FPU_STACK_SIZE 0x1000
+/* end of Linker Options */
+
+/* Compiler Options */
+
+#define CONFIG_OUTPUT_BINARY
+/* end of Compiler Options */
+/* end of Building Option */
+
+/* Component Configuration */
+
+/* Freertos Uart Drivers */
+
+#define CONFIG_FREERTOS_USE_UART
+/* end of Freertos Uart Drivers */
+
+/* Freertos Pwm Drivers */
+
+/* CONFIG_FREERTOS_USE_PWM is not set */
+/* end of Freertos Pwm Drivers */
+
+/* Freertos Qspi Drivers */
+
+/* CONFIG_FREERTOS_USE_QSPI is not set */
+/* end of Freertos Qspi Drivers */
+
+/* Freertos Wdt Drivers */
+
+/* CONFIG_FREERTOS_USE_WDT is not set */
+/* end of Freertos Wdt Drivers */
+
+/* Freertos Eth Drivers */
+
+/* CONFIG_FREERTOS_USE_XMAC is not set */
+/* end of Freertos Eth Drivers */
+
+/* Freertos Gpio Drivers */
+
+/* CONFIG_FREERTOS_USE_GPIO is not set */
+/* end of Freertos Gpio Drivers */
+
+/* Freertos Spim Drivers */
+
+#define CONFIG_FREERTOS_USE_FSPIM
+/* end of Freertos Spim Drivers */
+
+/* Freertos DMA Drivers */
+
+/* CONFIG_FREERTOS_USE_FDDMA is not set */
+/* CONFIG_FREERTOS_USE_FGDMA is not set */
+/* end of Freertos DMA Drivers */
+
+/* Freertos MMC Drivers */
+
+/* CONFIG_FREERTOS_USE_FSDIO is not set */
+/* end of Freertos MMC Drivers */
+
+/* Freertos Adc Drivers */
+
+/* CONFIG_FREERTOS_USE_ADC is not set */
+/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
+/* end of Component Configuration */
+
+/* FreeRTOS Setting */
+
+/* CONFIG_USE_LWIP is not set */
+#define CONFIG_USE_BACKTRACE
+/* CONFIG_USE_FATFS is not set */
+/* CONFIG_USE_SFUD is not set */
+/* CONFIG_USE_SPIFFS is not set */
+/* CONFIG_USE_AMP is not set */
+#define CONFIG_USE_LETTER_SHELL
+
+/* Letter Shell Configuration */
+
+#define CONFIG_LS_PL011_UART
+#define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1
+/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */
+/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */
+/* end of Letter Shell Configuration */
+#define CONFIG_USE_TLSF
+/* CONFIG_USE_SDMMC_CMD is not set */
+#define CONFIG_USE_CHERRY_USB
+
+/* CherryUSB Configuration */
+
+#define CONFIG_CHERRY_USB_PORT_XHCI
+/* CONFIG_CHERRY_USB_PORT_PHYTIUM_OTG is not set */
+#define CONFIG_CHERRYUSB_HOST
+/* CONFIG_CHERRYUSB_DEVICE is not set */
+#define CONFIG_CHERRY_USB_HOST_HUB
+#define CONFIG_CHERRY_USB_HOST_MSC
+#define CONFIG_CHERRY_USB_HOST_HID
+#define CONFIG_CHERRY_USB_HOST_VEDIO
+#define CONFIG_CHERRY_USB_HOST_CDC
+#define CONFIG_CHERRY_USB_HOST_RNDIS_WIRELESS
+/* end of CherryUSB Configuration */
+/* end of FreeRTOS Setting */
+
+#endif
diff --git a/example/peripheral/usb/cherryusb_host/src/cmd_usb.c b/example/peripheral/usb/cherryusb_host/src/cmd_usb.c
new file mode 100644
index 0000000000000000000000000000000000000000..f0faed086b00ce72327e75c45084a194d1852b24
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/src/cmd_usb.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: cmd_usb.c
+ * Date: 2022-09-19 14:34:44
+ * LastEditTime: 2022-09-19 14:34:45
+ * Description: This files is for
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ * 1.0 zhugengyu 2022/9/20 init commit
+ */
+#include
+#include
+#include "strto.h"
+#include "sdkconfig.h"
+
+#include "FreeRTOS.h"
+
+#include "../src/shell.h"
+#include "usb_host.h"
+
+static int USBCmdEntry(int argc, char *argv[])
+{
+ int ret = 0;
+
+ if (!strcmp(argv[1], "init"))
+ {
+ ret = FFreeRTOSInitUsb();
+ }
+ else if (!strcmp(argv[1], "disk"))
+ {
+ ret = FFreeRTOSRunUsbDisk();
+ }
+ else if (!strcmp(argv[1], "input"))
+ {
+ ret = FFreeRTOSRunUsbInput();
+ }
+ else if (!strcmp(argv[1], "lsusb"))
+ {
+ ret = FFreeRTOSListUsbDev(argc - 1, &argv[1]);
+ }
+
+ return ret;
+}
+SHELL_EXPORT_CMD(SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), usb, USBCmdEntry, test freertos usb driver);
\ No newline at end of file
diff --git a/example/peripheral/usb/cherryusb_host/src/usb_disk.c b/example/peripheral/usb/cherryusb_host/src/usb_disk.c
new file mode 100644
index 0000000000000000000000000000000000000000..6a54d8d9f98bbdd20e758c476e19c85b9c6b7c94
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/src/usb_disk.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: usb_disk.c
+ * Date: 2022-09-23 08:24:09
+ * LastEditTime: 2022-09-23 08:24:10
+ * Description: This files is for
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ */
+/***************************** Include Files *********************************/
+#include
+#include
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#include "ft_assert.h"
+#include "interrupt.h"
+#include "cpu_info.h"
+#include "ft_debug.h"
+
+#include "usbh_core.h"
+#include "usbh_msc.h"
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/************************** Variable Definitions *****************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+#define FUSB_DEBUG_TAG "USB-DISK"
+#define FUSB_ERROR(format, ...) FT_DEBUG_PRINT_E(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FUSB_WARN(format, ...) FT_DEBUG_PRINT_W(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FUSB_INFO(format, ...) FT_DEBUG_PRINT_I(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FUSB_DEBUG(format, ...) FT_DEBUG_PRINT_D(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+
+/************************** Function Prototypes ******************************/
+
+
+/*****************************************************************************/
+static void UsbMscTask(void * args)
+{
+ int ret;
+ struct usbh_msc *msc_class;
+ static uint8_t rd_table[512] = {0};
+ static uint8_t wr_table[512] = {0};
+ u32 loop = 0;
+
+ while (TRUE)
+ {
+ msc_class = (struct usbh_msc *)usbh_find_class_instance("/dev/sda");
+ if (msc_class == NULL)
+ {
+ USB_LOG_RAW("do not find /dev/sda\r\n");
+ goto err_exit;
+ }
+
+ /* write partition table */
+ memcpy(wr_table, rd_table, sizeof(rd_table));
+ for (uint32_t i = 0; i < 512; i++)
+ {
+ wr_table[i] ^= 0xfffff;
+ }
+
+ ret = usbh_msc_scsi_write10(msc_class, 0, wr_table, 1);
+ if (ret < 0)
+ {
+ USB_LOG_ERR("scsi_write10 error,ret:%d\r\n", ret);
+ goto err_exit;
+ }
+
+ /* get the partition table */
+ ret = usbh_msc_scsi_read10(msc_class, 0, rd_table, 1);
+ if (ret < 0)
+ {
+ USB_LOG_RAW("scsi_read10 error,ret:%d\r\n", ret);
+ goto err_exit;
+ }
+
+ /* check if read table == write table */
+ if (0 != memcmp(wr_table, rd_table, sizeof(rd_table)))
+ {
+ USB_LOG_ERR("check read and write failed !!!\r\n");
+ goto err_exit;
+ }
+ else
+ {
+ printf("[%d] disk read and write successful\r\n", loop++);
+ }
+
+ vTaskDelay(10);
+ }
+
+err_exit:
+ vTaskDelete(NULL);
+}
+
+BaseType_t FFreeRTOSRunUsbDisk(void)
+{
+ BaseType_t ret = pdPASS;
+
+ taskENTER_CRITICAL(); /* no schedule when create task */
+
+ ret = xTaskCreate((TaskFunction_t )UsbMscTask,
+ (const char* )"UsbMscTask",
+ (uint16_t )2048,
+ NULL,
+ (UBaseType_t )configMAX_PRIORITIES - 1,
+ NULL);
+ FASSERT_MSG(pdPASS == ret, "create task failed");
+
+ taskEXIT_CRITICAL(); /* allow schedule since task created */
+
+ return ret;
+}
diff --git a/example/peripheral/usb/cherryusb_host/src/usb_host.c b/example/peripheral/usb/cherryusb_host/src/usb_host.c
new file mode 100644
index 0000000000000000000000000000000000000000..483322fdd4209e79ece6619dc4687e43255354fe
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/src/usb_host.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: usb_host.c
+ * Date: 2022-07-22 13:57:42
+ * LastEditTime: 2022-07-22 13:57:43
+ * Description: This files is for
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ * 1.0 zhugengyu 2022/9/20 init commit
+ */
+/***************************** Include Files *********************************/
+#include
+#include
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#include "ft_assert.h"
+#include "interrupt.h"
+#include "cpu_info.h"
+#include "ft_debug.h"
+#include "cache.h"
+#include "fmemory_pool.h"
+
+#include "usbh_core.h"
+/************************** Constant Definitions *****************************/
+#define FUSB_MEMP_TOTAL_SIZE SZ_1M
+
+/**************************** Type Definitions *******************************/
+
+/************************** Variable Definitions *****************************/
+static FMemp memp;
+static u8 memp_buf[FUSB_MEMP_TOTAL_SIZE];
+
+/***************** Macros (Inline Functions) Definitions *********************/
+#define FUSB_DEBUG_TAG "USB-HC"
+#define FUSB_ERROR(format, ...) FT_DEBUG_PRINT_E(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FUSB_WARN(format, ...) FT_DEBUG_PRINT_W(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FUSB_INFO(format, ...) FT_DEBUG_PRINT_I(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FUSB_DEBUG(format, ...) FT_DEBUG_PRINT_D(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+
+/************************** Function Prototypes ******************************/
+extern void USBH_IRQHandler(void);
+
+/*****************************************************************************/
+static void UsbHcInterrruptHandler(s32 vector, void *param)
+{
+ USBH_IRQHandler();
+}
+
+static void UsbHcSetupInterrupt(void)
+{
+ u32 cpu_id;
+ u32 irq_num = FUSB3_0_IRQ_NUM;
+ u32 irq_priority = 13U;
+
+ GetCpuId(&cpu_id);
+ InterruptSetTargetCpus(irq_num, cpu_id);
+
+ InterruptSetPriority(irq_num, irq_priority);
+
+ /* register intr callback */
+ InterruptInstall(irq_num,
+ UsbHcInterrruptHandler,
+ NULL,
+ NULL);
+
+ /* enable irq */
+ InterruptUmask(irq_num);
+}
+
+void UsbHcSetupMemp(void)
+{
+ if (FT_COMPONENT_IS_READY != memp.is_ready)
+ {
+ USB_ASSERT(FT_SUCCESS == FMempInit(&memp, &memp_buf[0], &memp_buf[0] + FUSB_MEMP_TOTAL_SIZE));
+ }
+}
+
+/* implement cherryusb weak functions */
+void usb_hc_low_level_init(void)
+{
+ UsbHcSetupMemp();
+ UsbHcSetupInterrupt();
+}
+
+unsigned long usb_hc_get_register_base(void)
+{
+ return FUSB3_0_BASE_ADDR + FUSB3_XHCI_OFFSET;
+}
+
+void *usb_hc_malloc(size_t size)
+{
+ return usb_hc_malloc_align(sizeof(void *), size);
+}
+
+void *usb_hc_malloc_align(size_t align, size_t size)
+{
+ void *result = FMempMallocAlign(&memp, size, align);
+
+ if (result)
+ memset(result, 0U, size);
+
+ return result;
+}
+
+void usb_hc_free(void *ptr)
+{
+ if (NULL != ptr)
+ FMempFree(&memp, ptr);
+}
+
+void usb_assert(const char *filename, int linenum)
+{
+ FAssert(filename, linenum, 0xff);
+}
+
+void usb_hc_dcache_invalidate(void *addr, unsigned long len)
+{
+ FCacheDCacheInvalidateRange((uintptr)addr, len);
+}
+/*****************************************/
+
+static void UsbInitTask(void * args)
+{
+ if (0 == usbh_initialize())
+ {
+ printf("init cherryusb host success !!! input 'usb lsusb -t' to see devices\r\n");
+ }
+ else
+ {
+ FUSB_ERROR("init cherryusb host failed !!!");
+ }
+
+ vTaskDelete(NULL);
+}
+
+BaseType_t FFreeRTOSInitUsb(void)
+{
+ BaseType_t ret = pdPASS;
+
+ taskENTER_CRITICAL(); /* no schedule when create task */
+
+ ret = xTaskCreate((TaskFunction_t )UsbInitTask,
+ (const char* )"UsbInitTask",
+ (uint16_t )2048,
+ NULL,
+ (UBaseType_t )configMAX_PRIORITIES - 1,
+ NULL);
+ FASSERT_MSG(pdPASS == ret, "create task failed");
+
+ taskEXIT_CRITICAL(); /* allow schedule since task created */
+
+ return ret;
+}
+
+BaseType_t FFreeRTOSListUsbDev(int argc, char *argv[])
+{
+ return lsusb(argc, argv);
+}
\ No newline at end of file
diff --git a/example/peripheral/usb/cherryusb_host/src/usb_input.c b/example/peripheral/usb/cherryusb_host/src/usb_input.c
new file mode 100644
index 0000000000000000000000000000000000000000..11ec96a98af4f9c6eb31912ee4d3767647137900
--- /dev/null
+++ b/example/peripheral/usb/cherryusb_host/src/usb_input.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: usb_input.c
+ * Date: 2022-07-22 13:57:42
+ * LastEditTime: 2022-07-22 13:57:43
+ * Description: This files is for
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ * 1.0 zhugengyu 2022/9/20 init commit
+ */
+/***************************** Include Files *********************************/
+#include
+#include
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#include "ft_assert.h"
+#include "interrupt.h"
+#include "cpu_info.h"
+#include "ft_debug.h"
+
+#include "usbh_core.h"
+#include "usbh_hid.h"
+/************************** Constant Definitions *****************************/
+#define HID_KEYCODE_TO_ASCII \
+ {0 , 0 }, /* 0x00 */ \
+ {0 , 0 }, /* 0x01 */ \
+ {0 , 0 }, /* 0x02 */ \
+ {0 , 0 }, /* 0x03 */ \
+ {'a' , 'A' }, /* 0x04 */ \
+ {'b' , 'B' }, /* 0x05 */ \
+ {'c' , 'C' }, /* 0x06 */ \
+ {'d' , 'D' }, /* 0x07 */ \
+ {'e' , 'E' }, /* 0x08 */ \
+ {'f' , 'F' }, /* 0x09 */ \
+ {'g' , 'G' }, /* 0x0a */ \
+ {'h' , 'H' }, /* 0x0b */ \
+ {'i' , 'I' }, /* 0x0c */ \
+ {'j' , 'J' }, /* 0x0d */ \
+ {'k' , 'K' }, /* 0x0e */ \
+ {'l' , 'L' }, /* 0x0f */ \
+ {'m' , 'M' }, /* 0x10 */ \
+ {'n' , 'N' }, /* 0x11 */ \
+ {'o' , 'O' }, /* 0x12 */ \
+ {'p' , 'P' }, /* 0x13 */ \
+ {'q' , 'Q' }, /* 0x14 */ \
+ {'r' , 'R' }, /* 0x15 */ \
+ {'s' , 'S' }, /* 0x16 */ \
+ {'t' , 'T' }, /* 0x17 */ \
+ {'u' , 'U' }, /* 0x18 */ \
+ {'v' , 'V' }, /* 0x19 */ \
+ {'w' , 'W' }, /* 0x1a */ \
+ {'x' , 'X' }, /* 0x1b */ \
+ {'y' , 'Y' }, /* 0x1c */ \
+ {'z' , 'Z' }, /* 0x1d */ \
+ {'1' , '!' }, /* 0x1e */ \
+ {'2' , '@' }, /* 0x1f */ \
+ {'3' , '#' }, /* 0x20 */ \
+ {'4' , '$' }, /* 0x21 */ \
+ {'5' , '%' }, /* 0x22 */ \
+ {'6' , '^' }, /* 0x23 */ \
+ {'7' , '&' }, /* 0x24 */ \
+ {'8' , '*' }, /* 0x25 */ \
+ {'9' , '(' }, /* 0x26 */ \
+ {'0' , ')' }, /* 0x27 */ \
+ {'\r' , '\r' }, /* 0x28 */ \
+ {'\x1b', '\x1b' }, /* 0x29 */ \
+ {'\b' , '\b' }, /* 0x2a */ \
+ {'\t' , '\t' }, /* 0x2b */ \
+ {' ' , ' ' }, /* 0x2c */ \
+ {'-' , '_' }, /* 0x2d */ \
+ {'=' , '+' }, /* 0x2e */ \
+ {'[' , '{' }, /* 0x2f */ \
+ {']' , '}' }, /* 0x30 */ \
+ {'\\' , '|' }, /* 0x31 */ \
+ {'#' , '~' }, /* 0x32 */ \
+ {';' , ':' }, /* 0x33 */ \
+ {'\'' , '\"' }, /* 0x34 */ \
+ {'`' , '~' }, /* 0x35 */ \
+ {',' , '<' }, /* 0x36 */ \
+ {'.' , '>' }, /* 0x37 */ \
+ {'/' , '?' }, /* 0x38 */ \
+ \
+ {0 , 0 }, /* 0x39 */ \
+ {0 , 0 }, /* 0x3a */ \
+ {0 , 0 }, /* 0x3b */ \
+ {0 , 0 }, /* 0x3c */ \
+ {0 , 0 }, /* 0x3d */ \
+ {0 , 0 }, /* 0x3e */ \
+ {0 , 0 }, /* 0x3f */ \
+ {0 , 0 }, /* 0x40 */ \
+ {0 , 0 }, /* 0x41 */ \
+ {0 , 0 }, /* 0x42 */ \
+ {0 , 0 }, /* 0x43 */ \
+ {0 , 0 }, /* 0x44 */ \
+ {0 , 0 }, /* 0x45 */ \
+ {0 , 0 }, /* 0x46 */ \
+ {0 , 0 }, /* 0x47 */ \
+ {0 , 0 }, /* 0x48 */ \
+ {0 , 0 }, /* 0x49 */ \
+ {0 , 0 }, /* 0x4a */ \
+ {0 , 0 }, /* 0x4b */ \
+ {0 , 0 }, /* 0x4c */ \
+ {0 , 0 }, /* 0x4d */ \
+ {0 , 0 }, /* 0x4e */ \
+ {0 , 0 }, /* 0x4f */ \
+ {0 , 0 }, /* 0x50 */ \
+ {0 , 0 }, /* 0x51 */ \
+ {0 , 0 }, /* 0x52 */ \
+ {0 , 0 }, /* 0x53 */ \
+ \
+ {'/' , '/' }, /* 0x54 */ \
+ {'*' , '*' }, /* 0x55 */ \
+ {'-' , '-' }, /* 0x56 */ \
+ {'+' , '+' }, /* 0x57 */ \
+ {'\r' , '\r' }, /* 0x58 */ \
+ {'1' , 0 }, /* 0x59 */ \
+ {'2' , 0 }, /* 0x5a */ \
+ {'3' , 0 }, /* 0x5b */ \
+ {'4' , 0 }, /* 0x5c */ \
+ {'5' , '5' }, /* 0x5d */ \
+ {'6' , 0 }, /* 0x5e */ \
+ {'7' , 0 }, /* 0x5f */ \
+ {'8' , 0 }, /* 0x60 */ \
+ {'9' , 0 }, /* 0x61 */ \
+ {'0' , 0 }, /* 0x62 */ \
+ {'0' , 0 }, /* 0x63 */ \
+ {'=' , '=' }, /* 0x67 */ \
+
+/**************************** Type Definitions *******************************/
+
+/************************** Variable Definitions *****************************/
+static u8 const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
+static struct usbh_urb hid_intin_urb;
+static uint8_t hid_buffer[128] __attribute__((aligned(sizeof(unsigned long)))) = {0};
+
+/***************** Macros (Inline Functions) Definitions *********************/
+#define FUSB_DEBUG_TAG "USB-INPUT"
+#define FUSB_ERROR(format, ...) FT_DEBUG_PRINT_E(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FUSB_WARN(format, ...) FT_DEBUG_PRINT_W(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FUSB_INFO(format, ...) FT_DEBUG_PRINT_I(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+#define FUSB_DEBUG(format, ...) FT_DEBUG_PRINT_D(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
+
+/************************** Function Prototypes ******************************/
+
+
+/*****************************************************************************/
+static inline void UsbMouseLeftButtonCB(void)
+{
+ printf("[Left Button] ");
+}
+
+static inline void UsbMouseRightButtonCB(void)
+{
+ printf("[Right Button] ");
+}
+
+static inline void UsbMouseMiddleButtonCB(void)
+{
+ printf("[Middle Button] ");
+}
+
+static void UsbMouseHandleInput(struct usb_hid_mouse_report *input)
+{
+ /*------------- button state -------------*/
+ if (input->buttons & HID_MOUSE_INPUT_BUTTON_LEFT)
+ {
+ UsbMouseLeftButtonCB();
+ }
+
+ if (input->buttons & HID_MOUSE_INPUT_BUTTON_MIDDLE)
+ {
+ UsbMouseMiddleButtonCB();
+ }
+
+ if (input->buttons & HID_MOUSE_INPUT_BUTTON_RIGHT)
+ {
+ UsbMouseRightButtonCB();
+ }
+
+ /*------------- cursor movement -------------*/
+ printf("[Cursor@ x:%d y:%d]\r\n", input->xdisp, input->ydisp);
+}
+
+/* look up new key in previous keys */
+static inline boolean FindKeyInPrevInput(const struct usb_hid_kbd_report *report, u8 keycode)
+{
+ for(u8 i=0; i < 6; i++)
+ {
+ if (report->key[i] == keycode)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void UsbKeyBoardHandleInput(struct usb_hid_kbd_report *input)
+{
+ static struct usb_hid_kbd_report prev_input = { 0, 0, {0} }; /* previous report to check key released */
+
+ /* ------------- example code ignore control (non-printable) key affects ------------- */
+ for (u8 i = 0; i < 6; i++)
+ {
+ if (input->key[i])
+ {
+ if (FindKeyInPrevInput(&prev_input, input->key[i]))
+ {
+ /* exist in previous report means the current key is holding */
+ }
+ else
+ {
+ /* not existed in previous report means the current key is pressed */
+ boolean is_shift = input->modifier & (HID_MODIFER_LSHIFT | HID_MODIFER_RSHIFT);
+ u8 ch = keycode2ascii[input->key[i]][is_shift ? 1 : 0];
+ putchar(ch);
+ if ('\r' == ch)
+ {
+ putchar('\n');
+ }
+
+ fflush(stdout); /* flush right away, else libc will wait for newline */
+ }
+ }
+ }
+
+ prev_input = *input;
+}
+
+static u8 UsbInputGetInterfaceProtocol(struct usbh_hid *hid_class)
+{
+ struct usbh_hubport *hport = hid_class->hport;
+ u8 intf = hid_class->intf;
+ const struct usb_interface_descriptor *intf_desc = &hport->config.intf->altsetting[intf].intf_desc;
+
+ return intf_desc->bInterfaceProtocol;
+}
+
+static void UsbHidCallback(void *arg, int nbytes)
+{
+ u8 intf_protocol;
+ struct usbh_hid *hid_class = (struct usbh_hid *)arg;
+
+ intf_protocol = UsbInputGetInterfaceProtocol(hid_class);
+ if (HID_PROTOCOL_KEYBOARD == intf_protocol) /* handle input from keyboard */
+ {
+ if (nbytes < (int)sizeof(struct usb_hid_kbd_report))
+ {
+ FUSB_ERROR("nbytes = %d", nbytes);
+ }
+ else
+ {
+ UsbKeyBoardHandleInput((struct usb_hid_kbd_report *)hid_buffer);
+ }
+ }
+ else if (HID_PROTOCOL_MOUSE == intf_protocol) /* handle input from mouse */
+ {
+ if (nbytes < (int)sizeof(struct usb_hid_mouse_report))
+ {
+ FUSB_ERROR("nbytes = %d", nbytes);
+ }
+ else
+ {
+ UsbMouseHandleInput((struct usb_hid_mouse_report *)hid_buffer);
+ }
+ }
+ else
+ {
+ FUSB_ERROR("unsupported hid interface %d", intf_protocol);
+ }
+
+ usbh_submit_urb(&hid_intin_urb); /* ask for next inputs */
+}
+
+static void UsbInputTask(void * args)
+{
+ int ret;
+ struct usbh_hid *hid_class;
+ u8 intf_protocol;
+
+ while (TRUE)
+ {
+ hid_class = (struct usbh_hid *)usbh_find_class_instance("/dev/input0");
+ if (hid_class == NULL)
+ {
+ FUSB_ERROR("do not find /dev/input0");
+ goto err_exit;
+ }
+
+ usbh_int_urb_fill(&hid_intin_urb, hid_class->intin, hid_buffer, 8, 0, UsbHidCallback, hid_class);
+ ret = usbh_submit_urb(&hid_intin_urb);
+
+ vTaskDelay(1);
+ }
+
+err_exit:
+ vTaskDelete(NULL);
+}
+
+BaseType_t FFreeRTOSRunUsbInput(void)
+{
+ BaseType_t ret = pdPASS;
+
+ taskENTER_CRITICAL(); /* no schedule when create task */
+
+ ret = xTaskCreate((TaskFunction_t )UsbInputTask,
+ (const char* )"UsbInputTask",
+ (uint16_t )2048,
+ NULL,
+ (UBaseType_t )configMAX_PRIORITIES - 1,
+ NULL);
+ FASSERT_MSG(pdPASS == ret, "create task failed");
+
+ taskEXIT_CRITICAL(); /* allow schedule since task created */
+
+ return ret;
+}
\ No newline at end of file
diff --git a/example/peripheral/wdt/configs/d2000_aarch32_eg_configs b/example/peripheral/wdt/configs/d2000_aarch32_eg_configs
index 447a2bc8350f94d3b5714a71248b708171b1f891..df8d10c3c3493abd2eb759e4118b55048deea249 100644
--- a/example/peripheral/wdt/configs/d2000_aarch32_eg_configs
+++ b/example/peripheral/wdt/configs/d2000_aarch32_eg_configs
@@ -63,7 +63,7 @@ CONFIG_USE_WDT=y
#
# FWDT Configuration
#
-CONFIG_ENABLE_FWDT=y
+CONFIG_USE_FWDT=y
# end of FWDT Configuration
# CONFIG_USE_DMA is not set
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_WDT=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/wdt/configs/d2000_aarch64_eg_configs b/example/peripheral/wdt/configs/d2000_aarch64_eg_configs
index 14ce1486faa8f334075493126bfce4b1d5407ac7..7be34972e555c1e801deeebb57610a05f15f0d06 100644
--- a/example/peripheral/wdt/configs/d2000_aarch64_eg_configs
+++ b/example/peripheral/wdt/configs/d2000_aarch64_eg_configs
@@ -63,7 +63,7 @@ CONFIG_USE_WDT=y
#
# FWDT Configuration
#
-CONFIG_ENABLE_FWDT=y
+CONFIG_USE_FWDT=y
# end of FWDT Configuration
# CONFIG_USE_DMA is not set
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_WDT=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/wdt/configs/e2000d_aarch32_eg_configs b/example/peripheral/wdt/configs/e2000d_aarch32_eg_configs
index 0decd1e3c1e2be0adb9c3b31bd5341d48060f0c4..198c05b89e4b2d21882998b5b57d62af67c7810d 100644
--- a/example/peripheral/wdt/configs/e2000d_aarch32_eg_configs
+++ b/example/peripheral/wdt/configs/e2000d_aarch32_eg_configs
@@ -63,7 +63,7 @@ CONFIG_USE_WDT=y
#
# FWDT Configuration
#
-CONFIG_ENABLE_FWDT=y
+CONFIG_USE_FWDT=y
# end of FWDT Configuration
# CONFIG_USE_DMA is not set
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_WDT=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/wdt/configs/e2000d_aarch64_eg_configs b/example/peripheral/wdt/configs/e2000d_aarch64_eg_configs
index 815f4e4c3c854860876f5650f70545ec789d3c2e..5a09073ea3b1adb2fa9041f000c474b7157b73ec 100644
--- a/example/peripheral/wdt/configs/e2000d_aarch64_eg_configs
+++ b/example/peripheral/wdt/configs/e2000d_aarch64_eg_configs
@@ -63,7 +63,7 @@ CONFIG_USE_WDT=y
#
# FWDT Configuration
#
-CONFIG_ENABLE_FWDT=y
+CONFIG_USE_FWDT=y
# end of FWDT Configuration
# CONFIG_USE_DMA is not set
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_WDT=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/wdt/configs/ft2004_aarch32_eg_configs b/example/peripheral/wdt/configs/ft2004_aarch32_eg_configs
index dd6ad1241076f03c7a0bab80536fe7a4d1ccc1c1..65393228c23f88474f9fc4eb0bce1cba19e24d8c 100644
--- a/example/peripheral/wdt/configs/ft2004_aarch32_eg_configs
+++ b/example/peripheral/wdt/configs/ft2004_aarch32_eg_configs
@@ -63,7 +63,7 @@ CONFIG_USE_WDT=y
#
# FWDT Configuration
#
-CONFIG_ENABLE_FWDT=y
+CONFIG_USE_FWDT=y
# end of FWDT Configuration
# CONFIG_USE_DMA is not set
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_WDT=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/wdt/configs/ft2004_aarch64_eg_configs b/example/peripheral/wdt/configs/ft2004_aarch64_eg_configs
index be4efe831a1a180846b1c6174c56e643ca9f7bcb..b64b810ab1fe9f8a2e588fbd076fe60f3b372ba1 100644
--- a/example/peripheral/wdt/configs/ft2004_aarch64_eg_configs
+++ b/example/peripheral/wdt/configs/ft2004_aarch64_eg_configs
@@ -63,7 +63,7 @@ CONFIG_USE_WDT=y
#
# FWDT Configuration
#
-CONFIG_ENABLE_FWDT=y
+CONFIG_USE_FWDT=y
# end of FWDT Configuration
# CONFIG_USE_DMA is not set
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_WDT=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/wdt/sdkconfig b/example/peripheral/wdt/sdkconfig
index 815f4e4c3c854860876f5650f70545ec789d3c2e..5a09073ea3b1adb2fa9041f000c474b7157b73ec 100644
--- a/example/peripheral/wdt/sdkconfig
+++ b/example/peripheral/wdt/sdkconfig
@@ -63,7 +63,7 @@ CONFIG_USE_WDT=y
#
# FWDT Configuration
#
-CONFIG_ENABLE_FWDT=y
+CONFIG_USE_FWDT=y
# end of FWDT Configuration
# CONFIG_USE_DMA is not set
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_WDT=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/peripheral/wdt/sdkconfig.h b/example/peripheral/wdt/sdkconfig.h
index af42bfe66080b1f73bbb305ea5add6fab5424131..b3b4fae313e0eb7189c731b4ce3fc43ac866ec50 100644
--- a/example/peripheral/wdt/sdkconfig.h
+++ b/example/peripheral/wdt/sdkconfig.h
@@ -57,7 +57,7 @@
/* FWDT Configuration */
-#define CONFIG_ENABLE_FWDT
+#define CONFIG_USE_FWDT
/* end of FWDT Configuration */
/* CONFIG_USE_DMA is not set */
/* CONFIG_USE_NAND is not set */
@@ -159,6 +159,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/storage/qspi_spiffs/configs/d2000_aarch32_eg_configs b/example/storage/qspi_spiffs/configs/d2000_aarch32_eg_configs
index 1401ba5b27691dae485853f51cf1ecdb11841f5e..2289194665678330a7b5948193190b763c8c7ee0 100644
--- a/example/storage/qspi_spiffs/configs/d2000_aarch32_eg_configs
+++ b/example/storage/qspi_spiffs/configs/d2000_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/qspi_spiffs/configs/d2000_aarch64_eg_configs b/example/storage/qspi_spiffs/configs/d2000_aarch64_eg_configs
index c4514b80184bc017629415a20aab3e8c8ba50502..9bd920e256c3991e891f9f1ded3248b3a18c31b1 100644
--- a/example/storage/qspi_spiffs/configs/d2000_aarch64_eg_configs
+++ b/example/storage/qspi_spiffs/configs/d2000_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/qspi_spiffs/configs/e2000d_aarch32_eg_configs b/example/storage/qspi_spiffs/configs/e2000d_aarch32_eg_configs
index 7827871d0c44ea0c71dbba7258833943d05913b0..9614b73b47e5fc5ed94d0c80700a2b4d9b508368 100644
--- a/example/storage/qspi_spiffs/configs/e2000d_aarch32_eg_configs
+++ b/example/storage/qspi_spiffs/configs/e2000d_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/qspi_spiffs/configs/e2000d_aarch64_eg_configs b/example/storage/qspi_spiffs/configs/e2000d_aarch64_eg_configs
index 614338740d94ef0113f3d77abd58865a8ec0aab7..a165e34363c0250922744ea0684f824bd2005d0b 100644
--- a/example/storage/qspi_spiffs/configs/e2000d_aarch64_eg_configs
+++ b/example/storage/qspi_spiffs/configs/e2000d_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/qspi_spiffs/configs/e2000q_aarch32_eg_configs b/example/storage/qspi_spiffs/configs/e2000q_aarch32_eg_configs
index b5b6402da7430d1bec05217799d85907cd9b5ddf..f44aabed32774c6a13c7f9648db552639f3c3ee4 100644
--- a/example/storage/qspi_spiffs/configs/e2000q_aarch32_eg_configs
+++ b/example/storage/qspi_spiffs/configs/e2000q_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/qspi_spiffs/configs/e2000q_aarch64_eg_configs b/example/storage/qspi_spiffs/configs/e2000q_aarch64_eg_configs
index ab42b7cf4e408e84baa6fcf77d7342792ef7ef39..4d34dd779bf928b611fe370c87c58f7fbd32639a 100644
--- a/example/storage/qspi_spiffs/configs/e2000q_aarch64_eg_configs
+++ b/example/storage/qspi_spiffs/configs/e2000q_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/qspi_spiffs/configs/ft2004_aarch32_eg_configs b/example/storage/qspi_spiffs/configs/ft2004_aarch32_eg_configs
index 16e1bf81d2f122e647e8e41e31bbef2586b19c03..3a2c41068986efa51ea675b7fc8ccc7ea850161d 100644
--- a/example/storage/qspi_spiffs/configs/ft2004_aarch32_eg_configs
+++ b/example/storage/qspi_spiffs/configs/ft2004_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/qspi_spiffs/configs/ft2004_aarch64_eg_configs b/example/storage/qspi_spiffs/configs/ft2004_aarch64_eg_configs
index 783c693b9a8a89313754cf20901588dbfaab36b9..259919c7ff1f890716000e1fc3dcc122aef5f4f2 100644
--- a/example/storage/qspi_spiffs/configs/ft2004_aarch64_eg_configs
+++ b/example/storage/qspi_spiffs/configs/ft2004_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/qspi_spiffs/sdkconfig b/example/storage/qspi_spiffs/sdkconfig
index ab42b7cf4e408e84baa6fcf77d7342792ef7ef39..4d34dd779bf928b611fe370c87c58f7fbd32639a 100644
--- a/example/storage/qspi_spiffs/sdkconfig
+++ b/example/storage/qspi_spiffs/sdkconfig
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_QSPI=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/qspi_spiffs/sdkconfig.h b/example/storage/qspi_spiffs/sdkconfig.h
index 374d423ed40021e82b6040e3e63fbd0dad89612e..49c8dca702d88626348f2255920127338d383060 100644
--- a/example/storage/qspi_spiffs/sdkconfig.h
+++ b/example/storage/qspi_spiffs/sdkconfig.h
@@ -159,6 +159,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/storage/sata_fatfs/configs/d2000_aarch32_eg_configs b/example/storage/sata_fatfs/configs/d2000_aarch32_eg_configs
index e4ea018a6f11f19859e1683cfa4d0280eb5c9e62..7e4c0d2dc2e60a793641899c91bea8e2537ad190 100644
--- a/example/storage/sata_fatfs/configs/d2000_aarch32_eg_configs
+++ b/example/storage/sata_fatfs/configs/d2000_aarch32_eg_configs
@@ -193,6 +193,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/sata_fatfs/configs/d2000_aarch64_eg_configs b/example/storage/sata_fatfs/configs/d2000_aarch64_eg_configs
index e29762a857a5cbaef1aabd09c06e89a96ba4a999..f1eebcede177f86599d89e2dfcc97038f9e7444e 100644
--- a/example/storage/sata_fatfs/configs/d2000_aarch64_eg_configs
+++ b/example/storage/sata_fatfs/configs/d2000_aarch64_eg_configs
@@ -189,6 +189,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/sata_fatfs/configs/e2000d_aarch32_eg_configs b/example/storage/sata_fatfs/configs/e2000d_aarch32_eg_configs
index c4f58e128f0cc871d1a6e4b73317f9de6a94a1c5..29c2b3a3aff5008b7e8557ff9ae529ff01e7874b 100644
--- a/example/storage/sata_fatfs/configs/e2000d_aarch32_eg_configs
+++ b/example/storage/sata_fatfs/configs/e2000d_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/sata_fatfs/configs/e2000d_aarch64_eg_configs b/example/storage/sata_fatfs/configs/e2000d_aarch64_eg_configs
index a26950b7f0017812481a229f6db59fdbf0bb3816..853bb29e4aff4830be4a86d2e7c8b8996c02348e 100644
--- a/example/storage/sata_fatfs/configs/e2000d_aarch64_eg_configs
+++ b/example/storage/sata_fatfs/configs/e2000d_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/sata_fatfs/configs/e2000q_aarch32_eg_configs b/example/storage/sata_fatfs/configs/e2000q_aarch32_eg_configs
index eadea223b44d2d9d17c1705836f065d1d0bb4556..a63fe963e9bb0cd6437654ee191cbf64320dcc4f 100644
--- a/example/storage/sata_fatfs/configs/e2000q_aarch32_eg_configs
+++ b/example/storage/sata_fatfs/configs/e2000q_aarch32_eg_configs
@@ -186,6 +186,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/sata_fatfs/configs/e2000q_aarch64_eg_configs b/example/storage/sata_fatfs/configs/e2000q_aarch64_eg_configs
index f871d7a8fa765e9ae2432a3e41a8d704818d59a6..95e1c910b857da2c4036a7ec06acc9457f41b2ed 100644
--- a/example/storage/sata_fatfs/configs/e2000q_aarch64_eg_configs
+++ b/example/storage/sata_fatfs/configs/e2000q_aarch64_eg_configs
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/sata_fatfs/configs/ft2004_aarch32_eg_configs b/example/storage/sata_fatfs/configs/ft2004_aarch32_eg_configs
index 1133b0cbe8a45a86e0c105691b718541edf7e2b0..27c31f323b7752e1a9a521b994040e7750c232ec 100644
--- a/example/storage/sata_fatfs/configs/ft2004_aarch32_eg_configs
+++ b/example/storage/sata_fatfs/configs/ft2004_aarch32_eg_configs
@@ -193,6 +193,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/sata_fatfs/configs/ft2004_aarch64_eg_configs b/example/storage/sata_fatfs/configs/ft2004_aarch64_eg_configs
index d51d4557e1fd8f056d1bdea8aa90dcf15c611821..3f1ef095d4a29f3e554f3900bab401d3135f5bb7 100644
--- a/example/storage/sata_fatfs/configs/ft2004_aarch64_eg_configs
+++ b/example/storage/sata_fatfs/configs/ft2004_aarch64_eg_configs
@@ -189,6 +189,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/sata_fatfs/sdkconfig b/example/storage/sata_fatfs/sdkconfig
index f871d7a8fa765e9ae2432a3e41a8d704818d59a6..95e1c910b857da2c4036a7ec06acc9457f41b2ed 100644
--- a/example/storage/sata_fatfs/sdkconfig
+++ b/example/storage/sata_fatfs/sdkconfig
@@ -182,6 +182,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/storage/sata_fatfs/sdkconfig.h b/example/storage/sata_fatfs/sdkconfig.h
index e85caf83cafb8941162993bfb00f32869814671b..9d753391e69653f86412b5de5d3e74ad8bb87677 100644
--- a/example/storage/sata_fatfs/sdkconfig.h
+++ b/example/storage/sata_fatfs/sdkconfig.h
@@ -159,6 +159,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/example/template/configs/d2000_aarch32_eg_configs b/example/template/configs/d2000_aarch32_eg_configs
index 084147bfd7b99d1cda2b972c79dbb4a3045a7c18..c8911c8a289263fc4658b167eb1e060d8febf51f 100644
--- a/example/template/configs/d2000_aarch32_eg_configs
+++ b/example/template/configs/d2000_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/template/configs/d2000_aarch64_eg_configs b/example/template/configs/d2000_aarch64_eg_configs
index cb612d754a820d326b3cf0897d2bd03fc3205267..9564ed29fbcc1e3e3031ae52c7ee391f070c0cf4 100644
--- a/example/template/configs/d2000_aarch64_eg_configs
+++ b/example/template/configs/d2000_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/template/configs/e2000d_aarch32_eg_configs b/example/template/configs/e2000d_aarch32_eg_configs
index 17a6e12e7a69b47195b2765844e5206a4516d4b8..c47c391111e545d9da5349b593d59e4aec105057 100644
--- a/example/template/configs/e2000d_aarch32_eg_configs
+++ b/example/template/configs/e2000d_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/template/configs/e2000d_aarch64_eg_configs b/example/template/configs/e2000d_aarch64_eg_configs
index 9816214aa10458eb35b54a2cd6bd8ee5d382254e..852df71fe40fbea6b5e46caa0ac4b26582faacbb 100644
--- a/example/template/configs/e2000d_aarch64_eg_configs
+++ b/example/template/configs/e2000d_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/template/configs/ft2004_aarch32_eg_configs b/example/template/configs/ft2004_aarch32_eg_configs
index 2db403c0c4256d93dede178ecf853ff6e0b0e335..94bd24b0ea49be43d1df0211532f8bcaf77c87e9 100644
--- a/example/template/configs/ft2004_aarch32_eg_configs
+++ b/example/template/configs/ft2004_aarch32_eg_configs
@@ -179,6 +179,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/template/configs/ft2004_aarch64_eg_configs b/example/template/configs/ft2004_aarch64_eg_configs
index 70711d8387541f981df9c21078374a7352aefd83..eb694b5a427ee0983c9b1e9f2cf142f65b3753b5 100644
--- a/example/template/configs/ft2004_aarch64_eg_configs
+++ b/example/template/configs/ft2004_aarch64_eg_configs
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/template/sdkconfig b/example/template/sdkconfig
index 9816214aa10458eb35b54a2cd6bd8ee5d382254e..852df71fe40fbea6b5e46caa0ac4b26582faacbb 100644
--- a/example/template/sdkconfig
+++ b/example/template/sdkconfig
@@ -175,6 +175,12 @@ CONFIG_FREERTOS_USE_UART=y
#
# CONFIG_FREERTOS_USE_ADC is not set
# end of Freertos Adc Drivers
+
+#
+# Freertos Can Drivers
+#
+# CONFIG_FREERTOS_USE_CAN is not set
+# end of Freertos Can Drivers
# end of Component Configuration
#
diff --git a/example/template/sdkconfig.h b/example/template/sdkconfig.h
index 8dbf9e11738487e4a0cc9cff85a68b03e886e297..784d2fb2927f0db68aafbded9ff40b935c7d3db0 100644
--- a/example/template/sdkconfig.h
+++ b/example/template/sdkconfig.h
@@ -154,6 +154,11 @@
/* CONFIG_FREERTOS_USE_ADC is not set */
/* end of Freertos Adc Drivers */
+
+/* Freertos Can Drivers */
+
+/* CONFIG_FREERTOS_USE_CAN is not set */
+/* end of Freertos Can Drivers */
/* end of Component Configuration */
/* FreeRTOS Setting */
diff --git a/make/complier.mk b/make/complier.mk
index eeb028b36311199ebe6977b5584d06cc7f713385..7fa15f2a21e1a65989d0458f611b91f84ada1022 100755
--- a/make/complier.mk
+++ b/make/complier.mk
@@ -208,7 +208,7 @@ $(OUTPUT_DIR)/%.o : %.S | $(X_OUTPUT_DIRS)
$(OUTPUT_DIR)/%.o : %.c | $(X_OUTPUT_DIRS)
@echo " CC $@"
- $(QUIET) $(CC) -c $(TARGET_ARCH) $(CPPFLAGS) $(CFLAGS) -o $@ $<
+ $(QUIET) $(CC) -c $(TARGET_ARCH) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
clean:
$(call RM_DIRS,$(OUTPUT_DIR))
diff --git a/make/ld/aarch32_ram.ld b/make/ld/aarch32_ram.ld
index 6d69402d8ce2ba02e3ddb6f18170691c184e6f0b..22300636a354fd31d1ba7fa9eb4d4bdea3284026 100644
--- a/make/ld/aarch32_ram.ld
+++ b/make/ld/aarch32_ram.ld
@@ -74,6 +74,14 @@ SECTIONS
_shell_code_end = .;
}> ROM
+ .cherryusb (ALIGN(64)):{
+ /* section information for usbh class */
+ . = ALIGN(4);
+ __usbh_class_info_start__ = .;
+ KEEP(*(.usbh_class_info))
+ __usbh_class_info_end__ = .;
+ }> ROM
+
.init :{
KEEP (*(SORT_NONE(.init)))
}> ROM
diff --git a/make/ld/aarch64_ram.ld b/make/ld/aarch64_ram.ld
index 52b378e6d656c1f863b7aea9aa5f056e0c663a5c..aaa6f61f6e32d5cf761a1442f8c95cc20fbd7228 100644
--- a/make/ld/aarch64_ram.ld
+++ b/make/ld/aarch64_ram.ld
@@ -100,6 +100,13 @@ SECTIONS
_shell_code_end = .;
}> ROM
+ .cherryusb (ALIGN(64)):{
+ /* section information for usbh class */
+ . = ALIGN(4);
+ __usbh_class_info_start__ = .;
+ KEEP(*(.usbh_class_info))
+ __usbh_class_info_end__ = .;
+ }> ROM
.rodata1 (ALIGN(64)): {
__rodata1_start = .;
diff --git a/third-party/Kconfig b/third-party/Kconfig
index 77b651e5fd8054cf62ed2f94152f69ef14959def..9276ae4f3373c3ae43d40a570e037d29b65ed276 100644
--- a/third-party/Kconfig
+++ b/third-party/Kconfig
@@ -96,4 +96,15 @@ config USE_SDMMC_CMD
if USE_SDMMC_CMD
source "$(FREERTOS_SDK_ROOT)/third-party/sdmmc-1.0/Kconfig"
+ endif
+
+config USE_CHERRY_USB
+ bool
+ default n
+ prompt "Use CherryUSB"
+ help
+ Include CherryUSB
+
+ if USE_CHERRY_USB
+ source "$(FREERTOS_SDK_ROOT)/third-party/cherryusb-0.6.0/Kconfig"
endif
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/Kconfig b/third-party/cherryusb-0.6.0/Kconfig
new file mode 100644
index 0000000000000000000000000000000000000000..52451502e84a55005f38c29e8e64d3be182ec8fd
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/Kconfig
@@ -0,0 +1,97 @@
+menu "CherryUSB Configuration"
+ choice CHERRY_USB_PORT_TYPE
+ prompt "Select Cherry USB Port Type"
+ default CHERRY_USB_PORT_XHCI
+ help
+ Select Port Type for CherryUSB
+
+ config CHERRY_USB_PORT_XHCI
+ bool "XHCI"
+
+ config CHERRY_USB_PORT_PHYTIUM_OTG
+ bool "OTG(Phytium)"
+
+ endchoice # CHERRY_USB_PORT_TYPE
+
+ choice CHERRY_USB_WORK_MODE
+ prompt "Select Cherry USB Work Mode"
+ help
+ Select Work Mode for CherryUSB
+
+ config CHERRYUSB_HOST
+ bool "Host(Hc)"
+
+ config CHERRYUSB_DEVICE
+ bool "Device(Dc)"
+
+ endchoice #CHERRY_USB_WORK_MODE
+
+if CHERRYUSB_HOST
+ config CHERRY_USB_HOST_HUB
+ bool "HUB(Hc)"
+ default y
+
+ config CHERRY_USB_HOST_MSC
+ bool "MSC(Hc)"
+ default n
+
+ config CHERRY_USB_HOST_HID
+ bool "HID(Hc)"
+ default n
+
+ config CHERRY_USB_HOST_VEDIO
+ bool "VEDIO(Hc)"
+ default n
+
+ config CHERRY_USB_HOST_CDC
+ bool "CDC(Hc)"
+ default n
+
+ config CHERRY_USB_HOST_RNDIS_WIRELESS
+ bool "RndisWireless(Hc)"
+ default n
+
+endif #CHERRYUSB_HOST
+
+if CHERRYUSB_DEVICE
+
+ choice CHERRY_USB_DEVICE_TYPE
+ prompt "Select Cherry USB Device Type"
+ help
+ Select Device Type that Cherry USB Work as
+
+ config CHERRY_USB_DEVICE_HUB
+ bool "HUB(Dc)"
+
+ config CHERRY_USB_DEVICE_MSC
+ bool "MSC(Dc)"
+
+ config CHERRY_USB_DEVICE_HID
+ bool "HID(Dc)"
+
+ config CHERRY_USB_DEVICE_AUDIO
+ bool "Audio(Dc)"
+
+ config CHERRY_USB_DEVICE_CDC
+ bool "Cdc(Dc)"
+
+ config CHERRY_USB_DEVICE_DFU
+ bool "DFU(Dc)"
+
+ config CHERRY_USB_DEVICE_MTP
+ bool "MTP(Dc)"
+
+ config CHERRY_USB_DEVICE_PRINTER
+ bool "Printer(Dc)"
+
+ config CHERRY_USB_DEVICE_VEDIO
+ bool "Vedio(Dc)"
+
+ config CHERRY_USB_DEVICE_RNDIS_WIRELESS
+ bool "RndisWireless(Dc)"
+
+ endchoice #CHERRY_USB_DEVICE_TYPE
+
+endif #CHERRYUSB_DEVICE
+
+endmenu
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/LICENSE b/third-party/cherryusb-0.6.0/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/third-party/cherryusb-0.6.0/README.md b/third-party/cherryusb-0.6.0/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c4445e511991c81ac8f9f7a4b788ecec0e9f55fd
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/README.md
@@ -0,0 +1,154 @@
+# CherryUSB
+
+[中文版](./README_zh.md)
+
+CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB ip.
+
+
+
+## Why choose
+
+- Streamlined code with small memory usage which also can be further trimmed
+- Comprehensive class drivers and all master and slave class drivers are templated,making it easy for users to add new class drivers and find patterns when learning
+- The APIs available to the users are very few and clearly categorised. Device: initialisation + registration apis, command callback apis, data sending and receiving apis; Host: initialisation + lookup apis, data sending and receiving apis
+- Tree-based programming with a hierarchy of code that makes it easy for the user to sort out function call relationships, enumerations and class-driven loading processes
+- Standardised porting interface, no need to rewrite the driver for the same ip, and porting drivers are templated to make it easier for users to add new ports
+- The use of the device or host transceiver apis are equivalent to the use of the uart tx/rx dma, and there is no limit to the length
+- Capable of achieving theoretical USB hardware bandwidth
+
+## Directoy Structure
+
+```
+.
+├── class
+├── common
+├── core
+├── demo
+├── docs
+├── osal
+├── packet capture
+└── port
+└── tools
+
+```
+
+| Directory | Description |
+|:-------------:|:---------------------------:|
+|class | usb class driver |
+|common | usb spec macros and utils |
+|core | usb core implementation |
+|demo | different chips demo |
+|osal | os wrapper |
+|docs | doc for guiding |
+|packet capture | packet capture file |
+|port | usb dcd and hcd porting |
+|tools | tool used url |
+
+## Device Stack Overview
+
+CherryUSB Device Stack provides a unified framework of functions for standard device requests, CLASS requests, VENDOR requests and custom special requests. The object-oriented and chained approach allows the user to quickly get started with composite devices without having to worry about the underlying logic. At the same time, a standard dcd porting interface has been standardised for adapting different USB IPs to achieve ip-oriented programming.
+
+CherryUSB Device Stack has the following functions:
+
+- Support USB2.0 full and high speed
+- Support endpoint irq callback register by users, let users do whatever they wants in endpoint irq callback.
+- Support Composite Device
+- Support Communication Device Class (CDC)
+- Support Human Interface Device (HID)
+- Support Mass Storage Class (MSC)
+- Support USB VIDEO CLASS (UVC1.0、UVC1.5)
+- Support USB AUDIO CLASS (UAC1.0、UAC2.0)
+- Support Device Firmware Upgrade CLASS (DFU)
+- Support USB MIDI CLASS (MIDI)
+- Support Remote NDIS (RNDIS)
+- Support WINUSB1.0、WINUSB2.0(with BOS)
+- Support Vendor class
+
+CherryUSB Device Stack resource usage (GCC 10.2 with -O2):
+
+| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
+|:-------------:|:--------------:|:-------------------------:|:-------------:|:---------------------------------:|
+|usbd_core.c | 3263 | 384 | 17 | 0 |
+|usbd_cdc.c | 490 | 0 | 0 | sizeof(struct usbd_interface) * x |
+|usbd_msc.c | 2772 | 128 + 512(default) | 16 | sizeof(struct usbd_interface) * x |
+|usbd_hid.c | 501 | 0 | 0 | sizeof(struct usbd_interface) * x |
+|usbd_audio.c | 1208 | 0 | 4 | sizeof(struct usbd_interface) * x |
+|usbd_video.c | 2272 | 0 | 82 | sizeof(struct usbd_interface) * x |
+
+## Host Stack Overview
+
+The CherryUSB Host Stack has a standard enumeration implementation for devices mounted on roothubs and external hubs, and a standard interface for different Classes to indicate what the Class driver needs to do after enumeration and after disconnection. A standard hcd porting interface has also been standardised for adapting different USB IPs for IP-oriented programming. Finally, the host stack is managed using os, and provides osal to make a adaptation for different os.
+
+CherryUSB Host Stack has the following functions:
+
+- Automatic loading of supported Class drivers
+- Support blocking transfers and asynchronous transfers
+- Support Composite Device
+- Multi-level HUB support, expandable up to 7 levels
+- Support Communication Device Class (CDC)
+- Support Human Interface Device (HID)
+- Support Mass Storage Class (MSC)
+- Support USB VIDEO CLASS
+- Support Remote NDIS (RNDIS)
+- Support Vendor class
+
+The CherryUSB Host stack also provides the lsusb function, which allows you to view information about all mounted devices, including those on external hubs, with the help of a shell plugin.
+
+CherryUSB Host Stack resource usage (GCC 10.2 with -O2):
+
+| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
+|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
+|usbh_core.c | 4261 | 512 | 28 | sizeof(struct usbh_urb) |
+|usbh_hub.c | 4633 | sizeof(struct usbh_hub) * (1+n) | sizeof(struct usbh_hubport) + 20 | 0 |
+|usbh_cdc_acm.c | 1004 | 7 | 4 | sizeof(struct usbh_cdc_acm) * x |
+|usbh_msc.c | 1776 | 32 | 4 | sizeof(struct usbh_msc) * x |
+|usbh_hid.c | 822 | 128 | 4 | sizeof(struct usbh_hid) * x |
+|usbh_video.c | 3587 | 128 | 4100(yuv2rgb) | sizeof(struct usbh_video) * x |
+
+Among them, `sizeof(struct usbh_hub)` and `sizeof(struct usbh_hubport)` are affected by the following macros:
+
+```
+#define CONFIG_USBHOST_MAX_EXTHUBS 1
+#define CONFIG_USBHOST_MAX_EHPORTS 4
+#define CONFIG_USBHOST_MAX_INTERFACES 6
+#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
+#define CONFIG_USBHOST_MAX_ENDPOINTS 4
+```
+
+## Documentation Tutorial
+
+Quickly start, USB basic concepts, API manual, Class basic concepts and examples, see [CherryUSB Documentation Tutorial](https://cherryusb.readthedocs.io/)
+
+## Video Tutorial
+
+USB basic concepts and how the CherryUSB Device stack is implemented, see [CherryUSB Device Stack Tutorial](https://www.bilibili.com/video/BV1Ef4y1t73d).
+
+## Graphical Config Tool
+
+[chryusb_configurator](https://github.com/Egahp/chryusb_configurator) is written in **electron + vite2 + ts** framework,currently used to automate the generation of descriptor arrays, with additional functionality to be added later.
+
+## Demo Repo
+
+Note: After version 0.4.1, the dcd drivers have been refactored and some repositories are not maintained for a long time, so if you use a higher version, you need to update it yourself.
+
+| Manufacturer | CHIP or Series | USB IP| Repo Url |Corresponds to master version|
+|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
+|Bouffalolab | BL702 | bouffalolab|[bl_mcu_sdk](https://github.com/bouffalolab/bl_mcu_sdk/tree/master/examples/usb)| latest |
+|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/es32)|latest |
+|AllwinnerTech | F1C100S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|latest |
+|ST | STM32F103C8T6 | fsdev |[stm32f103_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f103c8t6)|latest |
+|ST | STM32F4 | dwc2 |[stm32f429_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f429igt6) [stm32f429_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32f429igt6)|latest |
+|ST | STM32H7 | dwc2 |[stm32h743_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32h743vbt6) [stm32h743_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32h743xih6)|latest |
+|HPMicro | HPM6750 | hpm/ehci |[hpm_repo](https://github.com/CherryUSB/cherryusb_hpmicro)|latest |
+|Phytium | e2000 | xhci |[phytium _repo](https://gitee.com/phytium_embedded/phytium-standalone-sdk)|latest |
+|WCH | CH32V307 | ch32_usbfs/ch32_usbhs|[ch32v307_repo](https://github.com/CherryUSB/cherryusb_ch32v307)|latest |
+|WCH | CH57x | ch58x |[ch57x_repo](https://github.com/CherryUSB/cherryusb_ch57x)|v0.4.1 |
+|Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/CherryUSB/cherryusb_nuc442)|v0.4.1 |
+|Geehy | APM32E10x APM32F0xx| fsdev |[apm32_repo](https://github.com/CherryUSB/cherryusb_apm32)|v0.4.1 |
+|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|latest |
+|Espressif | esp32 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|v0.4.1 |
+|Mindmotion | MM32L3xx | mm32 |[mm32_repo](https://github.com/CherryUSB/cherryusb_mm32)|v0.4.1 |
+
+## Contact
+
+QQ group: 642693751
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/README_zh.md b/third-party/cherryusb-0.6.0/README_zh.md
new file mode 100644
index 0000000000000000000000000000000000000000..d19d5207553a33480606a7768069e6ebc287be41
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/README_zh.md
@@ -0,0 +1,153 @@
+# CherryUSB
+
+[English](./README.md)
+
+CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB ip)的 USB 主从协议栈。
+
+
+
+## 为什么选择
+
+- 代码精简,并且内存占用极小,详细参考下面表格,而且还可进一步的裁剪
+- 全面的 class 驱动,并且主从 class 驱动全部模板化,方便用户增加新的 class 驱动以及学习的时候查找规律
+- 可供用户使用的 API 非常少,并且分类清晰。从机:初始化 + 注册类、命令回调类、数据收发类;主机:初始化 + 查找类、数据收发类
+- 树状化编程,代码层层递进,方便用户理清函数调用关系、枚举和 class 驱动加载过程
+- 标准化的 porting 接口,相同 ip 无需重写驱动,并且 porting 驱动也进行了模板化,方便用户新增 porting。
+- 主从收发接口的使用等价于 uart tx/rx dma 的使用,长度也没有限制
+- 能够达到 USB 硬件理论带宽
+
+## 目录结构
+
+```
+.
+├── class
+├── common
+├── core
+├── demo
+├── docs
+├── osal
+├── packet capture
+└── port
+└── tools
+```
+
+| 目录名 | 描述 |
+|:-------------:|:------------------------------:|
+|class | usb class 类主从驱动 |
+|common | usb spec 定义、常用宏、标准接口定义 |
+|core | usb 主从协议栈核心实现 |
+|demo | 示例 |
+|docs | 文档 |
+|osal | os 封装层 |
+|packet capture | 抓包文件(需要使用力科软件打开)|
+|port | usb 主从需要实现的 porting 接口 |
+|tools | 工具链接 |
+
+## Device 协议栈简介
+
+CherryUSB Device 协议栈对标准设备请求、CLASS 请求、VENDOR 请求以及 custom 特殊请求规范了一套统一的函数框架,采用面向对象和链表的方式,能够使得用户快速上手复合设备,不用管底层的逻辑。同时,规范了一套标准的 dcd porting 接口,用于适配不同的 USB IP,达到面向 ip 编程。
+
+CherryUSB Device 协议栈当前实现以下功能:
+
+- 支持 USB2.0 全速和高速设备
+- 支持端点中断注册功能,porting 给用户自己处理中断里的数据
+- 支持复合设备
+- 支持 Communication Device Class (CDC)
+- 支持 Human Interface Device (HID)
+- 支持 Mass Storage Class (MSC)
+- 支持 USB VIDEO CLASS (UVC1.0、UVC1.5)
+- 支持 USB AUDIO CLASS (UAC1.0、UAC2.0)
+- 支持 Device Firmware Upgrade CLASS (DFU)
+- 支持 USB MIDI CLASS (MIDI)
+- 支持 Remote NDIS (RNDIS)
+- 支持 WINUSB1.0、WINUSB2.0(带 BOS )
+- 支持 Vendor 类 class
+
+CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
+
+| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
+|:-------------:|:--------------:|:-------------------------:|:-------------:|:---------------------------------:|
+|usbd_core.c | 3263 | 384 | 17 | 0 |
+|usbd_cdc.c | 490 | 0 | 0 | sizeof(struct usbd_interface) * x |
+|usbd_msc.c | 2772 | 128 + 512(default) | 16 | sizeof(struct usbd_interface) * x |
+|usbd_hid.c | 501 | 0 | 0 | sizeof(struct usbd_interface) * x |
+|usbd_audio.c | 1208 | 0 | 4 | sizeof(struct usbd_interface) * x |
+|usbd_video.c | 2272 | 0 | 82 | sizeof(struct usbd_interface) * x |
+
+## Host 协议栈简介
+
+CherryUSB Host 协议栈对挂载在 roothub、外部 hub 上的设备规范了一套标准的枚举实现,对不同的 Class 类也规范了一套标准接口,用来指示在枚举后和断开连接后该 Class 驱动需要做的事情。同时,规范了一套标准的 hcd porting 接口,用于适配不同的 USB IP,达到面向 IP 编程。最后,协议栈使用 OS 管理,并提供了 osal 用来适配不同的 os。
+
+CherryUSB Host 协议栈当前实现以下功能:
+
+- 自动加载支持的Class 驱动
+- 支持阻塞式传输和异步传输
+- 支持复合设备
+- 支持多级 HUB,最高可拓展到 7 级
+- 支持 Communication Device Class (CDC)
+- 支持 Human Interface Device (HID)
+- 支持 Mass Storage Class (MSC)
+- 支持 USB VIDEO CLASS
+- 支持 Remote NDIS (RNDIS)
+- 支持 Vendor 类 class
+
+同时,CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
+
+CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
+
+| file | FLASH (Byte) | No Cache RAM (Byte) | RAM (Byte) | Heap (Byte) |
+|:-------------:|:--------------:|:-------------------------------:|:---------------------------:|:-------------------------------:|
+|usbh_core.c | 4261 | 512 | 28 | sizeof(struct usbh_urb) |
+|usbh_hub.c | 4633 | sizeof(struct usbh_hub) * (1+n) | sizeof(struct usbh_hubport) + 20 | 0 |
+|usbh_cdc_acm.c | 1004 | 7 | 4 | sizeof(struct usbh_cdc_acm) * x |
+|usbh_msc.c | 1776 | 32 | 4 | sizeof(struct usbh_msc) * x |
+|usbh_hid.c | 822 | 128 | 4 | sizeof(struct usbh_hid) * x |
+|usbh_video.c | 3587 | 128 | 4100(yuv2rgb) | sizeof(struct usbh_video) * x |
+
+其中,`sizeof(struct usbh_hub)` 和 `sizeof(struct usbh_hubport)` 受以下宏影响:
+
+```
+#define CONFIG_USBHOST_MAX_EXTHUBS 1
+#define CONFIG_USBHOST_MAX_EHPORTS 4
+#define CONFIG_USBHOST_MAX_INTERFACES 6
+#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
+#define CONFIG_USBHOST_MAX_ENDPOINTS 4
+```
+
+## 文档教程
+
+CherryUSB 快速入门、USB 基本概念,API 手册,Class 基本概念和例程,参考 [CherryUSB 文档教程](https://cherryusb.readthedocs.io/)
+
+## 视频教程
+
+USB 基本知识点与 CherryUSB Device 协议栈是如何编写的,参考 [CherryUSB Device 协议栈教程](https://www.bilibili.com/video/BV1Ef4y1t73d).
+
+## 图形化界面配置工具
+
+[chryusb_configurator](https://github.com/Egahp/chryusb_configurator) 采用 **electron + vite2 + ts** 框架编写,当前用于自动化生成描述符数组,后续会增加其他功能。
+
+## 示例仓库
+
+注意:0.4.1 版本以后 dcd 驱动进行了重构,部分仓库不做长期维护,所以如果使用高版本需要自行更新
+
+| 厂商 | 芯片或者系列 | USB IP| 仓库链接 | 对应 master 版本 |
+|:--------------------:|:------------------:|:-----:|:--------:|:---------------------------:|
+|Bouffalolab | BL702 | bouffalolab|[bl_mcu_sdk](https://github.com/bouffalolab/bl_mcu_sdk/tree/master/examples/usb)| latest |
+|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/es32)|latest |
+|AllwinnerTech | F1C100S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|latest |
+|ST | STM32F103C8T6 | fsdev |[stm32f103_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f103c8t6)|latest |
+|ST | STM32F4 | dwc2 |[stm32f429_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f429igt6) [stm32f429_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32f429igt6)|latest |
+|ST | STM32H7 | dwc2 |[stm32h743_device_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32h743vbt6) [stm32h743_host_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_host/stm32h743xih6)|latest |
+|HPMicro | HPM6750 | hpm/ehci |[hpm_repo](https://github.com/CherryUSB/cherryusb_hpmicro)|latest |
+|Phytium | e2000 | xhci |[phytium _repo](https://gitee.com/phytium_embedded/phytium-standalone-sdk)|latest |
+|WCH | CH32V307 | ch32_usbfs/ch32_usbhs|[ch32v307_repo](https://github.com/CherryUSB/cherryusb_ch32v307)|latest |
+|WCH | CH57x | ch58x |[ch57x_repo](https://github.com/CherryUSB/cherryusb_ch57x)|v0.4.1 |
+|Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/CherryUSB/cherryusb_nuc442)|v0.4.1 |
+|Geehy | APM32E10x APM32F0xx| fsdev |[apm32_repo](https://github.com/CherryUSB/cherryusb_apm32)|v0.4.1 |
+|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|latest |
+|Espressif | esp32 | dwc2 |[esp32_repo](https://github.com/CherryUSB/cherryusb_esp32)|v0.4.1 |
+|Mindmotion | MM32L3xx | mm32 |[mm32_repo](https://github.com/CherryUSB/cherryusb_mm32)|v0.4.1 |
+
+## Contact
+
+QQ 群:642693751
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/class/audio/usb_audio.h b/third-party/cherryusb-0.6.0/class/audio/usb_audio.h
new file mode 100644
index 0000000000000000000000000000000000000000..e9d4ff494cce37ed143e8631fd59157684f9ef77
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/audio/usb_audio.h
@@ -0,0 +1,1089 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_AUDIO_H
+#define USB_AUDIO_H
+
+/** Audio Interface Subclass Codes
+ * Refer to Table A-2 from audio10.pdf
+ */
+#define AUDIO_SUBCLASS_UNDEFINED 0x00
+#define AUDIO_SUBCLASS_AUDIOCONTROL 0x01
+#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02
+#define AUDIO_SUBCLASS_MIDISTREAMING 0x03
+
+#define AUDIO_PROTOCOL_UNDEFINED 0x00
+#define AUDIO_PROTOCOLv20 0x20 /* IP version 2.0 */
+
+/** Audio Class-Specific Request Codes
+ * Refer to Table A-9 from audio10.pdf
+ */
+#define AUDIO_REQUEST_UNDEFINED 0x00
+#define AUDIO_REQUEST_SET_CUR 0x01
+#define AUDIO_REQUEST_GET_CUR 0x81
+#define AUDIO_REQUEST_SET_MIN 0x02
+#define AUDIO_REQUEST_GET_MIN 0x82
+#define AUDIO_REQUEST_SET_MAX 0x03
+#define AUDIO_REQUEST_GET_MAX 0x83
+#define AUDIO_REQUEST_SET_RES 0x04
+#define AUDIO_REQUEST_GET_RES 0x84
+#define AUDIO_REQUEST_SET_MEM 0x05
+#define AUDIO_REQUEST_GET_MEM 0x85
+#define AUDIO_REQUEST_GET_STAT 0xFF
+
+/** Audio Class-Specific Request Codes
+ * Refer from audio20_final.pdf
+ */
+#define AUDIO_REQUEST_CUR 0x01
+#define AUDIO_REQUEST_RANGE 0x02
+/** Audio Class-Specific Control Interface Descriptor Subtypes
+ * Refer to Table A-5 from audio10.pdf
+ */
+#define AUDIO_CONTROL_UNDEF 0x01U
+#define AUDIO_CONTROL_HEADER 0x01U
+#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U
+#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U
+#define AUDIO_CONTROL_MIXER_UNIT 0x04U
+#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U
+#define AUDIO_CONTROL_FEATURE_UNIT 0x06U
+#define AUDIO_CONTROL_EFFECT_UNIT 0x07U
+#define AUDIO_CONTROL_PROCESSING_UNIT 0x08U
+#define AUDIO_CONTROL_EXTENSION_UNIT 0x09U
+#define AUDIO_CONTROL_CLOCK_SOURCE 0x0aU
+#define AUDIO_CONTROL_CLOCK_SELECTOR 0x0bU
+#define AUDIO_CONTROL_CLOCK_MULTIPLIER 0x0cU
+#define AUDIO_CONTROL_SAMPLERATE_CONVERTER 0x0dU
+
+/** Audio Class-Specific AS Interface Descriptor Subtypes
+ * Refer to Table A-6 from audio10.pdf
+ */
+#define AUDIO_STREAMING_UNDEFINED 0x00U
+#define AUDIO_STREAMING_GENERAL 0x01U
+#define AUDIO_STREAMING_FORMAT_TYPE 0x02U
+#define AUDIO_STREAMING_ENCODER 0x03U
+#define AUDIO_STREAMING_DECODER 0x04U
+
+/* Clock Source Descriptor Clock Types */
+#define AUDIO_CLKSRC_EXTERNAL 0x00 /* External clock */
+#define AUDIO_CLKSRC_INTERNAL_FIXED 0x01 /* Internal fixed clock */
+#define AUDIO_CLKSRC_INTERNAL_VAR 0x02 /* Internal variable clock */
+#define AUDIO_CLKSRC_INTERNAL_PROG 0x03 /* Internal programmable clock */
+
+/* Effect Unit Effect Types */
+#define AUDIO_EFFECT_UNDEF 0x00
+#define AUDIO_EFFECT_PARAM_EQ_SECTION 0x01
+#define AUDIO_EFFECT_REVERBERATION 0x02
+#define AUDIO_EFFECT_MOD_DELAY 0x03
+#define AUDIO_EFFECT_DYN_RANGE_COMP 0x04
+
+/* Processing Unit Process Types */
+#define AUDIO_PROCESS_UNDEFINED 0x00
+#define AUDIO_PROCESS_UPDOWNMIX 0x01
+#define AUDIO_PROCESS_DOLBY_PROLOGIC 0x02
+#define AUDIO_PROCESS_STEREO_EXTENDER 0x03
+
+/* Audio Class-Specific Endpoint Descriptor Subtypes */
+#define AUDIO_ENDPOINT_UNDEFINED 0x00U
+#define AUDIO_ENDPOINT_GENERAL 0x01U
+
+/* Feature Unit Control Bits */
+#define AUDIO_CONTROL_MUTE 0x0001
+#define AUDIO_CONTROL_VOLUME 0x0002
+#define AUDIO_CONTROL_BASS 0x0004
+#define AUDIO_CONTROL_MID 0x0008
+#define AUDIO_CONTROL_TREBLE 0x0010
+#define AUDIO_CONTROL_GRAPHIC_EQUALIZER 0x0020
+#define AUDIO_CONTROL_AUTOMATIC_GAIN 0x0040
+#define AUDIO_CONTROL_DEALY 0x0080
+#define AUDIO_CONTROL_BASS_BOOST 0x0100
+#define AUDIO_CONTROL_LOUDNESS 0x0200
+
+/* Encoder Type Codes */
+#define AUDIO_ENCODER_UNDEF 0x00
+#define AUDIO_ENCODER_OTHER 0x01
+#define AUDIO_ENCODER_MPEG 0x02
+#define AUDIO_ENCODER_AC3 0x03
+#define AUDIO_ENCODER_WMA 0x04
+#define AUDIO_ENCODER_DTS 0x05
+
+/* Decoder Type Codes */
+#define AUDIO_DECODER_UNDEF 0x00
+#define AUDIO_DECODER_OTHER 0x01
+#define AUDIO_DECODER_MPEG 0x02
+#define AUDIO_DECODER_AC3 0x03
+#define AUDIO_DECODER_WMA 0x04
+#define AUDIO_DECODER_DTS 0x05
+
+/* Audio Descriptor Types */
+#define AUDIO_UNDEFINED_DESCRIPTOR_TYPE 0x20
+#define AUDIO_DEVICE_DESCRIPTOR_TYPE 0x21
+#define AUDIO_CONFIGURATION_DESCRIPTOR_TYPE 0x22
+#define AUDIO_STRING_DESCRIPTOR_TYPE 0x23
+#define AUDIO_INTERFACE_DESCRIPTOR_TYPE 0x24
+#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE 0x25
+
+/* Audio Data Format Type I Codes */
+#define AUDIO_FORMAT_TYPE_I_UNDEFINED 0x0000
+#define AUDIO_FORMAT_PCM 0x0001
+#define AUDIO_FORMAT_PCM8 0x0002
+#define AUDIO_FORMAT_IEEE_FLOAT 0x0003
+#define AUDIO_FORMAT_ALAW 0x0004
+#define AUDIO_FORMAT_MULAW 0x0005
+
+/* bmChannelConfig: a bitmap field that indicates which spatial locations
+ * are occupied by the channels present in the cluster. The bit allocations
+ * are as follows:
+ */
+#define AUDIO_CHANNEL_M 0 /* Mono */
+#define AUDIO_CHANNEL_FL (1 << 0) /* Front Left */
+#define AUDIO_CHANNEL_FR (1 << 1) /* Front Right */
+#define AUDIO_CHANNEL_FC (1 << 2) /* Front Center */
+#define AUDIO_CHANNEL_LFE (1 << 3) /* Low Frequency Effects */
+#define AUDIO_CHANNEL_BL (1 << 4) /* Back Left */
+#define AUDIO_CHANNEL_BR (1 << 5) /* Back Right */
+#define AUDIO_CHANNEL_FLC (1 << 6) /* Front Left of Center */
+#define AUDIO_CHANNEL_FRC (1 << 7) /* Front Right of Center */
+#define AUDIO_CHANNEL_BC (1 << 8) /* Back Center */
+#define AUDIO_CHANNEL_SL (1 << 9) /* Side Left */
+#define AUDIO_CHANNEL_SR (1 << 10) /* Side Right */
+#define AUDIO_CHANNEL_TC (1 << 11) /* Top Center */
+#define AUDIO_CHANNEL_TFL (1 << 12) /* Top Front Left */
+#define AUDIO_CHANNEL_TFC (1 << 13) /* Top Front Center */
+#define AUDIO_CHANNEL_TFR (1 << 14) /* Top Front Right */
+#define AUDIO_CHANNEL_TBL (1 << 15) /* Top Back Left */
+#define AUDIO_CHANNEL_TBC (1 << 16) /* Top Back Center */
+#define AUDIO_CHANNEL_TBR (1 << 17) /* Top Back Right */
+#define AUDIO_CHANNEL_TFLC (1 << 18) /* Top Front Left of Center */
+#define AUDIO_CHANNEL_TFRC (1 << 19) /* Top Front Right of Center */
+#define AUDIO_CHANNEL_LLFE (1 << 20) /* Left Low Frequency Effects */
+#define AUDIO_CHANNEL_RLFE (1 << 21) /* Right Low Frequency Effects */
+#define AUDIO_CHANNEL_TSL (1 << 22) /* Top Side Left */
+#define AUDIO_CHANNEL_TSR (1 << 23) /* Top Side Right */
+#define AUDIO_CHANNEL_BOC (1 << 24) /* Bottom Center */
+#define AUDIO_CHANNEL_BLC (1 << 25) /* Back Left of Center */
+#define AUDIO_CHANNEL_BRC (1 << 26) /* Back Right of Center */
+ /* Bits 27-30: Reserved */
+#define AUDIO_CHANNEL_RD (1 << 31) /* Raw Data */
+
+/* Audio Function Category Codes */
+#define AUDIO_CATEGORY_UNDEF 0x00 /* Undefined */
+#define AUDIO_CATEGORY_SPEAKER 0x01 /* Desktop speaker */
+#define AUDIO_CATEGORY_THEATER 0x02 /* Home theater */
+#define AUDIO_CATEGORY_MICROPHONE 0x03 /* Microphone */
+#define AUDIO_CATEGORY_HEADSET 0x04 /* Headset */
+#define AUDIO_CATEGORY_TELEPHONE 0x05 /* Telephone */
+#define AUDIO_CATEGORY_CONVERTER 0x06 /* Converter */
+#define AUDIO_CATEGORY_RECORDER 0x07 /* Voice/Sound recorder */
+#define AUDIO_CATEGORY_IO_BOX 0x08 /* I/O box */
+#define AUDIO_CATEGORY_INSTRUMENT 0x09 /* Musical instrument */
+#define AUDIO_CATEGORY_PROAUDIO 0x0a /* Pro-audio */
+#define AUDIO_CATEGORY_AV 0x0b /* Audio/video */
+#define AUDIO_CATEGORY_CONTROL 0x0c /* Control panel */
+#define AUDIO_CATEGORY_OTHER 0xff
+
+/* Clock Source Control Selectors */
+#define AUDIO_CS_CONTROL_UNDEF 0x00
+#define AUDIO_CS_CONTROL_SAM_FREQ 0x01
+#define AUDIO_CS_CONTROL_CLOCK_VALID 0x02
+
+/* Clock Selector Control Selectors */
+#define AUDIO_CX_CONTROL_UNDEF 0x00
+#define AUDIO_CX_CONTROL_CLOCKSEL 0x01
+
+/* Clock Multiplier Control Selectors */
+#define AUDIO_CM_CONTROL_UNDEF 0x00
+#define AUDIO_CM_CONTROL_NUMERATOR 0x01
+#define AUDIO_CM_CONTROL_DENOMINATOR 0x02
+
+/* Terminal Control Selectors */
+#define AUDIO_TE_CONTROL_UNDEF 0x00
+#define AUDIO_TE_CONTROL_COPY_PROTECT 0x01
+#define AUDIO_TE_CONTROL_CONNECTOR 0x02
+#define AUDIO_TE_CONTROL_OVERLOAD 0x03
+#define AUDIO_TE_CONTROL_CLUSTER 0x04
+#define AUDIO_TE_CONTROL_UNDERFLOW 0x05
+#define AUDIO_TE_CONTROL_OVERFLOW 0x06
+#define AUDIO_TE_CONTROL_LATENCY 0x07
+
+/* Mixer Control Selectors */
+#define AUDIO_MU_CONTROL_UNDEF 0x00
+#define AUDIO_MU_CONTROL_MIXER 0x01
+#define AUDIO_MU_CONTROL_CLUSTER 0x02
+#define AUDIO_MU_CONTROL_UNDERFLOW 0x03
+#define AUDIO_MU_CONTROL_OVERFLOW 0x04
+#define AUDIO_MU_CONTROL_LATENCY 0x05
+
+/* Selector Control Selectors */
+#define AUDIO_SU_CONTROL_UNDEFINE 0x00
+#define AUDIO_SU_CONTROL_SELECTOR 0x01
+#define AUDIO_SU_CONTROL_LATENCY 0x02
+
+/* Feature Unit Control Selectors */
+#define AUDIO_FU_CONTROL_UNDEF 0x00
+#define AUDIO_FU_CONTROL_MUTE 0x01
+#define AUDIO_FU_CONTROL_VOLUME 0x02
+#define AUDIO_FU_CONTROL_BASS 0x03
+#define AUDIO_FU_CONTROL_MID 0x04
+#define AUDIO_FU_CONTROL_TREBLE 0x05
+#define AUDIO_FU_CONTROL_EQUALIZER 0x06
+#define AUDIO_FU_CONTROL_AGC 0x07
+#define AUDIO_FU_CONTROL_DELAY 0x08
+#define AUDIO_FU_CONTROL_BASS_BOOST 0x09
+#define AUDIO_FU_CONTROL_LOUDNESS 0x0a
+#define AUDIO_FU_CONTROL_INP_GAIN 0x0b
+#define AUDIO_FU_CONTROL_INP_GAIN_PAD 0x0c
+#define AUDIO_FU_CONTROL_PHASE_INVERT 0x0d
+#define AUDIO_FU_CONTROL_UNDERFLOW 0x0e
+#define AUDIO_FU_CONTROL_OVERFLOW 0x0f
+#define AUDIO_FU_CONTROL_LATENCY 0x10
+
+#define AUDIO_V2_FU_CONTROL_UNDEF 0x00
+#define AUDIO_V2_FU_CONTROL_MUTE (0x03 << 0)
+#define AUDIO_V2_FU_CONTROL_VOLUME (0x03 << 2)
+#define AUDIO_V2_FU_CONTROL_BASS (0x03 << 4)
+#define AUDIO_V2_FU_CONTROL_MID (0x03 << 6)
+#define AUDIO_V2_FU_CONTROL_TREBLE (0x03 << 8)
+#define AUDIO_V2_FU_CONTROL_EQUALIZER (0x03 << 10)
+#define AUDIO_V2_FU_CONTROL_AGC (0x03 << 12)
+#define AUDIO_V2_FU_CONTROL_DELAY (0x03 << 14)
+#define AUDIO_V2_FU_CONTROL_BASS_BOOST (0x03 << 16)
+#define AUDIO_V2_FU_CONTROL_LOUDNESS (0x03 << 18)
+#define AUDIO_V2_FU_CONTROL_INP_GAIN (0x03 << 20)
+#define AUDIO_V2_FU_CONTROL_INP_GAIN_PAD (0x03 << 22)
+#define AUDIO_V2_FU_CONTROL_PHASE_INVERT (0x03 << 24)
+#define AUDIO_V2_FU_CONTROL_UNDERFLOW (0x03 << 26)
+#define AUDIO_V2_FU_CONTROL_OVERFLOW (0x03 << 28)
+
+/* Parametric Equalizer Section Effect Unit Control Selectors */
+#define AUDIO_PE_CONTROL_UNDEF 0x00
+#define AUDIO_PE_CONTROL_ENABLE 0x01
+#define AUDIO_PE_CONTROL_CENTERFREQ 0x02
+#define AUDIO_PE_CONTROL_QFACTOR 0x03
+#define AUDIO_PE_CONTROL_GAIN 0x04
+#define AUDIO_PE_CONTROL_UNDERFLOW 0x05
+#define AUDIO_PE_CONTROL_OVERFLOW 0x06
+#define AUDIO_PE_CONTROL_LATENCY 0x07
+
+/* Reverberation Effect Unit Control Selectors */
+#define AUDIO_RV_CONTROL_UNDEF 0x00
+#define AUDIO_RV_CONTROL_ENABLE 0x01
+#define AUDIO_RV_CONTROL_TYPE 0x02
+#define AUDIO_RV_CONTROL_LEVEL 0x03
+#define AUDIO_RV_CONTROL_TIME 0x04
+#define AUDIO_RV_CONTROL_FEEDBACK 0x05
+#define AUDIO_RV_CONTROL_PREDELAY 0x06
+#define AUDIO_RV_CONTROL_DENSITY 0x07
+#define AUDIO_RV_CONTROL_HF_ROLLOFF 0x08
+#define AUDIO_RV_CONTROL_UNDERFLOW 0x09
+#define AUDIO_RV_CONTROL_OVERFLOW 0x0a
+#define AUDIO_RV_CONTROL_LATENCY 0x0b
+
+/* Modulation Delay Effect Unit Control Selectors */
+#define AUDIO_MD_CONTROL_UNDEF 0x00
+#define AUDIO_MD_CONTROL_ENABLE 0x01
+#define AUDIO_MD_CONTROL_BALANCE 0x02
+#define AUDIO_MD_CONTROL_RATE 0x03
+#define AUDIO_MD_CONTROL_DEPTH 0x04
+#define AUDIO_MD_CONTROL_TIME 0x05
+#define AUDIO_MD_CONTROL_FEEDBACK 0x06
+#define AUDIO_MD_CONTROL_UNDERFLOW 0x07
+#define AUDIO_MD_CONTROL_OVERFLOW 0x08
+#define AUDIO_MD_CONTROL_LATENCY 0x09
+
+/* Dynamic Range Compressor Effect Unit Control Selectors */
+#define AUDIO_DR_CONTROL_UNDEF 0x00
+#define AUDIO_DR_CONTROL_ENABLE 0x01
+#define AUDIO_DR_CONTROL_COMP_RATE 0x02
+#define AUDIO_DR_CONTROL_MAXAMPL 0x03
+#define AUDIO_DR_CONTROL_THRESHOLD 0x04
+#define AUDIO_DR_CONTROL_ATTACK_TIME 0x05
+#define AUDIO_DR_CONTROL_RELEASE_TIME 0x06
+#define AUDIO_DR_CONTROL_UNDERFLOW 0x07
+#define AUDIO_DR_CONTROL_OVERFLOW 0x08
+#define AUDIO_DR_CONTROL_LATENCY 0x09
+
+/* Up/Down-mix Processing Unit Control Selectors */
+#define AUDIO_UD_CONTROL_UNDEF 0x00
+#define AUDIO_UD_CONTROL_ENABLE 0x01
+#define AUDIO_UD_CONTROL_MODE_SELECT 0x02
+#define AUDIO_UD_CONTROL_CLUSTER 0x03
+#define AUDIO_UD_CONTROL_UNDERFLOW 0x04
+#define AUDIO_UD_CONTROL_OVERFLOW 0x05
+#define AUDIO_UD_CONTROL_LATENCY 0x06
+
+/* Dolby Prologic?Processing Unit Control Selectors */
+#define AUDIO_DP_CONTROL_UNDEF 0x00
+#define AUDIO_DP_CONTROL_ENABLE 0x01
+#define AUDIO_DP_CONTROL_MODE_SELECT 0x02
+#define AUDIO_DP_CONTROL_CLUSTER 0x03
+#define AUDIO_DP_CONTROL_UNDERFLOW 0x04
+#define AUDIO_DP_CONTROL_OVERFLOW 0x05
+#define AUDIO_DP_CONTROL_LATENCY 0x06
+
+/* Stereo Extender Processing Unit Control Selectors */
+#define AUDIO_STEXT_CONTROL_UNDEF 0x00
+#define AUDIO_STEXT_CONTROL_ENABLE 0x01
+#define AUDIO_STEXT_CONTROL_WIDTH 0x02
+#define AUDIO_STEXT_CONTROL_UNDERFLOW 0x03
+#define AUDIO_STEXT_CONTROL_OVERFLOW 0x04
+#define AUDIO_STEXT_CONTROL_LATENCY 0x05
+
+/* Extension Unit Control Selectors */
+
+#define AUDIO_XU_CONTROL_UNDEF 0x00
+#define AUDIO_XU_CONTROL_ENABLE 0x01
+#define AUDIO_XU_CONTROL_CLUSTER 0x02
+#define AUDIO_XU_CONTROL_UNDERFLOW 0x03
+#define AUDIO_XU_CONTROL_OVERFLOW 0x04
+#define AUDIO_XU_CONTROL_LATENCY 0x05
+
+/* AudioStreaming Interface Control Selectors */
+
+#define AUDIO_AS_CONTROL_UNDEF 0x00
+#define AUDIO_AS_CONTROL_ACT_ALT 0x01
+#define AUDIO_AS_CONTROL_VAL_ALT 0x02
+#define AUDIO_AS_CONTROL_AUDIO_FORMAT 0x03
+
+/* Encoder Control Selectors */
+
+#define AUDIO_EN_CONTROL_UNDEF 0x00
+#define AUDIO_EN_CONTROL_BIT_RATE 0x01
+#define AUDIO_EN_CONTROL_QUALITY 0x02
+#define AUDIO_EN_CONTROL_VBR 0x03
+#define AUDIO_EN_CONTROL_TYPE 0x04
+#define AUDIO_EN_CONTROL_UNDERFLOW 0x05
+#define AUDIO_EN_CONTROL_OVERFLOW 0x06
+#define AUDIO_EN_CONTROL_ENCODER_ERR 0x07
+#define AUDIO_EN_CONTROL_PARAM1 0x08
+#define AUDIO_EN_CONTROL_PARAM2 0x09
+#define AUDIO_EN_CONTROL_PARAM3 0x0a
+#define AUDIO_EN_CONTROL_PARAM4 0x0b
+#define AUDIO_EN_CONTROL_PARAM5 0x0c
+#define AUDIO_EN_CONTROL_PARAM6 0x0d
+#define AUDIO_EN_CONTROL_PARAM7 0x0e
+#define AUDIO_EN_CONTROL_PARAM8 0x0f
+
+/* MPEG Decoder Control Selectors */
+
+#define AUDIO_MPGD_CONTROL_UNDEF 0x00
+#define AUDIO_MPGD_CONTROL_DUAL_CHAN 0x01
+#define AUDIO_MPGD_CONTROL_2ND_STEREO 0x02
+#define AUDIO_MPGD_CONTROL_MULTILING 0x03
+#define AUDIO_MPGD_CONTROL_DYN_RANGE 0x04
+#define AUDIO_MPGD_CONTROL_SCALING 0x05
+#define AUDIO_MPGD_CONTROL_HILO_SCALE 0x06
+#define AUDIO_MPGD_CONTROL_UNDERFLOW 0x07
+#define AUDIO_MPGD_CONTROL_OVERFLOW 0x08
+#define AUDIO_MPGD_CONTROL_DECODE_ERR 0x09
+
+/* AC-3 Decoder Control Selectors */
+
+#define AUDIO_AC3D_CONTROL_UNDEF 0x00
+#define AUDIO_AC3D_CONTROL_MODE 0x01
+#define AUDIO_AC3D_CONTROL_DYN_RANGE 0x02
+#define AUDIO_AC3D_CONTROL_SCALING 0x03
+#define AUDIO_AC3D_CONTROL_HILO_SCALE 0x04
+#define AUDIO_AC3D_CONTROL_UNDERFLOW 0x05
+#define AUDIO_AC3D_CONTROL_OVERFLOW 0x06
+#define AUDIO_AC3D_CONTROL_DECODE_ERR 0x07
+
+/* WMA Decoder Control Selectors */
+
+#define AUDIO_WMAD_CONTROL_UNDEF 0x00
+#define AUDIO_WMAD_CONTROL_UNDERFLOW 0x01
+#define AUDIO_WMAD_CONTROL_OVERFLOW 0x02
+#define AUDIO_WMAD_CONTROL_DECODE_ERR 0x03
+
+/* DTS Decoder Control Selectors */
+
+#define AUDIO_DTSD_CONTROL_UNDEF 0x00
+#define AUDIO_DTSD_CONTROL_UNDERFLOW 0x01
+#define AUDIO_DTSD_CONTROL_OVERFLOW 0x02
+#define AUDIO_DTSD_CONTROL_DECODE_ERR 0x03
+
+/* Endpoint Control Selectors */
+#define AUDIO_EP_CONTROL_UNDEF 0x00
+#define AUDIO_EP_CONTROL_SAMPLING_FEQ 0x01
+#define AUDIO_EP_CONTROL_PITCH 0x02
+
+/* Encoder Error Codes */
+
+/* <0: Reserved for vendor extensions */
+
+#define AUDIO_ENCODER_SUCCESS 0 /* No Error */
+#define AUDIO_ENCODER_ERROR_NOMEM 1 /* Out of Memory */
+#define AUDIO_ENCODER_ERROR_BW 2 /* Out of Bandwidth */
+#define AUDIO_ENCODER_ERROR_CYCLE 3 /* Out of Processing Cycles */
+#define AUDIO_ENCODER_ERROR_FRAME 4 /* General Format Frame Error */
+#define AUDIO_ENCODER_ERROR_TOOSMALL 5 /* Format Frame Too Small */
+#define AUDIO_ENCODER_ERROR_TOOBIG 6 /* Format Frame Too Large */
+#define AUDIO_ENCODER_ERROR_BADFORMAT 7 /* Bad Data Format */
+#define AUDIO_ENCODER_ERROR_NCHAN 8 /* Incorrect Number of Channels */
+#define AUDIO_ENCODER_ERROR_RATE 9 /* Incorrect Sampling Rate */
+#define AUDIO_ENCODER_ERROR_BITRATE 10 /* Unable to Meet Target Bitrate */
+#define AUDIO_ENCODER_ERROR_PARMS 11 /* Inconsistent Set of Parameters */
+#define AUDIO_ENCODER_ERROR_NOTREADY 12 /* Not Ready */
+#define AUDIO_ENCODER_ERROR_BUSY 13 /* Busy */
+ /* >13: Reserved */
+
+/* Format Type Codes */
+
+#define AUDIO_FORMAT_TYPE_UNDEF 0x00
+#define AUDIO_FORMAT_TYPEI 0x01
+#define AUDIO_FORMAT_TYPEII 0x02
+#define AUDIO_FORMAT_TYPEIII 0x03
+#define AUDIO_FORMAT_TYPEIV 0x04
+#define AUDIO_FORMAT_EXT_TYPEI 0x81
+#define AUDIO_FORMAT_EXT_TYPEII 0x82
+#define AUDIO_FORMAT_EXT_TYPEIII 0x83
+
+/* Audio Data Format Type I Bit Allocations */
+
+#define AUDIO_FORMAT_TYPEI_PCM (1 << 0)
+#define AUDIO_FORMAT_TYPEI_PCM8 (1 << 1)
+#define AUDIO_FORMAT_TYPEI_IEEEFLOAT (1 << 2)
+#define AUDIO_FORMAT_TYPEI_ALAW (1 << 3)
+#define AUDIO_FORMAT_TYPEI_MULAW (1 << 4)
+#define AUDIO_FORMAT_TYPEI_RAWDATA (1 << 31)
+
+/* Audio Data Format Type II Bit Allocations */
+
+#define AUDIO_FORMAT_TYPEII_MPEG (1 << 0)
+#define AUDIO_FORMAT_TYPEII_AC3 (1 << 1)
+#define AUDIO_FORMAT_TYPEII_WMA (1 << 2)
+#define AUDIO_FORMAT_TYPEII_DTS (1 << 3)
+#define AUDIO_FORMAT_TYPEII_RAWDATA (1 << 31)
+
+/* Audio Data Format Type III Bit Allocations */
+
+#define AUDIO_FORMAT_TYPEIII_IEC61937_AC3 (1 << 0)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG1_L1 (1 << 1)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG1_L2_3 (1 << 1)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG2_NOEXT (1 << 2)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG2_EXT (1 << 3)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG2_AAC_ADTS (1 << 4)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG2_L1_LS (1 << 5)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG2_L2_3_LS (1 << 6)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_DTS_I (1 << 7)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_DTS_II (1 << 8)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_DTS_III (1 << 9)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_ATRAC (1 << 10)
+#define AUDIO_FORMAT_TYPEIII_IEC61937_ATRAC2_3 (1 << 11)
+#define AUDIO_FORMAT_TYPEIII_WMA (1 << 12)
+
+/* Audio Data Format Type IV Bit Allocations */
+
+#define AUDIO_FORMAT_TYPEIV_PCM (1 << 0)
+#define AUDIO_FORMAT_TYPEIV_PCM8 (1 << 1)
+#define AUDIO_FORMAT_TYPEIV_IEEE_FLOAT (1 << 2)
+#define AUDIO_FORMAT_TYPEIV_ALAW (1 << 3)
+#define AUDIO_FORMAT_TYPEIV_MULAW (1 << 4)
+#define AUDIO_FORMAT_TYPEIV_MPEG (1 << 5)
+#define AUDIO_FORMAT_TYPEIV_AC3 (1 << 6)
+#define AUDIO_FORMAT_TYPEIV_WMA (1 << 7)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_AC3 (1 << 8)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG1_L1 (1 << 9)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG1_L2_3 (1 << 10)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG2_NOEXT (1 << 10)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG2_EXT (1 << 11)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG2_AAC_ADTS (1 << 12)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG2_L1_LS (1 << 13)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG2_L2_3_LS (1 << 14)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_DTS_I (1 << 15)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_DTS_II (1 << 16)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_DTS_III (1 << 17)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_ATRAC (1 << 18)
+#define AUDIO_FORMAT_TYPEIV_IEC61937_ATRAC2_3 (1 << 19)
+#define AUDIO_FORMAT_TYPEIV_TYPE_III_WMA (1 << 20)
+#define AUDIO_FORMAT_TYPEIV_IEC60958_PCM (1 << 21)
+
+/* Side Band Protocol Codes */
+#define AUDIO_SIDEBAND_PROTOCOL_UNDEF 0x00
+#define AUDIO_PRES_TIMESTAMP_PROTOCOL 0x01
+
+/** USB Terminal Types
+ * Refer to Table 2-1 - Table 2-4 from termt10.pdf
+ */
+
+/* USB Terminal Types */
+#define AUDIO_TERMINAL_UNDEF 0x0100
+#define AUDIO_TERMINAL_STREAMING 0x0101
+#define AUDIO_TERMINAL_VENDOR 0x01ff
+
+/* Input Terminal Types */
+#define AUDIO_INTERM_UNDEF 0x0200 /* Undefined Type */
+#define AUDIO_INTERM_MIC 0x0201 /* A generic microhpone */
+#define AUDIO_INTERM_DESKTOP_MIC 0x0202 /* A desktop microphone */
+#define AUDIO_INTERM_PERSONAL_MIC 0x0203 /* Head-mounted or clip-on microphone */
+#define AUDIO_INTERM_OMNI_MIC 0x0204 /* Omni-directional microphone */
+#define AUDIO_INTERM_MIC_ARRAY 0x0205 /* Microphone array */
+#define AUDIO_INTERM_PROC_MIC_ARRAY 0x0206 /* Microphone array with signal processor */
+
+/* Output Terminal Types */
+#define AUDIO_OUTTERM_UNDEF 0x0300 /* Undefined Type */
+#define AUDIO_OUTTERM_SPEAKER 0x0301 /* Generic speakers */
+#define AUDIO_OUTTERM_HEADPHONES 0x0302 /* A head-mounted audio output device */
+#define AUDIO_OUTTERM_HEADDISPLAY 0x0303 /* Head Mounted Display Audio */
+#define AUDIO_OUTTERM_DESKTOP 0x0304 /* Desktop speaker */
+#define AUDIO_OUTTERM_ROOM 0x0305 /* Room speaker */
+#define AUDIO_OUTTERM_COMMS 0x0306 /* Communication speaker */
+#define AUDIO_OUTTERM_LOFREQ 0x0307 /* Low frequency effects speaker */
+
+/* Bi-directional Terminal Types */
+#define AUDIO_BIDITERM_UNDEF 0x0400 /* Undefined Type */
+#define AUDIO_BIDITERM_HANDSET 0x0401 /* Hand-held bi-directional audio device */
+#define AUDIO_BIDITERM_HEADSET 0x0402 /* Head-mounted bi-directional audio device */
+#define AUDIO_BIDITERM_SPEAKERPHONE 0x0403 /* Speakerphone, no echo reduction */
+#define AUDIO_BIDITERM_ECHOSUPPRESS 0x0404 /* Echo-suppressing speakerphone */
+#define AUDIO_BIDITERM_ECHOCANCEL 0x0405 /* Echo-canceling speakerphone */
+
+/* Telephony Terminal Types */
+#define AUDIO_TELETERM_UNDEF 0x0500 /* Undefined Type */
+#define AUDIO_TELETERM_PHONELINE 0x0501 /* Analog telephone line jack, an ISDN line,
+ * a proprietary PBX interface, or a wireless link */
+#define AUDIO_TELETERM_TELEPHONE 0x0502 /* Device can be used as a telephone */
+#define AUDIO_TELETERM_DOWNLINE 0x0503 /* Down Line Phone */
+
+/* External Terminal Types */
+#define AUDIO_EXTTERM_UNDEF 0x0600 /* Undefined Type */
+#define AUDIO_EXTTERM_ANALOG 0x0601 /* Generic analog connector */
+#define AUDIO_EXTTERM_DIGITAL 0x0602 /* Generic digital audio interface */
+#define AUDIO_EXTTERM_LINE 0x0603 /* Analog connector at standard line levels */
+#define AUDIO_EXTTERM_LEGACY 0x0604 /* Legacy audio line out connector */
+#define AUDIO_EXTTERM_SPDIF 0x0605 /* SPDIF interface */
+#define AUDIO_EXTTERM_1394DA 0x0606 /* 1394 DA stream */
+#define AUDIO_EXTTERM_1394DV 0x0607 /* 1394 DV stream soundtrack */
+#define AUDIO_EXTTERM_ADAT 0x0608 /* ADAT Lightpipe */
+#define AUDIO_EXTTERM_TDIF 0x0609 /* TDIF - Tascam Digital Interface */
+#define AUDIO_EXTTERM_MADI 0x060a /* MADI - Multi-channel Audio Digital Interface (AES) */
+
+/* Embedded Function Terminal Types */
+#define AUDIO_EMBEDTERM_UNDEF 0x0700 /* Undefined Type */
+#define AUDIO_EMBEDTERM_CALIBRATION 0x0701 /* Level Calibration Noise Source */
+#define AUDIO_EMBEDTERM_EQUALIZATION 0x0702 /* Equalization Noise */
+#define AUDIO_EMBEDTERM_CD 0x0703 /* CD player */
+#define AUDIO_EMBEDTERM_DAT 0x0704 /* Digital Audio Tape */
+#define AUDIO_EMBEDTERM_DCC 0x0705 /* Digital Compact Cassette */
+#define AUDIO_EMBEDTERM_COMPRESSED 0x0706 /* Compressed Audio Player */
+#define AUDIO_EMBEDTERM_TAPE 0x0707 /* Analog Audio Tape */
+#define AUDIO_EMBEDTERM_PHONOGRAPH 0x0708 /* Analog vinyl record player */
+#define AUDIO_EMBEDTERM_VCR 0x0709 /* Audio track of VCR */
+#define AUDIO_EMBEDTERM_VIDDISC 0x070a /* Audio track of VideoDisc player */
+#define AUDIO_EMBEDTERM_DVD 0x070b /* Audio track of DVD player */
+#define AUDIO_EMBEDTERM_TVTUNER 0x070c /* Audio track of TV tuner */
+#define AUDIO_EMBEDTERM_SATELLITE 0x070d /* Audio track of satellite receiver */
+#define AUDIO_EMBEDTERM_CABLETUNER 0x070e /* Audio track of cable tuner */
+#define AUDIO_EMBEDTERM_DSS 0x070f /* Audio track of DSS receiver */
+#define AUDIO_EMBEDTERM_RADIO 0x0710 /* AM/FM radio receiver */
+#define AUDIO_EMBEDTERM_TRANSMITTER 0x0711 /* AM/FM radio transmitter */
+#define AUDIO_EMBEDTERM_MULTITRACK 0x0712 /* A multi-track recording system */
+#define AUDIO_EMBEDTERM_SYNTHESIZER 0x0713 /* Synthesizer */
+#define AUDIO_EMBEDTERM_PIANO 0x0714 /* Piano */
+#define AUDIO_EMBEDTERM_GUITAR 0x0715 /* Guitar */
+#define AUDIO_EMBEDTERM_PERCUSSON 0x0716 /* Percussion Instrument */
+#define AUDIO_EMBEDTERM_INSTRUMENT 0x0717 /* Other Musical Instrument */
+
+#define AUDIO_FORMAT_TYPE_I 0x01
+#define AUDIO_FORMAT_TYPE_II 0x02
+#define AUDIO_FORMAT_TYPE_III 0x03
+
+struct audio_cs_if_ac_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint16_t bcdADC;
+ uint16_t wTotalLength;
+ uint8_t bInCollection;
+ uint8_t baInterfaceNr[];
+} __PACKED;
+
+#define AUDIO_SIZEOF_AC_HEADER_DESC(n) (8 + n)
+
+struct audio_cs_if_ac_input_terminal_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t bNrChannels;
+ uint16_t wChannelConfig;
+ uint8_t iChannelNames;
+ uint8_t iTerminal;
+} __PACKED;
+
+#define AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC (12)
+
+struct audio_cs_if_ac_output_terminal_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t bSourceID;
+ uint8_t iTerminal;
+} __PACKED;
+
+#define AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC (9)
+
+struct audio_cs_if_ac_feature_unit_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bUnitID;
+ uint8_t bSourceID;
+ uint8_t bControlSize;
+ uint8_t bmaControls[1];
+ uint8_t iFeature;
+} __PACKED;
+
+#define AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(ch, n) (7 + ch * n)
+
+struct audio_cs_if_as_general_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bTerminalLink;
+ uint8_t bDelay;
+ uint16_t wFormatTag;
+} __PACKED;
+
+#define AUDIO_SIZEOF_AS_GENERAL_DESC (7)
+
+struct audio_cs_if_as_format_type_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bFormatType;
+ uint8_t bNrChannels;
+ uint8_t bSubframeSize;
+ uint8_t bBitResolution;
+ uint8_t bSamFreqType;
+ uint8_t tSamFreq[3];
+} __PACKED;
+
+#define AUDIO_SIZEOF_FORMAT_TYPE_DESC(n) (8 + 3 * n)
+
+struct audio_ep_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bEndpointAddress;
+ uint8_t bmAttributes;
+ uint16_t wMaxPacketSize;
+ uint8_t bInterval;
+ uint8_t bRefresh;
+ uint8_t bSynchAddress;
+} __PACKED;
+
+#define AUDIO_SIZEOF_EP_DESC (9)
+
+struct audio_cs_ep_ep_general_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bmAttributes;
+ uint8_t bLockDelayUnits;
+ uint16_t wLockDelay;
+} __PACKED;
+
+#define AUDIO_SIZEOF_CS_EP_GENERAL_DESC (7)
+
+// clang-format off
+#define AUDIO_AC_DESCRIPTOR_INIT(bFirstInterface, bInterfaceCount, wTotalLength, stridx, ...) \
+ /* Interface Association Descriptor */ \
+ 0x08, \
+ USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
+ bFirstInterface, \
+ bInterfaceCount, \
+ USB_DEVICE_CLASS_AUDIO, \
+ AUDIO_SUBCLASS_AUDIOCONTROL, \
+ AUDIO_PROTOCOL_UNDEFINED, \
+ 0x00, \
+ /* ------------------ AudioControl Interface ------------------ */\
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bFirstInterface, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x00, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
+ AUDIO_SUBCLASS_AUDIOCONTROL, /* bInterfaceSubClass */ \
+ AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
+ stridx, /* iInterface */ \
+ 0x08 + PP_NARG(__VA_ARGS__), /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_CONTROL_HEADER, /* bDescriptorSubtype */ \
+ WBVAL(0x0100), /* bcdADC */ \
+ WBVAL(wTotalLength), /* wTotalLength */ \
+ PP_NARG(__VA_ARGS__), /* bInCollection */ \
+ __VA_ARGS__ /* baInterfaceNr */
+
+#define AUDIO_AC_DESCRIPTOR_INIT_LEN(n) (0x08 + 0x09 + 0x08 + n)
+
+#define AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(bTerminalID, wTerminalType, bNrChannels, wChannelConfig) \
+ 0x0C, /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_CONTROL_INPUT_TERMINAL, /* bDescriptorSubtype */ \
+ bTerminalID, /* bTerminalID */ \
+ WBVAL(wTerminalType), /* wTerminalType : Microphone 0x0201 */ \
+ 0x00, /* bAssocTerminal */ \
+ bNrChannels, /* bNrChannels */ \
+ WBVAL(wChannelConfig), /* wChannelConfig : Mono sets no position bits */ \
+ 0x00, /* iChannelNames */ \
+ 0x00 /* iTerminal */
+
+#define AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(bTerminalID, wTerminalType, bSourceID) \
+ 0x09, /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_CONTROL_OUTPUT_TERMINAL, /* bDescriptorSubtype */ \
+ bTerminalID, /* bTerminalID */ \
+ WBVAL(wTerminalType), /* wTerminalType : USB Streaming */ \
+ 0x00, /* bAssocTerminal */ \
+ bSourceID, /* bSourceID */ \
+ 0x00 /* iTerminal */
+
+#define AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(bUnitID, bSourceID, bControlSize, ...) \
+ 0x07 + PP_NARG(__VA_ARGS__), /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_CONTROL_FEATURE_UNIT, /* bDescriptorSubtype */ \
+ bUnitID, /* bUnitID */ \
+ bSourceID, /* bSourceID */ \
+ bControlSize, /* bControlSize */ \
+ __VA_ARGS__, /* bmaControls(0) Mute */ \
+ 0x00 /* iTerminal */
+
+#define AUDIO_AS_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bEndpointAddress, wMaxPacketSize, bInterval, ...) \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bInterfaceNumber, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x00, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
+ AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
+ AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
+ 0x00, /* iInterface */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bInterfaceNumber, /* bInterfaceNumber */ \
+ 0x01, /* bAlternateSetting */ \
+ 0x01, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
+ AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
+ AUDIO_PROTOCOL_UNDEFINED, /* bInterfaceProtocol */ \
+ 0x00, /* iInterface */ \
+ 0x07, /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ \
+ bTerminalLink, /* bTerminalLink : Unit ID of the Output Terminal*/ \
+ 0x01, /* bDelay */ \
+ WBVAL(AUDIO_FORMAT_PCM), /* wFormatTag : AUDIO_FORMAT_PCM */ \
+ 0x08 + PP_NARG(__VA_ARGS__), /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ \
+ AUDIO_FORMAT_TYPE_I, /* bFormatType */ \
+ bNrChannels, /* bNrChannels */ \
+ 0x02, /* bSubFrameSize : 2 Bytes per audio subframe */ \
+ 0x10, /* bBitResolution : 16 bits per sample */ \
+ (PP_NARG(__VA_ARGS__)/3), /* bSamFreqType : only one frequency supported */ \
+ __VA_ARGS__, /* tSamFreq : Audio sampling frequency coded on 3 bytes */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ bEndpointAddress, /* bEndpointAddress : IN endpoint 1 */ \
+ 0x01, /* bmAttributes */ \
+ WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
+ bInterval, /* bInterval : one packet per frame */ \
+ 0x00, /* bRefresh */ \
+ 0x00, /* bSynchAddress */ \
+ 0x07, /* bLength */ \
+ AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ \
+ AUDIO_EP_CONTROL_SAMPLING_FEQ, /* bmAttributes AUDIO_SAMPLING_FREQ_CONTROL */ \
+ 0x00, /* bLockDelayUnits */ \
+ 0x00, /* wLockDelay */ \
+ 0x00
+
+#define AUDIO_AS_DESCRIPTOR_INIT_LEN(n) (0x09 + 0x09 + 0x07 + 0x08 + 3 * n + 0x09 + 0x07)
+
+struct audio_v2_channel_cluster_descriptor {
+ uint8_t bNrChannels;
+ uint32_t bmChannelConfig;
+ uint8_t iChannelNames;
+} __PACKED;
+
+#define AUDIO_V2_SIZEOF_CHANNEL_CLUSTER_DESC (6)
+
+struct audio_v2_cs_if_ac_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint16_t bcdADC;
+ uint8_t bCategory;
+ uint16_t wTotalLength;
+ uint8_t bmControls;
+} __PACKED;
+
+#define AUDIO_V2_SIZEOF_AC_HEADER_DESC (9)
+
+struct audio_v2_cs_if_ac_clock_source_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bClockID;
+ uint8_t bmAttributes;
+ uint8_t bmControls;
+ uint8_t bAssocTerminal;
+ uint8_t iClockSource;
+} __PACKED;
+
+#define AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC (8)
+
+struct audio_v2_cs_if_ac_clock_selector_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bClockID;
+ uint8_t bNrInPins;
+ uint8_t baCSourceID[1];
+ uint8_t iClockSelector;
+} __PACKED;
+
+#define AUDIO_SIZEOF_AC_CLOCK_SELECTOR_DESC(n) (7 + n)
+
+struct audio_v2_cs_if_ac_clock_multiplier_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bClockID;
+ uint8_t bCSourceID;
+ uint8_t bmControls;
+ uint8_t iClockMultiplier;
+} __PACKED;
+
+#define AUDIO_SIZEOF_AC_CLOCK_MULTIPLIER_DESC() (7)
+
+struct audio_v2_cs_if_ac_input_terminal_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t bCSourceID;
+ uint8_t bNrChannels;
+ uint32_t wChannelConfig;
+ uint8_t iChannelNames;
+ uint16_t bmControls;
+ uint8_t iTerminal;
+} __PACKED;
+
+#define AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC (17)
+
+struct audio_v2_cs_if_ac_output_terminal_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t bSourceID;
+ uint8_t bCSourceID;
+ uint16_t bmControls;
+ uint8_t iTerminal;
+} __PACKED;
+
+#define AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC (12)
+
+struct audio_v2_cs_if_ac_feature_unit_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bUnitID;
+ uint8_t bSourceID;
+ uint32_t bmaControls[1];
+ uint8_t iFeature;
+} __PACKED;
+
+#define AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(ch) (6 + ch * 4)
+
+struct audio_v2_cs_if_as_general_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bTerminalLink;
+ uint8_t bmControls;
+ uint8_t bFormatType;
+ uint32_t bmFormats;
+ uint8_t bNrChannels;
+ uint32_t bmChannelConfig;
+ uint8_t iChannelNames;
+} __PACKED;
+
+#define AUDIO_V2_SIZEOF_AS_GENERAL_DESC (16)
+
+struct audio_v2_control_range1_param_block {
+ uint16_t wNumSubRanges;
+ struct
+ {
+ uint8_t bMin;
+ uint8_t bMax;
+ uint8_t bRes;
+ }subrange[];
+} __PACKED;
+
+struct audio_v2_control_range2_param_block {
+ uint16_t wNumSubRanges;
+ struct
+ {
+ uint16_t wMin;
+ uint16_t wMax;
+ uint16_t wRes;
+ }subrange[];
+} __PACKED;
+
+struct audio_v2_control_range3_param_block {
+ uint16_t wNumSubRanges;
+ struct
+ {
+ uint32_t dMin;
+ uint32_t dMax;
+ uint32_t dRes;
+ }subrange[];
+} __PACKED;
+
+#define AUDIO_V2_AC_DESCRIPTOR_INIT(bFirstInterface, bInterfaceCount, wTotalLength, bCategory, bmControls, stridx) \
+ /* Interface Association Descriptor */ \
+ 0x08, \
+ USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
+ bFirstInterface, \
+ bInterfaceCount, \
+ USB_DEVICE_CLASS_AUDIO, \
+ AUDIO_SUBCLASS_AUDIOCONTROL, \
+ AUDIO_PROTOCOLv20, \
+ 0x00, \
+ /* ------------------ AudioControl Interface ------------------ */\
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bFirstInterface, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x00, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
+ AUDIO_SUBCLASS_AUDIOCONTROL, /* bInterfaceSubClass */ \
+ AUDIO_PROTOCOLv20, /* bInterfaceProtocol */ \
+ stridx, /* iInterface */ \
+ 0x09, /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_CONTROL_HEADER, /* bDescriptorSubtype */ \
+ WBVAL(0x0200), /* bcdADC */ \
+ bCategory, /* bCategory */ \
+ WBVAL(wTotalLength), /* wTotalLength */ \
+ bmControls /* bmControls */ \
+
+#define AUDIO_V2_AC_DESCRIPTOR_INIT_LEN (0x08 + 0x09 + 0x09)
+
+#define AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(bClockID, bmAttributes, bmControls) \
+ 0x08, /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_CONTROL_CLOCK_SOURCE, /* bDescriptorSubtype */ \
+ bClockID, /* bClockID */ \
+ bmAttributes, /* bmAttributes */ \
+ bmControls, /* bmControls */ \
+ 0x00, /* bAssocTerminal */ \
+ 0x00 /* iClockSource */
+
+#define AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(bTerminalID, wTerminalType, bCSourceID, bNrChannels, wChannelConfig, bmControls) \
+ 0x11, /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_CONTROL_INPUT_TERMINAL, /* bDescriptorSubtype */ \
+ bTerminalID, /* bTerminalID */ \
+ WBVAL(wTerminalType), /* wTerminalType : Microphone 0x0201 */ \
+ 0x00, /* bAssocTerminal */ \
+ bCSourceID, /* bCSourceID */ \
+ bNrChannels, /* bNrChannels */ \
+ DBVAL(wChannelConfig), /* wChannelConfig : Mono sets no position bits */ \
+ 0x00, /* iChannelNames */ \
+ WBVAL(bmControls), /* bmControls */ \
+ 0x00 /* iTerminal */
+
+#define AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(bTerminalID, wTerminalType, bSourceID, bCSourceID, bmControls) \
+ 0x0c, /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_CONTROL_OUTPUT_TERMINAL, /* bDescriptorSubtype */ \
+ bTerminalID, /* bTerminalID */ \
+ WBVAL(wTerminalType), /* wTerminalType : USB Streaming */ \
+ 0x00, /* bAssocTerminal */ \
+ bSourceID, /* bSourceID */ \
+ bCSourceID, /* bCSourceID */ \
+ WBVAL(bmControls), /* bmControls */ \
+ 0x00 /* iTerminal */
+
+#define AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(bUnitID, bSourceID, ...) \
+ 0x06 + (PP_NARG(__VA_ARGS__)), /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_CONTROL_FEATURE_UNIT, /* bDescriptorSubtype */ \
+ bUnitID, /* bUnitID */ \
+ bSourceID, /* bSourceID */ \
+ __VA_ARGS__, /* bmaControls(0) Mute */ \
+ 0x00 /* iTerminal */
+
+#define AUDIO_V2_AS_DESCRIPTOR_INIT(bInterfaceNumber, bTerminalLink, bNrChannels, bmChannelConfig, bSubslotSize, bBitResolution, bEndpointAddress, wMaxPacketSize, bInterval) \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bInterfaceNumber, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x00, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
+ AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
+ AUDIO_PROTOCOLv20, /* bInterfaceProtocol */ \
+ 0x00, /* iInterface */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bInterfaceNumber, /* bInterfaceNumber */ \
+ 0x01, /* bAlternateSetting */ \
+ 0x01, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_AUDIO, /* bInterfaceClass */ \
+ AUDIO_SUBCLASS_AUDIOSTREAMING, /* bInterfaceSubClass */ \
+ AUDIO_PROTOCOLv20, /* bInterfaceProtocol */ \
+ 0x00, /* iInterface */ \
+ 0x10, /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_STREAMING_GENERAL, /* bDescriptorSubtype */ \
+ bTerminalLink, /* bTerminalLink : Unit ID of the Output Terminal*/ \
+ 0x00, /* bmControls */ \
+ AUDIO_FORMAT_TYPE_I, /* bFormatType : AUDIO_FORMAT_TYPE_I */ \
+ DBVAL(AUDIO_FORMAT_PCM), /* bmFormats PCM */ \
+ bNrChannels, /* bNrChannels */ \
+ DBVAL(bmChannelConfig), /* bmChannelConfig */ \
+ 0x00, /* iChannelNames */ \
+ 0x06, /* bLength */ \
+ AUDIO_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_STREAMING_FORMAT_TYPE, /* bDescriptorSubtype */ \
+ AUDIO_FORMAT_TYPE_I, /* bFormatType */ \
+ bSubslotSize, /* bSubslotSize */ \
+ bBitResolution, /* bBitResolution */ \
+ 0x07, /* bLength */ \
+ 0x05, /* bDescriptorType */ \
+ bEndpointAddress, /* bEndpointAddress 3 out endpoint for Audio */ \
+ 0x01, /* bmAttributes */ \
+ WBVAL(wMaxPacketSize), /* XXXX wMaxPacketSize in Bytes (Freq(Samples)*2(Stereo)*2(HalfWord)) */ \
+ bInterval, /* bInterval */ \
+ 0x08, /* bLength */ \
+ AUDIO_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ \
+ AUDIO_ENDPOINT_GENERAL, /* bDescriptor */ \
+ 0x00, /* bmAttributes */ \
+ 0x00, /* bmControls */ \
+ 0x00, /* bLockDelayUnits */ \
+ 0x00, /* wLockDelay */ \
+ 0x00
+
+// clang-format on
+
+#define AUDIO_V2_AS_DESCRIPTOR_INIT_LEN (0x09 + 0x09 + 0x10 + 0x06 + 0x07 + 0x08)
+
+#define AUDIO_SAMPLE_FREQ_NUM(num) (uint8_t)(num), (uint8_t)((num >> 8))
+#define AUDIO_SAMPLE_FREQ_3B(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))
+#define AUDIO_SAMPLE_FREQ_4B(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), \
+ (uint8_t)((frq >> 16)), (uint8_t)((frq >> 24))
+
+#endif /* USB_AUDIO_H */
diff --git a/third-party/cherryusb-0.6.0/class/audio/usbd_audio.c b/third-party/cherryusb-0.6.0/class/audio/usbd_audio.c
new file mode 100644
index 0000000000000000000000000000000000000000..6755b83dcc264e4fb098c73076e3bf9f7dda5d91
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/audio/usbd_audio.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "usbd_audio.h"
+
+#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
+struct usbd_audio_volume_info {
+ uint16_t vol_min;
+ uint16_t vol_max;
+ uint16_t vol_res;
+ uint16_t vol_current;
+};
+
+struct usbd_audio_attribute_control {
+ struct usbd_audio_volume_info volume[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
+ uint8_t mute[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
+ uint8_t automatic_gain[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
+};
+#else
+struct audio_v2_control_range2_param_block_default {
+ uint16_t wNumSubRanges;
+ struct
+ {
+ uint16_t wMin;
+ uint16_t wMax;
+ uint16_t wRes;
+ } subrange[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
+} __PACKED;
+
+struct usbd_audio_attribute_control {
+ uint32_t volume_bCUR;
+ uint32_t mute_bCUR;
+ struct audio_v2_control_range2_param_block_default volume;
+ uint8_t mute[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
+};
+#endif
+struct audio_entity_info {
+ usb_slist_t list;
+ uint8_t bDescriptorSubtype;
+ uint8_t bEntityId;
+ void *priv[2];
+};
+
+static usb_slist_t usbd_audio_entity_info_head = USB_SLIST_OBJECT_INIT(usbd_audio_entity_info_head);
+
+#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
+const uint8_t default_sampling_freq_table[] = {
+ AUDIO_SAMPLE_FREQ_NUM(1),
+ // AUDIO_SAMPLE_FREQ_4B(8000),
+ // AUDIO_SAMPLE_FREQ_4B(8000),
+ // AUDIO_SAMPLE_FREQ_4B(0x00),
+ AUDIO_SAMPLE_FREQ_4B(16000),
+ AUDIO_SAMPLE_FREQ_4B(16000),
+ AUDIO_SAMPLE_FREQ_4B(0x00),
+ AUDIO_SAMPLE_FREQ_4B(32000),
+ AUDIO_SAMPLE_FREQ_4B(32000),
+ AUDIO_SAMPLE_FREQ_4B(0x00),
+ AUDIO_SAMPLE_FREQ_4B(44100),
+ AUDIO_SAMPLE_FREQ_4B(44100),
+ AUDIO_SAMPLE_FREQ_4B(0x00),
+ AUDIO_SAMPLE_FREQ_4B(48000),
+ AUDIO_SAMPLE_FREQ_4B(48000),
+ AUDIO_SAMPLE_FREQ_4B(0x00),
+ AUDIO_SAMPLE_FREQ_4B(88200),
+ AUDIO_SAMPLE_FREQ_4B(88200),
+ AUDIO_SAMPLE_FREQ_4B(0x00),
+ AUDIO_SAMPLE_FREQ_4B(96000),
+ AUDIO_SAMPLE_FREQ_4B(96000),
+ AUDIO_SAMPLE_FREQ_4B(0x00),
+ AUDIO_SAMPLE_FREQ_4B(192000),
+ AUDIO_SAMPLE_FREQ_4B(192000),
+ AUDIO_SAMPLE_FREQ_4B(0x00),
+};
+#endif
+
+#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
+static int audio_class_endpoint_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ uint8_t control_selector;
+ uint32_t sampling_freq = 0;
+ uint8_t pitch_enable;
+ uint8_t ep;
+
+ if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_ENDPOINT) {
+ control_selector = HI_BYTE(setup->wValue);
+ ep = LO_BYTE(setup->wIndex);
+
+ switch (setup->bRequest) {
+ case AUDIO_REQUEST_SET_CUR:
+ switch (control_selector) {
+ case AUDIO_EP_CONTROL_SAMPLING_FEQ:
+ memcpy((uint8_t *)&sampling_freq, *data, *len);
+ USB_LOG_DBG("Set ep:%02x %d Hz\r\n", ep, (int)sampling_freq);
+ usbd_audio_set_sampling_freq(0, ep, sampling_freq);
+ break;
+ case AUDIO_EP_CONTROL_PITCH:
+ pitch_enable = (*data)[0];
+ usbd_audio_set_pitch(ep, pitch_enable);
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
+ return -1;
+ }
+ break;
+ case AUDIO_REQUEST_GET_CUR:
+ sampling_freq = 16000;
+ memcpy(*data, &sampling_freq, 4);
+ *len = 4;
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+static int audio_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ USB_LOG_DBG("AUDIO Class request: "
+ "bRequest 0x%02x\r\n",
+ setup->bRequest);
+
+ struct audio_entity_info *current_entity_info = NULL;
+ struct usbd_audio_attribute_control *current_feature_control = NULL;
+#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
+ uint32_t *sampling_freq;
+#endif
+ usb_slist_t *i;
+ uint8_t entity_id;
+ uint8_t control_selector;
+ uint8_t ch;
+ uint8_t mute;
+ uint16_t volume;
+ const char *mute_string[2] = { "off", "on" };
+
+ entity_id = HI_BYTE(setup->wIndex);
+ control_selector = HI_BYTE(setup->wValue);
+ ch = LO_BYTE(setup->wValue);
+
+ ARG_UNUSED(mute_string);
+ if (ch > (CONFIG_USBDEV_AUDIO_MAX_CHANNEL - 1)) {
+ return -2;
+ }
+
+ usb_slist_for_each(i, &usbd_audio_entity_info_head)
+ {
+ struct audio_entity_info *tmp_entity_info = usb_slist_entry(i, struct audio_entity_info, list);
+ if (tmp_entity_info->bEntityId == entity_id) {
+ current_entity_info = tmp_entity_info;
+ break;
+ }
+ }
+
+ if (current_entity_info == NULL) {
+ return -2;
+ }
+
+ current_feature_control = (struct usbd_audio_attribute_control *)current_entity_info->priv[0];
+#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
+ sampling_freq = (uint32_t *)current_entity_info->priv[1];
+#endif
+ if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
+#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
+ float volume2db = 0.0;
+
+ switch (control_selector) {
+ case AUDIO_FU_CONTROL_MUTE:
+ switch (setup->bRequest) {
+ case AUDIO_REQUEST_SET_CUR:
+ mute = (*data)[0];
+ current_feature_control->mute[ch] = mute;
+ USB_LOG_DBG("Set UnitId:%d ch[%d] mute %s\r\n", entity_id, ch, mute_string[mute]);
+ usbd_audio_set_mute(entity_id, ch, mute);
+ break;
+ case AUDIO_REQUEST_GET_CUR:
+ (*data)[0] = current_feature_control->mute[ch];
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+
+ break;
+ case AUDIO_FU_CONTROL_VOLUME:
+ switch (setup->bRequest) {
+ case AUDIO_REQUEST_SET_CUR:
+ volume = (((uint16_t)(*data)[1] << 8) | ((uint16_t)(*data)[0]));
+ current_feature_control->volume[ch].vol_current = volume;
+
+ if (volume < 0x8000) {
+ volume2db = 0.00390625 * volume;
+ } else if (volume > 0x8000) {
+ volume2db = -0.00390625 * (0xffff - volume + 1);
+ }
+
+ USB_LOG_DBG("Set UnitId:%d ch[%d] %0.4f dB\r\n", entity_id, ch, volume2db);
+ usbd_audio_set_volume(entity_id, ch, volume2db);
+ break;
+ case AUDIO_REQUEST_GET_CUR:
+ memcpy(*data, ¤t_feature_control->volume[ch].vol_current, 2);
+ *len = 2;
+ break;
+
+ case AUDIO_REQUEST_GET_MIN:
+ memcpy(*data, ¤t_feature_control->volume[ch].vol_min, 2);
+ *len = 2;
+ break;
+
+ case AUDIO_REQUEST_GET_MAX:
+ memcpy(*data, ¤t_feature_control->volume[ch].vol_max, 2);
+ *len = 2;
+ break;
+
+ case AUDIO_REQUEST_GET_RES:
+ memcpy(*data, ¤t_feature_control->volume[ch].vol_res, 2);
+ *len = 2;
+ break;
+
+ case AUDIO_REQUEST_SET_RES:
+ memcpy(¤t_feature_control->volume[ch].vol_res, *data, 2);
+ *len = 2;
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
+ return -1;
+ }
+#else
+ switch (setup->bRequest) {
+ case AUDIO_REQUEST_CUR:
+ switch (control_selector) {
+ case AUDIO_FU_CONTROL_MUTE:
+ if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
+ (*data)[0] = current_feature_control->mute_bCUR;
+ *len = 1;
+ } else {
+ mute = (*data)[0];
+ USB_LOG_DBG("Set UnitId:%d ch[%d] mute %s\r\n", entity_id, ch, mute_string[mute]);
+ usbd_audio_set_mute(entity_id, ch, mute);
+ }
+ break;
+ case AUDIO_FU_CONTROL_VOLUME:
+ if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
+ (*data)[0] = current_feature_control->volume_bCUR & 0XFF;
+ (*data)[1] = (current_feature_control->volume_bCUR >> 8) & 0xff;
+ *len = 2;
+ } else {
+ volume = (((uint16_t)(*data)[1] << 8) | ((uint16_t)(*data)[0]));
+ current_feature_control->volume_bCUR = volume;
+ USB_LOG_DBG("Set UnitId:%d ch[%d] %d dB\r\n", entity_id, ch, volume);
+ usbd_audio_set_volume(entity_id, ch, volume);
+ }
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
+ return -1;
+ }
+ break;
+ case AUDIO_REQUEST_RANGE:
+ switch (control_selector) {
+ case AUDIO_FU_CONTROL_VOLUME:
+ if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
+ *((uint16_t *)(*data + 0)) = current_feature_control->volume.wNumSubRanges;
+ *((uint16_t *)(*data + 2)) = current_feature_control->volume.subrange[ch].wMin;
+ *((uint16_t *)(*data + 4)) = current_feature_control->volume.subrange[ch].wMax;
+ *((uint16_t *)(*data + 6)) = current_feature_control->volume.subrange[ch].wRes;
+ *len = 8;
+ } else {
+ }
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
+ return -1;
+ }
+
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+#endif
+ }
+#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
+ else if (current_entity_info->bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
+ switch (setup->bRequest) {
+ case AUDIO_REQUEST_CUR:
+ switch (control_selector) {
+ case AUDIO_CS_CONTROL_SAM_FREQ:
+ if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
+ memcpy(*data, &sampling_freq[ch], sizeof(uint32_t));
+ *len = 4;
+ } else {
+ memcpy(&sampling_freq[ch], *data, setup->wLength);
+ USB_LOG_DBG("Set ClockId:%d ch[%d] %d Hz\r\n", entity_id, ch, (int)sampling_freq[ch]);
+ usbd_audio_set_sampling_freq(entity_id, ch, sampling_freq[ch]);
+ }
+ break;
+ case AUDIO_CS_CONTROL_CLOCK_VALID:
+ if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
+ (*data)[0] = 1;
+ *len = 1;
+ } else {
+ }
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
+ return -1;
+ }
+ break;
+ case AUDIO_REQUEST_RANGE:
+ switch (control_selector) {
+ case AUDIO_CS_CONTROL_SAM_FREQ:
+ if (setup->bmRequestType & USB_REQUEST_DIR_MASK) {
+ uint8_t *sampling_freq_table = NULL;
+ uint16_t num;
+
+ usbd_audio_get_sampling_freq_table(entity_id, &sampling_freq_table);
+ num = (uint16_t)((uint16_t)(sampling_freq_table[1] << 8) | ((uint16_t)sampling_freq_table[0]));
+ *data = sampling_freq_table;
+ *len = (12 * num + 2);
+ } else {
+ }
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Audio Class control selector 0x%02x\r\n", control_selector);
+ return -1;
+ }
+
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ }
+#endif
+ else {
+ return -1;
+ }
+ return 0;
+}
+
+static void audio_notify_handler(uint8_t event, void *arg)
+{
+ switch (event) {
+ case USBD_EVENT_RESET:
+
+ break;
+
+ case USBD_EVENT_SET_INTERFACE: {
+ struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
+ if (intf->bAlternateSetting == 1) {
+ usbd_audio_open(intf->bInterfaceNumber);
+ } else {
+ usbd_audio_close(intf->bInterfaceNumber);
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+struct usbd_interface *usbd_audio_alloc_intf(void)
+{
+ struct usbd_interface *intf = usb_malloc(sizeof(struct usbd_interface));
+ if (intf == NULL) {
+ USB_LOG_ERR("no mem to alloc intf\r\n");
+ return NULL;
+ }
+
+ intf->class_interface_handler = audio_class_interface_request_handler;
+#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
+ intf->class_endpoint_handler = audio_class_endpoint_request_handler;
+#else
+ intf->class_endpoint_handler = NULL;
+#endif
+ intf->vendor_handler = NULL;
+ intf->notify_handler = audio_notify_handler;
+
+ return intf;
+}
+
+void usbd_audio_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype)
+{
+ struct audio_entity_info *entity_info = usb_malloc(sizeof(struct audio_entity_info));
+ memset(entity_info, 0, sizeof(struct audio_entity_info));
+ entity_info->bEntityId = entity_id;
+ entity_info->bDescriptorSubtype = bDescriptorSubtype;
+
+ if (bDescriptorSubtype == AUDIO_CONTROL_FEATURE_UNIT) {
+#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
+ struct usbd_audio_attribute_control *control = usb_malloc(sizeof(struct usbd_audio_attribute_control));
+ memset(control, 0, sizeof(struct usbd_audio_attribute_control));
+ for (uint8_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
+ control->volume[ch].vol_min = 0xdb00;
+ control->volume[ch].vol_max = 0x0000;
+ control->volume[ch].vol_res = 0x0100;
+ control->volume[ch].vol_current = 0xf600;
+ control->mute[ch] = 0;
+ control->automatic_gain[ch] = 0;
+ }
+#else
+ struct usbd_audio_attribute_control *control = usb_malloc(sizeof(struct usbd_audio_attribute_control));
+ memset(control, 0, sizeof(struct usbd_audio_attribute_control));
+ for (uint8_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
+ control->volume.wNumSubRanges = 1;
+ control->volume.subrange[ch].wMin = 0;
+ control->volume.subrange[ch].wMax = 100;
+ control->volume.subrange[ch].wRes = 1;
+ control->mute[ch] = 0;
+ control->volume_bCUR = 50;
+ control->mute_bCUR = 0;
+ }
+#endif
+ entity_info->priv[0] = control;
+ } else if (bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
+#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
+ uint32_t *sampling_freq = usb_malloc(sizeof(uint32_t) * CONFIG_USBDEV_AUDIO_MAX_CHANNEL);
+ for (size_t ch = 0; ch < CONFIG_USBDEV_AUDIO_MAX_CHANNEL; ch++) {
+ sampling_freq[ch] = 16000;
+ }
+ entity_info->priv[1] = sampling_freq;
+#else
+ entity_info->priv[1] = NULL;
+#endif
+ }
+
+ usb_slist_add_tail(&usbd_audio_entity_info_head, &entity_info->list);
+}
+
+__WEAK void usbd_audio_set_volume(uint8_t entity_id, uint8_t ch, float dB)
+{
+}
+
+__WEAK void usbd_audio_set_mute(uint8_t entity_id, uint8_t ch, uint8_t enable)
+{
+}
+
+__WEAK void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
+{
+}
+#if CONFIG_USBDEV_AUDIO_VERSION >= 0x0200
+__WEAK void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table)
+{
+ *sampling_freq_table = (uint8_t *)default_sampling_freq_table;
+}
+#endif
+__WEAK void usbd_audio_set_pitch(uint8_t ep, bool enable)
+{
+}
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/class/audio/usbd_audio.h b/third-party/cherryusb-0.6.0/class/audio/usbd_audio.h
new file mode 100644
index 0000000000000000000000000000000000000000..723e866687531f1518d4a8f9239c0f2acf8d2136
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/audio/usbd_audio.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBD_AUDIO_H
+#define USBD_AUDIO_H
+
+#include "usb_audio.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Alloc audio interface driver */
+struct usbd_interface *usbd_audio_alloc_intf(void);
+
+void usbd_audio_open(uint8_t intf);
+void usbd_audio_close(uint8_t intf);
+void usbd_audio_add_entity(uint8_t entity_id, uint16_t bDescriptorSubtype);
+void usbd_audio_set_volume(uint8_t entity_id, uint8_t ch, float dB);
+void usbd_audio_set_mute(uint8_t entity_id, uint8_t ch, uint8_t enable);
+void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq);
+void usbd_audio_get_sampling_freq_table(uint8_t entity_id, uint8_t **sampling_freq_table);
+void usbd_audio_set_pitch(uint8_t ep, bool enable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBD_AUDIO_H */
diff --git a/third-party/cherryusb-0.6.0/class/cdc/usb_cdc.h b/third-party/cherryusb-0.6.0/class/cdc/usb_cdc.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed8184ebbf10350d801678de98002d16638c5beb
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/cdc/usb_cdc.h
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_CDC_H
+#define USB_CDC_H
+
+/*------------------------------------------------------------------------------
+ * Definitions based on usbcdc11.pdf (www.usb.org)
+ *----------------------------------------------------------------------------*/
+/* Communication device class specification version 1.10 */
+#define CDC_V1_10 0x0110U
+// Communication device class specification version 1.2
+#define CDC_V1_2_0 0x0120U
+
+/* Communication interface class code */
+/* (usbcdc11.pdf, 4.2, Table 15) */
+#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02U
+
+/* Communication interface class subclass codes */
+/* (usbcdc11.pdf, 4.3, Table 16) */
+#define CDC_SUBCLASS_NONE 0x00 /* Reserved */
+#define CDC_SUBCLASS_DLC 0x01 /* Direct Line Control Model */
+#define CDC_SUBCLASS_ACM 0x02 /* Abstract Control Model */
+#define CDC_SUBCLASS_TCM 0x03 /* Telephone Control Model */
+#define CDC_SUBCLASS_MCM 0x04 /* Multi-Channel Control Model */
+#define CDC_SUBCLASS_CAPI 0x05 /* CAPI Control Model */
+#define CDC_SUBCLASS_ECM 0x06 /* Ethernet Networking Control Model */
+#define CDC_SUBCLASS_ATM 0x07 /* ATM Networking Control Model */
+ /* 0x08-0x0d Reserved (future use) */
+#define CDC_SUBCLASS_MBIM 0x0e /* MBIM Control Model */
+ /* 0x0f-0x7f Reserved (future use) */
+ /* 0x80-0xfe Reserved (vendor specific) */
+
+#define CDC_DIRECT_LINE_CONTROL_MODEL 0x01U
+#define CDC_ABSTRACT_CONTROL_MODEL 0x02U
+#define CDC_TELEPHONE_CONTROL_MODEL 0x03U
+#define CDC_MULTI_CHANNEL_CONTROL_MODEL 0x04U
+#define CDC_CAPI_CONTROL_MODEL 0x05U
+#define CDC_ETHERNET_NETWORKING_CONTROL_MODEL 0x06U
+#define CDC_ATM_NETWORKING_CONTROL_MODEL 0x07U
+#define CDC_WIRELESS_HANDSET_CONTROL_MODEL 0x08U
+#define CDC_DEVICE_MANAGEMENT 0x09U
+#define CDC_MOBILE_DIRECT_LINE_MODEL 0x0AU
+#define CDC_OBEX 0x0BU
+#define CDC_ETHERNET_EMULATION_MODEL 0x0CU
+#define CDC_NETWORK_CONTROL_MODEL 0x0DU
+
+/* Communication interface class control protocol codes */
+/* (usbcdc11.pdf, 4.4, Table 17) */
+#define CDC_COMMON_PROTOCOL_NONE 0x00U
+#define CDC_COMMON_PROTOCOL_AT_COMMANDS 0x01U
+#define CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101 0x02U
+#define CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO 0x03U
+#define CDC_COMMON_PROTOCOL_AT_COMMANDS_GSM_707 0x04U
+#define CDC_COMMON_PROTOCOL_AT_COMMANDS_3GPP_27007 0x05U
+#define CDC_COMMON_PROTOCOL_AT_COMMANDS_CDMA 0x06U
+#define CDC_COMMON_PROTOCOL_ETHERNET_EMULATION_MODEL 0x07U
+// NCM Communication Interface Protocol Codes
+// (usbncm10.pdf, 4.2, Table 4-2)
+#define CDC_NCM_PROTOCOL_NONE 0x00U
+#define CDC_NCM_PROTOCOL_OEM 0xFEU
+
+/* Data interface class code */
+/* (usbcdc11.pdf, 4.5, Table 18) */
+#define CDC_DATA_INTERFACE_CLASS 0x0A
+
+/* Data Interface Sub-Class Codes ********************************************/
+#define CDC_DATA_SUBCLASS_NONE 0x00
+
+/* Data interface class protocol codes */
+/* (usbcdc11.pdf, 4.7, Table 19) */
+#define CDC_DATA_PROTOCOL_ISDN_BRI 0x30
+#define CDC_DATA_PROTOCOL_HDLC 0x31
+#define CDC_DATA_PROTOCOL_TRANSPARENT 0x32
+#define CDC_DATA_PROTOCOL_Q921_MANAGEMENT 0x50
+#define CDC_DATA_PROTOCOL_Q921_DATA_LINK 0x51
+#define CDC_DATA_PROTOCOL_Q921_MULTIPLEXOR 0x52
+#define CDC_DATA_PROTOCOL_V42 0x90
+#define CDC_DATA_PROTOCOL_EURO_ISDN 0x91
+#define CDC_DATA_PROTOCOL_V24_RATE_ADAPTATION 0x92
+#define CDC_DATA_PROTOCOL_CAPI 0x93
+#define CDC_DATA_PROTOCOL_HOST_BASED_DRIVER 0xFD
+#define CDC_DATA_PROTOCOL_DESCRIBED_IN_PUFD 0xFE
+
+/* Type values for bDescriptorType field of functional descriptors */
+/* (usbcdc11.pdf, 5.2.3, Table 24) */
+#define CDC_CS_INTERFACE 0x24
+#define CDC_CS_ENDPOINT 0x25
+
+/* Type values for bDescriptorSubtype field of functional descriptors */
+/* (usbcdc11.pdf, 5.2.3, Table 25) */
+#define CDC_FUNC_DESC_HEADER 0x00
+#define CDC_FUNC_DESC_CALL_MANAGEMENT 0x01
+#define CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT 0x02
+#define CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT 0x03
+#define CDC_FUNC_DESC_TELEPHONE_RINGER 0x04
+#define CDC_FUNC_DESC_REPORTING_CAPABILITIES 0x05
+#define CDC_FUNC_DESC_UNION 0x06
+#define CDC_FUNC_DESC_COUNTRY_SELECTION 0x07
+#define CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES 0x08
+#define CDC_FUNC_DESC_USB_TERMINAL 0x09
+#define CDC_FUNC_DESC_NETWORK_CHANNEL 0x0A
+#define CDC_FUNC_DESC_PROTOCOL_UNIT 0x0B
+#define CDC_FUNC_DESC_EXTENSION_UNIT 0x0C
+#define CDC_FUNC_DESC_MULTI_CHANNEL_MANAGEMENT 0x0D
+#define CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT 0x0E
+#define CDC_FUNC_DESC_ETHERNET_NETWORKING 0x0F
+#define CDC_FUNC_DESC_ATM_NETWORKING 0x10
+#define CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL 0x11
+#define CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL 0x12
+#define CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL 0x13
+#define CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL 0x14
+#define CDC_FUNC_DESC_OBEX 0x15
+#define CDC_FUNC_DESC_COMMAND_SET 0x16
+#define CDC_FUNC_DESC_COMMAND_SET_DETAIL 0x17
+#define CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL 0x18
+#define CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER 0x19
+
+/* CDC class-specific request codes */
+/* (usbcdc11.pdf, 6.2, Table 46) */
+/* see Table 45 for info about the specific requests. */
+#define CDC_REQUEST_SEND_ENCAPSULATED_COMMAND 0x00
+#define CDC_REQUEST_GET_ENCAPSULATED_RESPONSE 0x01
+#define CDC_REQUEST_SET_COMM_FEATURE 0x02
+#define CDC_REQUEST_GET_COMM_FEATURE 0x03
+#define CDC_REQUEST_CLEAR_COMM_FEATURE 0x04
+#define CDC_REQUEST_SET_AUX_LINE_STATE 0x10
+#define CDC_REQUEST_SET_HOOK_STATE 0x11
+#define CDC_REQUEST_PULSE_SETUP 0x12
+#define CDC_REQUEST_SEND_PULSE 0x13
+#define CDC_REQUEST_SET_PULSE_TIME 0x14
+#define CDC_REQUEST_RING_AUX_JACK 0x15
+#define CDC_REQUEST_SET_LINE_CODING 0x20
+#define CDC_REQUEST_GET_LINE_CODING 0x21
+#define CDC_REQUEST_SET_CONTROL_LINE_STATE 0x22
+#define CDC_REQUEST_SEND_BREAK 0x23
+#define CDC_REQUEST_SET_RINGER_PARMS 0x30
+#define CDC_REQUEST_GET_RINGER_PARMS 0x31
+#define CDC_REQUEST_SET_OPERATION_PARMS 0x32
+#define CDC_REQUEST_GET_OPERATION_PARMS 0x33
+#define CDC_REQUEST_SET_LINE_PARMS 0x34
+#define CDC_REQUEST_GET_LINE_PARMS 0x35
+#define CDC_REQUEST_DIAL_DIGITS 0x36
+#define CDC_REQUEST_SET_UNIT_PARAMETER 0x37
+#define CDC_REQUEST_GET_UNIT_PARAMETER 0x38
+#define CDC_REQUEST_CLEAR_UNIT_PARAMETER 0x39
+#define CDC_REQUEST_GET_PROFILE 0x3A
+#define CDC_REQUEST_SET_ETHERNET_MULTICAST_FILTERS 0x40
+#define CDC_REQUEST_SET_ETHERNET_PMP_FILTER 0x41
+#define CDC_REQUEST_GET_ETHERNET_PMP_FILTER 0x42
+#define CDC_REQUEST_SET_ETHERNET_PACKET_FILTER 0x43
+#define CDC_REQUEST_GET_ETHERNET_STATISTIC 0x44
+#define CDC_REQUEST_SET_ATM_DATA_FORMAT 0x50
+#define CDC_REQUEST_GET_ATM_DEVICE_STATISTICS 0x51
+#define CDC_REQUEST_SET_ATM_DEFAULT_VC 0x52
+#define CDC_REQUEST_GET_ATM_VC_STATISTICS 0x53
+
+/* Communication feature selector codes */
+/* (usbcdc11.pdf, 6.2.2..6.2.4, Table 47) */
+#define CDC_ABSTRACT_STATE 0x01
+#define CDC_COUNTRY_SETTING 0x02
+
+/** Control Signal Bitmap Values for SetControlLineState */
+#define SET_CONTROL_LINE_STATE_RTS 0x02
+#define SET_CONTROL_LINE_STATE_DTR 0x01
+
+/* Feature Status returned for ABSTRACT_STATE Selector */
+/* (usbcdc11.pdf, 6.2.3, Table 48) */
+#define CDC_IDLE_SETTING (1 << 0)
+#define CDC_DATA_MULTPLEXED_STATE (1 << 1)
+
+/* Control signal bitmap values for the SetControlLineState request */
+/* (usbcdc11.pdf, 6.2.14, Table 51) */
+#define CDC_DTE_PRESENT (1 << 0)
+#define CDC_ACTIVATE_CARRIER (1 << 1)
+
+/* CDC class-specific notification codes */
+/* (usbcdc11.pdf, 6.3, Table 68) */
+/* see Table 67 for Info about class-specific notifications */
+#define CDC_NOTIFICATION_NETWORK_CONNECTION 0x00
+#define CDC_RESPONSE_AVAILABLE 0x01
+#define CDC_AUX_JACK_HOOK_STATE 0x08
+#define CDC_RING_DETECT 0x09
+#define CDC_NOTIFICATION_SERIAL_STATE 0x20
+#define CDC_CALL_STATE_CHANGE 0x28
+#define CDC_LINE_STATE_CHANGE 0x29
+#define CDC_CONNECTION_SPEED_CHANGE 0x2A
+
+/* UART state bitmap values (Serial state notification). */
+/* (usbcdc11.pdf, 6.3.5, Table 69) */
+#define CDC_SERIAL_STATE_OVERRUN (1 << 6) /* receive data overrun error has occurred */
+#define CDC_SERIAL_STATE_OVERRUN_Pos (6)
+#define CDC_SERIAL_STATE_OVERRUN_Msk (1 << CDC_SERIAL_STATE_OVERRUN_Pos)
+#define CDC_SERIAL_STATE_PARITY (1 << 5) /* parity error has occurred */
+#define CDC_SERIAL_STATE_PARITY_Pos (5)
+#define CDC_SERIAL_STATE_PARITY_Msk (1 << CDC_SERIAL_STATE_PARITY_Pos)
+#define CDC_SERIAL_STATE_FRAMING (1 << 4) /* framing error has occurred */
+#define CDC_SERIAL_STATE_FRAMING_Pos (4)
+#define CDC_SERIAL_STATE_FRAMING_Msk (1 << CDC_SERIAL_STATE_FRAMING_Pos)
+#define CDC_SERIAL_STATE_RING (1 << 3) /* state of ring signal detection */
+#define CDC_SERIAL_STATE_RING_Pos (3)
+#define CDC_SERIAL_STATE_RING_Msk (1 << CDC_SERIAL_STATE_RING_Pos)
+#define CDC_SERIAL_STATE_BREAK (1 << 2) /* state of break detection */
+#define CDC_SERIAL_STATE_BREAK_Pos (2)
+#define CDC_SERIAL_STATE_BREAK_Msk (1 << CDC_SERIAL_STATE_BREAK_Pos)
+#define CDC_SERIAL_STATE_TX_CARRIER (1 << 1) /* state of transmission carrier */
+#define CDC_SERIAL_STATE_TX_CARRIER_Pos (1)
+#define CDC_SERIAL_STATE_TX_CARRIER_Msk (1 << CDC_SERIAL_STATE_TX_CARRIER_Pos)
+#define CDC_SERIAL_STATE_RX_CARRIER (1 << 0) /* state of receiver carrier */
+#define CDC_SERIAL_STATE_RX_CARRIER_Pos (0)
+#define CDC_SERIAL_STATE_RX_CARRIER_Msk (1 << CDC_SERIAL_STATE_RX_CARRIER_Pos)
+
+/*------------------------------------------------------------------------------
+ * Structures based on usbcdc11.pdf (www.usb.org)
+ *----------------------------------------------------------------------------*/
+
+/* Header functional descriptor */
+/* (usbcdc11.pdf, 5.2.3.1) */
+/* This header must precede any list of class-specific descriptors. */
+struct cdc_header_descriptor {
+ uint8_t bFunctionLength; /* size of this descriptor in bytes */
+ uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
+ uint8_t bDescriptorSubtype; /* Header functional descriptor subtype */
+ uint16_t bcdCDC; /* USB CDC specification release version */
+} __PACKED;
+
+/* Call management functional descriptor */
+/* (usbcdc11.pdf, 5.2.3.2) */
+/* Describes the processing of calls for the communication class interface. */
+struct cdc_call_management_descriptor {
+ uint8_t bFunctionLength; /* size of this descriptor in bytes */
+ uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
+ uint8_t bDescriptorSubtype; /* call management functional descriptor subtype */
+ uint8_t bmCapabilities; /* capabilities that this configuration supports */
+ uint8_t bDataInterface; /* interface number of the data class interface used for call management (optional) */
+} __PACKED;
+
+/* Abstract control management functional descriptor */
+/* (usbcdc11.pdf, 5.2.3.3) */
+/* Describes the command supported by the communication interface class with the Abstract Control Model subclass code. */
+struct cdc_abstract_control_management_descriptor {
+ uint8_t bFunctionLength; /* size of this descriptor in bytes */
+ uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
+ uint8_t bDescriptorSubtype; /* abstract control management functional descriptor subtype */
+ uint8_t bmCapabilities; /* capabilities supported by this configuration */
+} __PACKED;
+
+/* Union functional descriptors */
+/* (usbcdc11.pdf, 5.2.3.8) */
+/* Describes the relationship between a group of interfaces that can be considered to form a functional unit. */
+struct cdc_union_descriptor {
+ uint8_t bFunctionLength; /* size of this descriptor in bytes */
+ uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */
+ uint8_t bDescriptorSubtype; /* union functional descriptor subtype */
+ uint8_t bMasterInterface; /* interface number designated as master */
+} __PACKED;
+
+/* Union functional descriptors with one slave interface */
+/* (usbcdc11.pdf, 5.2.3.8) */
+struct cdc_union_1slave_descriptor {
+ uint8_t bFunctionLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bControlInterface;
+ uint8_t bSubordinateInterface0;
+} __PACKED;
+
+/* Line coding structure for GET_LINE_CODING / SET_LINE_CODING class requests*/
+/* Format of the data returned when a GetLineCoding request is received */
+/* (usbcdc11.pdf, 6.2.13) */
+struct cdc_line_coding {
+ uint32_t dwDTERate; /* Data terminal rate in bits per second */
+ uint8_t bCharFormat; /* Number of stop bits */
+ uint8_t bParityType; /* Parity bit type */
+ uint8_t bDataBits; /* Number of data bits */
+} __PACKED;
+
+/** Data structure for the notification about SerialState */
+struct cdc_acm_notification {
+ uint8_t bmRequestType;
+ uint8_t bNotificationType;
+ uint16_t wValue;
+ uint16_t wIndex;
+ uint16_t wLength;
+ uint16_t data;
+} __PACKED;
+
+/** Ethernet Networking Functional Descriptor */
+struct cdc_ecm_descriptor {
+ uint8_t bFunctionLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t iMACAddress;
+ uint32_t bmEthernetStatistics;
+ uint16_t wMaxSegmentSize;
+ uint16_t wNumberMCFilters;
+ uint8_t bNumberPowerFilters;
+} __PACKED;
+
+/*Length of template descriptor: 66 bytes*/
+#define CDC_ACM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
+// clang-format off
+#ifndef CONFIG_USB_HS
+#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
+ /* Interface Associate */ \
+ 0x08, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
+ bFirstInterface, /* bFirstInterface */ \
+ 0x02, /* bInterfaceCount */ \
+ USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
+ CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \
+ CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bFunctionProtocol */ \
+ 0x00, /* iFunction */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bFirstInterface, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x01, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
+ CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \
+ CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bInterfaceProtocol */ \
+ str_idx, /* iInterface */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
+ WBVAL(CDC_V1_10), /* bcdCDC */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
+ 0x00, /* bmCapabilities */ \
+ (uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
+ 0x04, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
+ 0x02, /* bmCapabilities */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
+ bFirstInterface, /* bMasterInterface */ \
+ (uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ int_ep, /* bEndpointAddress */ \
+ 0x03, /* bmAttributes */ \
+ 0x08, 0x00, /* wMaxPacketSize */ \
+ 0x0a, /* bInterval */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ (uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x02, /* bNumEndpoints */ \
+ CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
+ 0x00, /* bInterfaceSubClass */ \
+ 0x00, /* bInterfaceProtocol */ \
+ 0x00, /* iInterface */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ out_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x40, 0x00, /* wMaxPacketSize */ \
+ 0x00, /* bInterval */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ in_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x40, 0x00, /* wMaxPacketSize */ \
+ 0x00 /* bInterval */
+#else
+#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
+ /* Interface Associate */ \
+ 0x08, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
+ bFirstInterface, /* bFirstInterface */ \
+ 0x02, /* bInterfaceCount */ \
+ USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \
+ CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \
+ CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bFunctionProtocol */ \
+ 0x00, /* iFunction */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bFirstInterface, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x01, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \
+ CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \
+ CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bInterfaceProtocol */ \
+ str_idx, /* iInterface */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
+ WBVAL(CDC_V1_10), /* bcdCDC */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
+ 0x00, /* bmCapabilities */ \
+ (uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
+ 0x04, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
+ 0x02, /* bmCapabilities */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
+ bFirstInterface, /* bMasterInterface */ \
+ (uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ int_ep, /* bEndpointAddress */ \
+ 0x03, /* bmAttributes */ \
+ 0x08, 0x00, /* wMaxPacketSize */ \
+ 0x10, /* bInterval */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ (uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x02, /* bNumEndpoints */ \
+ CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
+ 0x00, /* bInterfaceSubClass */ \
+ 0x00, /* bInterfaceProtocol */ \
+ 0x00, /* iInterface */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ out_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x00, 0x02, /* wMaxPacketSize */ \
+ 0x00, /* bInterval */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ in_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x00, 0x02, /* wMaxPacketSize */ \
+ 0x00 /* bInterval */
+#endif
+// clang-format on
+
+/*Length of template descriptor: 66 bytes*/
+#define CDC_RNDIS_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7)
+// clang-format off
+#ifndef CONFIG_USB_HS
+#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
+ /* Interface Associate */ \
+ 0x08, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
+ bFirstInterface, /* bFirstInterface */ \
+ 0x02, /* bInterfaceCount */ \
+ USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
+ CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
+ CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
+ 0x00, /* iFunction */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bFirstInterface, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x01, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
+ CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
+ CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
+ str_idx, /* iInterface */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
+ WBVAL(CDC_V1_10), /* bcdCDC */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
+ 0x00, /* bmCapabilities */ \
+ (uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
+ 0x04, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
+ 0x00, /* bmCapabilities */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
+ bFirstInterface, /* bMasterInterface */ \
+ (uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ int_ep, /* bEndpointAddress */ \
+ 0x03, /* bmAttributes */ \
+ 0x08, 0x00, /* wMaxPacketSize */ \
+ 0x10, /* bInterval */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ (uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x02, /* bNumEndpoints */ \
+ CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
+ 0x00, /* bInterfaceSubClass */ \
+ 0x00, /* bInterfaceProtocol */ \
+ 0x00, /* iInterface */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ out_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x40, 0x00, /* wMaxPacketSize */ \
+ 0x00, /* bInterval */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ in_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x40, 0x00, /* wMaxPacketSize */ \
+ 0x00 /* bInterval */
+#else
+#define CDC_RNDIS_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \
+ /* Interface Associate */ \
+ 0x08, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
+ bFirstInterface, /* bFirstInterface */ \
+ 0x02, /* bInterfaceCount */ \
+ USB_DEVICE_CLASS_WIRELESS, /* bFunctionClass */ \
+ CDC_DIRECT_LINE_CONTROL_MODEL, /* bFunctionSubClass */ \
+ CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bFunctionProtocol */ \
+ 0x00, /* iFunction */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bFirstInterface, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x01, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_WIRELESS, /* bInterfaceClass */ \
+ CDC_DIRECT_LINE_CONTROL_MODEL, /* bInterfaceSubClass */ \
+ CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO, /* bInterfaceProtocol */ \
+ str_idx, /* iInterface */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \
+ WBVAL(CDC_V1_10), /* bcdCDC */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \
+ 0x00, /* bmCapabilities */ \
+ (uint8_t)(bFirstInterface + 1), /* bDataInterface */ \
+ 0x04, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \
+ 0x00, /* bmCapabilities */ \
+ 0x05, /* bLength */ \
+ CDC_CS_INTERFACE, /* bDescriptorType */ \
+ CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \
+ bFirstInterface, /* bMasterInterface */ \
+ (uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ int_ep, /* bEndpointAddress */ \
+ 0x03, /* bmAttributes */ \
+ 0x08, 0x00, /* wMaxPacketSize */ \
+ 0x10, /* bInterval */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ (uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x02, /* bNumEndpoints */ \
+ CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \
+ 0x00, /* bInterfaceSubClass */ \
+ 0x00, /* bInterfaceProtocol */ \
+ 0x00, /* iInterface */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ out_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x00, 0x02, /* wMaxPacketSize */ \
+ 0x00, /* bInterval */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ in_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x00, 0x02, /* wMaxPacketSize */ \
+ 0x00 /* bInterval */
+#endif
+// clang-format on
+
+#endif /* USB_CDC_H */
diff --git a/third-party/cherryusb-0.6.0/class/cdc/usbd_cdc.c b/third-party/cherryusb-0.6.0/class/cdc/usbd_cdc.c
new file mode 100644
index 0000000000000000000000000000000000000000..8c9ee5a8d1fd9398df92c74e9310eff967a64d39
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/cdc/usbd_cdc.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "usbd_cdc.h"
+
+const char *stop_name[] = { "1", "1.5", "2" };
+const char *parity_name[] = { "N", "O", "E", "M", "S" };
+
+static int cdc_acm_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ USB_LOG_DBG("CDC Class request: "
+ "bRequest 0x%02x\r\n",
+ setup->bRequest);
+
+ struct cdc_line_coding line_coding;
+ bool dtr, rts;
+ uint8_t intf_num = LO_BYTE(setup->wIndex);
+
+ switch (setup->bRequest) {
+ case CDC_REQUEST_SET_LINE_CODING:
+
+ /*******************************************************************************/
+ /* Line Coding Structure */
+ /*-----------------------------------------------------------------------------*/
+ /* Offset | Field | Size | Value | Description */
+ /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/
+ /* 4 | bCharFormat | 1 | Number | Stop bits */
+ /* 0 - 1 Stop bit */
+ /* 1 - 1.5 Stop bits */
+ /* 2 - 2 Stop bits */
+ /* 5 | bParityType | 1 | Number | Parity */
+ /* 0 - None */
+ /* 1 - Odd */
+ /* 2 - Even */
+ /* 3 - Mark */
+ /* 4 - Space */
+ /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
+ /*******************************************************************************/
+ memcpy(&line_coding, *data, setup->wLength);
+ USB_LOG_DBG("Set intf:%d linecoding <%d %d %s %s>\r\n",
+ intf_num,
+ line_coding.dwDTERate,
+ line_coding.bDataBits,
+ parity_name[line_coding.bParityType],
+ stop_name[line_coding.bCharFormat]);
+ usbd_cdc_acm_set_line_coding(intf_num, &line_coding);
+ break;
+
+ case CDC_REQUEST_SET_CONTROL_LINE_STATE: {
+ dtr = (setup->wValue & 0x0001);
+ rts = (setup->wValue & 0x0002);
+ USB_LOG_DBG("Set intf:%d DTR 0x%x,RTS 0x%x\r\n",
+ intf_num,
+ dtr,
+ rts);
+ usbd_cdc_acm_set_dtr(intf_num, dtr);
+ usbd_cdc_acm_set_rts(intf_num, rts);
+ } break;
+
+ case CDC_REQUEST_GET_LINE_CODING:
+ usbd_cdc_acm_get_line_coding(intf_num, &line_coding);
+ memcpy(*data, &line_coding, 7);
+ *len = 7;
+ USB_LOG_DBG("Get intf:%d linecoding %d %d %d %d\r\n",
+ intf_num,
+ line_coding.dwDTERate,
+ line_coding.bCharFormat,
+ line_coding.bParityType,
+ line_coding.bDataBits);
+ break;
+
+ default:
+ USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void cdc_notify_handler(uint8_t event, void *arg)
+{
+ switch (event) {
+ case USBD_EVENT_RESET:
+ break;
+ default:
+ break;
+ }
+}
+
+struct usbd_interface *usbd_cdc_acm_alloc_intf(void)
+{
+ struct usbd_interface *intf = usb_malloc(sizeof(struct usbd_interface));
+ if (intf == NULL) {
+ USB_LOG_ERR("no mem to alloc intf\r\n");
+ return NULL;
+ }
+
+ intf->class_interface_handler = cdc_acm_class_interface_request_handler;
+ intf->class_endpoint_handler = NULL;
+ intf->vendor_handler = NULL;
+ intf->notify_handler = cdc_notify_handler;
+
+ return intf;
+}
+
+__WEAK void usbd_cdc_acm_set_line_coding(uint8_t intf, struct cdc_line_coding *line_coding)
+{
+}
+
+__WEAK void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *line_coding)
+{
+ line_coding->dwDTERate = 2000000;
+ line_coding->bDataBits = 8;
+ line_coding->bParityType = 0;
+ line_coding->bCharFormat = 0;
+}
+
+__WEAK void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr)
+{
+}
+
+__WEAK void usbd_cdc_acm_set_rts(uint8_t intf, bool rts)
+{
+}
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/class/cdc/usbd_cdc.h b/third-party/cherryusb-0.6.0/class/cdc/usbd_cdc.h
new file mode 100644
index 0000000000000000000000000000000000000000..8cd88270d86529829aec763fa5cd3c2c96605de3
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/cdc/usbd_cdc.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBD_CDC_H
+#define USBD_CDC_H
+
+#include "usb_cdc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Alloc cdc acm interface driver */
+struct usbd_interface *usbd_cdc_acm_alloc_intf(void);
+
+/* Setup request command callback api */
+void usbd_cdc_acm_set_line_coding(uint8_t intf, struct cdc_line_coding *line_coding);
+void usbd_cdc_acm_get_line_coding(uint8_t intf, struct cdc_line_coding *line_coding);
+void usbd_cdc_acm_set_dtr(uint8_t intf, bool dtr);
+void usbd_cdc_acm_set_rts(uint8_t intf, bool rts);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBD_CDC_H */
diff --git a/third-party/cherryusb-0.6.0/class/cdc/usbh_cdc_acm.c b/third-party/cherryusb-0.6.0/class/cdc/usbh_cdc_acm.c
new file mode 100644
index 0000000000000000000000000000000000000000..8d5a85f10c4b55d9e4097a6a35ef741432a414e4
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/cdc/usbh_cdc_acm.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbh_core.h"
+#include "usbh_cdc_acm.h"
+
+#define DEV_FORMAT "/dev/ttyACM%d"
+
+static uint32_t g_devinuse = 0;
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct cdc_line_coding g_cdc_line_coding;
+
+static int usbh_cdc_acm_devno_alloc(struct usbh_cdc_acm *cdc_acm_class)
+{
+ int devno;
+
+ for (devno = 0; devno < 32; devno++) {
+ uint32_t bitno = 1 << devno;
+ if ((g_devinuse & bitno) == 0) {
+ g_devinuse |= bitno;
+ cdc_acm_class->minor = devno;
+ return 0;
+ }
+ }
+ return -EMFILE;
+}
+
+static void usbh_cdc_acm_devno_free(struct usbh_cdc_acm *cdc_acm_class)
+{
+ int devno = cdc_acm_class->minor;
+
+ if (devno >= 0 && devno < 32) {
+ g_devinuse &= ~(1 << devno);
+ }
+}
+
+int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
+{
+ struct usb_setup_packet *setup = &cdc_acm_class->hport->setup;
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = CDC_REQUEST_SET_LINE_CODING;
+ setup->wValue = 0;
+ setup->wIndex = cdc_acm_class->ctrl_intf;
+ setup->wLength = 7;
+
+ memcpy((uint8_t *)&g_cdc_line_coding, line_coding, sizeof(struct cdc_line_coding));
+
+ return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding);
+}
+
+int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding)
+{
+ struct usb_setup_packet *setup = &cdc_acm_class->hport->setup;
+ int ret;
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = CDC_REQUEST_GET_LINE_CODING;
+ setup->wValue = 0;
+ setup->wIndex = cdc_acm_class->ctrl_intf;
+ setup->wLength = 7;
+
+ ret = usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)&g_cdc_line_coding);
+ if (ret < 0) {
+ return ret;
+ }
+ memcpy(line_coding, (uint8_t *)&g_cdc_line_coding, sizeof(struct cdc_line_coding));
+ return ret;
+}
+
+int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts)
+{
+ struct usb_setup_packet *setup = &cdc_acm_class->hport->setup;
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE;
+ setup->wValue = (dtr << 0) | (rts << 1);
+ setup->wIndex = cdc_acm_class->ctrl_intf;
+ setup->wLength = 0;
+
+ cdc_acm_class->dtr = dtr;
+ cdc_acm_class->rts = rts;
+
+ return usbh_control_transfer(cdc_acm_class->hport->ep0, setup, NULL);
+}
+
+static int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf)
+{
+ struct usb_endpoint_descriptor *ep_desc;
+ int ret;
+
+ struct usbh_cdc_acm *cdc_acm_class = usb_malloc(sizeof(struct usbh_cdc_acm));
+ if (cdc_acm_class == NULL) {
+ USB_LOG_ERR("Fail to alloc cdc_acm_class\r\n");
+ return -ENOMEM;
+ }
+
+ memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
+ usbh_cdc_acm_devno_alloc(cdc_acm_class);
+ cdc_acm_class->hport = hport;
+ cdc_acm_class->ctrl_intf = intf;
+ cdc_acm_class->data_intf = intf + 1;
+
+ hport->config.intf[intf].priv = cdc_acm_class;
+ hport->config.intf[intf + 1].priv = NULL;
+
+ cdc_acm_class->linecoding.dwDTERate = 115200;
+ cdc_acm_class->linecoding.bDataBits = 8;
+ cdc_acm_class->linecoding.bParityType = 0;
+ cdc_acm_class->linecoding.bCharFormat = 0;
+ ret = usbh_cdc_acm_set_line_coding(cdc_acm_class, &cdc_acm_class->linecoding);
+ if (ret < 0) {
+ USB_LOG_ERR("Fail to set linecoding\r\n");
+ return ret;
+ }
+
+ ret = usbh_cdc_acm_set_line_state(cdc_acm_class, true, true);
+ if (ret < 0) {
+ USB_LOG_ERR("Fail to set line state\r\n");
+ return ret;
+ }
+
+#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
+ ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
+ ep_cfg.ep_addr = ep_desc->bEndpointAddress;
+ ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
+ ep_cfg.ep_mps = ep_desc->wMaxPacketSize;
+ ep_cfg.ep_interval = ep_desc->bInterval;
+ ep_cfg.hport = hport;
+ usbh_pipe_alloc(&cdc_acm_class->intin, &ep_cfg);
+
+#endif
+ for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
+ ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
+
+ if (ep_desc->bEndpointAddress & 0x80) {
+ usbh_hport_activate_epx(&cdc_acm_class->bulkin, hport, ep_desc);
+ } else {
+ usbh_hport_activate_epx(&cdc_acm_class->bulkout, hport, ep_desc);
+ }
+ }
+
+ snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, cdc_acm_class->minor);
+
+ USB_LOG_INFO("Register CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
+
+ return ret;
+}
+
+static int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf)
+{
+ int ret = 0;
+
+ struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)hport->config.intf[intf].priv;
+
+ if (cdc_acm_class) {
+ usbh_cdc_acm_devno_free(cdc_acm_class);
+
+ if (cdc_acm_class->bulkin) {
+ usbh_pipe_free(cdc_acm_class->bulkin);
+ }
+
+ if (cdc_acm_class->bulkout) {
+ usbh_pipe_free(cdc_acm_class->bulkout);
+ }
+
+ memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm));
+ usb_free(cdc_acm_class);
+
+ if (hport->config.intf[intf].devname[0] != '\0'){
+ USB_LOG_INFO("Unregister CDC ACM Class:%s\r\n", hport->config.intf[intf].devname);
+ }
+ }
+
+ return ret;
+}
+
+const struct usbh_class_driver cdc_acm_class_driver = {
+ .driver_name = "cdc_acm",
+ .connect = usbh_cdc_acm_connect,
+ .disconnect = usbh_cdc_acm_disconnect
+};
+
+CLASS_INFO_DEFINE const struct usbh_class_info cdc_acm_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_ABSTRACT_CONTROL_MODEL,
+ .protocol = CDC_COMMON_PROTOCOL_AT_COMMANDS,
+ .vid = 0x00,
+ .pid = 0x00,
+ .class_driver = &cdc_acm_class_driver
+};
diff --git a/third-party/cherryusb-0.6.0/class/cdc/usbh_cdc_acm.h b/third-party/cherryusb-0.6.0/class/cdc/usbh_cdc_acm.h
new file mode 100644
index 0000000000000000000000000000000000000000..eda1ea935f8ad96751fa6b2910ee868d23e26505
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/cdc/usbh_cdc_acm.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBH_CDC_ACM_H
+#define USBH_CDC_ACM_H
+
+#include "usb_cdc.h"
+
+struct usbh_cdc_acm {
+ struct usbh_hubport *hport;
+
+ struct cdc_line_coding linecoding;
+ uint8_t ctrl_intf; /* Control interface number */
+ uint8_t data_intf; /* Data interface number */
+ bool dtr;
+ bool rts;
+ uint8_t minor;
+ usbh_pipe_t bulkin; /* Bulk IN endpoint */
+ usbh_pipe_t bulkout; /* Bulk OUT endpoint */
+#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
+ usbh_pipe_t intin; /* Interrupt IN endpoint (optional) */
+#endif
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int usbh_cdc_acm_set_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding);
+int usbh_cdc_acm_get_line_coding(struct usbh_cdc_acm *cdc_acm_class, struct cdc_line_coding *line_coding);
+int usbh_cdc_acm_set_line_state(struct usbh_cdc_acm *cdc_acm_class, bool dtr, bool rts);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBH_CDC_ACM_H */
diff --git a/third-party/cherryusb-0.6.0/class/dfu/usb_dfu.h b/third-party/cherryusb-0.6.0/class/dfu/usb_dfu.h
new file mode 100644
index 0000000000000000000000000000000000000000..f1ccba88cfbd902c376e8b17c6383db331fda6f3
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/dfu/usb_dfu.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_DFU_H
+#define USB_DFU_H
+
+/**\addtogroup USB_MODULE_DFU USB DFU class
+ * \brief This module contains USB Device Firmware Upgrade class definitions.
+ * \details This module based on
+ * + [USB Device Firmware Upgrade Specification, Revision 1.1]
+ * (https://www.usb.org/sites/default/files/DFU_1.1.pdf)
+ * @{ */
+
+/** DFU Specification release */
+#define DFU_VERSION 0x0110
+
+/** DFU Class Subclass */
+#define DFU_SUBCLASS_DFU 0x01
+
+/** DFU Class runtime Protocol */
+#define DFU_PROTOCOL_RUNTIME 0x01
+
+/** DFU Class DFU mode Protocol */
+#define DFU_PROTOCOL_MODE 0x02
+
+/**
+ * @brief DFU Class Specific Requests
+ */
+#define DFU_REQUEST_DETACH 0x00
+#define DFU_REQUEST_DNLOAD 0x01
+#define DFU_REQUEST_UPLOAD 0x02
+#define DFU_REQUEST_GETSTATUS 0x03
+#define DFU_REQUEST_CLRSTATUS 0x04
+#define DFU_REQUEST_GETSTATE 0x05
+#define DFU_REQUEST_ABORT 0x06
+
+/** DFU FUNCTIONAL descriptor type */
+#define DFU_FUNC_DESC 0x21
+
+/** DFU attributes DFU Functional Descriptor */
+#define DFU_ATTR_WILL_DETACH 0x08
+#define DFU_ATTR_MANIFESTATION_TOLERANT 0x04
+#define DFU_ATTR_CAN_UPLOAD 0x02
+#define DFU_ATTR_CAN_DNLOAD 0x01
+
+/** bStatus values for the DFU_GETSTATUS response */
+#define DFU_STATUS_OK 0x00U
+#define DFU_STATUS_ERR_TARGET 0x01U
+#define DFU_STATUS_ERR_FILE 0x02U
+#define DFU_STATUS_ERR_WRITE 0x03U
+#define DFU_STATUS_ERR_ERASE 0x04U
+#define DFU_STATUS_ERR_CHECK_ERASED 0x05U
+#define DFU_STATUS_ERR_PROG 0x06U
+#define DFU_STATUS_ERR_VERIFY 0x07U
+#define DFU_STATUS_ERR_ADDRESS 0x08U
+#define DFU_STATUS_ERR_NOTDONE 0x09U
+#define DFU_STATUS_ERR_FIRMWARE 0x0AU
+#define DFU_STATUS_ERR_VENDOR 0x0BU
+#define DFU_STATUS_ERR_USB 0x0CU
+#define DFU_STATUS_ERR_POR 0x0DU
+#define DFU_STATUS_ERR_UNKNOWN 0x0EU
+#define DFU_STATUS_ERR_STALLEDPKT 0x0FU
+
+/** bState values for the DFU_GETSTATUS response */
+#define DFU_STATE_APP_IDLE 0U
+#define DFU_STATE_APP_DETACH 1U
+#define DFU_STATE_DFU_IDLE 2U
+#define DFU_STATE_DFU_DNLOAD_SYNC 3U
+#define DFU_STATE_DFU_DNLOAD_BUSY 4U
+#define DFU_STATE_DFU_DNLOAD_IDLE 5U
+#define DFU_STATE_DFU_MANIFEST_SYNC 6U
+#define DFU_STATE_DFU_MANIFEST 7U
+#define DFU_STATE_DFU_MANIFEST_WAIT_RESET 8U
+#define DFU_STATE_DFU_UPLOAD_IDLE 9U
+#define DFU_STATE_DFU_ERROR 10U
+
+/** DFU Manifestation State */
+#define DFU_MANIFEST_COMPLETE 0U
+#define DFU_MANIFEST_IN_PROGRESS 1U
+
+/** Special Commands with Download Request */
+#define DFU_CMD_GETCOMMANDS 0U
+#define DFU_CMD_SETADDRESSPOINTER 0x21U
+#define DFU_CMD_ERASE 0x41U
+#define DFU_MEDIA_ERASE 0x00U
+#define DFU_MEDIA_PROGRAM 0x01U
+
+/** Other defines */
+/* Bit Detach capable = bit 3 in bmAttributes field */
+#define DFU_DETACH_MASK (1U << 3)
+#define DFU_MANIFEST_MASK (1U << 2)
+
+/** Run-Time Functional Descriptor */
+struct dfu_runtime_descriptor {
+ uint8_t bLength; /**<\brief Descriptor length in bytes.*/
+ uint8_t bDescriptorType; /**<\brief DFU functional descriptor type.*/
+ uint8_t bmAttributes; /**<\brief USB DFU capabilities \ref USB_DFU_CAPAB*/
+ uint16_t wDetachTimeout; /**<\brief USB DFU detach timeout in ms.*/
+ uint16_t wTransferSize; /**<\brief USB DFU maximum transfer block size in bytes.*/
+ uint16_t bcdDFUVersion; /**<\brief USB DFU version \ref VERSION_BCD utility macro.*/
+} __PACKED;
+
+/**\brief Payload packet to response in DFU_GETSTATUS request */
+struct dfu_info {
+ uint8_t bStatus; /**<\brief An indication of the status resulting from the
+ * execution of the most recent request.*/
+ uint8_t bPollTimeout; /**<\brief Minimum time (LSB) in ms, that the host should wait
+ * before sending a subsequent DFU_GETSTATUS request.*/
+ uint16_t wPollTimeout; /**<\brief Minimum time (MSB) in ms, that the host should wait
+ * before sending a subsequent DFU_GETSTATUS request.*/
+ uint8_t bState; /**<\brief An indication of the state that the device is going
+ * to enter immediately following transmission of this response.*/
+ uint8_t iString; /**<\brief Index of the status string descriptor.*/
+};
+
+// clang-format off
+#define DFU_DESCRIPTOR_INIT() \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ 0x00, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x00, /* bNumEndpoints Default Control Pipe only */ \
+ USB_DEVICE_CLASS_APP_SPECIFIC, /* bInterfaceClass */ \
+ 0x01, /* bInterfaceSubClass Device Firmware Upgrade */ \
+ 0x02, /* bInterfaceProtocol DFU mode */ \
+ 0x04, /* iInterface */ /*!< Device Firmware Update Functional Descriptor */ \
+ 0x09, /* bLength */ \
+ 0x21, /* DFU Functional Descriptor */ \
+ 0x0B, /* bmAttributes */ \
+ WBVAL(0x00ff), /* wDetachTimeOut */ \
+ WBVAL(USBD_DFU_XFER_SIZE), /* wTransferSize */ \
+ WBVAL(0x011a) /* bcdDFUVersion */
+// clang-format on
+
+#endif /* USB_DFU_H */
diff --git a/third-party/cherryusb-0.6.0/class/dfu/usbd_dfu.c b/third-party/cherryusb-0.6.0/class/dfu/usbd_dfu.c
new file mode 100644
index 0000000000000000000000000000000000000000..10c33a485f4787bab9c0c45cf82d04dd17020eb5
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/dfu/usbd_dfu.c
@@ -0,0 +1,513 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "usbd_dfu.h"
+
+/** Modify the following three parameters according to different platforms */
+#ifndef USBD_DFU_XFER_SIZE
+#define USBD_DFU_XFER_SIZE 1024
+#endif
+
+#ifndef USBD_DFU_APP_DEFAULT_ADD
+#define USBD_DFU_APP_DEFAULT_ADD 0x8004000
+#endif
+
+#ifndef FLASH_PROGRAM_TIME
+#define FLASH_PROGRAM_TIME 50
+#endif
+
+#ifndef FLASH_ERASE_TIME
+#define FLASH_ERASE_TIME 50
+#endif
+
+struct dfu_cfg_priv {
+ struct dfu_info info;
+ union {
+ uint32_t d32[USBD_DFU_XFER_SIZE / 4U];
+ uint8_t d8[USBD_DFU_XFER_SIZE];
+ } buffer;
+
+ uint32_t wblock_num;
+ uint32_t wlength;
+ uint32_t data_ptr;
+ uint32_t alt_setting;
+
+ uint8_t dev_status[6];
+ uint8_t ReservedForAlign[2];
+ uint8_t dev_state;
+ uint8_t manif_state;
+ uint8_t firmwar_flag;
+} usbd_dfu_cfg;
+
+static void dfu_reset(void)
+{
+ memset(&usbd_dfu_cfg, 0, sizeof(usbd_dfu_cfg));
+
+ usbd_dfu_cfg.alt_setting = 0U;
+ usbd_dfu_cfg.data_ptr = USBD_DFU_APP_DEFAULT_ADD;
+ usbd_dfu_cfg.wblock_num = 0U;
+ usbd_dfu_cfg.wlength = 0U;
+
+ usbd_dfu_cfg.manif_state = DFU_MANIFEST_COMPLETE;
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
+
+ usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = DFU_STATE_DFU_IDLE;
+ usbd_dfu_cfg.dev_status[5] = 0U;
+}
+
+static uint16_t dfu_getstatus(uint32_t add, uint8_t cmd, uint8_t *buffer)
+{
+ switch (cmd) {
+ case DFU_MEDIA_PROGRAM:
+ buffer[1] = (uint8_t)FLASH_PROGRAM_TIME;
+ buffer[2] = (uint8_t)(FLASH_PROGRAM_TIME << 8);
+ buffer[3] = 0;
+ break;
+
+ case DFU_MEDIA_ERASE:
+ buffer[1] = (uint8_t)FLASH_ERASE_TIME;
+ buffer[2] = (uint8_t)(FLASH_ERASE_TIME << 8);
+ buffer[3] = 0;
+ default:
+
+ break;
+ }
+ return (0);
+}
+
+static void dfu_request_detach(void)
+{
+ if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) ||
+ (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
+ (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
+ (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
+ (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
+ /* Update the state machine */
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
+ usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U; /*bwPollTimeout=0ms*/
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+ usbd_dfu_cfg.dev_status[5] = 0U; /*iString*/
+ usbd_dfu_cfg.wblock_num = 0U;
+ usbd_dfu_cfg.wlength = 0U;
+ }
+}
+
+static void dfu_request_upload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ struct usb_setup_packet *req = setup;
+ uint32_t addr;
+ uint8_t *phaddr;
+ /* Data setup request */
+ if (req->wLength > 0U) {
+ if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
+ /* Update the global length and block number */
+ usbd_dfu_cfg.wblock_num = req->wValue;
+ usbd_dfu_cfg.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
+
+ /* DFU Get Command */
+ if (usbd_dfu_cfg.wblock_num == 0U) {
+ /* Update the state machine */
+ usbd_dfu_cfg.dev_state = (usbd_dfu_cfg.wlength > 3U) ? DFU_STATE_DFU_IDLE : DFU_STATE_DFU_UPLOAD_IDLE;
+
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+
+ /* Store the values of all supported commands */
+ usbd_dfu_cfg.buffer.d8[0] = DFU_CMD_GETCOMMANDS;
+ usbd_dfu_cfg.buffer.d8[1] = DFU_CMD_SETADDRESSPOINTER;
+ usbd_dfu_cfg.buffer.d8[2] = DFU_CMD_ERASE;
+
+ /* Send the status data over EP0 */
+ *data = usbd_dfu_cfg.buffer.d8;
+ *len = 3;
+ } else if (usbd_dfu_cfg.wblock_num > 1U) {
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_UPLOAD_IDLE;
+
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+
+ addr = ((usbd_dfu_cfg.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + usbd_dfu_cfg.data_ptr;
+
+ /* Return the physical address where data are stored */
+ phaddr = dfu_read_flash((uint8_t *)addr, usbd_dfu_cfg.buffer.d8, usbd_dfu_cfg.wlength);
+
+ /* Send the status data over EP0 */
+ *data = usbd_dfu_cfg.buffer.d8;
+ *len = usbd_dfu_cfg.wlength;
+ } else /* unsupported usbd_dfu_cfg.wblock_num */
+ {
+ usbd_dfu_cfg.dev_state = DFU_STATUS_ERR_STALLEDPKT;
+
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+
+ /* Call the error management function (command will be NAKed */
+ USB_LOG_ERR("Dfu_request_upload unsupported usbd_dfu_cfg.wblock_num\r\n");
+ }
+ }
+ /* Unsupported state */
+ else {
+ usbd_dfu_cfg.wlength = 0U;
+ usbd_dfu_cfg.wblock_num = 0U;
+
+ /* Call the error management function (command will be NAKed */
+ USB_LOG_ERR("Dfu_request_upload unsupported state\r\n");
+ }
+ }
+ /* No Data setup request */
+ else {
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
+
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+ }
+}
+
+static void dfu_request_dnload(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ /* Data setup request */
+ struct usb_setup_packet *req = setup;
+ if (req->wLength > 0U) {
+ if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE)) {
+ /* Update the global length and block number */
+ usbd_dfu_cfg.wblock_num = req->wValue;
+ usbd_dfu_cfg.wlength = MIN(req->wLength, USBD_DFU_XFER_SIZE);
+
+ /* Update the state machine */
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+
+ /*!< Data has received complete */
+ memcpy((uint8_t *)usbd_dfu_cfg.buffer.d8, (uint8_t *)*data, usbd_dfu_cfg.wlength);
+ /*!< Set flag = 1 Write the firmware to the flash in the next dfu_request_getstatus */
+ usbd_dfu_cfg.firmwar_flag = 1;
+ }
+ /* Unsupported state */
+ else {
+ USB_LOG_ERR("Dfu_request_dnload unsupported state\r\n");
+ }
+ }
+ /* 0 Data DNLOAD request */
+ else {
+ /* End of DNLOAD operation*/
+ if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) || (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE)) {
+ usbd_dfu_cfg.manif_state = DFU_MANIFEST_IN_PROGRESS;
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+ } else {
+ /* Call the error management function (command will be NAKed */
+ USB_LOG_ERR("Dfu_request_dnload End of DNLOAD operation but dev_state %02x \r\n", usbd_dfu_cfg.dev_state);
+ }
+ }
+}
+
+static int8_t dfu_getstatus_special_handler(void)
+{
+ uint32_t addr;
+ if (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_BUSY) {
+ /* Decode the Special Command */
+ if (usbd_dfu_cfg.wblock_num == 0U) {
+ if (usbd_dfu_cfg.wlength == 1U) {
+ if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_GETCOMMANDS) {
+ /* Nothing to do */
+ }
+ } else if (usbd_dfu_cfg.wlength == 5U) {
+ if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_SETADDRESSPOINTER) {
+ usbd_dfu_cfg.data_ptr = usbd_dfu_cfg.buffer.d8[1];
+ usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[2] << 8;
+ usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[3] << 16;
+ usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[4] << 24;
+ } else if (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_ERASE) {
+ usbd_dfu_cfg.data_ptr = usbd_dfu_cfg.buffer.d8[1];
+ usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[2] << 8;
+ usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[3] << 16;
+ usbd_dfu_cfg.data_ptr += (uint32_t)usbd_dfu_cfg.buffer.d8[4] << 24;
+
+ USB_LOG_DBG("Erase start add %08x \r\n", usbd_dfu_cfg.data_ptr);
+ /*!< Erase */
+ dfu_erase_flash(usbd_dfu_cfg.data_ptr);
+ } else {
+ return -1;
+ }
+ } else {
+ /* Reset the global length and block number */
+ usbd_dfu_cfg.wlength = 0U;
+ usbd_dfu_cfg.wblock_num = 0U;
+ /* Call the error management function (command will be NAKed) */
+ USB_LOG_ERR("Reset the global length and block number\r\n");
+ }
+ }
+ /* Regular Download Command */
+ else {
+ if (usbd_dfu_cfg.wblock_num > 1U) {
+ /* Decode the required address */
+ addr = ((usbd_dfu_cfg.wblock_num - 2U) * USBD_DFU_XFER_SIZE) + usbd_dfu_cfg.data_ptr;
+
+ /* Perform the write operation */
+ /* Write flash */
+ USB_LOG_DBG("Write start add %08x length %d\r\n", addr, usbd_dfu_cfg.wlength);
+ dfu_write_flash(usbd_dfu_cfg.buffer.d8, (uint8_t *)addr, usbd_dfu_cfg.wlength);
+ }
+ }
+
+ /* Reset the global length and block number */
+ usbd_dfu_cfg.wlength = 0U;
+ usbd_dfu_cfg.wblock_num = 0U;
+
+ /* Update the state machine */
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_SYNC;
+
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+ }
+ return 0;
+}
+
+static void dfu_request_getstatus(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ /*!< Determine whether to leave DFU mode */
+ if (usbd_dfu_cfg.manif_state == DFU_MANIFEST_IN_PROGRESS &&
+ usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC &&
+ usbd_dfu_cfg.dev_status[1] == 0U &&
+ usbd_dfu_cfg.dev_status[2] == 0U &&
+ usbd_dfu_cfg.dev_status[3] == 0U &&
+ usbd_dfu_cfg.dev_status[4] == usbd_dfu_cfg.dev_state) {
+ usbd_dfu_cfg.manif_state = DFU_MANIFEST_COMPLETE;
+
+ if ((0x0B & DFU_MANIFEST_MASK) != 0U) {
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_SYNC;
+
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+ return;
+ } else {
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST_WAIT_RESET;
+
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+ /* Generate system reset to allow jumping to the user code */
+ dfu_leave();
+ }
+ }
+
+ switch (usbd_dfu_cfg.dev_state) {
+ case DFU_STATE_DFU_DNLOAD_SYNC:
+ if (usbd_dfu_cfg.wlength != 0U) {
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_BUSY;
+
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+
+ if ((usbd_dfu_cfg.wblock_num == 0U) && (usbd_dfu_cfg.buffer.d8[0] == DFU_CMD_ERASE)) {
+ dfu_getstatus(usbd_dfu_cfg.data_ptr, DFU_MEDIA_ERASE, usbd_dfu_cfg.dev_status);
+ } else {
+ dfu_getstatus(usbd_dfu_cfg.data_ptr, DFU_MEDIA_PROGRAM, usbd_dfu_cfg.dev_status);
+ }
+ } else /* (usbd_dfu_cfg.wlength==0)*/
+ {
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_DNLOAD_IDLE;
+
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+ }
+ break;
+
+ case DFU_STATE_DFU_MANIFEST_SYNC:
+ if (usbd_dfu_cfg.manif_state == DFU_MANIFEST_IN_PROGRESS) {
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_MANIFEST;
+
+ usbd_dfu_cfg.dev_status[1] = 1U; /*bwPollTimeout = 1ms*/
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+ } else {
+ if ((usbd_dfu_cfg.manif_state == DFU_MANIFEST_COMPLETE) &&
+ ((0x0B & DFU_MANIFEST_MASK) != 0U)) {
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
+
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U;
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Send the status data over EP0 */
+ uint8_t temp_data[6];
+ memcpy(temp_data, usbd_dfu_cfg.dev_status, 6);
+ *data = temp_data;
+ *len = 6;
+
+ if (usbd_dfu_cfg.firmwar_flag == 1) {
+ if (dfu_getstatus_special_handler() != 0) {
+ USB_LOG_ERR("dfu_getstatus_special_handler error \r\n");
+ }
+ usbd_dfu_cfg.firmwar_flag = 0;
+ }
+}
+
+static void dfu_request_clrstatus(void)
+{
+ if (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_ERROR) {
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
+ usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK; /* bStatus */
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state; /* bState */
+ usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
+ } else {
+ /* State Error */
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_ERROR;
+ usbd_dfu_cfg.dev_status[0] = DFU_STATUS_ERR_UNKNOWN; /* bStatus */
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state; /* bState */
+ usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
+ }
+}
+
+static void dfu_request_getstate(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ /* Return the current state of the DFU interface */
+ *data = &usbd_dfu_cfg.dev_state;
+ *len = 1;
+}
+
+void dfu_request_abort(void)
+{
+ if ((usbd_dfu_cfg.dev_state == DFU_STATE_DFU_IDLE) ||
+ (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_SYNC) ||
+ (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_DNLOAD_IDLE) ||
+ (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_MANIFEST_SYNC) ||
+ (usbd_dfu_cfg.dev_state == DFU_STATE_DFU_UPLOAD_IDLE)) {
+ usbd_dfu_cfg.dev_state = DFU_STATE_DFU_IDLE;
+ usbd_dfu_cfg.dev_status[0] = DFU_STATUS_OK;
+ usbd_dfu_cfg.dev_status[1] = 0U;
+ usbd_dfu_cfg.dev_status[2] = 0U;
+ usbd_dfu_cfg.dev_status[3] = 0U; /* bwPollTimeout=0ms */
+ usbd_dfu_cfg.dev_status[4] = usbd_dfu_cfg.dev_state;
+ usbd_dfu_cfg.dev_status[5] = 0U; /* iString */
+ usbd_dfu_cfg.wblock_num = 0U;
+ usbd_dfu_cfg.wlength = 0U;
+ }
+}
+
+static int dfu_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ USB_LOG_DBG("DFU Class request: "
+ "bRequest 0x%02x\r\n",
+ setup->bRequest);
+
+ switch (setup->bRequest) {
+ case DFU_REQUEST_DETACH:
+ dfu_request_detach();
+ break;
+ case DFU_REQUEST_DNLOAD:
+ dfu_request_dnload(setup, data, len);
+ break;
+ case DFU_REQUEST_UPLOAD:
+ dfu_request_upload(setup, data, len);
+ break;
+ case DFU_REQUEST_GETSTATUS:
+ dfu_request_getstatus(setup, data, len);
+ break;
+ case DFU_REQUEST_CLRSTATUS:
+ dfu_request_clrstatus();
+ break;
+ case DFU_REQUEST_GETSTATE:
+ dfu_request_getstate(setup, data, len);
+ break;
+ case DFU_REQUEST_ABORT:
+ dfu_request_abort();
+ break;
+ default:
+ USB_LOG_WRN("Unhandled DFU Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void dfu_notify_handler(uint8_t event, void *arg)
+{
+ switch (event) {
+ case USBD_EVENT_RESET:
+ dfu_reset();
+ break;
+ default:
+ break;
+ }
+}
+
+struct usbd_interface *usbd_dfu_alloc_intf(void)
+{
+ struct usbd_interface *intf = usb_malloc(sizeof(struct usbd_interface));
+ if (intf == NULL) {
+ USB_LOG_ERR("no mem to alloc intf\r\n");
+ return NULL;
+ }
+
+ intf->class_interface_handler = dfu_class_interface_request_handler;
+ intf->class_endpoint_handler = NULL;
+ intf->vendor_handler = NULL;
+ intf->notify_handler = dfu_notify_handler;
+
+ return intf;
+}
+
+__WEAK uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len)
+{
+ return dest;
+}
+
+__WEAK uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len)
+{
+ return 0;
+}
+
+__WEAK uint16_t dfu_erase_flash(uint32_t add)
+{
+ return 0;
+}
+
+__WEAK void dfu_leave(void)
+{
+}
diff --git a/third-party/cherryusb-0.6.0/class/dfu/usbd_dfu.h b/third-party/cherryusb-0.6.0/class/dfu/usbd_dfu.h
new file mode 100644
index 0000000000000000000000000000000000000000..1cc4510bbee098902e66cee8d588626d7e06af42
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/dfu/usbd_dfu.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBD_DFU_H
+#define USBD_DFU_H
+
+#include "usb_dfu.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Alloc dfu interface driver */
+struct usbd_interface *usbd_dfu_alloc_intf(void);
+
+/* Interface functions that need to be implemented by the user */
+uint8_t *dfu_read_flash(uint8_t *src, uint8_t *dest, uint32_t len);
+uint16_t dfu_write_flash(uint8_t *src, uint8_t *dest, uint32_t len);
+uint16_t dfu_erase_flash(uint32_t add);
+void dfu_leave(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBD_DFU_H */
diff --git a/third-party/cherryusb-0.6.0/class/hid/usb_hid.h b/third-party/cherryusb-0.6.0/class/hid/usb_hid.h
new file mode 100644
index 0000000000000000000000000000000000000000..19539e7fb6715b0fdb1c82044153785ff654c8f2
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/hid/usb_hid.h
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_HID_H
+#define USB_HID_H
+
+/* Subclass codes (HID 4.2) */
+#define HID_SUBCLASS_NONE 0 /* No subclass */
+#define HID_SUBCLASS_BOOTIF 1 /* Boot Interface Subclass */
+
+/* HID Protocol Codes (HID 4.3) */
+#define HID_PROTOCOL_NONE 0x00
+#define HID_PROTOCOL_BOOT 0x00
+#define HID_PROTOCOL_KEYBOARD 0x01
+#define HID_PROTOCOL_REPORT 0x01
+#define HID_PROTOCOL_MOUSE 0x02
+
+/* HID Class Descriptor Types (HID 7.1) */
+#define HID_DESCRIPTOR_TYPE_HID 0x21
+#define HID_DESCRIPTOR_TYPE_HID_REPORT 0x22
+#define HID_DESCRIPTOR_TYPE_HID_PHYSICAL 0x23
+
+/* HID Class Specific Requests (HID 7.2) */
+#define HID_REQUEST_GET_REPORT 0x01
+#define HID_REQUEST_GET_IDLE 0x02
+#define HID_REQUEST_GET_PROTOCOL 0x03
+#define HID_REQUEST_SET_REPORT 0x09
+#define HID_REQUEST_SET_IDLE 0x0A
+#define HID_REQUEST_SET_PROTOCOL 0x0B
+
+/* Report Type (MS byte of wValue for GET_REPORT) (HID 7.2.1) */
+#define HID_REPORT_INPUT 0x01
+#define HID_REPORT_OUTPUT 0x02
+#define HID_REPORT_FEATURE 0x03
+
+/* HID Descriptor ***********************************************************/
+
+#define HID_COUNTRY_NONE 0x00 /* Not Supported */
+#define HID_COUNTRY_ARABIC 0x01 /* Arabic */
+#define HID_COUNTRY_BELGIAN 0x02 /* Belgian */
+#define HID_COUNTRY_CANADA 0x03 /* Canadian-Bilingual */
+#define HID_COUNTRY_CANADRFR 0x04 /* Canadian-French */
+#define HID_COUNTRY_CZECH 0x05 /* Czech Republic */
+#define HID_COUNTRY_DANISH 0x06 /* Danish */
+#define HID_COUNTRY_FINNISH 0x07 /* Finnish */
+#define HID_COUNTRY_FRENCH 0x08 /* French */
+#define HID_COUNTRY_GERMAN 0x09 /* German */
+#define HID_COUNTRY_GREEK 0x10 /* Greek */
+#define HID_COUNTRY_HEBREW 0x11 /* Hebrew */
+#define HID_COUNTRY_HUNGARY 0x12 /* Hungary */
+#define HID_COUNTRY_ISO 0x13 /* International (ISO) */
+#define HID_COUNTRY_ITALIAN 0x14 /* Italian */
+#define HID_COUNTRY_JAPAN 0x15 /* Japan (Katakana) */
+#define HID_COUNTRY_KOREAN 0x16 /* Korean */
+#define HID_COUNTRY_LATINAM 0x17 /* Latin American */
+#define HID_COUNTRY_DUTCH 0x18 /* Netherlands/Dutch */
+#define HID_COUNTRY_NORWEGIAN 0x19 /* Norwegian */
+#define HID_COUNTRY_PERSIAN 0x20 /* Persian (Farsi) */
+#define HID_COUNTRY_POLAND 0x21 /* Poland */
+#define HID_COUNTRY_PORTUGUESE 0x22 /* Portuguese */
+#define HID_COUNTRY_RUSSIA 0x23 /* Russia */
+#define HID_COUNTRY_SLOVAKIA 0x24 /* Slovakia */
+#define HID_COUNTRY_SPANISH 0x25 /* Spanish */
+#define HID_COUNTRY_SWEDISH 0x26 /* Swedish */
+#define HID_COUNTRY_SWISSFR 0x27 /* Swiss/French */
+#define HID_COUNTRY_SWISSGR 0x28 /* Swiss/German */
+#define HID_COUNTRY_SWITZERLAND 0x29 /* Switzerland */
+#define HID_COUNTRY_TAIWAN 0x30 /* Taiwan */
+#define HID_COUNTRY_TURKISHQ 0x31 /* Turkish-Q */
+#define HID_COUNTRY_UK 0x32 /* UK */
+#define HID_COUNTRY_US 0x33 /* US */
+#define HID_COUNTRY_YUGOSLAVIA 0x34 /* Yugoslavia */
+#define HID_COUNTRY_TURKISHF 0x35 /* Turkish-F */
+
+/* HID report items */
+#define HID_REPORT_ITEM_SIZE_MASK 0x03
+#define HID_REPORT_ITEM_SIZE_0 0x00 /* No data follows */
+#define HID_REPORT_ITEM_SIZE_1 0x01 /* 1 byte of data follows */
+#define HID_REPORT_ITEM_SIZE_2 0x02 /* 2 bytes of data follow */
+#define HID_REPORT_ITEM_SIZE_4 0x03 /* 4 bytes of data follow */
+#define HID_REPORT_ITEM_TYPE_MASK 0x0c
+#define HID_REPORT_ITEM_TYPE_MAIN 0x00
+#define HID_REPORT_ITEM_TYPE_GLOBAL 0x04
+#define HID_REPORT_ITEM_TYPE_LOCAL 0x08
+#define HID_REPORT_ITEM_TAG_MASK 0xf0
+
+/* Main Items (HID 6.2.2.4) */
+#define HID_MAIN_ITEM_CONSTANT (1 << 0) /* Constant(1) vs Data(0) */
+#define HID_MAIN_ITEM_VARIABLE (1 << 1) /* Variable(1) vs Array(0) */
+#define HID_MAIN_ITEM_RELATIVE (1 << 2) /* Relative(1) vs Absolute(0) */
+#define HID_MAIN_ITEM_WRAP (1 << 3) /* Wrap(1) vs No Wrap(0) */
+#define HID_MAIN_ITEM_NONLINEAR (1 << 4) /* Non Linear(1) vs Linear(0) */
+#define HID_MAIN_ITEM_NOPREFERRED (1 << 5) /* No Preferred (1) vs Preferred State(0) */
+#define HID_MAIN_ITEM_NULLSTATE (1 << 6) /* Null state(1) vs No Null position(0) */
+#define HID_MAIN_ITEM_VOLATILE (1 << 7) /* Volatile(1) vs Non volatile(0) */
+#define HID_MAIN_ITEM_BUFFEREDBYTES (1 << 8) /* Buffered Bytes(1) vs Bit Field(0) */
+
+#define HID_MAIN_ITEM_SIZE(pfx) ((pfx)&HID_REPORT_ITEM_SIZE_MASK)
+#define HID_MAIN_ITEM_INPUT_PREFIX 0x80
+#define HID_MAIN_ITEM_INPUT_CONSTANT HID_MAIN_ITEM_CONSTANT
+#define HID_MAIN_ITEM_INPUT_VARIABLE HID_MAIN_ITEM_VARIABLE
+#define HID_MAIN_ITEM_INPUT_RELATIVE HID_MAIN_ITEM_RELATIVE
+#define HID_MAIN_ITEM_INPUT_WRAP HID_MAIN_ITEM_WRAP
+#define HID_MAIN_ITEM_INPUT_NONLINEAR HID_MAIN_ITEM_NONLINEAR
+#define HID_MAIN_ITEM_INPUT_NOPREFERRED HID_MAIN_ITEM_NOPREFERRED
+#define HID_MAIN_ITEM_INPUT_NULLSTATE HID_MAIN_ITEM_NULLSTATE
+#define HID_MAIN_ITEM_INPUT_BUFFEREDBYTES HID_MAIN_ITEM_BUFFEREDBYTES
+
+#define HID_MAIN_ITEM_OUTPUT_PREFIX 0x90
+#define HID_MAIN_ITEM_OUTPUT_CONSTANT HID_MAIN_ITEM_CONSTANT
+#define HID_MAIN_ITEM_OUTPUT_VARIABLE HID_MAIN_ITEM_VARIABLE
+#define HID_MAIN_ITEM_OUTPUT_RELATIVE HID_MAIN_ITEM_RELATIVE
+#define HID_MAIN_ITEM_OUTPUT_WRAP HID_MAIN_ITEM_WRAP
+#define HID_MAIN_ITEM_OUTPUT_NONLINEAR HID_MAIN_ITEM_NONLINEAR
+#define HID_MAIN_ITEM_OUTPUT_NOPREFERRED HID_MAIN_ITEM_NOPREFERRED
+#define HID_MAIN_ITEM_OUTPUT_NULLSTATE HID_MAIN_ITEM_NULLSTATE
+#define HID_MAIN_ITEM_OUTPUT_VOLATILE HID_MAIN_ITEM_VOLATILE
+#define HID_MAIN_ITEM_OUTPUT_BUFFEREDBYTES HID_MAIN_ITEM_BUFFEREDBYTES
+
+#define HID_MAIN_ITEM_FEATURE_PREFIX 0xb0
+#define HID_MAIN_ITEM_FEATURE_CONSTANT HID_MAIN_ITEM_CONSTANT
+#define HID_MAIN_ITEM_FEATURE_VARIABLE HID_MAIN_ITEM_VARIABLE
+#define HID_MAIN_ITEM_FEATURE_RELATIVE HID_MAIN_ITEM_RELATIVE
+#define HID_MAIN_ITEM_FEATURE_WRAP HID_MAIN_ITEM_WRAP
+#define HID_MAIN_ITEM_FEATURE_NONLINEAR HID_MAIN_ITEM_NONLINEAR
+#define HID_MAIN_ITEM_FEATURE_NOPREFERRED HID_MAIN_ITEM_NOPREFERRED
+#define HID_MAIN_ITEM_FEATURE_NULLSTATE HID_MAIN_ITEM_NULLSTATE
+#define HID_MAIN_ITEM_FEATURE_VOLATILE HID_MAIN_ITEM_VOLATILE
+#define HID_MAIN_ITEM_FEATURE_BUFFEREDBYTES HID_MAIN_ITEM_BUFFEREDBYTES
+
+#define HID_MAIN_ITEM_COLLECTION_PREFIX 0xa0
+#define HID_MAIN_ITEM_COLLECTION_PHYSICAL 0x00 /* Physical (group of axes) */
+#define HID_MAIN_ITEM_COLLECTION_APPL 0x01 /* Application (mouse, keyboard) */
+#define HID_MAIN_ITEM_COLLECTION_LOGICAL 0x02 /* Logical (interrelated data) */
+#define HID_MAIN_ITEM_COLLECTION_REPORT 0x03 /* Report */
+#define HID_MAIN_ITEM_COLLECTION_ARRAY 0x04 /* Named Array */
+#define HID_MAIN_ITEM_COLLECTION_SWITCH 0x05 /* Usage Switch */
+#define HID_MAIN_ITEM_COLLECTION_MODIFIER 0x06 /* Usage Modifier */
+#define HID_MAIN_ITEM_ENDCOLLECTION_PREFIX 0xc0
+
+/* Global Items (HID 6.2.2.7) */
+#define HID_GLOBAL_ITEM_SIZE(pfx) ((pfx)&HID_REPORT_ITEM_SIZE_MASK)
+#define HID_GLOBAL_ITEM_USAGEPAGE_PREFIX 0x04 /* Usage Page */
+#define HID_GLOBAL_ITEM_LOGICALMIN_PREFIX 0x14 /* Logical Minimum */
+#define HID_GLOBAL_ITEM_LOGICALMAX_PREFIX 0x24 /* Logical Maximum */
+#define HID_GLOBAL_ITEM_PHYSICALMIN_PREFIX 0x34 /* Physical Minimum */
+#define HID_GLOBAL_ITEM_PHYSMICALAX_PREFIX 0x44 /* Physical Maximum */
+#define HID_GLOBAL_ITEM_UNITEXP_PREFIX 0x54 /* Unit Exponent */
+#define HID_GLOBAL_ITEM_UNIT_PREFIX 0x64 /* Unit */
+#define HID_GLOBAL_ITEM_REPORTSIZE_PREFIX 0x74 /* Report Size */
+#define HID_GLOBAL_ITEM_REPORTID_PREFIX 0x84 /* Report ID */
+#define HID_GLOBAL_ITEM_REPORTCOUNT_PREFIX 0x94 /* Report Count */
+#define HID_GLOBAL_ITEM_PUSH_PREFIX 0xa4 /* Push */
+#define HID_GLOBAL_ITEM_POP_PREFIX 0xb4 /* Pop */
+
+/* Local Items (HID 6.2.2.8) */
+#define HID_LOCAL_ITEM_SIZE(pfx) ((pfx)&HID_REPORT_ITEM_SIZE_MASK)
+#define HID_LOCAL_ITEM_USAGE_PREFIX 0x08 /* Usage */
+#define HID_LOCAL_ITEM_USAGEMIN_PREFIX 0x18 /* Usage Minimum */
+#define HID_LOCAL_ITEM_USAGEMAX_PREFIX 0x28 /* Usage Maximum */
+#define HID_LOCAL_ITEM_DESIGNATORIDX_PREFIX 0x38 /* Designator Index */
+#define HID_LOCAL_ITEM_DESIGNATORMIN_PREFIX 0x48 /* Designator Minimum */
+#define HID_LOCAL_ITEM_DESIGNATORMAX_PREFIX 0x58 /* Designator Maximum */
+#define HID_LOCAL_ITEM_STRINGIDX_PREFIX 0x78 /* String Index */
+#define HID_LOCAL_ITEM_STRINGMIN_PREFIX 0x88 /* String Minimum */
+#define HID_LOCAL_ITEM_STRINGMAX_PREFIX 0x98 /* xx */
+#define HID_LOCAL_ITEM_DELIMITER_PREFIX 0xa8 /* Delimiter */
+
+/* Modifier Keys (HID 8.3) */
+#define HID_MODIFER_LCTRL (1 << 0) /* Left Ctrl */
+#define HID_MODIFER_LSHIFT (1 << 1) /* Left Shift */
+#define HID_MODIFER_LALT (1 << 2) /* Left Alt */
+#define HID_MODIFER_LGUI (1 << 3) /* Left GUI */
+#define HID_MODIFER_RCTRL (1 << 4) /* Right Ctrl */
+#define HID_MODIFER_RSHIFT (1 << 5) /* Right Shift */
+#define HID_MODIFER_RALT (1 << 6) /* Right Alt */
+#define HID_MODIFER_RGUI (1 << 7) /* Right GUI */
+
+/* Keyboard output report (1 byte) (HID B.1) */
+#define HID_KBD_OUTPUT_REPORT_NUMLOCK (1 << 0)
+#define HID_KBD_OUTPUT_REPORT_CAPSLOCK (1 << 1)
+#define HID_KBD_OUTPUT_REPORT_SCROLLLOCK (1 << 2)
+#define HID_KBD_OUTPUT_REPORT_COMPOSE (1 << 3)
+#define HID_KBD_OUTPUT_REPORT_KANA (1 << 4)
+
+/* Mouse input report (HID B.2) */
+#define HID_MOUSE_INPUT_REPORT_BUTTON1 (1 << 0)
+#define HID_MOUSE_INPUT_REPORT_BUTTON2 (1 << 1)
+#define HID_MOUSE_INPUT_REPORT_BUTTON3 (1 << 2)
+#define HID_MOUSE_INPUT_REPORT_BUTTON_MASK (7)
+
+#define HID_MOUSE_INPUT_BUTTON_LEFT (1 << 0)
+#define HID_MOUSE_INPUT_BUTTON_RIGHT (1 << 1)
+#define HID_MOUSE_INPUT_BUTTON_MIDDLE (1 << 2)
+#define HID_MOUSE_INPUT_BUTTON_BACKWARD (1 << 3)
+#define HID_MOUSE_INPUT_BUTTON_FORWARD (1 << 4)
+
+/* Joystick input report (4 bytes) (HID D.1) */
+#define HID_JS_INPUT_REPORT_HATSWITCH_SHIFT (0)
+#define HID_JS_INPUT_REPORT_HATSWITCH_MASK (15 << HID_JSIN_HATSWITCH_SHIFT)
+#define HID_JS_INPUT_REPORT_BUTTON1 (1 << 4)
+#define HID_JS_INPUT_REPORT_BUTTON2 (1 << 5)
+#define HID_JS_INPUT_REPORT_BUTTON3 (1 << 6)
+#define HID_JS_INPUT_REPORT_BUTTON4 (1 << 7)
+
+/* Usage pages (HuT 3) */
+#define HID_USAGE_PAGE_UNDEFINED 0x00 /* Undefined */
+#define HID_USAGE_PAGE_GENERIC_DCTRL 0x01 /* Generic Desktop Controls */
+#define HID_USAGE_PAGE_SIMCTRL 0x02 /* Simulation Controls */
+#define HID_USAGE_PAGE_VRCTRL 0x03 /* VR Controls */
+#define HID_USAGE_PAGE_SPORTCTRL 0x04 /* Sport Controls */
+#define HID_USAGE_PAGE_GAMECTRL 0x05 /* Game Controls */
+#define HID_USAGE_PAGE_GENERIC_DEVCTRL 0x06 /* Generic Device Controls */
+#define HID_USAGE_PAGE_KBD 0x07 /* Keyboard/Keypad */
+#define HID_USAGE_PAGE_LEDS 0x08 /* LEDs */
+#define HID_USAGE_PAGE_BUTTON 0x09 /* Button */
+#define HID_USAGE_PAGE_ORDINAL 0x0a /* Ordinal */
+#define HID_USAGE_PAGE_TELEPHONY 0x0b /* Telephony */
+#define HID_USAGE_PAGE_CONSUMER 0x0c /* Consumer */
+#define HID_USAGE_PAGE_DIGITIZER 0x0d /* Digitizer */
+ /* 0x0e Reserved */
+#define HID_USAGE_PAGE_PIDPAGE 0x0f /* PID Page Physical Interface Device */
+#define HID_USAGE_PAGE_UNICODE 0x10 /* Unicode */
+ /* 0x11-13 Reserved */
+#define HID_USAGE_PAGE_ALPHA_DISPLAY 0x14 /* Alphanumeric Display */
+ /* 0x15-3f Reserved */
+#define HID_USAGE_PAGE_MEDICAL 0x40 /* Medical Instruments */
+ /* 0x41-7f Reserved */
+ /* 0x80-83 Monitor Devices */
+ /* 0x84-87 Power Devices */
+ /* 0x88-8b Reserved */
+#define HID_USAGE_PAGE_BARCODE_SCANNER 0x8c /* Bar Code Scanner page */
+#define HID_USAGE_PAGE_SCALE 0x8d /* Scale page */
+#define HID_USAGE_PAGE_MSR 0x8e /* Magnetic Stripe Reading (MSR) Devices */
+#define HID_USAGE_PAGE_POS 0x8f /* Point of Sale devices */
+#define HID_USAGE_PAGE_CAMERA_CTRL 0x90 /* Camera Control Page */
+
+/* Generic Desktop Page Usage IDs (HuT 4) */
+#define HID_DESKTOP_USAGE_UNDEFINED 0x00 /* Undefined */
+#define HID_DESKTOP_USAGE_POINTER 0x01 /* Pointer */
+#define HID_DESKTOP_USAGE_MOUSE 0x02 /* Mouse */
+ /* 0x03 Reserved */
+#define HID_DESKTOP_USAGE_JOYSTICK 0x04 /* Joystick */
+#define HID_DESKTOP_USAGE_GAMEPAD 0x05 /* Game Pad */
+#define HID_DESKTOP_USAGE_KEYBOARD 0x06 /* Keyboard */
+#define HID_DESKTOP_USAGE_KEYPAD 0x07 /* Keypad */
+#define HID_DESKTOP_USAGE_MULTIAXIS 0x08 /* Multi-axis Controller */
+#define HID_DESKTOP_USAGE_TABLET 0x09 /* Tablet PC System Controls */
+ /* 0x0a-2f Reserved */
+#define HID_DESKTOP_USAGE_X 0x30 /* X */
+#define HID_DESKTOP_USAGE_Y 0x31 /* Y */
+#define HID_DESKTOP_USAGE_Z 0x32 /* Z */
+#define HID_DESKTOP_USAGE_RX 0x33 /* Rx */
+#define HID_DESKTOP_USAGE_RY 0x34 /* Ry */
+#define HID_DESKTOP_USAGE_RZ 0x35 /* Rz */
+#define HID_DESKTOP_USAGE_SLIDER 0x36 /* Slider */
+#define HID_DESKTOP_USAGE_DIAL 0x37 /* Dial */
+#define HID_DESKTOP_USAGE_WHEEL 0x38 /* Wheel */
+#define HID_DESKTOP_USAGE_HATSWITCH 0x39 /* Hat switch */
+#define HID_DESKTOP_USAGE_COUNTED 0x3a /* Counted Buffer */
+#define HID_DESKTOP_USAGE_BYTECOUNT 0x3b /* Byte Count */
+#define HID_DESKTOP_USAGE_MOTION 0x3c /* Motion Wakeup */
+#define HID_DESKTOP_USAGE_START 0x3d /* Start */
+#define HID_DESKTOP_USAGE_SELECT 0x3e /* Select */
+ /* 0x3f Reserved */
+#define HID_DESKTOP_USAGE_VX 0x40 /* Vx */
+#define HID_DESKTOP_USAGE_VY 0x41 /* Vy */
+#define HID_DESKTOP_USAGE_VZ 0x42 /* Vz */
+#define HID_DESKTOP_USAGE_VBRX 0x43 /* Vbrx */
+#define HID_DESKTOP_USAGE_VBRY 0x44 /* Vbry */
+#define HID_DESKTOP_USAGE_VBRZ 0x45 /* Vbrz */
+#define HID_DESKTOP_USAGE_VNO 0x46 /* Vno */
+#define HID_DESKTOP_USAGE_FEATURE 0x47 /* Feature Notification */
+#define HID_DESKTOP_USAGE_RESOLUTION 0x48 /* Resolution Multiplier */
+ /* 0x49-7f Reserved */
+#define HID_DESKTOP_USAGE_CONTROL 0x80 /* System Control */
+#define HID_DESKTOP_USAGE_POWERDOWN 0x81 /* System Power Down */
+#define HID_DESKTOP_USAGE_SLEEP 0x82 /* System Sleep */
+#define HID_DESKTOP_USAGE_WAKEUP 0x83 /* System Wake Up */
+#define HID_DESKTOP_USAGE_CONTEXT_MENU 0x84 /* System Context Menu */
+#define HID_DESKTOP_USAGE_MAIN_MENU 0x85 /* System Main Menu */
+#define HID_DESKTOP_USAGE_APP_MENU 0x86 /* System App Menu */
+#define HID_DESKTOP_USAGE_MENU_HELP 0x87 /* System Menu Help */
+#define HID_DESKTOP_USAGE_MENU_EXIT 0x88 /* System Menu Exit */
+#define HID_DESKTOP_USAGE_MENU_SELECT 0x89 /* System Menu Select */
+#define HID_DESKTOP_USAGE_MENU_RIGHT 0x8a /* System Menu Right */
+#define HID_DESKTOP_USAGE_MENU_LEFT 0x8b /* System Menu Left */
+#define HID_DESKTOP_USAGE_MENU_UP 0x8c /* System Menu Up */
+#define HID_DESKTOP_USAGE_MENU_DOWN 0x8d /* System Menu Down */
+#define HID_DESKTOP_USAGE_COLD_RESTART 0x8e /* System Cold Restart */
+#define HID_DESKTOP_USAGE_WARM_RESTART 0x8f /* System Warm Restart */
+#define HID_DESKTOP_USAGE_DPAD_UP 0x90 /* D-pad Up */
+#define HID_DESKTOP_USAGE_DPAD_DOWN 0x91 /* D-pad Down */
+#define HID_DESKTOP_USAGE_DPAD_RIGHT 0x92 /* D-pad Right */
+#define HID_DESKTOP_USAGE_DPAD_LEFT 0x93 /* D-pad Left */
+ /* 0x94-9f Reserved */
+#define HID_DESKTOP_USAGE_DOCK 0xa0 /* System Dock */
+#define HID_DESKTOP_USAGE_UNDOCK 0xa1 /* System Undock */
+#define HID_DESKTOP_USAGE_SETUP 0xa2 /* System Setup */
+#define HID_DESKTOP_USAGE_BREAK 0xa3 /* System Break */
+#define HID_DESKTOP_USAGE_DEBUG_BREAK 0xa4 /* System Debugger Break */
+#define HID_DESKTOP_USAGE_APP_BREAK 0xa5 /* Application Break */
+#define HID_DESKTOP_USAGE_APP_DEBUG_BREAK 0xa6 /* Application Debugger Break */
+#define HID_DESKTOP_USAGE_MUTE 0xa7 /* System Speaker Mute */
+#define HID_DESKTOP_USAGE_HIBERNATE 0xa8 /* System Hibernate */
+ /* 0xa9-af Reserved */
+#define HID_DESKTOP_USAGE_DISPLAY_INVERT 0xb0 /* System Display Invert */
+#define HID_DESKTOP_USAGE_DISPALY_INTERNAL 0xb1 /* System Display Internal */
+#define HID_DESKTOP_USAGE_DISPLAY_EXTERNAL 0xb2 /* System Display External */
+#define HID_DESKTOP_USAGE_DISPLAY_BOTH 0xb3 /* System Display Both */
+#define HID_DESKTOP_USAGE_DISPLAY_DUAL 0xb4 /* System Display Dual */
+#define HID_DESKTOP_USAGE_DISPLAY_TOGGLE 0xb5 /* System Display Toggle Int/Ext */
+#define HID_DESKTOP_USAGE_DISPLAY_SWAP 0xb6 /* System Display Swap */
+#define HID_DESKTOP_USAGE_ 0xb7 /* System Display LCD Autoscale */
+ /* 0xb8-ffff Reserved */
+
+/* Keyboard usage IDs (HuT 10) */
+#define HID_KBD_USAGE_NONE 0x00 /* Reserved (no event indicated) */
+#define HID_KBD_USAGE_ERRORROLLOVER 0x01 /* Keyboard ErrorRollOver */
+#define HID_KBD_USAGE_POSTFAIL 0x02 /* Keyboard POSTFail */
+#define HID_KBD_USAGE_ERRUNDEF 0x03 /* Keyboard ErrorUndefined */
+#define HID_KBD_USAGE_A 0x04 /* Keyboard a or A (B-Z follow) */
+#define HID_KBD_USAGE_1 0x1e /* Keyboard 1 (2-9 follow) */
+#define HID_KBD_USAGE_EXCLAM 0x1e /* Keyboard 1 and ! */
+#define HID_KBD_USAGE_AT 0x1f /* Keyboard 2 and @ */
+#define HID_KBD_USAGE_POUND 0x20 /* Keyboard 3 and # */
+#define HID_KBD_USAGE_DOLLAR 0x21 /* Keyboard 4 and $ */
+#define HID_KBD_USAGE_PERCENT 0x22 /* Keyboard 5 and % */
+#define HID_KBD_USAGE_CARAT 0x23 /* Keyboard 6 and ^ */
+#define HID_KBD_USAGE_AMPERSAND 0x24 /* Keyboard 7 and & */
+#define HID_KBD_USAGE_ASTERISK 0x25 /* Keyboard 8 and * */
+#define HID_KBD_USAGE_LPAREN 0x26 /* Keyboard 9 and ( */
+#define HID_KBD_USAGE_0 0x27 /* Keyboard 0 and ) */
+#define HID_KBD_USAGE_RPAREN 0x27 /* Keyboard 0 and ) */
+#define HID_KBD_USAGE_ENTER 0x28 /* Keyboard Return (ENTER) */
+#define HID_KBD_USAGE_ESCAPE 0x29 /* Keyboard ESCAPE */
+#define HID_KBD_USAGE_DELETE 0x2a /* Keyboard DELETE (Backspace) */
+#define HID_KBD_USAGE_TAB 0x2b /* Keyboard Tab */
+#define HID_KBD_USAGE_SPACE 0x2c /* Keyboard Spacebar */
+#define HID_KBD_USAGE_HYPHEN 0x2d /* Keyboard - and (underscore) */
+#define HID_KBD_USAGE_UNDERSCORE 0x2d /* Keyboard - and (underscore) */
+#define HID_KBD_USAGE_EQUAL 0x2e /* Keyboard = and + */
+#define HID_KBD_USAGE_PLUS 0x2e /* Keyboard = and + */
+#define HID_KBD_USAGE_LBRACKET 0x2f /* Keyboard [ and { */
+#define HID_KBD_USAGE_LBRACE 0x2f /* Keyboard [ and { */
+#define HID_KBD_USAGE_RBRACKET 0x30 /* Keyboard ] and } */
+#define HID_KBD_USAGE_RBRACE 0x30 /* Keyboard ] and } */
+#define HID_KBD_USAGE_BSLASH 0x31 /* Keyboard \ and | */
+#define HID_KBD_USAGE_VERTBAR 0x31 /* Keyboard \ and | */
+#define HID_KBD_USAGE_NONUSPOUND 0x32 /* Keyboard Non-US # and ~ */
+#define HID_KBD_USAGE_TILDE 0x32 /* Keyboard Non-US # and ~ */
+#define HID_KBD_USAGE_SEMICOLON 0x33 /* Keyboard ; and : */
+#define HID_KBD_USAGE_COLON 0x33 /* Keyboard ; and : */
+#define HID_KBD_USAGE_SQUOTE 0x34 /* Keyboard ' and " */
+#define HID_KBD_USAGE_DQUOUTE 0x34 /* Keyboard ' and " */
+#define HID_KBD_USAGE_GACCENT 0x35 /* Keyboard Grave Accent and Tilde */
+#define HID_KBD_USAGE_GTILDE 0x35 /* Keyboard Grave Accent and Tilde */
+#define HID_KBD_USAGE_COMMON 0x36 /* Keyboard , and < */
+#define HID_KBD_USAGE_LT 0x36 /* Keyboard , and < */
+#define HID_KBD_USAGE_PERIOD 0x37 /* Keyboard . and > */
+#define HID_KBD_USAGE_GT 0x37 /* Keyboard . and > */
+#define HID_KBD_USAGE_DIV 0x38 /* Keyboard / and ? */
+#define HID_KBD_USAGE_QUESTION 0x38 /* Keyboard / and ? */
+#define HID_KBD_USAGE_CAPSLOCK 0x39 /* Keyboard Caps Lock */
+#define HID_KBD_USAGE_F1 0x3a /* Keyboard F1 */
+#define HID_KBD_USAGE_F2 0x3b /* Keyboard F2 */
+#define HID_KBD_USAGE_F3 0x3c /* Keyboard F3 */
+#define HID_KBD_USAGE_F4 0x3d /* Keyboard F4 */
+#define HID_KBD_USAGE_F5 0x3e /* Keyboard F5 */
+#define HID_KBD_USAGE_F6 0x3f /* Keyboard F6 */
+#define HID_KBD_USAGE_F7 0x40 /* Keyboard F7 */
+#define HID_KBD_USAGE_F8 0x41 /* Keyboard F8 */
+#define HID_KBD_USAGE_F9 0x42 /* Keyboard F9 */
+#define HID_KBD_USAGE_F10 0x43 /* Keyboard F10 */
+#define HID_KBD_USAGE_F11 0x44 /* Keyboard F11 */
+#define HID_KBD_USAGE_F12 0x45 /* Keyboard F12 */
+#define HID_KBD_USAGE_PRINTSCN 0x46 /* Keyboard PrintScreen */
+#define HID_KBD_USAGE_SCROLLLOCK 0x47 /* Keyboard Scroll Lock */
+#define HID_KBD_USAGE_PAUSE 0x48 /* Keyboard Pause */
+#define HID_KBD_USAGE_INSERT 0x49 /* Keyboard Insert */
+#define HID_KBD_USAGE_HOME 0x4a /* Keyboard Home */
+#define HID_KBD_USAGE_PAGEUP 0x4b /* Keyboard PageUp */
+#define HID_KBD_USAGE_DELFWD 0x4c /* Keyboard Delete Forward */
+#define HID_KBD_USAGE_END 0x4d /* Keyboard End */
+#define HID_KBD_USAGE_PAGEDOWN 0x4e /* Keyboard PageDown */
+#define HID_KBD_USAGE_RIGHT 0x4f /* eyboard RightArrow */
+#define HID_KBD_USAGE_LEFT 0x50 /* Keyboard LeftArrow */
+#define HID_KBD_USAGE_DOWN 0x5a /* Keyboard DownArrow */
+#define HID_KBD_USAGE_UP 0x52 /* Keyboard UpArrow */
+#define HID_KBD_USAGE_KPDNUMLOCK 0x53 /* Keypad Num Lock and Clear */
+#define HID_KBD_USAGE_KPDNUMLOCKCLEAR 0x53 /* Keypad Num Lock and Clear */
+#define HID_KBD_USAGE_KPDDIV 0x54 /* Keypad / */
+#define HID_KBD_USAGE_KPDMUL 0x55 /* Keypad * */
+#define HID_KBD_USAGE_KPDHMINUS 0x56 /* Keypad - */
+#define HID_KBD_USAGE_KPDPLUS 0x57 /* Keypad + */
+#define HID_KBD_USAGE_KPDEMTER 0x58 /* Keypad ENTER */
+#define HID_KBD_USAGE_KPD1 0x59 /* Keypad 1 (2-9 follow) */
+#define HID_KBD_USAGE_KPDEND 0x59 /* Keypad 1 and End */
+#define HID_KBD_USAGE_KPDDOWN 0x5a /* Keypad 2 and Down Arrow */
+#define HID_KBD_USAGE_KPDPAGEDN 0x5b /* Keypad 3 and PageDn */
+#define HID_KBD_USAGE_KPDLEFT 0x5c /* Keypad 4 and Left Arrow */
+#define HID_KBD_USAGE_KPDRIGHT 0x5e /* Keypad 6 and Right Arrow */
+#define HID_KBD_USAGE_KPDHOME 0x5f /* Keypad 7 and Home */
+#define HID_KBD_USAGE_KPDUP 0x60 /* Keypad 8 and Up Arrow */
+#define HID_KBD_USAGE_KPDPAGEUP 0x61 /* Keypad 9 and PageUp */
+#define HID_KBD_USAGE_KPD0 0x62 /* Keypad 0 and Insert */
+#define HID_KBD_USAGE_KPDINSERT 0x62 /* Keypad 0 and Insert */
+#define HID_KBD_USAGE_KPDDECIMALPT 0x63 /* Keypad . and Delete */
+#define HID_KBD_USAGE_KPDDELETE 0x63 /* Keypad . and Delete */
+#define HID_KBD_USAGE_NONSLASH 0x64 /* Keyboard Non-US \ and | */
+#define HID_KBD_USAGE_NONUSVERT 0x64 /* Keyboard Non-US \ and | */
+#define HID_KBD_USAGE_APPLICATION 0x65 /* Keyboard Application */
+#define HID_KBD_USAGE_POWER 0x66 /* Keyboard Power */
+#define HID_KBD_USAGE_KPDEQUAL 0x67 /* Keypad = */
+#define HID_KBD_USAGE_F13 0x68 /* Keyboard F13 */
+#define HID_KBD_USAGE_F14 0x69 /* Keyboard F14 */
+#define HID_KBD_USAGE_F15 0x6a /* Keyboard F15 */
+#define HID_KBD_USAGE_F16 0x6b /* Keyboard F16 */
+#define HID_KBD_USAGE_F17 0x6c /* Keyboard F17 */
+#define HID_KBD_USAGE_F18 0x6d /* Keyboard F18 */
+#define HID_KBD_USAGE_F19 0x6e /* Keyboard F19 */
+#define HID_KBD_USAGE_F20 0x6f /* Keyboard F20 */
+#define HID_KBD_USAGE_F21 0x70 /* Keyboard F21 */
+#define HID_KBD_USAGE_F22 0x71 /* Keyboard F22 */
+#define HID_KBD_USAGE_F23 0x72 /* Keyboard F23 */
+#define HID_KBD_USAGE_F24 0x73 /* Keyboard F24 */
+#define HID_KBD_USAGE_EXECUTE 0x74 /* Keyboard Execute */
+#define HID_KBD_USAGE_HELP 0x75 /* Keyboard Help */
+#define HID_KBD_USAGE_MENU 0x76 /* Keyboard Menu */
+#define HID_KBD_USAGE_SELECT 0x77 /* Keyboard Select */
+#define HID_KBD_USAGE_STOP 0x78 /* Keyboard Stop */
+#define HID_KBD_USAGE_AGAIN 0x79 /* Keyboard Again */
+#define HID_KBD_USAGE_UNDO 0x7a /* Keyboard Undo */
+#define HID_KBD_USAGE_CUT 0x7b /* Keyboard Cut */
+#define HID_KBD_USAGE_COPY 0x7c /* Keyboard Copy */
+#define HID_KBD_USAGE_PASTE 0x7d /* Keyboard Paste */
+#define HID_KBD_USAGE_FIND 0x7e /* Keyboard Find */
+#define HID_KBD_USAGE_MUTE 0x7f /* Keyboard Mute */
+#define HID_KBD_USAGE_VOLUP 0x80 /* Keyboard Volume Up */
+#define HID_KBD_USAGE_VOLDOWN 0x81 /* Keyboard Volume Down */
+#define HID_KBD_USAGE_LCAPSLOCK 0x82 /* Keyboard Locking Caps Lock */
+#define HID_KBD_USAGE_LNUMLOCK 0x83 /* Keyboard Locking Num Lock */
+#define HID_KBD_USAGE_LSCROLLLOCK 0x84 /* Keyboard Locking Scroll Lock */
+#define HID_KBD_USAGE_KPDCOMMA 0x85 /* Keypad Comma */
+#define HID_KBD_USAGE_KPDEQUALSIGN 0x86 /* Keypad Equal Sign */
+#define HID_KBD_USAGE_INTERNATIONAL1 0x87 /* Keyboard International 1 */
+#define HID_KBD_USAGE_INTERNATIONAL2 0x88 /* Keyboard International 2 */
+#define HID_KBD_USAGE_INTERNATIONAL3 0x89 /* Keyboard International 3 */
+#define HID_KBD_USAGE_INTERNATIONAL4 0x8a /* Keyboard International 4 */
+#define HID_KBD_USAGE_INTERNATIONAL5 0x8b /* Keyboard International 5 */
+#define HID_KBD_USAGE_INTERNATIONAL6 0x8c /* Keyboard International 6 */
+#define HID_KBD_USAGE_INTERNATIONAL7 0x8d /* Keyboard International 7 */
+#define HID_KBD_USAGE_INTERNATIONAL8 0x8e /* Keyboard International 8 */
+#define HID_KBD_USAGE_INTERNATIONAL9 0x8f /* Keyboard International 9 */
+#define HID_KBD_USAGE_LANG1 0x90 /* Keyboard LANG1 */
+#define HID_KBD_USAGE_LANG2 0x91 /* Keyboard LANG2 */
+#define HID_KBD_USAGE_LANG3 0x92 /* Keyboard LANG3 */
+#define HID_KBD_USAGE_LANG4 0x93 /* Keyboard LANG4 */
+#define HID_KBD_USAGE_LANG5 0x94 /* Keyboard LANG5 */
+#define HID_KBD_USAGE_LANG6 0x95 /* Keyboard LANG6 */
+#define HID_KBD_USAGE_LANG7 0x96 /* Keyboard LANG7 */
+#define HID_KBD_USAGE_LANG8 0x97 /* Keyboard LANG8 */
+#define HID_KBD_USAGE_LANG9 0x98 /* Keyboard LANG9 */
+#define HID_KBD_USAGE_ALTERASE 0x99 /* Keyboard Alternate Erase */
+#define HID_KBD_USAGE_SYSREQ 0x9a /* Keyboard SysReq/Attention */
+#define HID_KBD_USAGE_CANCEL 0x9b /* Keyboard Cancel */
+#define HID_KBD_USAGE_CLEAR 0x9c /* Keyboard Clear */
+#define HID_KBD_USAGE_PRIOR 0x9d /* Keyboard Prior */
+#define HID_KBD_USAGE_RETURN 0x9e /* Keyboard Return */
+#define HID_KBD_USAGE_SEPARATOR 0x9f /* Keyboard Separator */
+#define HID_KBD_USAGE_OUT 0xa0 /* Keyboard Out */
+#define HID_KBD_USAGE_OPER 0xa1 /* Keyboard Oper */
+#define HID_KBD_USAGE_CLEARAGAIN 0xa2 /* Keyboard Clear/Again */
+#define HID_KBD_USAGE_CLRSEL 0xa3 /* Keyboard CrSel/Props */
+#define HID_KBD_USAGE_EXSEL 0xa4 /* Keyboard ExSel */
+#define HID_KBD_USAGE_KPD00 0xb0 /* Keypad 00 */
+#define HID_KBD_USAGE_KPD000 0xb1 /* Keypad 000 */
+#define HID_KBD_USAGE_THOUSEPARATOR 0xb2 /* Thousands Separator */
+#define HID_KBD_USAGE_DECSEPARATOR 0xb3 /* Decimal Separator */
+#define HID_KBD_USAGE_CURRUNIT 0xb4 /* Currency Unit */
+#define HID_KBD_USAGE_CURRSUBUNIT 0xb5 /* Currency Sub-unit */
+#define HID_KBD_USAGE_KPDLPAREN 0xb6 /* Keypad ( */
+#define HID_KBD_USAGE_KPDRPAREN 0xb7 /* Keypad ) */
+#define HID_KBD_USAGE_KPDLBRACE 0xb8 /* Keypad { */
+#define HID_KBD_USAGE_KPDRBRACE 0xb9 /* Keypad } */
+#define HID_KBD_USAGE_KPDTAB 0xba /* Keypad Tab */
+#define HID_KBD_USAGE_KPDBACKSPACE 0xbb /* Keypad Backspace */
+#define HID_KBD_USAGE_KPDA 0xbc /* Keypad A (B-F follow) */
+#define HID_KBD_USAGE_KPDXOR 0xc2 /* Keypad XOR */
+#define HID_KBD_USAGE_KPDEXP 0xc3 /* Keypad ^ */
+#define HID_KBD_USAGE_KPDPERCENT 0xc4 /* Keypad % */
+#define HID_KBD_USAGE_KPDLT 0xc5 /* Keypad < */
+#define HID_KBD_USAGE_KPDGT 0xc6 /* Keypad > */
+#define HID_KBD_USAGE_KPDAMPERSAND 0xc7 /* Keypad & */
+#define HID_KBD_USAGE_KPDAND 0xc8 /* Keypad && */
+#define HID_KBD_USAGE_KPDVERT 0xc9 /* Keypad | */
+#define HID_KBD_USAGE_KPDOR 0xca /* Keypad || */
+#define HID_KBD_USAGE_KPDCOLON 0xcb /* Keypad : */
+#define HID_KBD_USAGE_KPDPOUND 0xcc /* Keypad # */
+#define HID_KBD_USAGE_KPDSPACE 0xcd /* Keypad Space */
+#define HID_KBD_USAGE_KPDAT 0xce /* Keypad @ */
+#define HID_KBD_USAGE_KPDEXCLAM 0xcf /* Keypad ! */
+#define HID_KBD_USAGE_KPDMEMSTORE 0xd0 /* Keypad Memory Store */
+#define HID_KBD_USAGE_KPDMEMRECALL 0xd1 /* Keypad Memory Recall */
+#define HID_KBD_USAGE_KPDMEMCLEAR 0xd2 /* Keypad Memory Clear */
+#define HID_KBD_USAGE_KPDMEMADD 0xd3 /* Keypad Memory Add */
+#define HID_KBD_USAGE_KPDMEMSUB 0xd4 /* Keypad Memory Subtract */
+#define HID_KBD_USAGE_KPDMEMMULT 0xd5 /* Keypad Memory Multiply */
+#define HID_KBD_USAGE_KPDMEMDIV 0xd6 /* Keypad Memory Divide */
+#define HID_KBD_USAGE_KPDPLUSMINUS 0xd7 /* Keypad +/- */
+#define HID_KBD_USAGE_KPDCLEAR 0xd8 /* Keypad Clear */
+#define HID_KBD_USAGE_KPDCLEARENTRY 0xd9 /* Keypad Clear Entry */
+#define HID_KBD_USAGE_KPDBINARY 0xda /* Keypad Binary */
+#define HID_KBD_USAGE_KPDOCTAL 0xdb /* Keypad Octal */
+#define HID_KBD_USAGE_KPDDECIMAL 0xdc /* Keypad Decimal */
+#define HID_KBD_USAGE_KPDHEXADECIMAL 0xdd /* Keypad Hexadecimal */
+#define HID_KBD_USAGE_LCTRL 0xe0 /* Keyboard LeftControl */
+#define HID_KBD_USAGE_LSHIFT 0xe1 /* Keyboard LeftShift */
+#define HID_KBD_USAGE_LALT 0xe2 /* Keyboard LeftAlt */
+#define HID_KBD_USAGE_LGUI 0xe3 /* Keyboard Left GUI */
+#define HID_KBD_USAGE_RCTRL 0xe4 /* Keyboard RightControl */
+#define HID_KBD_USAGE_RSHIFT 0xe5 /* Keyboard RightShift */
+#define HID_KBD_USAGE_RALT 0xe6 /* Keyboard RightAlt */
+#define HID_KBD_USAGE_RGUI 0xe7 /* Keyboard Right GUI */
+
+#define HID_KBD_USAGE_MAX 0xe7
+
+/* HID Report Definitions */
+struct usb_hid_class_subdescriptor {
+ uint8_t bDescriptorType;/* Class descriptor type (See 7.1) */
+ uint16_t wDescriptorLength;/* Size of the report descriptor */
+} __PACKED;
+
+struct usb_hid_descriptor {
+ uint8_t bLength; /* Size of the HID descriptor */
+ uint8_t bDescriptorType;/* HID descriptor type */
+ uint16_t bcdHID;/* HID class specification release */
+ uint8_t bCountryCode;/* Country code */
+ uint8_t bNumDescriptors;/* Number of descriptors (>=1) */
+
+ /*
+ * Specification says at least one Class Descriptor needs to
+ * be present (Report Descriptor).
+ */
+ struct usb_hid_class_subdescriptor subdesc[1];
+} __PACKED;
+
+/* Standard Reports *********************************************************/
+
+/* Keyboard input report (8 bytes) (HID B.1) */
+struct usb_hid_kbd_report
+{
+ uint8_t modifier; /* Modifier keys. See HID_MODIFER_* definitions */
+ uint8_t reserved;
+ uint8_t key[6]; /* Keycode 1-6 */
+};
+
+/* Keyboard output report (1 byte) (HID B.1),
+ * see USBHID_KBDOUT_* definitions
+ */
+
+/* Mouse input report (HID B.2) */
+struct usb_hid_mouse_report
+{
+ uint8_t buttons; /* See HID_MOUSE_INPUT_BUTTON_* definitions */
+ uint8_t xdisp; /* X displacement */
+ uint8_t ydisp; /* y displacement */
+ /* Device specific additional bytes may follow */
+#ifdef CONFIG_INPUT_MOUSE_WHEEL
+ uint8_t wdisp; /* Wheel displacement */
+#endif
+};
+
+/* Joystick input report (1 bytes) (HID D.1) */
+struct usb_hid_js_report
+{
+ uint8_t xpos; /* X position */
+ uint8_t ypos; /* X position */
+ uint8_t buttons; /* See USBHID_JSIN_* definitions */
+ uint8_t throttle; /* Throttle */
+};
+
+#endif /* USB_HID_H */
diff --git a/third-party/cherryusb-0.6.0/class/hid/usbd_hid.c b/third-party/cherryusb-0.6.0/class/hid/usbd_hid.c
new file mode 100644
index 0000000000000000000000000000000000000000..1f47bb3f1d9fb7f0097a8875f4679c1cc3a3afb9
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/hid/usbd_hid.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "usbd_hid.h"
+
+static int hid_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ USB_LOG_DBG("HID Custom request: "
+ "bRequest 0x%02x\r\n",
+ setup->bRequest);
+
+ if (((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_IN) &&
+ setup->bRequest == USB_REQUEST_GET_DESCRIPTOR) {
+ uint8_t value = (uint8_t)(setup->wValue >> 8);
+ uint8_t intf_num = (uint8_t)setup->wIndex;
+
+ usb_slist_t *i;
+ struct usbd_interface *match_intf = NULL;
+
+ usb_slist_for_each(i, &usbd_intf_head)
+ {
+ struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
+
+ if (intf->intf_num == intf_num) {
+ match_intf = intf;
+ break;
+ }
+ }
+
+ if (match_intf == NULL) {
+ return -2;
+ }
+
+ switch (value) {
+ case HID_DESCRIPTOR_TYPE_HID:
+ USB_LOG_INFO("get HID Descriptor\r\n");
+ // *data = (uint8_t *)match_intf->hid_descriptor;
+ // *len = match_intf->hid_descriptor[0];
+ break;
+
+ case HID_DESCRIPTOR_TYPE_HID_REPORT:
+ USB_LOG_INFO("get Report Descriptor\r\n");
+ *data = (uint8_t *)match_intf->hid_report_descriptor;
+ *len = match_intf->hid_report_descriptor_len;
+ break;
+
+ case HID_DESCRIPTOR_TYPE_HID_PHYSICAL:
+ USB_LOG_INFO("get PHYSICAL Descriptor\r\n");
+
+ break;
+
+ default:
+ return -2;
+ }
+
+ return 0;
+ }
+
+ return -1;
+}
+
+static int hid_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ USB_LOG_DBG("HID Class request: "
+ "bRequest 0x%02x\r\n",
+ setup->bRequest);
+
+ uint8_t intf_num = LO_BYTE(setup->wIndex);
+
+ switch (setup->bRequest) {
+ case HID_REQUEST_GET_REPORT:
+ /* report id ,report type */
+ (*data)[0] = usbh_hid_get_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
+ *len = 1;
+ break;
+ case HID_REQUEST_GET_IDLE:
+ (*data)[0] = usbh_hid_get_idle(intf_num, LO_BYTE(setup->wValue));
+ *len = 1;
+ break;
+ case HID_REQUEST_GET_PROTOCOL:
+ (*data)[0] = usbh_hid_get_protocol(intf_num);
+ *len = 1;
+ break;
+ case HID_REQUEST_SET_REPORT:
+ /* report id ,report type, report, report len */
+ usbh_hid_set_report(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len);
+ break;
+ case HID_REQUEST_SET_IDLE:
+ /* report id, duration */
+ usbh_hid_set_idle(intf_num, LO_BYTE(setup->wValue), HI_BYTE(setup->wValue));
+ break;
+ case HID_REQUEST_SET_PROTOCOL:
+ /* protocol */
+ usbh_hid_set_protocol(intf_num, LO_BYTE(setup->wValue));
+ break;
+
+ default:
+ USB_LOG_WRN("Unhandled HID Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct usbd_interface *usbd_hid_alloc_intf(const uint8_t *desc, uint32_t desc_len)
+{
+ struct usbd_interface *intf = usb_malloc(sizeof(struct usbd_interface));
+ if (intf == NULL) {
+ USB_LOG_ERR("no mem to alloc intf\r\n");
+ return NULL;
+ }
+
+ intf->class_interface_handler = hid_class_interface_request_handler;
+ intf->class_endpoint_handler = NULL;
+ intf->vendor_handler = NULL;
+ intf->notify_handler = NULL;
+
+ intf->hid_report_descriptor = desc;
+ intf->hid_report_descriptor_len = desc_len;
+ return intf;
+}
+
+__WEAK uint8_t usbh_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type)
+{
+ return 0;
+}
+
+__WEAK uint8_t usbh_hid_get_idle(uint8_t intf, uint8_t report_id)
+{
+ return 0;
+}
+
+__WEAK uint8_t usbh_hid_get_protocol(uint8_t intf)
+{
+ return 0;
+}
+
+__WEAK void usbh_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len)
+{
+}
+
+__WEAK void usbh_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration)
+{
+}
+
+__WEAK void usbh_hid_set_protocol(uint8_t intf, uint8_t protocol)
+{
+}
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/class/hid/usbd_hid.h b/third-party/cherryusb-0.6.0/class/hid/usbd_hid.h
new file mode 100644
index 0000000000000000000000000000000000000000..d065cf456f9fff3173701f5f9127f448d1fc575e
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/hid/usbd_hid.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBD_HID_H
+#define USBD_HID_H
+
+#include "usb_hid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Alloc hid interface driver */
+struct usbd_interface *usbd_hid_alloc_intf(const uint8_t *desc, uint32_t desc_len);
+
+/* Register desc api */
+void usbd_hid_descriptor_register(uint8_t intf_num, const uint8_t *desc);
+void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
+
+/* Setup request command callback api */
+uint8_t usbh_hid_get_report(uint8_t intf, uint8_t report_id, uint8_t report_type);
+uint8_t usbh_hid_get_idle(uint8_t intf, uint8_t report_id);
+uint8_t usbh_hid_get_protocol(uint8_t intf);
+void usbh_hid_set_report(uint8_t intf, uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len);
+void usbh_hid_set_idle(uint8_t intf, uint8_t report_id, uint8_t duration);
+void usbh_hid_set_protocol(uint8_t intf, uint8_t protocol);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBD_HID_H */
diff --git a/third-party/cherryusb-0.6.0/class/hid/usbh_hid.c b/third-party/cherryusb-0.6.0/class/hid/usbh_hid.c
new file mode 100644
index 0000000000000000000000000000000000000000..6fc861a96b941af229881a4e99f94c4f0e0eb7c5
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/hid/usbh_hid.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbh_core.h"
+#include "usbh_hid.h"
+
+#define DEV_FORMAT "/dev/input%d"
+
+static uint32_t g_devinuse = 0;
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hid_buf[128];
+
+static int usbh_hid_devno_alloc(struct usbh_hid *hid_class)
+{
+ int devno;
+
+ for (devno = 0; devno < 32; devno++) {
+ uint32_t bitno = 1 << devno;
+ if ((g_devinuse & bitno) == 0) {
+ g_devinuse |= bitno;
+ hid_class->minor = devno;
+ return 0;
+ }
+ }
+
+ return -EMFILE;
+}
+
+static void usbh_hid_devno_free(struct usbh_hid *hid_class)
+{
+ int devno = hid_class->minor;
+
+ if (devno >= 0 && devno < 32) {
+ g_devinuse &= ~(1 << devno);
+ }
+}
+
+static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer)
+{
+ struct usb_setup_packet *setup = &hid_class->hport->setup;
+ int ret;
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ setup->wValue = HID_DESCRIPTOR_TYPE_HID_REPORT << 8;
+ setup->wIndex = hid_class->intf;
+ setup->wLength = 128;
+
+ ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf);
+ if (ret < 0) {
+ return ret;
+ }
+ memcpy(buffer, g_hid_buf, ret - 8);
+ return ret;
+}
+
+int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration)
+{
+ struct usb_setup_packet *setup = &hid_class->hport->setup;
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = HID_REQUEST_SET_IDLE;
+ setup->wValue = (duration << 8) | report_id;
+ setup->wIndex = hid_class->intf;
+ setup->wLength = 0;
+
+ return usbh_control_transfer(hid_class->hport->ep0, setup, NULL);
+}
+
+int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer)
+{
+ struct usb_setup_packet *setup = &hid_class->hport->setup;
+ int ret;
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = HID_REQUEST_GET_IDLE;
+ setup->wValue = 0;
+ setup->wIndex = hid_class->intf;
+ setup->wLength = 1;
+
+ ret = usbh_control_transfer(hid_class->hport->ep0, setup, g_hid_buf);
+ if (ret < 0) {
+ return ret;
+ }
+ memcpy(buffer, g_hid_buf, 1);
+ return ret;
+}
+
+int usbh_hid_set_protocol(struct usbh_hid *hid_class, uint8_t protocol)
+{
+ struct usb_setup_packet *setup = &hid_class->hport->setup;
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = HID_REQUEST_SET_PROTOCOL;
+ setup->wValue = protocol;
+ setup->wIndex = 0;
+ setup->wLength = 0;
+
+ return usbh_control_transfer(hid_class->hport->ep0, setup, NULL);
+}
+
+int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf)
+{
+ struct usb_endpoint_descriptor *ep_desc;
+ int ret;
+
+ struct usbh_hid *hid_class = usb_malloc(sizeof(struct usbh_hid));
+ if (hid_class == NULL) {
+ USB_LOG_ERR("Fail to alloc hid_class\r\n");
+ return -ENOMEM;
+ }
+
+ memset(hid_class, 0, sizeof(struct usbh_hid));
+ usbh_hid_devno_alloc(hid_class);
+ hid_class->hport = hport;
+ hid_class->intf = intf;
+
+ hport->config.intf[intf].priv = hid_class;
+
+ // /* 0x0 = boot protocol, 0x1 = report protocol */
+ // ret = usbh_hid_set_protocol(hid_class, 0x1);
+ // if (ret < 0) {
+ // return ret;
+ // }
+
+ ret = usbh_hid_set_idle(hid_class, 0, 0);
+ if (ret < 0) {
+ USB_LOG_WRN("Do not support set idle\r\n");
+ }
+
+ ret = usbh_hid_get_report_descriptor(hid_class, hid_class->report_desc);
+ if (ret < 0) {
+ return ret;
+ }
+
+ 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_hport_activate_epx(&hid_class->intin, hport, ep_desc);
+ } else {
+ usbh_hport_activate_epx(&hid_class->intout, hport, ep_desc);
+ }
+ }
+
+ snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hid_class->minor);
+
+ USB_LOG_INFO("Register HID Class:%s\r\n", hport->config.intf[intf].devname);
+
+ return 0;
+}
+
+int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf)
+{
+ int ret = 0;
+
+ struct usbh_hid *hid_class = (struct usbh_hid *)hport->config.intf[intf].priv;
+
+ if (hid_class) {
+ usbh_hid_devno_free(hid_class);
+
+ if (hid_class->intin) {
+ usbh_pipe_free(hid_class->intin);
+ }
+
+ if (hid_class->intout) {
+ usbh_pipe_free(hid_class->intout);
+ }
+
+ memset(hid_class, 0, sizeof(struct usbh_hid));
+ usb_free(hid_class);
+
+ if (hport->config.intf[intf].devname[0] != '\0'){
+ USB_LOG_INFO("Unregister HID Class:%s\r\n", hport->config.intf[intf].devname);
+ }
+ }
+
+ return ret;
+}
+
+const struct usbh_class_driver hid_class_driver = {
+ .driver_name = "hid",
+ .connect = usbh_hid_connect,
+ .disconnect = usbh_hid_disconnect
+};
+
+CLASS_INFO_DEFINE const struct usbh_class_info hid_keyboard_class_info = {
+ .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
+ .class = USB_DEVICE_CLASS_HID,
+ .subclass = HID_SUBCLASS_BOOTIF,
+ .protocol = HID_PROTOCOL_KEYBOARD,
+ .vid = 0x00,
+ .pid = 0x00,
+ .class_driver = &hid_class_driver
+};
+
+CLASS_INFO_DEFINE const struct usbh_class_info hid_mouse_class_info = {
+ .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
+ .class = USB_DEVICE_CLASS_HID,
+ .subclass = HID_SUBCLASS_BOOTIF,
+ .protocol = HID_PROTOCOL_MOUSE,
+ .vid = 0x00,
+ .pid = 0x00,
+ .class_driver = &hid_class_driver
+};
diff --git a/third-party/cherryusb-0.6.0/class/hid/usbh_hid.h b/third-party/cherryusb-0.6.0/class/hid/usbh_hid.h
new file mode 100644
index 0000000000000000000000000000000000000000..74e8b4082c96d72cfa4cb105832de63b27d0e7a7
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/hid/usbh_hid.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBH_HID_H
+#define USBH_HID_H
+
+#include "usb_hid.h"
+
+struct usbh_hid {
+ struct usbh_hubport *hport;
+
+ uint8_t report_desc[128];
+ uint8_t intf; /* interface number */
+ uint8_t minor;
+ usbh_pipe_t intin; /* INTR IN endpoint */
+ usbh_pipe_t intout; /* INTR OUT endpoint */
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int usbh_hid_set_idle(struct usbh_hid *hid_class, uint8_t report_id, uint8_t duration);
+int usbh_hid_get_idle(struct usbh_hid *hid_class, uint8_t *buffer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBH_HID_H */
diff --git a/third-party/cherryusb-0.6.0/class/hub/usb_hub.h b/third-party/cherryusb-0.6.0/class/hub/usb_hub.h
new file mode 100644
index 0000000000000000000000000000000000000000..022ca2a05c9300d0e5e001f4c18f5f4fb8f9c4e8
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/hub/usb_hub.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_HUB_H
+#define USB_HUB_H
+
+/* HUB Class Descriptor Types */
+#define HUB_DESCRIPTOR_TYPE_HUB 0x29
+
+/* Hub class requests */
+#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS
+#define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE
+#define HUB_REQUEST_SET_FEATURE USB_REQUEST_SET_FEATURE
+#define HUB_REQUEST_GET_DESCRIPTOR USB_REQUEST_GET_DESCRIPTOR
+#define HUB_REQUEST_SET_DESCRIPTOR USB_REQUEST_SET_DESCRIPTOR
+#define HUB_REQUEST_CLEAR_TT_BUFFER (0x08)
+#define HUB_REQUEST_RESET_TT (0x09)
+#define HUB_REQUEST_GET_TT_STATE (0x0a)
+#define HUB_REQUEST_STOP_TT (0x0b)
+
+/* Hub class features */
+#define HUB_FEATURE_HUB_C_LOCALPOWER (0x0)
+#define HUB_FEATURE_HUB_C_OVERCURRENT (0x1)
+
+/* Port features */
+#define HUB_PORT_FEATURE_CONNECTION (0x00)
+#define HUB_PORT_FEATURE_ENABLE (0x01)
+#define HUB_PORT_FEATURE_SUSPEND (0x02)
+#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
+#define HUB_PORT_FEATURE_RESET (0x04)
+#define HUB_PORT_FEATURE_L1 (0x05)
+#define HUB_PORT_FEATURE_POWER (0x08)
+#define HUB_PORT_FEATURE_LOWSPEED (0x09)
+#define HUB_PORT_FEATURE_HIGHSPEED (0x0a)
+#define HUB_PORT_FEATURE_C_CONNECTION (0x10)
+#define HUB_PORT_FEATURE_C_ENABLE (0x11)
+#define HUB_PORT_FEATURE_C_SUSPEND (0x12)
+#define HUB_PORT_FEATURE_C_OVER_CURREN (0x13)
+#define HUB_PORT_FEATURE_C_RESET (0x14)
+#define HUB_PORT_FEATURE_TEST (0x15)
+#define HUB_PORT_FEATURE_INDICATOR (0x16)
+#define HUB_PORT_FEATURE_C_PORTL1 (0x17)
+
+/* Hub status */
+#define HUB_STATUS_LOCALPOWER (1 << 0)
+#define HUB_STATUS_OVERCURRENT (1 << 1)
+
+/* Hub status change */
+#define HUB_STATUS_C_LOCALPOWER (1 << 0)
+#define HUB_STATUS_C_OVERCURRENT (1 << 1)
+
+/* Hub port status */
+#define HUB_PORT_STATUS_CONNECTION (1 << 0)
+#define HUB_PORT_STATUS_ENABLE (1 << 1)
+#define HUB_PORT_STATUS_SUSPEND (1 << 2)
+#define HUB_PORT_STATUS_OVERCURRENT (1 << 3)
+#define HUB_PORT_STATUS_RESET (1 << 4)
+#define HUB_PORT_STATUS_L1 (1 << 5)
+#define HUB_PORT_STATUS_POWER (1 << 8)
+#define HUB_PORT_STATUS_LOW_SPEED (1 << 9)
+#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10)
+#define HUB_PORT_STATUS_TEST (1 << 11)
+#define HUB_PORT_STATUS_INDICATOR (1 << 12)
+
+/* Hub port status change */
+#define HUB_PORT_STATUS_C_CONNECTION (1 << 0)
+#define HUB_PORT_STATUS_C_ENABLE (1 << 1)
+#define HUB_PORT_STATUS_C_SUSPEND (1 << 2)
+#define HUB_PORT_STATUS_C_OVERCURRENT (1 << 3)
+#define HUB_PORT_STATUS_C_RESET (1 << 4)
+#define HUB_PORT_STATUS_C_L1 (1 << 5)
+
+/* Hub characteristics */
+#define HUB_CHAR_LPSM_SHIFT (0) /* Bits 0-1: Logical Power Switching Mode */
+#define HUB_CHAR_LPSM_MASK (3 << HUB_CHAR_LPSM_SHIFT)
+#define HUB_CHAR_LPSM_GANGED (0 << HUB_CHAR_LPSM_SHIFT)
+#define HUB_CHAR_LPSM_INDIVIDUAL (1 << HUB_CHAR_LPSM_SHIFT)
+#define HUB_CHAR_COMPOUND (1 << 2) /* Bit 2: Compound device */
+#define HUB_CHAR_OCPM_SHIFT (3) /* Bits 3-4: Over-current Protection Mode */
+#define HUB_CHAR_OCPM_MASK (3 << HUB_CHAR_OCPM_SHIFT)
+#define HUB_CHAR_OCPM_GLOBAL (0 << HUB_CHAR_OCPM_SHIFT)
+#define HUB_CHAR_OCPM_INDIVIDUAL (1 << HUB_CHAR_OCPM_SHIFT)
+#define HUB_CHAR_TTTT_SHIFT (5) /* Bits 5-6: TT Think Time */
+#define HUB_CHAR_TTTT_MASK (3 << HUB_CHAR_TTTT_SHIFT)
+#define HUB_CHAR_TTTT_8_BITS (0 << HUB_CHAR_TTTT_SHIFT)
+#define HUB_CHAR_TTTT_16_BITS (1 << HUB_CHAR_TTTT_SHIFT)
+#define HUB_CHAR_TTTT_24_BITS (2 << HUB_CHAR_TTTT_SHIFT)
+#define HUB_CHAR_TTTT_32_BITS (3 << HUB_CHAR_TTTT_SHIFT)
+#define HUB_CHAR_PORTIND (1 << 7) /* Bit 7: Port Indicators Supported */
+
+/* Hub descriptor */
+struct usb_hub_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bNbrPorts;
+ uint16_t wHubCharacteristics;
+ uint8_t bPwrOn2PwrGood;
+ uint8_t bHubContrCurrent;
+ uint8_t DeviceRemovable;
+ uint8_t PortPwrCtrlMask;
+} __PACKED;
+
+#define USB_SIZEOF_HUB_DESC 9
+
+/* Hub status */
+struct hub_status {
+ uint16_t wPortStatus;
+ uint16_t wPortChange;
+};
+
+/* Hub port status */
+struct hub_port_status {
+ uint16_t wPortStatus;
+ uint16_t wPortChange;
+};
+
+#endif /* USB_HUB_H */
diff --git a/third-party/cherryusb-0.6.0/class/hub/usbh_hub.c b/third-party/cherryusb-0.6.0/class/hub/usbh_hub.c
new file mode 100644
index 0000000000000000000000000000000000000000..67374eaa16eee2ab4f40f5ba87ceef94bc7454f9
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/hub/usbh_hub.c
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbh_hub.h"
+
+#define DEV_FORMAT "/dev/hub%d"
+
+#define DEBOUNCE_TIMEOUT 400
+#define DEBOUNCE_TIME_STEP 25
+#define DELAY_TIME_AFTER_RESET 200
+
+#define EXTHUB_FIRST_INDEX 2
+
+static uint32_t g_devinuse = 0;
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_hub_buf[32];
+
+usb_slist_t hub_event_head = USB_SLIST_OBJECT_INIT(hub_event_head);
+usb_slist_t hub_class_head = USB_SLIST_OBJECT_INIT(hub_class_head);
+
+usb_osal_sem_t hub_event_wait;
+usb_osal_thread_t hub_thread;
+
+USB_NOCACHE_RAM_SECTION struct usbh_hub roothub;
+struct usbh_hubport roothub_parent_port;
+
+USB_NOCACHE_RAM_SECTION struct usbh_hub exthub[CONFIG_USBHOST_MAX_EXTHUBS];
+
+extern int usbh_hport_activate_ep0(struct usbh_hubport *hport);
+extern int usbh_hport_deactivate_ep0(struct usbh_hubport *hport);
+extern int usbh_enumerate(struct usbh_hubport *hport);
+
+static const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
+
+static int usbh_hub_devno_alloc(void)
+{
+ int devno;
+
+ for (devno = EXTHUB_FIRST_INDEX; devno < 32; devno++) {
+ uint32_t bitno = 1 << devno;
+ if ((g_devinuse & bitno) == 0) {
+ g_devinuse |= bitno;
+ return devno;
+ }
+ }
+
+ return -EMFILE;
+}
+
+static void usbh_hub_devno_free(uint8_t devno)
+{
+ if (devno >= EXTHUB_FIRST_INDEX && devno < 32) {
+ g_devinuse &= ~(1 << devno);
+ }
+}
+
+static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
+{
+ struct usb_setup_packet *setup;
+ int ret;
+
+ setup = &hub->parent->setup;
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
+ setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
+ setup->wIndex = 0;
+ setup->wLength = USB_SIZEOF_HUB_DESC;
+
+ ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
+ if (ret < 0) {
+ return ret;
+ }
+ memcpy(buffer, g_hub_buf, USB_SIZEOF_HUB_DESC);
+ return ret;
+}
+
+static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
+{
+ struct usb_setup_packet *setup;
+ int ret;
+
+ setup = &hub->parent->setup;
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
+ setup->bRequest = HUB_REQUEST_GET_STATUS;
+ setup->wValue = 0;
+ setup->wIndex = 0;
+ setup->wLength = 2;
+
+ ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
+ if (ret < 0) {
+ return ret;
+ }
+ memcpy(buffer, g_hub_buf, 2);
+ return ret;
+}
+
+static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
+{
+ struct usb_setup_packet *setup;
+ int ret;
+
+ setup = &hub->parent->setup;
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
+ setup->bRequest = HUB_REQUEST_GET_STATUS;
+ setup->wValue = 0;
+ setup->wIndex = port;
+ setup->wLength = 4;
+
+ ret = usbh_control_transfer(hub->parent->ep0, setup, g_hub_buf);
+ if (ret < 0) {
+ return ret;
+ }
+ memcpy(port_status, g_hub_buf, 4);
+ return ret;
+}
+
+static int _usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
+{
+ struct usb_setup_packet *setup;
+
+ setup = &hub->parent->setup;
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
+ setup->bRequest = HUB_REQUEST_SET_FEATURE;
+ setup->wValue = feature;
+ setup->wIndex = port;
+ setup->wLength = 0;
+
+ return usbh_control_transfer(hub->parent->ep0, setup, NULL);
+}
+
+static int _usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
+{
+ struct usb_setup_packet *setup;
+
+ setup = &hub->parent->setup;
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
+ setup->bRequest = HUB_REQUEST_CLEAR_FEATURE;
+ setup->wValue = feature;
+ setup->wIndex = port;
+ setup->wLength = 0;
+
+ return usbh_control_transfer(hub->parent->ep0, setup, NULL);
+}
+
+static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length)
+{
+ if (desc->bLength != USB_SIZEOF_HUB_DESC) {
+ USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
+ return -1;
+ } else if (desc->bDescriptorType != HUB_DESCRIPTOR_TYPE_HUB) {
+ USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType);
+ return -2;
+ } else {
+ USB_LOG_RAW("Hub Descriptor:\r\n");
+ USB_LOG_RAW("bLength: 0x%02x \r\n", desc->bLength);
+ USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
+ USB_LOG_RAW("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
+ USB_LOG_RAW("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
+ USB_LOG_RAW("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
+ USB_LOG_RAW("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
+ USB_LOG_RAW("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable);
+ USB_LOG_RAW("PortPwrCtrlMask: 0x%02x \r\n", desc->PortPwrCtrlMask);
+ }
+ return 0;
+}
+
+static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
+{
+ struct usb_setup_packet roothub_setup;
+ struct usb_setup_packet *setup;
+
+ if (hub->is_roothub) {
+ setup = &roothub_setup;
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
+ setup->bRequest = HUB_REQUEST_GET_STATUS;
+ setup->wValue = 0;
+ setup->wIndex = port;
+ setup->wLength = 4;
+ return usbh_roothub_control(&roothub_setup, (uint8_t *)port_status);
+ } else {
+ return _usbh_hub_get_portstatus(hub, port, port_status);
+ }
+}
+
+static int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
+{
+ struct usb_setup_packet roothub_setup;
+ struct usb_setup_packet *setup;
+
+ if (hub->is_roothub) {
+ setup = &roothub_setup;
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
+ setup->bRequest = HUB_REQUEST_SET_FEATURE;
+ setup->wValue = feature;
+ setup->wIndex = port;
+ setup->wLength = 0;
+ return usbh_roothub_control(setup, NULL);
+ } else {
+ return _usbh_hub_set_feature(hub, port, feature);
+ }
+}
+
+static int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
+{
+ struct usb_setup_packet roothub_setup;
+ struct usb_setup_packet *setup;
+
+ if (hub->is_roothub) {
+ setup = &roothub_setup;
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER;
+ setup->bRequest = HUB_REQUEST_CLEAR_FEATURE;
+ setup->wValue = feature;
+ setup->wIndex = port;
+ setup->wLength = 0;
+ return usbh_roothub_control(setup, NULL);
+ } else {
+ return _usbh_hub_clear_feature(hub, port, feature);
+ }
+}
+
+static void usbh_hub_thread_wakeup(struct usbh_hub *hub)
+{
+ usb_slist_add_tail(&hub_event_head, &hub->hub_event_list);
+ usb_osal_sem_give(hub_event_wait);
+}
+
+static void hub_int_complete_callback(void *arg, int nbytes)
+{
+ struct usbh_hub *hub = (struct usbh_hub *)arg;
+
+ if (nbytes > 0) {
+ usbh_hub_thread_wakeup(hub);
+ }
+}
+
+static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
+{
+ struct usb_endpoint_descriptor *ep_desc;
+ struct hub_port_status port_status;
+ int ret;
+ int index;
+
+ index = usbh_hub_devno_alloc();
+ if (index > (CONFIG_USBHOST_MAX_EXTHUBS + EXTHUB_FIRST_INDEX - 1)) {
+ USB_LOG_ERR("No memory to alloc hub class\r\n");
+ usbh_hub_devno_free(index);
+ return -ENOMEM;
+ }
+
+ struct usbh_hub *hub = &exthub[index - EXTHUB_FIRST_INDEX];
+
+ memset(hub, 0, sizeof(struct usbh_hub));
+ hub->hub_addr = hport->dev_addr;
+ hub->parent = hport;
+ hub->index = index;
+
+ hport->config.intf[intf].priv = hub;
+
+ ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
+ if (ret < 0) {
+ return ret;
+ }
+
+ parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
+
+ for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ hub->child[port].port = port + 1;
+ hub->child[port].parent = hub;
+ }
+
+ ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
+ if (ep_desc->bEndpointAddress & 0x80) {
+ usbh_hport_activate_epx(&hub->intin, hport, ep_desc);
+ } else {
+ return -1;
+ }
+
+ for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
+ USB_LOG_INFO("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, port_status.wPortStatus, port_status.wPortChange);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ hub->connected = true;
+ snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub->index);
+ usbh_hub_register(hub);
+ USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
+
+ usbh_int_urb_fill(&hub->intin_urb, hub->intin, hub->int_buffer, 1, 0, hub_int_complete_callback, hub);
+ usbh_submit_urb(&hub->intin_urb);
+ return 0;
+}
+
+static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
+{
+ struct usbh_hubport *child;
+ int ret = 0;
+
+ struct usbh_hub *hub = (struct usbh_hub *)hport->config.intf[intf].priv;
+
+ if (hub) {
+ usbh_hub_devno_free(hub->index);
+
+ if (hub->intin) {
+ usbh_pipe_free(hub->intin);
+ }
+
+ for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ child = &hub->child[port];
+ usbh_hport_deactivate_ep0(child);
+ for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
+ if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
+ ret = CLASS_DISCONNECT(child, i);
+ }
+ }
+
+ child->config.config_desc.bNumInterfaces = 0;
+ child->parent = NULL;
+ }
+
+ usbh_hub_unregister(hub);
+ memset(hub, 0, sizeof(struct usbh_hub));
+
+ if (hport->config.intf[intf].devname[0] != '\0'){
+ USB_LOG_INFO("Unregister HUB Class:%s\r\n", hport->config.intf[intf].devname);
+ }
+ }
+ return ret;
+}
+
+static void usbh_roothub_register(void)
+{
+ memset(&roothub, 0, sizeof(struct usbh_hub));
+ memset(&roothub_parent_port, 0, sizeof(struct usbh_hubport));
+ roothub_parent_port.port = 1;
+ roothub_parent_port.dev_addr = 1;
+ roothub.connected = true;
+ roothub.index = 1;
+ roothub.is_roothub = true;
+ roothub.parent = &roothub_parent_port;
+ roothub.hub_addr = roothub_parent_port.dev_addr;
+ roothub.hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
+ usbh_hub_register(&roothub);
+}
+
+static void usbh_hub_events(struct usbh_hub *hub)
+{
+ struct usbh_hubport *child;
+ struct hub_port_status port_status;
+ uint8_t portchange_index;
+ uint16_t portstatus;
+ uint16_t portchange;
+ uint16_t mask;
+ uint16_t feat;
+ uint8_t speed;
+ int ret;
+
+ if (!hub->connected) {
+ return;
+ }
+
+ for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ portchange_index = hub->int_buffer[0];
+
+ USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
+
+ if (!(portchange_index & (1 << (port + 1)))) {
+ continue;
+ }
+ portchange_index &= ~(1 << (port + 1));
+ USB_LOG_DBG("Port %d change\r\n", port + 1);
+
+ /* Read hub port status */
+ ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
+ continue;
+ }
+
+ portstatus = port_status.wPortStatus;
+ portchange = port_status.wPortChange;
+
+ USB_LOG_DBG("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, portstatus, portchange);
+
+ /* First, clear all change bits */
+ mask = 1;
+ feat = HUB_PORT_FEATURE_C_CONNECTION;
+ while (portchange) {
+ if (portchange & mask) {
+ ret = usbh_hub_clear_feature(hub, port + 1, feat);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to clear port %u, change mask:%04x, errorcode:%d\r\n", port + 1, mask, ret);
+ continue;
+ }
+ portchange &= (~mask);
+ }
+ mask <<= 1;
+ feat++;
+ }
+
+ portchange = port_status.wPortChange;
+
+ /* Second, if port changes, debounces first */
+ if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
+ uint16_t connection = 0;
+ uint16_t debouncestable = 0;
+ for (uint32_t debouncetime = 0; debouncetime < DEBOUNCE_TIMEOUT; debouncetime += DEBOUNCE_TIME_STEP) {
+ usb_osal_msleep(DEBOUNCE_TIME_STEP);
+ /* Read hub port status */
+ ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
+ continue;
+ }
+
+ portstatus = port_status.wPortStatus;
+ portchange = port_status.wPortChange;
+
+ USB_LOG_DBG("Port %u, status:0x%02x, change:0x%02x\r\n", port + 1, portstatus, portchange);
+ if ((portstatus & HUB_PORT_STATUS_CONNECTION) == connection) {
+ if (connection) {
+ if (++debouncestable == 4) {
+ break;
+ }
+ }
+ } else {
+ debouncestable = 0;
+ }
+
+ connection = portstatus & HUB_PORT_STATUS_CONNECTION;
+
+ if (portchange & HUB_PORT_STATUS_C_CONNECTION) {
+ usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_CONNECTION);
+ }
+ }
+
+ /* Last, check connect status */
+ if (portstatus & HUB_PORT_STATUS_CONNECTION) {
+ ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_RESET);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to reset port %u,errorcode:%d\r\n", port, ret);
+ continue;
+ }
+
+ usb_osal_msleep(DELAY_TIME_AFTER_RESET);
+ /* Read hub port status */
+ ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to read port %u status, errorcode: %d\r\n", port + 1, ret);
+ continue;
+ }
+
+ portstatus = port_status.wPortStatus;
+ portchange = port_status.wPortChange;
+ if (!(portstatus & HUB_PORT_STATUS_RESET) && (portstatus & HUB_PORT_STATUS_ENABLE)) {
+ if (portchange & HUB_PORT_STATUS_C_RESET) {
+ ret = usbh_hub_clear_feature(hub, port + 1, HUB_PORT_FEATURE_C_RESET);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to clear port %u reset change, errorcode: %d\r\n", port, ret);
+ }
+ }
+
+ if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
+ speed = USB_SPEED_HIGH;
+ } else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
+ speed = USB_SPEED_LOW;
+ } else {
+ speed = USB_SPEED_FULL;
+ }
+
+ child = &hub->child[port];
+
+ memset(child, 0, sizeof(struct usbh_hubport));
+ child->parent = hub;
+ child->connected = true;
+ child->port = port + 1;
+ child->speed = speed;
+
+ USB_LOG_INFO("New %s device on Hub %u, Port %u connected\r\n", speed_table[speed], hub->index, port + 1);
+
+ if (usbh_enumerate(child) < 0) {
+ USB_LOG_ERR("Port %u enumerate fail\r\n", port + 1);
+ }
+ } else {
+ USB_LOG_ERR("Failed to enable port %u\r\n", port + 1);
+ continue;
+ }
+ } else {
+ child = &hub->child[port];
+ child->connected = false;
+ usbh_hport_deactivate_ep0(child);
+ for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) {
+ if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) {
+ CLASS_DISCONNECT(child, i);
+ }
+ }
+
+ USB_LOG_INFO("Device on Hub %u, Port %u disconnected\r\n", hub->index, port + 1);
+ usbh_device_unmount_done_callback(child);
+ child->config.config_desc.bNumInterfaces = 0;
+ }
+ }
+ }
+
+ /* Start next hub int transfer */
+ if (!hub->is_roothub && hub->connected) {
+ usbh_submit_urb(&hub->intin_urb);
+ }
+}
+
+static void usbh_hub_thread(void *argument)
+{
+ size_t flags;
+ int ret = 0;
+
+ usb_hc_init();
+ while (1) {
+ ret = usb_osal_sem_take(hub_event_wait, 0xffffffff);
+ if (ret < 0) {
+ continue;
+ }
+
+ while (!usb_slist_isempty(&hub_event_head)) {
+ struct usbh_hub *hub = usb_slist_first_entry(&hub_event_head, struct usbh_hub, hub_event_list);
+ flags = usb_osal_enter_critical_section();
+ usb_slist_remove(&hub_event_head, &hub->hub_event_list);
+ usb_osal_leave_critical_section(flags);
+ usbh_hub_events(hub);
+ }
+ }
+}
+
+void usbh_roothub_thread_wakeup(uint8_t port)
+{
+ roothub.int_buffer[0] |= (1 << port);
+ usbh_hub_thread_wakeup(&roothub);
+}
+
+void usbh_hub_register(struct usbh_hub *hub)
+{
+ usb_slist_add_tail(&hub_class_head, &hub->list);
+}
+
+void usbh_hub_unregister(struct usbh_hub *hub)
+{
+ usb_slist_remove(&hub_class_head, &hub->list);
+}
+
+int usbh_hub_initialize(void)
+{
+ usbh_roothub_register();
+
+ hub_event_wait = usb_osal_sem_create(0);
+ if (hub_event_wait == NULL) {
+ return -1;
+ }
+
+ hub_thread = usb_osal_thread_create("usbh_hub", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_hub_thread, NULL);
+ if (hub_thread == NULL) {
+ return -1;
+ }
+ return 0;
+}
+
+const struct usbh_class_driver hub_driver = {
+ .driver_name = "hub",
+ .connect = usbh_hub_connect,
+ .disconnect = usbh_hub_disconnect
+};
+
+CLASS_INFO_DEFINE const struct usbh_class_info hub_info = {
+ .match_flags = USB_CLASS_MATCH_INTF_CLASS,
+ .class = USB_DEVICE_CLASS_HUB,
+ .subclass = 0,
+ .protocol = 0,
+ .vid = 0x00,
+ .pid = 0x00,
+ .class_driver = &hub_driver
+};
diff --git a/third-party/cherryusb-0.6.0/class/hub/usbh_hub.h b/third-party/cherryusb-0.6.0/class/hub/usbh_hub.h
new file mode 100644
index 0000000000000000000000000000000000000000..41807de04390d91aa103ed69dcdfeb4e38aecb99
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/hub/usbh_hub.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBH_HUB_H
+#define USBH_HUB_H
+
+#include "usbh_core.h"
+#include "usb_hub.h"
+
+#define USBH_HUB_MAX_PORTS 4
+/* Maximum size of an interrupt IN transfer */
+#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
+
+extern usb_slist_t hub_class_head;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void usbh_roothub_thread_wakeup(uint8_t port);
+void usbh_hub_register(struct usbh_hub *hub);
+void usbh_hub_unregister(struct usbh_hub *hub);
+int usbh_hub_initialize(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBH_HUB_H */
diff --git a/third-party/cherryusb-0.6.0/class/midi/usb_midi.h b/third-party/cherryusb-0.6.0/class/midi/usb_midi.h
new file mode 100644
index 0000000000000000000000000000000000000000..01f4035bac9e7ded24f3342fa686ba520811d1dc
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/midi/usb_midi.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_MIDI_H
+#define USB_MIDI_H
+
+/* bDescriptorSubType */
+#define MIDI_VC_HEADER_DESCRIPTOR_SUBTYPE 0x01U
+#define MIDI_MS_HEADER_DESCRIPTOR_SUBTYPE 0x01U
+#define MIDI_MS_GENERAL_DESCRIPTOR_SUBTYPE 0x01U
+#define MIDI_MIDI_IN_JACK_DESCRIPTOR_SUBTYPE 0x02U
+#define MIDI_MIDI_OUT_JACK_DESCRIPTOR_SUBTYPE 0x03U
+
+/* bJackType */
+#define MIDI_JACK_TYPE_EMBEDDED 0x01
+#define MIDI_JACK_TYPE_EXTERNAL 0x02
+
+#define MIDI_CHANNEL_OMNI 0
+#define MIDI_CHANNEL_OFF 17
+
+#define MIDI_PITCHBEND_MIN -8192
+#define MIDI_PITCHBEND_MAX 8191
+
+/*! Enumeration of MIDI types */
+enum MidiType {
+ InvalidType = 0x00, ///< For notifying errors
+ NoteOff = 0x80, ///< Note Off
+ NoteOn = 0x90, ///< Note On
+ AfterTouchPoly = 0xA0, ///< Polyphonic AfterTouch
+ ControlChange = 0xB0, ///< Control Change / Channel Mode
+ ProgramChange = 0xC0, ///< Program Change
+ AfterTouchChannel = 0xD0, ///< Channel (monophonic) AfterTouch
+ PitchBend = 0xE0, ///< Pitch Bend
+ SystemExclusive = 0xF0, ///< System Exclusive
+ TimeCodeQuarterFrame = 0xF1, ///< System Common - MIDI Time Code Quarter Frame
+ SongPosition = 0xF2, ///< System Common - Song Position Pointer
+ SongSelect = 0xF3, ///< System Common - Song Select
+ TuneRequest = 0xF6, ///< System Common - Tune Request
+ Clock = 0xF8, ///< System Real Time - Timing Clock
+ Start = 0xFA, ///< System Real Time - Start
+ Continue = 0xFB, ///< System Real Time - Continue
+ Stop = 0xFC, ///< System Real Time - Stop
+ ActiveSensing = 0xFE, ///< System Real Time - Active Sensing
+ SystemReset = 0xFF, ///< System Real Time - System Reset
+};
+
+/*! Enumeration of Thru filter modes */
+enum MidiFilterMode {
+ Off = 0, ///< Thru disabled (nothing passes through).
+ Full = 1, ///< Fully enabled Thru (every incoming message is sent back).
+ SameChannel = 2, ///< Only the messages on the Input Channel will be sent back.
+ DifferentChannel = 3, ///< All the messages but the ones on the Input Channel will be sent back.
+};
+
+/*! \brief Enumeration of Control Change command numbers.
+ See the detailed controllers numbers & description here:
+ http://www.somascape.org/midi/tech/spec.html#ctrlnums
+ */
+enum MidiControlChangeNumber {
+ // High resolution Continuous Controllers MSB (+32 for LSB) ----------------
+ BankSelect = 0,
+ ModulationWheel = 1,
+ BreathController = 2,
+ // CC3 undefined
+ FootController = 4,
+ PortamentoTime = 5,
+ DataEntry = 6,
+ ChannelVolume = 7,
+ Balance = 8,
+ // CC9 undefined
+ Pan = 10,
+ ExpressionController = 11,
+ EffectControl1 = 12,
+ EffectControl2 = 13,
+ // CC14 undefined
+ // CC15 undefined
+ GeneralPurposeController1 = 16,
+ GeneralPurposeController2 = 17,
+ GeneralPurposeController3 = 18,
+ GeneralPurposeController4 = 19,
+
+ // Switches ----------------------------------------------------------------
+ Sustain = 64,
+ Portamento = 65,
+ Sostenuto = 66,
+ SoftPedal = 67,
+ Legato = 68,
+ Hold = 69,
+
+ // Low resolution continuous controllers -----------------------------------
+ SoundController1 = 70, ///< Synth: Sound Variation FX: Exciter On/Off
+ SoundController2 = 71, ///< Synth: Harmonic Content FX: Compressor On/Off
+ SoundController3 = 72, ///< Synth: Release Time FX: Distortion On/Off
+ SoundController4 = 73, ///< Synth: Attack Time FX: EQ On/Off
+ SoundController5 = 74, ///< Synth: Brightness FX: Expander On/Off
+ SoundController6 = 75, ///< Synth: Decay Time FX: Reverb On/Off
+ SoundController7 = 76, ///< Synth: Vibrato Rate FX: Delay On/Off
+ SoundController8 = 77, ///< Synth: Vibrato Depth FX: Pitch Transpose On/Off
+ SoundController9 = 78, ///< Synth: Vibrato Delay FX: Flange/Chorus On/Off
+ SoundController10 = 79, ///< Synth: Undefined FX: Special Effects On/Off
+ GeneralPurposeController5 = 80,
+ GeneralPurposeController6 = 81,
+ GeneralPurposeController7 = 82,
+ GeneralPurposeController8 = 83,
+ PortamentoControl = 84,
+ // CC85 to CC90 undefined
+ Effects1 = 91, ///< Reverb send level
+ Effects2 = 92, ///< Tremolo depth
+ Effects3 = 93, ///< Chorus send level
+ Effects4 = 94, ///< Celeste depth
+ Effects5 = 95, ///< Phaser depth
+
+ // Channel Mode messages ---------------------------------------------------
+ AllSoundOff = 120,
+ ResetAllControllers = 121,
+ LocalControl = 122,
+ AllNotesOff = 123,
+ OmniModeOff = 124,
+ OmniModeOn = 125,
+ MonoModeOn = 126,
+ PolyModeOn = 127
+};
+
+struct midi_cs_if_ac_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint16_t bcdADC;
+ uint16_t wTotalLength;
+ uint8_t bInCollection;
+ uint8_t baInterfaceNr[];
+} __PACKED;
+
+#define MIDI_SIZEOF_AC_HEADER_DESC(n) (8 + n)
+
+struct midi_cs_if_ms_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint16_t bcdMSC;
+ uint16_t wTotalLength;
+} __PACKED;
+
+#define MIDI_SIZEOF_MS_HEADER_DESC (7)
+
+struct midi_cs_if_in_jack_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bJackType;
+ uint8_t bJackId;
+ uint8_t iJack;
+} __PACKED;
+
+#define MIDI_SIZEOF_IN_JACK_DESC (6)
+
+struct midi_cs_if_out_jack_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bJackType;
+ uint8_t bJackId;
+ uint8_t bNrInputPins;
+ uint8_t baSourceId;
+ uint8_t baSourcePin;
+ uint8_t iJack;
+} __PACKED;
+
+#define MIDI_SIZEOF_OUT_JACK_DESC (9)
+
+struct midi_cs_ep_ms_general_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bNumEmbMIDIJack;
+ uint8_t baAssocJackID[];
+} __PACKED;
+
+#define MIDI_SIZEOF_MS_GENERAL_DESC(n) (4 + n)
+
+// clang-format off
+#define MIDI_IN_JACK_DESCRIPTOR_INIT(bJackType, bJackID) \
+ 0x06, \
+ 0x24, \
+ MIDI_MIDI_IN_JACK_DESCRIPTOR_SUBTYPE, \
+ bJackType, \
+ bJackID, \
+ 0x00
+
+#define MIDI_OUT_JACK_DESCRIPTOR_INIT(bJackType, bJackID, baSourceID) \
+ 0x09, \
+ 0x24, \
+ MIDI_MIDI_OUT_JACK_DESCRIPTOR_SUBTYPE, \
+ bJackType, \
+ bJackID, \
+ 0x01, \
+ baSourceID, \
+ 0x01, \
+ 0x00
+
+#define MIDI_JACK_DESCRIPTOR_INIT(bJackFirstID) \
+ MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, bJackFirstID), \
+ MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, (bJackFirstID + 1)), \
+ MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, (bJackFirstID + 2), (bJackFirstID + 1)), \
+ MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, (bJackFirstID + 3), (bJackFirstID))
+
+#define MIDI_SIZEOF_JACK_DESC (6 + 6 + 9 + 9)
+
+// clang-format on
+
+#endif /* USB_MIDI_H */
diff --git a/third-party/cherryusb-0.6.0/class/msc/usb_msc.h b/third-party/cherryusb-0.6.0/class/msc/usb_msc.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e7634a049ea6939c2af9eb22f6eeb90dd0dedce
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/msc/usb_msc.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_MSC_H
+#define USB_MSC_H
+
+/* MSC Subclass Codes */
+#define MSC_SUBCLASS_RBC 0x01 /* Reduced block commands (e.g., flash devices) */
+#define MSC_SUBCLASS_SFF8020I_MMC2 0x02 /* SFF-8020i/MMC-2 (ATAPI) (e.g., C/DVD) */
+#define MSC_SUBCLASS_QIC157 0x03 /* QIC-157 (e.g., tape device) */
+#define MSC_SUBCLASS_UFI 0x04 /* e.g. floppy device */
+#define MSC_SUBCLASS_SFF8070I 0x05 /* SFF-8070i (e.g. floppy disk) */
+#define MSC_SUBCLASS_SCSI 0x06 /* SCSI transparent */
+
+/* MSC Protocol Codes */
+#define MSC_PROTOCOL_CBI_INT 0x00 /* CBI transport with command completion interrupt */
+#define MSC_PROTOCOL_CBI_NOINT 0x01 /* CBI transport without command completion interrupt */
+#define MSC_PROTOCOL_BULK_ONLY 0x50 /* Bulk only transport */
+
+/* MSC Request Codes */
+#define MSC_REQUEST_RESET 0xFF
+#define MSC_REQUEST_GET_MAX_LUN 0xFE
+
+/** MSC Command Block Wrapper (CBW) Signature */
+#define MSC_CBW_Signature 0x43425355
+/** Bulk-only Command Status Wrapper (CSW) Signature */
+#define MSC_CSW_Signature 0x53425355
+
+/** MSC Command Block Status Values */
+#define CSW_STATUS_CMD_PASSED 0x00
+#define CSW_STATUS_CMD_FAILED 0x01
+#define CSW_STATUS_PHASE_ERROR 0x02
+
+#define MSC_MAX_CDB_LEN (16) /* Max length of SCSI Command Data Block */
+
+/** MSC Bulk-Only Command Block Wrapper (CBW) */
+struct CBW {
+ uint32_t dSignature; /* 'USBC' = 0x43425355 */
+ uint32_t dTag; /* Depends on command id */
+ uint32_t dDataLength; /* Number of bytes that host expects to transfer */
+ uint8_t bmFlags; /* Bit 7: Direction=IN (other obsolete or reserved) */
+ uint8_t bLUN; /* LUN (normally 0) */
+ uint8_t bCBLength; /* len of cdb[] */
+ uint8_t CB[MSC_MAX_CDB_LEN]; /* Command Data Block */
+} __PACKED;
+
+#define USB_SIZEOF_MSC_CBW 31
+
+/** MSC Bulk-Only Command Status Wrapper (CSW) */
+struct CSW {
+ uint32_t dSignature; /* 'USBS' = 0x53425355 */
+ uint32_t dTag; /* Same tag as original command */
+ uint32_t dDataResidue; /* Amount not transferred */
+ uint8_t bStatus; /* Status of transfer */
+} __PACKED;
+
+#define USB_SIZEOF_MSC_CSW 13
+
+/*Length of template descriptor: 23 bytes*/
+#define MSC_DESCRIPTOR_LEN (9 + 7 + 7)
+// clang-format off
+#ifndef CONFIG_USB_HS
+#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep,str_idx) \
+ /* Interface */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bFirstInterface, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x02, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \
+ MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ \
+ MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ \
+ str_idx, /* iInterface */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ out_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x40, 0x00, /* wMaxPacketSize */ \
+ 0x00, /* bInterval */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ in_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x40, 0x00, /* wMaxPacketSize */ \
+ 0x00 /* bInterval */
+#else
+#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep,str_idx) \
+ /* Interface */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bFirstInterface, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ 0x02, /* bNumEndpoints */ \
+ USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \
+ MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ \
+ MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ \
+ str_idx, /* iInterface */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ out_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x00, 0x02, /* wMaxPacketSize */ \
+ 0x00, /* bInterval */ \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ in_ep, /* bEndpointAddress */ \
+ 0x02, /* bmAttributes */ \
+ 0x00, 0x02, /* wMaxPacketSize */ \
+ 0x00 /* bInterval */
+#endif
+// clang-format on
+
+#endif /* USB_MSC_H */
diff --git a/third-party/cherryusb-0.6.0/class/msc/usb_scsi.h b/third-party/cherryusb-0.6.0/class/msc/usb_scsi.h
new file mode 100644
index 0000000000000000000000000000000000000000..7eeb50a72ca1f3a7fd5b8458d40d8188a0648c79
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/msc/usb_scsi.h
@@ -0,0 +1,972 @@
+/*
+ * Apache NuttX
+ * Copyright 2020 The Apache Software Foundation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef __INCLUDE_NUTTX_SCSI_H
+#define __INCLUDE_NUTTX_SCSI_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* SCSI commands ************************************************************/
+
+#define SCSI_CMD_TESTUNITREADY 0x00
+#define SCSI_CMD_REZEROUNIT 0x01
+#define SCSI_CMD_REQUESTSENSE 0x03
+#define SCSI_CMD_FORMAT_UNIT 0x04
+#define SCSI_CMD_REASSIGNBLOCKS 0x07
+#define SCSI_CMD_READ6 0x08
+#define SCSI_CMD_WRITE6 0x0a
+#define SCSI_CMD_SEEK6 0x0b
+#define SCSI_CMD_SPACE6 0x11
+#define SCSI_CMD_INQUIRY 0x12
+#define SCSI_CMD_MODESELECT6 0x15
+#define SCSI_CMD_RESERVE6 0x16
+#define SCSI_CMD_RELEASE6 0x17
+#define SCSI_CMD_COPY 0x18
+#define SCSI_CMD_MODESENSE6 0x1a
+#define SCSI_CMD_STARTSTOPUNIT 0x1b
+#define SCSI_CMD_RECEIVEDIAGNOSTICRESULTS 0x1c
+#define SCSI_CMD_SENDDIAGNOSTIC 0x1d
+#define SCSI_CMD_PREVENTMEDIAREMOVAL 0x1e
+#define SCSI_CMD_READFORMATCAPACITIES 0x23
+#define SCSI_CMD_READCAPACITY10 0x25
+#define SCSI_CMD_READ10 0x28
+#define SCSI_CMD_WRITE10 0x2a
+#define SCSI_CMD_SEEK10 0x2b
+#define SCSI_CMD_WRITEANDVERIFY 0x2e
+#define SCSI_CMD_VERIFY10 0x2f
+#define SCSI_CMD_SEARCHDATAHIGH 0x30
+#define SCSI_CMD_SEARCHDATAEQUAL 0x31
+#define SCSI_CMD_SEARCHDATALOW 0x32
+#define SCSI_CMD_SETLIMITS10 0x33
+#define SCSI_CMD_PREFETCH10 0x34
+#define SCSI_CMD_SYNCHCACHE10 0x35
+#define SCSI_CMD_LOCKCACHE 0x36
+#define SCSI_CMD_READDEFECTDATA10 0x37
+#define SCSI_CMD_COMPARE 0x39
+#define SCSI_CMD_COPYANDVERIFY 0x3a
+#define SCSI_CMD_WRITEBUFFER 0x3b
+#define SCSI_CMD_READBUFFER 0x3c
+#define SCSI_CMD_READLONG10 0x3e
+#define SCSI_CMD_WRITELONG10 0x3f
+#define SCSI_CMD_CHANGEDEFINITION 0x40
+#define SCSI_CMD_WRITESAME10 0x41
+#define SCSI_CMD_LOGSELECT 0x4c
+#define SCSI_CMD_LOGSENSE 0x4d
+#define SCSI_CMD_XDWRITE10 0x50
+#define SCSI_CMD_XPWRITE10 0x51
+#define SCSI_CMD_XDREAD10 0x52
+#define SCSI_CMD_MODESELECT10 0x55
+#define SCSI_CMD_RESERVE10 0x56
+#define SCSI_CMD_RELEASE10 0x57
+#define SCSI_CMD_MODESENSE10 0x5a
+#define SCSI_CMD_PERSISTENTRESERVEIN 0x5e
+#define SCSI_CMD_PERSISTENTRESERVEOUT 0x5f
+#define SCSI_CMD_32 0x7f
+#define SCSI_CMD_XDWRITEEXTENDED 0x80
+#define SCSI_CMD_REBUILD 0x82
+#define SCSI_CMD_REGENERATE 0x82
+#define SCSI_CMD_EXTENDEDCOPY 0x83
+#define SCSI_CMD_COPYRESULTS 0x84
+#define SCSI_CMD_ACCESSCONTROLIN 0x86
+#define SCSI_CMD_ACCESSCONTROLOUT 0x87
+#define SCSI_CMD_READ16 0x88
+#define SCSI_CMD_WRITE16 0x8a
+#define SCSI_CMD_READATTRIBUTE 0x8c
+#define SCSI_CMD_WRITEATTRIBUTE 0x8d
+#define SCSI_CMD_WRITEANDVERIFY16 0x8e
+#define SCSI_CMD_PREFETCH16 0x90
+#define SCSI_CMD_SYNCHCACHE16 0x91
+#define SCSI_CMD_LOCKUNLOCKACACHE 0x92
+#define SCSI_CMD_WRITESAME16 0x93
+#define SCSI_CMD_READCAPACITY16 0x9e
+#define SCSI_CMD_READLONG16 0x9e
+#define SCSI_CMD_WRITELONG106 0x9f
+#define SCSI_CMD_REPORTLUNS 0xa0
+#define SCSI_CMD_MAINTENANCEIN 0xa3
+#define SCSI_CMD_MAINTENANCEOUT 0xa4
+#define SCSI_CMD_MOVEMEDIUM 0xa5
+#define SCSI_CMD_MOVEMEDIUMATTACHED 0xa7
+#define SCSI_CMD_READ12 0xa8
+#define SCSI_CMD_WRITE12 0xaa
+#define SCSI_CMD_READMEDIASERIALNUMBER 0xab
+#define SCSI_CMD_WRITEANDVERIFY12 0xae
+#define SCSI_CMD_VERIFY12 0xaf
+#define SCSI_CMD_SETLIMITS12 0xb3
+#define SCSI_CMD_READELEMENTSTATUS 0xb4
+#define SCSI_CMD_READDEFECTDATA12 0xb7
+#define SCSI_CMD_REDUNDANCYGROUPIN 0xba
+#define SCSI_CMD_REDUNDANCYGROUPOUT 0xbb
+#define SCSI_CMD_SPAREIN 0xbc
+#define SCSI_CMD_SPAREOUT 0xbd
+#define SCSI_CMD_VOLUMESETIN 0xbe
+#define SCSI_CMD_VOLUMESETOUT 0xbf
+
+/* Common SCSI KCQ values (sense Key/additional sense Code/ASC Qualifier) ***
+ *
+ * 0xnn0386 Write Fault Data Corruption
+ * 0xnn0500 Illegal request
+ * 0xnn0600 Unit attention
+ * 0xnn0700 Data protect
+ * 0xnn0800 LUN communication failure
+ * 0xnn0801 LUN communication timeout
+ * 0xnn0802 LUN communication parity error
+ * 0xnn0803 LUN communication CRC error
+ * 0xnn0900 vendor specific sense key
+ * 0xnn0901 servo fault
+ * 0xnn0904 head select fault
+ * 0xnn0a00 error log overflow
+ * 0xnn0b00 aborted command
+ * 0xnn0c00 write error
+ * 0xnn0c02 write error - auto-realloc failed
+ * 0xnn0e00 data miscompare
+ * 0xnn1200 address mark not founf for ID field
+ * 0xnn1400 logical block not found
+ * 0xnn1500 random positioning error
+ * 0xnn1501 mechanical positioning error
+ * 0xnn1502 positioning error detected by read of medium
+ * 0xnn2700 write protected
+ * 0xnn2900 POR or bus reset occurred
+ * 0xnn3101 format failed
+ * 0xnn3191 format corrupted
+ * 0xnn3201 defect list update error
+ * 0xnn3202 no spares available
+ * 0xnn3501 unspecified enclosure services failure
+ * 0xnn3700 parameter rounded
+ * 0xnn3d00 invalid bits in identify message
+ * 0xnn3e00 LUN not self-configured yet
+ * 0xnn4001 DRAM parity error
+ * 0xnn4002 DRAM parity error
+ * 0xnn4200 power-on or self-test failure
+ * 0xnn4c00 LUN failed self-configuration
+ * 0xnn5c00 RPL status change
+ * 0xnn5c01 spindles synchronized
+ * 0xnn5c02 spindles not synchronized
+ * 0xnn6500 voltage fault
+ * 0xnn8000 general firmware error
+ */
+
+/* No sense KCQ values */
+
+#define SCSI_KCQ_NOSENSE 0x000000 /* No error */
+#define SCSI_KCQ_PFATHRESHOLDREACHED 0x005c00 /* No sense - PFA threshold reached */
+
+/* Soft error KCQ values */
+
+#define SCSI_KCQSE_RWENOINDEX 0x010100 /* Recovered Write error - no index */
+#define SCSI_KCQSE_RECOVEREDNOSEEKCOMPLETION 0x010200 /* Recovered no seek completion */
+#define SCSI_KCQSE_RWEWRITEFAULT 0x010300 /* Recovered Write error - write fault */
+#define SCSI_KCQSE_TRACKFOLLOWINGERROR 0x010900 /* Track following error */
+#define SCSI_KCQSE_TEMPERATUREWARNING 0x010b01 /* Temperature warning */
+#define SCSI_KCQSE_RWEWARREALLOCATED 0x010c01 /* Recovered Write error with auto-realloc - reallocated */
+#define SCSI_KCQSE_RWERECOMMENDREASSIGN 0x010c03 /* Recovered Write error - recommend reassign */
+#define SCSI_KCQSE_RDWOEUSINGPREVLBI 0x011201 /* Recovered data without ECC using prev logical block ID */
+#define SCSI_KCQSE_RDWEUSINGPREVLBI 0x011202 /* Recovered data with ECC using prev logical block ID */
+#define SCSI_KCQSE_RECOVEREDRECORDNOTFOUND 0x011401 /* Recovered Record Not Found */
+#define SCSI_KCQSE_RWEDSME 0x011600 /* Recovered Write error - Data Sync Mark Error */
+#define SCSI_KCQSE_RWEDSEDATAREWRITTEN 0x011601 /* Recovered Write error - Data Sync Error - data rewritten */
+#define SCSI_KCQSE_RWEDSERECOMMENDREWRITE 0x011602 /* Recovered Write error - Data Sync Error - recommend rewrite */
+#define SCSI_KCQSE_RWEDSEDATAAUTOREALLOCATED 0x011603 /* Recovered Write error - Data Sync Error - data auto-reallocated */
+#define SCSI_KCQSE_RWEDSERECOMMENDREASSIGNMENT 0x011604 /* Recovered Write error - Data Sync Error - recommend reassignment */
+#define SCSI_KCQSE_RDWNECORRECTIONAPPLIED 0x011700 /* Recovered data with no error correction applied */
+#define SCSI_KCQSE_RREWITHRETRIES 0x011701 /* Recovered Read error - with retries */
+#define SCSI_KCQSE_RDUSINGPOSITIVEOFFSET 0x011702 /* Recovered data using positive offset */
+#define SCSI_KCQSE_RDUSINGNEGATIVEOFFSET 0x011703 /* Recovered data using negative offset */
+#define SCSI_KCQSE_RDUSINGPREVIOUSLBI 0x011705 /* Recovered data using previous logical block ID */
+#define SCSI_KCQSE_RREWOEAUTOREALLOCATED 0x011706 /* Recovered Read error - without ECC, auto reallocated */
+#define SCSI_KCQSE_RREWOERECOMMENDREASSIGN 0x011707 /* Recovered Read error - without ECC, recommend reassign */
+#define SCSI_KCQSE_RREWOERECOMMENDREWRITE 0x011708 /* Recovered Read error - without ECC, recommend rewrite */
+#define SCSI_KCQSE_RREWOEDATAREWRITTEN 0x011709 /* Recovered Read error - without ECC, data rewritten */
+#define SCSI_KCQSE_RREWE 0x011800 /* Recovered Read error - with ECC */
+#define SCSI_KCQSE_RDWEANDRETRIES 0x011801 /* Recovered data with ECC and retries */
+#define SCSI_KCQSE_RREWEAUTOREALLOCATED 0x011802 /* Recovered Read error - with ECC, auto reallocated */
+#define SCSI_KCQSE_RREWERECOMMENDREASSIGN 0x011805 /* Recovered Read error - with ECC, recommend reassign */
+#define SCSI_KCQSE_RDUSINGECCANDOFFSETS 0x011806 /* Recovered data using ECC and offsets */
+#define SCSI_KCQSE_RREWEDATAREWRITTEN 0x011807 /* Recovered Read error - with ECC, data rewritten */
+#define SCSI_KCQSE_DLNOTFOUND 0x011c00 /* Defect List not found */
+#define SCSI_KCQSE_PRIMARYDLNOTFOUND 0x011c01 /* Primary defect list not found */
+#define SCSI_KCQSE_GROWNDLNOTFOUND 0x011c02 /* Grown defect list not found */
+#define SCSI_KCQSE_PARTIALDLTRANSFERRED 0x011f00 /* Partial defect list transferred */
+#define SCSI_KCQSE_INTERNALTARGETFAILURE 0x014400 /* Internal target failure */
+#define SCSI_KCQSE_PFATHRESHOLDREACHED 0x015d00 /* PFA threshold reached */
+#define SCSI_KCQSE_PFATESTWARNING 0x015dff /* PFA test warning */
+#define SCSI_KCQSE_INTERNALLOGICFAILURE 0x018100 /* Internal logic failure */
+
+/* Not Ready / Diagnostic Failure KCQ values */
+
+#define SCSI_KCQNR_CAUSENOTREPORTABLE 0x020400 /* Not Ready - Cause not reportable. */
+#define SCSI_KCQNR_BECOMINGREADY 0x020401 /* Not Ready - becoming ready */
+#define SCSI_KCQNR_NEEDINITIALIZECOMMAND 0x020402 /* Not Ready - need initialize command (start unit) */
+#define SCSI_KCQNR_MANUALINTERVENTIONREQUIRED 0x020403 /* Not Ready - manual intervention required */
+#define SCSI_KCQNR_FORMATINPROGRESS 0x020404 /* Not Ready - format in progress */
+#define SCSI_KCQNR_SELFTESTINPROGRESS 0x020409 /* Not Ready - self-test in progress */
+#define SCSI_KCQNR_MEDIUMFORMATCORRUPTED 0x023100 /* Not Ready - medium format corrupted */
+#define SCSI_KCQNR_FORMATCOMMANDFAILED 0x023101 /* Not Ready - format command failed */
+#define SCSI_KCQNR_ESUNAVAILABLE 0x023502 /* Not Ready - enclosure services unavailable */
+#define SCSI_KCQNR_MEDIANOTPRESENT 0x023a00 /* Not Ready - media not present */
+#define SCSI_KCQDF_BRINGUPFAILORDEGRADEDMODE 0x024080 /* Diagnostic Failure - bring-up fail or degraded mode */
+#define SCSI_KCQDF_HARDDISKCONTROLLER 0x024081 /* Diagnostic Failure - Hard Disk Controller */
+#define SCSI_KCQDF_RAMMICROCODENOTLOADED 0x024085 /* Diagnostic Failure - RAM microcode not loaded */
+#define SCSI_KCQDF_RROCALIBRATION 0x024090 /* Diagnostic Failure - RRO Calibration */
+#define SCSI_KCQDF_CHANNELCALIBRATION 0x024091 /* Diagnostic Failure - Channel Calibration */
+#define SCSI_KCQDF_HEADLOAD 0x024092 /* Diagnostic Failure - Head Load */
+#define SCSI_KCQDF_WRITEAE 0x024093 /* Diagnostic Failure - Write AE */
+#define SCSI_KCQDF_12VOVERCURRENT 0x024094 /* Diagnostic Failure - 12V over current */
+#define SCSI_KCQDF_OTHERSPINDLEFAILURE 0x024095 /* Diagnostic Failure - Other spindle failure */
+#define SCSI_KCQDF_SELFRESET 0x0240b0 /* Diagnostic Failure - self-reset */
+#define SCSI_KCQDF_CONFIGNOTLOADED 0x024c00 /* Diagnostic Failure - config not loaded */
+
+/* Medium error KCQ values */
+
+#define SCSI_KCQME_WRITEFAULT 0x030300 /* Medium Error - write fault */
+#define SCSI_KCQME_WRITEFAULTAUTOREALLOCFAILED 0x030c02 /* Medium Error - write error - auto-realloc failed */
+#define SCSI_KCQME_WRITERTLIMITEXCEEDED 0x030cbb /* Medium Error - write recovery time limit exceeded */
+#define SCSI_KCQME_IDCRCERROR 0x031000 /* Medium Error - ID CRC error */
+#define SCSI_KCQME_UNRRE1 0x031100 /* Medium Error - unrecovered read error */
+#define SCSI_KCQME_READRETRIESEXHAUSTED 0x031101 /* Medium Error - read retries exhausted */
+#define SCSI_KCQME_ERRORTOOLONGTOCORRECT 0x031102 /* Medium Error - error too long to correct */
+#define SCSI_KCQME_UREAUTOREALLOCFAILED 0x031104 /* Medium Error - unrecovered read error - auto re-alloc failed */
+#define SCSI_KCQME_URERECOMMENDREASSIGN 0x03110b /* Medium Error - unrecovered read error - recommend reassign */
+#define SCSI_KCQME_READRTLIMITEXCEEDED 0x0311ff /* Medium Error - read recovery time limit exceeded */
+#define SCSI_KCQME_RECORDNOTFOUND 0x031401 /* Medium Error - record not found */
+#define SCSI_KCQME_DSME 0x031600 /* Medium Error - Data Sync Mark error */
+#define SCSI_KCQME_DSERECOMMENDREASSIGN 0x031604 /* Medium Error - Data Sync Error - recommend reassign */
+#define SCSI_KCQME_DLE 0x031900 /* Medium Error - defect list error */
+#define SCSI_KCQME_DLNOTAVAILABLE 0x031901 /* Medium Error - defect list not available */
+#define SCSI_KCQME_DLEINPRIMARYLIST 0x031902 /* Medium Error - defect list error in primary list */
+#define SCSI_KCQME_DLEINGROWNLIST 0x031903 /* Medium Error - defect list error in grown list */
+#define SCSI_KCQME_FEWERTHAN50PCTDLCOPIES 0x03190e /* Medium Error - fewer than 50% defect list copies */
+#define SCSI_KCQME_MEDIUMFORMATCORRUPTED 0x033100 /* Medium Error - medium format corrupted */
+#define SCSI_KCQME_FORMATCOMMANDFAILED 0x033101 /* Medium Error - format command failed */
+#define SCSI_KCQME_DATAAUTOREALLOCATED 0x038000 /* Medium Error - data auto-reallocated */
+
+/* Hardware Error KCQ values */
+
+#define SCSI_KCQHE_NOINDEXORSECTOR 0x040100 /* Hardware Error - no index or sector */
+#define SCSI_KCQHE_NOSEEKCOMPLETE 0x040200 /* Hardware Error - no seek complete */
+#define SCSI_KCQHE_WRITEFAULT 0x040300 /* Hardware Error - write fault */
+#define SCSI_KCQHE_COMMUNICATIONFAILURE 0x040800 /* Hardware Error - communication failure */
+#define SCSI_KCQHE_TRACKFOLLOWINGERROR 0x040900 /* Hardware Error - track following error */
+#define SCSI_KCQHE_UREINRESERVEDAREA 0x041100 /* Hardware Error - unrecovered read error in reserved area */
+#define SCSI_KCQHE_DSMEINRESERVEDAREA 0x041600 /* Hardware Error - Data Sync Mark error in reserved area */
+#define SCSI_KCQHE_DLE 0x041900 /* Hardware Error - defect list error */
+#define SCSI_KCQHE_DLEINPRIMARYLIST 0x041902 /* Hardware Error - defect list error in Primary List */
+#define SCSI_KCQHE_DLEINGROWNLIST 0x041903 /* Hardware Error - defect list error in Grown List */
+#define SCSI_KCQHE_REASSIGNFAILED 0x043100 /* Hardware Error - reassign failed */
+#define SCSI_KCQHE_NODEFECTSPAREAVAILABLE 0x043200 /* Hardware Error - no defect spare available */
+#define SCSI_KCQHE_UNSUPPORTEDENCLOSUREFUNCTION 0x043501 /* Hardware Error - unsupported enclosure function */
+#define SCSI_KCQHE_ESUNAVAILABLE 0x043502 /* Hardware Error - enclosure services unavailable */
+#define SCSI_KCQHE_ESTRANSFERFAILURE 0x043503 /* Hardware Error - enclosure services transfer failure */
+#define SCSI_KCQHE_ESREFUSED 0x043504 /* Hardware Error - enclosure services refused */
+#define SCSI_KCQHE_SELFTESTFAILED 0x043e03 /* Hardware Error - self-test failed */
+#define SCSI_KCQHE_UNABLETOUPDATESELFTEST 0x043e04 /* Hardware Error - unable to update self-test */
+#define SCSI_KCQHE_DMDIAGNOSTICFAIL 0x044080 /* Hardware Error - Degrade Mode. Diagnostic Fail */
+#define SCSI_KCQHE_DMHWERROR 0x044081 /* Hardware Error - Degrade Mode. H/W Error */
+#define SCSI_KCQHE_DMRAMMICROCODENOTLOADED 0x044085 /* Hardware Error - Degrade Mode. RAM microcode not loaded */
+#define SCSI_KCQHE_SEEKTESTFAILURE 0x044090 /* Hardware Error - seek test failure */
+#define SCSI_KCQHE_READWRITETESTFAILURE 0x0440a0 /* Hardware Error - read/write test failure */
+#define SCSI_KCQHE_DEVICESELFRESET 0x0440b0 /* Hardware Error - device self-reset */
+#define SCSI_KCQHE_COMPONENTMISMATCH 0x0440d0 /* Hardware Error - component mismatch */
+#define SCSI_KCQHE_INTERNALTARGETFAILURE 0x044400 /* Hardware Error - internal target failure */
+#define SCSI_KCQHE_INTERNALLOGICERROR 0x048100 /* Hardware Error - internal logic error */
+#define SCSI_KCQHE_COMMANDTIMEOUT 0x048200 /* Hardware Error - command timeout */
+
+/* Illegal Request KCQ values */
+
+#define SCSI_KCQIR_PARMLISTLENGTHERROR 0x051a00 /* Illegal Request - parm list length error */
+#define SCSI_KCQIR_INVALIDCOMMAND 0x052000 /* Illegal Request - invalid/unsupported command code */
+#define SCSI_KCQIR_LBAOUTOFRANGE 0x052100 /* Illegal Request - LBA out of range */
+#define SCSI_KCQIR_INVALIDFIELDINCBA 0x052400 /* Illegal Request - invalid field in CDB (Command Descriptor Block) */
+#define SCSI_KCQIR_INVALIDLUN 0x052500 /* Illegal Request - invalid LUN */
+#define SCSI_KCQIR_INVALIDFIELDSINPARMLIST 0x052600 /* Illegal Request - invalid fields in parm list */
+#define SCSI_KCQIR_PARAMETERNOTSUPPORTED 0x052601 /* Illegal Request - parameter not supported */
+#define SCSI_KCQIR_INVALIDPARMVALUE 0x052602 /* Illegal Request - invalid parm value */
+#define SCSI_KCQIR_IFPTHRESHOLDPARAMETER 0x052603 /* Illegal Request - invalid field parameter - threshold parameter */
+#define SCSI_KCQIR_INVALIDRELEASEOFPR 0x052604 /* Illegal Request - invalid release of persistent reservation */
+#define SCSI_KCQIR_IFPTMSFIRMWARETAG 0x052697 /* Illegal Request - invalid field parameter - TMS firmware tag */
+#define SCSI_KCQIR_IFPCHECKSUM 0x052698 /* Illegal Request - invalid field parameter - check sum */
+#define SCSI_KCQIR_IFPFIRMWARETAG 0x052699 /* Illegal Request - invalid field parameter - firmware tag */
+#define SCSI_KCQIR_COMMANDSEQUENCEERROR 0x052c00 /* Illegal Request - command sequence error */
+#define SCSI_KCQIR_UNSUPPORTEDENCLOSUREFUNCTION 0x053501 /* Illegal Request - unsupported enclosure function */
+#define SCSI_KCQIR_SAVINGPARMSNOTSUPPORTED 0x053900 /* Illegal Request - Saving parameters not supported */
+#define SCSI_KCQIR_INVALIDMESSAGE 0x054900 /* Illegal Request - invalid message */
+#define SCSI_KCQIR_MEDIALOADOREJECTFAILED 0x055300 /* Illegal Request - media load or eject failed */
+#define SCSI_KCQIR_UNLOADTAPEFAILURE 0x055301 /* Illegal Request - unload tape failure */
+#define SCSI_KCQIR_MEDIUMREMOVALPREVENTED 0x055302 /* Illegal Request - medium removal prevented */
+#define SCSI_KCQIR_SYSTEMRESOURCEFAILURE 0x055500 /* Illegal Request - system resource failure */
+#define SCSI_KCQIR_SYSTEMBUFFERFULL 0x055501 /* Illegal Request - system buffer full */
+#define SCSI_KCQIR_INSUFFICIENTRR 0x055504 /* Illegal Request - Insufficient Registration Resources */
+
+/* Unit Attention KCQ values */
+
+#define SCSI_KCQUA_NOTREADYTOTRANSITION 0x062800 /* Unit Attention - not-ready to ready transition (format complete) */
+#define SCSI_KCQUA_DEVICERESETOCCURRED 0x062900 /* Unit Attention - POR or device reset occurred */
+#define SCSI_KCQUA_POROCCURRED 0x062901 /* Unit Attention - POR occurred */
+#define SCSI_KCQUA_SCSIBUSRESETOCCURRED 0x062902 /* Unit Attention - SCSI bus reset occurred */
+#define SCSI_KCQUA_TARGETRESETOCCURRED 0x062903 /* Unit Attention - TARGET RESET occurred */
+#define SCSI_KCQUA_SELFINITIATEDRESETOCCURRED 0x062904 /* Unit Attention - self-initiated-reset occurred */
+#define SCSI_KCQUA_TRANSCEIVERMODECHANGETOSE 0x062905 /* Unit Attention - transceiver mode change to SE */
+#define SCSI_KCQUA_TRANSCEIVERMODECHANGETOLVD 0x062906 /* Unit Attention - transceiver mode change to LVD */
+#define SCSI_KCQUA_PARAMETERSCHANGED 0x062a00 /* Unit Attention - parameters changed */
+#define SCSI_KCQUA_MODEPARAMETERSCHANGED 0x062a01 /* Unit Attention - mode parameters changed */
+#define SCSI_KCQUA_LOGSELECTPARMSCHANGED 0x062a02 /* Unit Attention - log select parms changed */
+#define SCSI_KCQUA_RESERVATIONSPREEMPTED 0x062a03 /* Unit Attention - Reservations pre-empted */
+#define SCSI_KCQUA_RESERVATIONSRELEASED 0x062a04 /* Unit Attention - Reservations released */
+#define SCSI_KCQUA_REGISTRATIONSPREEMPTED 0x062a05 /* Unit Attention - Registrations pre-empted */
+#define SCSI_KCQUA_COMMANDSCLEARED 0x062f00 /* Unit Attention - commands cleared by another initiator */
+#define SCSI_KCQUA_OPERATINGCONDITIONSCHANGED 0x063f00 /* Unit Attention - target operating conditions have changed */
+#define SCSI_KCQUA_MICROCODECHANGED 0x063f01 /* Unit Attention - microcode changed */
+#define SCSI_KCQUA_CHANGEDOPERATINGDEFINITION 0x063f02 /* Unit Attention - changed operating definition */
+#define SCSI_KCQUA_INQUIRYPARAMETERSCHANGED 0x063f03 /* Unit Attention - inquiry parameters changed */
+#define SCSI_KCQUA_DEVICEIDENTIFIERCHANGED 0x063f05 /* Unit Attention - device identifier changed */
+#define SCSI_KCQUA_INVALIDAPMPARAMETERS 0x063f90 /* Unit Attention - invalid APM parameters */
+#define SCSI_KCQUA_WORLDWIDENAMEMISMATCH 0x063f91 /* Unit Attention - world-wide name mismatch */
+#define SCSI_KCQUA_PFATHRESHOLDREACHED 0x065d00 /* Unit Attention - PFA threshold reached */
+#define SCSI_KCQUA_PFATHRESHOLDEXCEEDED 0x065dff /* Unit Attention - PFA threshold exceeded */
+
+/* Write Protect KCQ values */
+
+#define SCSI_KCQWP_COMMANDNOTALLOWED 0x072700 /* Write Protect - command not allowed */
+
+/* Aborted Command KCQ values */
+
+#define SCSI_KCQAC_NOADDITIONALSENSECODE 0x0b0000 /* Aborted Command - no additional sense code */
+#define SCSI_KCQAC_SYNCDATATRANSFERERROR 0x0b1b00 /* Aborted Command - sync data transfer error (extra ACK) */
+#define SCSI_KCQAC_UNSUPPORTEDLUN 0x0b2500 /* Aborted Command - unsupported LUN */
+#define SCSI_KCQAC_ECHOBUFFEROVERWRITTEN 0x0b3f0f /* Aborted Command - echo buffer overwritten */
+#define SCSI_KCQAC_MESSAGEREJECTERROR 0x0b4300 /* Aborted Command - message reject error */
+#define SCSI_KCQAC_INTERNALTARGETFAILURE 0x0b4400 /* Aborted Command - internal target failure */
+#define SCSI_KCQAC_SELECTIONFAILURE 0x0b4500 /* Aborted Command - Selection/Reselection failure */
+#define SCSI_KCQAC_SCSIPARITYERROR 0x0b4700 /* Aborted Command - SCSI parity error */
+#define SCSI_KCQAC_INITIATORDETECTEDERRORECEIVED 0x0b4800 /* Aborted Command - initiator-detected error message received */
+#define SCSI_KCQAC_ILLEGALMESSAGE 0x0b4900 /* Aborted Command - inappropriate/illegal message */
+#define SCSI_KCQAC_DATAPHASEERROR 0x0b4b00 /* Aborted Command - data phase error */
+#define SCSI_KCQAC_OVERLAPPEDCOMMANDSATTEMPTED 0x0b4e00 /* Aborted Command - overlapped commands attempted */
+#define SCSI_KCQAC_LOOPINITIALIZATION 0x0b4f00 /* Aborted Command - due to loop initialization */
+
+/* Other KCQ values: */
+
+#define SCSO_KCQOTHER_MISCOMPARE 0x0e1d00 /* Miscompare - during verify byte check operation */
+
+/* SSCSI Status Codes *******************************************************/
+
+#define SCSI_STATUS_OK 0x00 /* OK */
+#define SCSI_STATUS_CHECKCONDITION 0x02 /* Check condition */
+#define SCSI_STATUS_CONDITIONMET 0x04 /* Condition met */
+#define SCSI_STATUS_BUSY 0x08 /* Busy */
+#define SCSI_STATUS_INTERMEDIATE 0x10 /* Intermediate */
+#define SCSI_STATUS_DATAOVERUNDERRUN 0x12 /* Data Under/Over Run? */
+#define SCSI_STATUS_INTERMEDIATECONDITIONMET 0x14 /* Intermediate - Condition met */
+#define SCSI_STATUS_RESERVATIONCONFLICT 0x18 /* Reservation conflict */
+#define SCSI_STATUS_COMMANDTERMINATED 0x22 /* Command terminated */
+#define SCSI_STATUS_QUEUEFULL 0x28 /* Queue (task set) full */
+#define SCSI_STATUS_ACAACTIVE 0x30 /* ACA active */
+#define SCSI_STATUS_TASKABORTED 0x40 /* Task aborted */
+
+/* Definitions for selected SCSI commands ***********************************/
+
+/* Inquiry */
+
+#define SCSICMD_INQUIRYFLAGS_EVPD 0x01 /* Bit 0: EVPD */
+ /* Bits 5-7: Peripheral Qualifier */
+#define SCSIRESP_INQUIRYPQ_CONNECTED 0x00 /* 000: Device is connected */
+#define SCSIRESP_INQUIRYPQ_NOTCONNECTED 0x20 /* 001: Device is NOT connected */
+#define SCSIRESP_INQUIRYPQ_NOTCAPABLE 0x60 /* 011: LUN not supported */
+ /* Bits 0-4: Peripheral Device */
+#define SCSIRESP_INQUIRYPD_DIRECTACCESS 0x00 /* Direct-access block device */
+#define SCSIRESP_INQUIRYPD_SEQUENTIALACCESS 0x01 /* Sequential-access block device */
+#define SCSIRESP_INQUIRYPD_PRINTER 0x02 /* Printer device */
+#define SCSIRESP_INQUIRYPD_PROCESSOR 0x03 /* Processor device */
+#define SCSIRESP_INQUIRYPD_WRONCE 0x04 /* Write once device */
+#define SCSIRESP_INQUIRYPD_CDDVD 0x05 /* CD/DVD device */
+#define SCSIRESP_INQUIRYPD_SCANNER 0x06 /* Scanner device (obsolete) */
+#define SCSIRESP_INQUIRYPD_OPTICAL 0x07 /* Optical memory device */
+#define SCSIRESP_INQUIRYPD_MEDIUMCHANGER 0x08 /* Medium changer device (Jukebox) */
+#define SCSIRESP_INQUIRYPD_COMMUNICATIONS 0x09 /* Communications device (obsolete) */
+#define SCSIRESP_INQUIRYPD_STORAGEARRAY 0x0c /* Storage array controller device */
+#define SCSIRESP_INQUIRYPD_ENCLOSURESERVICES 0x0d /* Enclosure services device */
+#define SCSIRESP_INQUIRYPD_RBC 0x0e /* Simplified direct-access device */
+#define SCSIRESP_INQUIRYPD_OCRW 0x0f /* Optical reader/writer device */
+#define SCSIRESP_INQUIRYPD_BCC 0x10 /* Bridge controller commands */
+#define SCSIRESP_INQUIRYPD_OSD 0x11 /* Object-based storage device */
+#define SCSIRESP_INQUIRYPD_ADC 0x12 /* Automation/drive interface */
+#define SCSIRESP_INQUIRYPD_WKLU 0x1e /* Well-known logical unit */
+#define SCSIRESP_INQUIRYPD_UNKNOWN 0x1f /* Direct-access block device */
+
+#define SCSIRESP_INQUIRYFLAGS1_RMB 0x80 /* Bit 7: RMB */
+#define SCSIRESP_INQUIRYFLAGS2_NORMACA 0x20 /* Bit 5: NormACA */
+#define SCSIRESP_INQUIRYFLAGS2_HISUP 0x10 /* Bit 4: HiSup */
+#define SCSIRESP_INQUIRYFLAGS2_FMTMASK 0x0f /* Bits 0-3: Response data format */
+
+#define SCSIRESP_INQUIRYFLAGS3_SCCS 0x80 /* Bit 8: SCCS */
+#define SCSIRESP_INQUIRYFLAGS3_ACC 0x40 /* Bit 7: ACC */
+#define SCSIRESP_INQUIRYFLAGS3_TPGSMASK 0x30 /* Bits 4-5: TPGS */
+#define SCSIRESP_INQUIRYFLAGS3_3PC 0x08 /* Bit 3: 3PC */
+#define SCSIRESP_INQUIRYFLAGS3_PROTECT 0x01 /* Bit 0: Protect */
+
+#define SCSIRESP_INQUIRYFLAGS4_BQUE 0x80 /* Bit 7: BQue */
+#define SCSIRESP_INQUIRYFLAGS4_ENCSERV 0x40 /* Bit 6: EncServ */
+#define SCSIRESP_INQUIRYFLAGS4_VS 0x20 /* Bit 5: VS */
+#define SCSIRESP_INQUIRYFLAGS4_MULTIP 0x10 /* Bit 4: MultIP */
+#define SCSIRESP_INQUIRYFLAGS4_MCHNGR 0x08 /* Bit 3: MChngr */
+#define SCSIRESP_INQUIRYFLAGS4_ADDR16 0x01 /* Bit 0: Addr16 */
+
+#define SCSIRESP_INQUIRYFLAGS5_WBUS16 0x20 /* Bit 5: WBus16 */
+#define SCSIRESP_INQUIRYFLAGS5_SYNC 0x10 /* Bit 4: SYNC */
+#define SCSIRESP_INQUIRYFLAGS5_LINKED 0x08 /* Bit 3: LINKED */
+#define SCSIRESP_INQUIRYFLAGS5_CMDQUEUE 0x02 /* Bit 1: CmdQue */
+#define SCSIRESP_INQUIRYFLAGS5_VS 0x01 /* Bit 0: VS */
+
+#define SCSIRESP_INQUIRYFLAGS6_CLOCKINGMASK 0xc0 /* Bits 2-3: Clocking */
+#define SCSIRESP_INQUIRYFLAGS6_QAS 0x02 /* Bit 1: QAS */
+#define SCSIRESP_INQUIRYFLAGS6_IUS 0x01 /* Bit 0: IUS */
+
+/* Sense data */
+
+/* Sense data response codes */
+
+#define SCSIRESP_SENSEDATA_CURRENTFIXED 0x70 /* Byte 1 is always the response code */
+#define SCSIRESP_SENSEDATA_DEFERREDFIXED 0x71
+#define SCSIRESP_SENSEDATA_CURRENTDESC 0x72
+#define SCSIRESP_SENSEDATA_DEFERREDDESC 0x73
+
+#define SCSIRESP_SENSEDATA_RESPVALID 0x80
+
+/* Fixed sense data flags */
+
+#define SCSIRESP_SENSEDATA_FILEMARK 0x80 /* Bit 7: FileMark */
+#define SCSIRESP_SENSEDATA_EOM 0x40 /* Bit 6: EOM */
+#define SCSIRESP_SENSEDATA_ILI 0x20 /* Bit 5: ILI */
+#define SCSIRESP_SENSEDATA_SENSEKEYMASK 0x0f /* Bits 0-3: Sense key */
+#define SCSIRESP_SENSEDATA_NOSENSE 0x00 /* Nothing to be reported */
+#define SCSIRESP_SENSEDATA_RECOVEREDERROR 0x01 /* Successful after recovery action */
+#define SCSIRESP_SENSEDATA_NOTREADY 0x02 /* Logical unit is not accessible */
+#define SCSIRESP_SENSEDATA_MEDIUMERROR 0x03 /* Error possibly caused by flaw in medium */
+#define SCSIRESP_SENSEDATA_HARDWAREERROR 0x04 /* Non-recoverable hardware error */
+#define SCSIRESP_SENSEDATA_ILLEGALREQUEST 0x05 /* Error in received request */
+#define SCSIRESP_SENSEDATA_UNITATTENTION 0x06 /* Unit attention condition */
+#define SCSIRESP_SENSEDATA_DATAPROTECT 0x07 /* Action failed, medium protected */
+#define SCSIRESP_SENSEDATA_BLANKCHECK 0x08 /* Encountered blank media */
+#define SCSIRESP_SENSEDATA_VENDORSPECIFIC 0x09 /* Vendor specific condition */
+#define SCSIRESP_SENSEDATA_ABORTEDCOMMAND 0x0b /* Command was aborted */
+
+#define SCSIRESP_SENSEDATA_KEYVALID 0x80 /* Sense-specific data valid */
+
+/* Mode Select 6 */
+
+#define SCSICMD_MODESELECT6_PF 0x10 /* Bit 4: PF */
+#define SCSICMD_MODESELECT6_SP 0x01 /* Bit 0: SP */
+
+/* Mode Sense 6 */
+
+#define SCSICMD_MODESENSE6_DBD 0x08 /* Bit 3: PF */
+
+#define SCSICMD_MODESENSE_PCMASK 0xc0 /* Bits 6-7: Page control (PC) */
+#define SCSICMD_MODESENSE_PCCURRENT 0x00 /* Current values */
+#define SCSICMD_MODESENSE_PCCHANGEABLE 0x40 /* Changeable values */
+#define SCSICMD_MODESENSE_PCDEFAULT 0x80 /* Default values */
+#define SCSICMD_MODESENSE_PCSAVED 0xc0 /* Saved values */
+#define SCSICMD_MODESENSE_PGCODEMASK 0x3f /* Bits 0-5: Page code */
+
+#define SCSICMD_MODESENSE6_PCDEFAULT 0x80 /* Default values */
+ /* Direct-access device page codes */
+#define SCSIRESP_MODESENSE_PGCCODE_VENDOR 0x00 /* Vendor-specific */
+#define SCSIRESP_MODESENSE_PGCCODE_RWERROR 0x01 /* Read/Write error recovery mode page */
+#define SCSIRESP_MODESENSE_PGCCODE_RECONNECT 0x02 /* Disconnect-reconnect mode page */
+#define SCSIRESP_MODESENSE_PGCCODE_FORMATDEV 0x03 /* Format device mode page (obsolete) */
+#define SCSIRESP_MODESENSE_PGCCODE_RIGID 0x04 /* Rigid disk geometry mode page (obsolete) */
+#define SCSIRESP_MODESENSE_PGCCODE_FLEXIBLE 0x05 /* Flexible disk geometry mode page (obsolete) */
+#define SCSIRESP_MODESENSE_PGCCODE_VERIFY 0x07 /* Verify error recovery mode page */
+#define SCSIRESP_MODESENSE_PGCCODE_CACHING 0x08 /* Caching mode page */
+#define SCSIRESP_MODESENSE_PGCCODE_CONTROL 0x0a /* Control mode page (0x0a/0x00) */
+#define SCSIRESP_MODESENSE_PGCCODE_CONTROLEXT 0x0a /* Control extension mode page (0x0a/0x01) */
+#define SCSIRESP_MODESENSE_PGCCODE_MEDIUMTYPES 0x0b /* Medum types supported mode page (obsolete) */
+#define SCSIRESP_MODESENSE_PGCCODE_NP 0x0c /* Notch and partition mode page (obsolete) */
+#define SCSIRESP_MODESENSE_PGCCODE_XOR 0x10 /* XOR control mode page */
+#define SCSIRESP_MODESENSE_PGCCODE_ES 0x14 /* Enclosure services mode page */
+#define SCSIRESP_MODESENSE_PGCCODE_PSLUN 0x18 /* Protocol-specific LUN mode page */
+#define SCSIRESP_MODESENSE_PGCCODE_PSPORT 0x19 /* Protocol-specific port mode page */
+#define SCSIRESP_MODESENSE_PGCCODE_POWER 0x1a /* Power condition mode page */
+#define SCSIRESP_MODESENSE_PGCCODE_IE 0x1c /* Informational exceptions control mode page (0x1c/0x00) */
+#define SCSIRESP_MODESENSE_PGCCODE_BC 0x1c /* Background control mode page (0x1c/0x01) */
+#define SCSIRESP_MODESENSE_PGCCODE_RETURNALL 0x3f /* Return all mode pages */
+ /* Direct-access caching mode page */
+#define SCSIRESP_CACHINGMODEPG_PS 0x80 /* Byte 0, Bit 7: PS */
+#define SCSIRESP_CACHINGMODEPG_SPF 0x60 /* Byte 0, Bit 6: SPF */
+#define SCSIRESP_CACHINGMODEPG_IC 0x80 /* Byte 2, Bit 7: IC */
+#define SCSIRESP_CACHINGMODEPG_ABPF 0x40 /* Byte 2, Bit 6: ABPF */
+#define SCSIRESP_CACHINGMODEPG_CAP 0x20 /* Byte 2, Bit 5: CAP */
+#define SCSIRESP_CACHINGMODEPG_DISC 0x10 /* Byte 2, Bit 4: DISC */
+#define SCSIRESP_CACHINGMODEPG_SIZE 0x08 /* Byte 2, Bit 3: SIZE */
+#define SCSIRESP_CACHINGMODEPG_WCE 0x04 /* Byte 2, Bit 2: Write cache enable (WCE) */
+#define SCSIRESP_CACHINGMODEPG_MF 0x02 /* Byte 2, Bit 1: MF */
+#define SCSIRESP_CACHINGMODEPG_RCD 0x01 /* Byte 2, Bit 0: Read cache disable (RCD) */
+
+#define SCSIRESP_MODEPARMHDR_DAPARM_WP 0x80 /* Bit 7: WP (Direct-access block devices only) */
+#define SCSIRESP_MODEPARMHDR_DAPARM_DBPFUA 0x10 /* Bit 4: DBOFUA (Direct-access block devices only) */
+
+#define SCSIRESP_PAGEFMT_PS 0x80 /* Bit 7: PS */
+#define SCSIRESP_PAGEFMT_SPF 0x40 /* Bit 6: SPF */
+#define SCSIRESP_PAGEFMT_PGCODEMASK 0x3f /* Bits 0-5: Page code */
+
+/* Prevent / Allow Medium Removal */
+
+#define SCSICMD_PREVENTMEDIUMREMOVAL_TRANSPORT 0x01 /* Removal prohibited from data transport */
+#define SCSICMD_PREVENTMEDIUMREMOVAL_MCHANGER 0x02 /* Removal prohibited from medium changer */
+
+/* Read format capacities */
+
+#define SCIRESP_RDFMTCAPACITIES_UNFORMATED 0x01 /* Unformatted media */
+#define SCIRESP_RDFMTCAPACITIES_FORMATED 0x02 /* Formatted media */
+#define SCIRESP_RDFMTCAPACITIES_NOMEDIA 0x03 /* No media */
+
+/* Read 6 */
+
+#define SCSICMD_READ6_MSLBAMASK 0x1f
+
+/* Write 6 */
+
+#define SCSICMD_WRITE6_MSLBAMASK 0x1f
+
+/* Mode Select 10 */
+
+#define SCSICMD_MODESELECT10_PF 0x10 /* Bit 4: PF */
+#define SCSICMD_MODESELECT10_SP 0x01 /* Bit 0: SP */
+
+/* Mode Sense 10 */
+
+#define SCSICMD_MODESENSE10_LLBAA 0x10 /* Bit 4: LLBAA */
+#define SCSICMD_MODESENSE10_DBD 0x08 /* Bit 3: PF */
+
+/* Read 10 */
+
+#define SCSICMD_READ10FLAGS_RDPROTECTMASK 0xe0
+#define SCSICMD_READ10FLAGS_DPO 0x10 /* Disable Page Out */
+#define SCSICMD_READ10FLAGS_FUA 0x08
+#define SCSICMD_READ10FLAGS_FUANV 0x02
+
+/* Write 10 */
+
+#define SCSICMD_WRITE10FLAGS_WRPROTECTMASK 0xe0
+#define SCSICMD_WRITE10FLAGS_DPO 0x10 /* Disable Page Out */
+#define SCSICMD_WRITE10FLAGS_FUA 0x08
+#define SCSICMD_WRITE10FLAGS_FUANV 0x02
+
+/* Verify 10 */
+
+#define SCSICMD_VERIFY10_VRPROTECTMASK 0xe0 /* Byte 1: Bits 5-7: VRPROTECT */
+#define SCSICMD_VERIFY10_DPO 0x10 /* Byte 1: Bit 4: Disable Page Out (DPO) */
+#define SCSICMD_VERIFY10_BYTCHK 0x02 /* Byte 1: Bit 2: BytChk */
+
+/* Read 12 */
+
+#define SCSICMD_READ12FLAGS_RDPROTECTMASK 0xe0
+#define SCSICMD_READ12FLAGS_DPO 0x10 /* Disable Page Out */
+#define SCSICMD_READ12FLAGS_FUA 0x08
+#define SCSICMD_READ12FLAGS_FUANV 0x02
+
+/* Write 12 */
+
+#define SCSICMD_WRITE12FLAGS_WRPROTECTMASK 0xe0
+#define SCSICMD_WRITE12FLAGS_DPO 0x10 /* Disable Page Out */
+#define SCSICMD_WRITE12FLAGS_FUA 0x08
+#define SCSICMD_WRITE12FLAGS_FUANV 0x02
+
+/* Verify 12 */
+
+#define SCSICMD_VERIFY12_VRPROTECTMASK 0xe0 /* Byte 1: Bits 5-7: VRPROTECT */
+#define SCSICMD_VERIFY12_DPO 0x10 /* Byte 1: Bit 4: Disable Page Out (DPO) */
+#define SCSICMD_VERIFY12_BYTCHK 0x02 /* Byte 1: Bit 2: BytChk */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Format structures for selected SCSI primary commands */
+
+#define SCSICMD_TESTUNITREADY_SIZEOF 6
+
+struct scsicmd_requestsense_s
+{
+ uint8_t opcode; /* 0: 0x03 */
+ uint8_t flags; /* 1: See SCSICMD_REQUESTSENSE_FLAGS_* */
+ uint8_t reserved[2]; /* 2-3: Reserved */
+ uint8_t alloclen; /* 4: Allocation length */
+ uint8_t control; /* 5: Control */
+};
+#define SCSICMD_REQUESTSENSE_SIZEOF 6
+#define SCSICMD_REQUESTSENSE_MSSIZEOF 12 /* MS-Windows REQUEST SENSE with cbw->cdblen == 12 */
+
+struct scsiresp_fixedsensedata_s
+{
+ uint8_t code; /* 0: Response code See SCSIRESP_SENSEDATA_*FIXED defns */
+ uint8_t obsolete; /* 1: */
+ uint8_t flags; /* 2: See SCSIRESP_SENSEDATA_* definitions */
+ uint8_t info[4]; /* 3-6: Information */
+ uint8_t len; /* 7: Additional length */
+ uint8_t cmdinfo[4]; /* 8-11: Command-specific information */
+ uint8_t code2; /* 12: Additional sense code */
+ uint8_t qual2; /* 13: Additional sense code qualifier */
+ uint8_t fru; /* 14: Field replacement unit code */
+ uint8_t key[3]; /* 15-17: Sense key specific */
+ /* 18-: Additional bytes may follow */
+};
+#define SCSIRESP_FIXEDSENSEDATA_SIZEOF 18 /* Minimum size */
+
+struct scscicmd_inquiry_s
+{
+ uint8_t opcode; /* 0: 0x12 */
+ uint8_t flags; /* 1: See SCSICMD_INQUIRY_FLAGS_* */
+ uint8_t pagecode; /* 2: Page code */
+ uint8_t alloclen[2]; /* 3-4: Allocation length */
+ uint8_t control; /* 5: Control */
+};
+#define SCSICMD_INQUIRY_SIZEOF 6
+
+struct scsiresp_inquiry_s
+{
+ /* Mandatory */
+
+ uint8_t qualtype; /* 0: Bits 5-7: Peripheral qualifier; Bits 0-4: Peripheral device type */
+ uint8_t flags1; /* 1: See SCSIRESP_INQUIRY_FLAGS1_* */
+ uint8_t version; /* 2: Version */
+ uint8_t flags2; /* 3: See SCSIRESP_INQUIRY_FLAGS2_* */
+ uint8_t len; /* 4: Additional length */
+ uint8_t flags3; /* 5: See SCSIRESP_INQUIRY_FLAGS3_* */
+ uint8_t flags4; /* 6: See SCSIRESP_INQUIRY_FLAGS4_* */
+ uint8_t flags5; /* 7: See SCSIRESP_INQUIRY_FLAGS5_* */
+ uint8_t vendorid[8]; /* 8-15: T10 Vendor Identification */
+ uint8_t productid[16]; /* 16-31: Product Identification */
+ uint8_t revision[4]; /* 32-35: Product Revision Level */
+
+ /* Optional */
+
+ uint8_t vendor[20]; /* 36-55: Vendor specific */
+ uint8_t flags6; /* 56: See SCSIRESP_INQUIRY_FLAGS6_* */
+ uint8_t reserved1; /* 57: Reserved */
+ uint8_t version1[2]; /* 58-59: Version Descriptor 1 */
+ uint8_t version2[2]; /* 60-61: Version Descriptor 2 */
+ uint8_t version3[2]; /* 62-63: Version Descriptor 3 */
+ uint8_t version4[2]; /* 64-65: Version Descriptor 4 */
+ uint8_t version5[2]; /* 66-67: Version Descriptor 5 */
+ uint8_t version6[2]; /* 68-69: Version Descriptor 6 */
+ uint8_t version7[2]; /* 70-71: Version Descriptor 7 */
+ uint8_t version8[2]; /* 72-73: Version Descriptor 8 */
+ uint8_t reserved2[22]; /* 74-95: Reserved */
+ /* 96-: Vendor-specific parameters may follow */
+};
+#define SCSIRESP_INQUIRY_SIZEOF 36 /* Minimum size */
+
+struct scsicmd_modeselect6_s
+{
+ uint8_t opcode; /* 0x15 */
+ uint8_t flags; /* 1: See SCSICMD_MODESELECT6_FLAGS_* */
+ uint8_t reserved[2]; /* 2-3: Reserved */
+ uint8_t plen; /* 4: Parameter list length */
+ uint8_t control; /* 5: Control */
+};
+#define SCSICMD_MODESELECT6_SIZEOF 6
+
+struct scsicmd_modesense6_s
+{
+ uint8_t opcode; /* 0x1a */
+ uint8_t flags; /* 1: See SCSICMD_MODESENSE6_FLAGS_* */
+ uint8_t pcpgcode; /* 2: Bits 6-7: PC, bits 0-5: page code */
+ uint8_t subpgcode; /* 3: subpage code */
+ uint8_t alloclen; /* 4: Allocation length */
+ uint8_t control; /* 5: Control */
+};
+#define SCSICMD_MODESENSE6_SIZEOF 6
+
+struct scsiresp_modeparameterhdr6_s
+{
+ uint8_t mdlen; /* 0: Mode data length */
+ uint8_t type; /* 1: Medium type */
+ uint8_t param; /* 2: Device-specific parameter */
+ uint8_t bdlen; /* 3: Block descriptor length */
+};
+#define SCSIRESP_MODEPARAMETERHDR6_SIZEOF 4
+
+struct scsiresp_blockdesc_s
+{
+ uint8_t density; /* 0: density code */
+ uint8_t nblocks[3]; /* 1-3: Number of blocks */
+ uint8_t reserved; /* 4: reserved */
+ uint8_t blklen[3]; /* 5-7: Block len */
+};
+#define SCSIRESP_BLOCKDESC_SIZEOF 8
+
+struct scsiresp_pageformat_s
+{
+ uint8_t pgcode; /* 0: See SCSIRESP_PAGEFMT_* definitions */
+ uint8_t pglen; /* 1: Page length (n-1) */
+ uint8_t parms[1]; /* 2-n: Mode parameters */
+};
+
+struct scsiresp_subpageformat_s
+{
+ uint8_t pgcode; /* 0: See SCSIRESP_PAGEFMT_* definitions */
+ uint8_t subpgcode; /* 1: sub-page code */
+ uint8_t pglen[2]; /* 2-3: Page length (n-3) */
+ uint8_t parms[1]; /* 4-n: Mode parameters */
+};
+
+struct scsiresp_cachingmodepage_s
+{
+ uint8_t pgcode; /* 0: Bit 7: PS; Bit 6: SPF, Bits 0-5: page code == 8 */
+ uint8_t len; /* 1: Page length (18) */
+ uint8_t flags1; /* 2: See SCSIRESP_CACHINGMODEPG_* definitions */
+ uint8_t priority; /* 3: Bits 4-7: Demand read retention priority; Bits 0-3: Write retention priority */
+ uint8_t dpflen[2]; /* 4-5: Disable prefetch transfer length */
+ uint8_t minpf[2]; /* 6-7: Minimum pre-fetch */
+ uint8_t maxpf[2]; /* 8-9: Maximum pre-fetch */
+ uint8_t maxpfc[2]; /* 10-11: Maximum pref-fetch ceiling */
+ uint8_t flags2; /* 12: See SCSIRESP_CACHINGMODEPG_* definitions */
+ uint8_t nsegments; /* 13: Number of cache segments */
+ uint8_t segsize[2]; /* 14-15: Cache segment size */
+ uint8_t reserved; /* 16: Reserved */
+ uint8_t obsolete[3]; /* 17-19: Obsolete */
+};
+
+/* Format structures for selected SCSI block commands */
+
+struct scsicmd_read6_s
+{
+ uint8_t opcode; /* 0: 0x08 */
+ uint8_t mslba; /* 1: Bits 5-7: reserved; Bits 0-6: MS Logical Block Address (LBA) */
+ uint8_t lslba[2]; /* 2-3: LS Logical Block Address (LBA) */
+ uint8_t xfrlen; /* 4: Transfer length (in contiguous logical blocks) */
+ uint8_t control; /* 5: Control */
+};
+#define SCSICMD_READ6_SIZEOF 6
+
+struct scsicmd_write6_s
+{
+ uint8_t opcode; /* 0: 0x0a */
+ uint8_t mslba; /* 1: Bits 5-7: reserved; Bits 0-6: MS Logical Block Address (LBA) */
+ uint8_t lslba[2]; /* 2-3: LS Logical Block Address (LBA) */
+ uint8_t xfrlen; /* 4: Transfer length (in contiguous logical blocks) */
+ uint8_t control; /* 5: Control */
+};
+#define SCSICMD_WRITE6_SIZEOF 6
+
+struct scsicmd_startstopunit_s
+{
+ uint8_t opcode; /* 0: 0x1b */
+ uint8_t immed; /* 1: Bits 2-7: Reserved, Bit 0: Immed */
+ uint8_t reserved; /* 2: reserved */
+ uint8_t pcm; /* 3: Bits 4-7: Reserved, Bits 0-3: Power condition modifier */
+ uint8_t pc; /* 4: Bits 4-7: Power condition, Bit 2: NO_FLUSH, Bit 1: LOEJ, Bit 0: START */
+ uint8_t control; /* 5: Control */
+};
+#define SCSICMD_STARTSTOPUNIT_SIZEOF 6
+
+struct scsicmd_preventmediumremoval_s
+{
+ uint8_t opcode; /* 0: 0x1e */
+ uint8_t reserved[3]; /* 1-3: Reserved */
+ uint8_t prevent; /* 4: Bits 2-7: Reserved, Bits 0:1: prevent */
+ uint8_t control; /* 5: Control */
+};
+#define SCSICMD_PREVENTMEDIUMREMOVAL_SIZEOF 6
+
+struct scsicmd_readformatcapcacities_s
+{
+ uint8_t opcode; /* 0: 0x23 */
+ uint8_t reserved[6]; /* 1-6: Reserved */
+ uint8_t alloclen[2]; /* 7-8: Allocation length */
+ uint8_t control; /* 9: Control */
+};
+#define SCSICMD_READFORMATCAPACITIES_SIZEOF 10
+
+struct scsiresp_readformatcapacities_s
+{
+ /* Current capacity header */
+
+ uint8_t reserved[3]; /* 0-2: Reserved */
+ uint8_t listlen; /* 3: Capacity list length */
+
+ /* Current/Maximum Capacity Descriptor (actually a separate structure) */
+
+ uint8_t nblocks[4]; /* 4-7: Number of blocks */
+ uint8_t type; /* 8: Bits 2-7: Reserved, Bits 0-1: Descriptor type */
+ uint8_t blocklen[3]; /* 9-11: Block length */
+};
+#define SCSIRESP_READFORMATCAPACITIES_SIZEOF 12
+#define SCSIRESP_CURRCAPACITYDESC_SIZEOF 8
+
+struct scsiresp_formattedcapacitydesc_s
+{
+ uint8_t nblocks[4]; /* 0-3: Number of blocks */
+ uint8_t type; /* 4: Bits 2-7: Type, bits 0-1, reserved */
+ uint8_t param[3]; /* 5-7: Type dependent parameter */
+};
+#define SCSIRESP_FORMATTEDCAPACITYDESC_SIZEOF 8
+
+struct scsicmd_readcapacity10_s
+{
+ uint8_t opcode; /* 0: 0x25 */
+ uint8_t reserved1; /* 1: Bits 1-7: Reserved, Bit 0: Obsolete */
+ uint8_t lba[4]; /* 2-5: Logical block address (LBA) */
+ uint8_t reserved2[2]; /* 6-7: Reserved */
+ uint8_t pmi; /* 8: Bits 1-7 Reserved; Bit 0: PMI */
+ uint8_t control; /* 9: Control */
+};
+#define SCSICMD_READCAPACITY10_SIZEOF 10
+
+struct scsiresp_readcapacity10_s
+{
+ uint8_t lba[4]; /* 0-3: Returned logical block address (LBA) */
+ uint8_t blklen[4]; /* 4-7: Logical block length (in bytes) */
+};
+#define SCSIRESP_READCAPACITY10_SIZEOF 8
+
+struct scsicmd_read10_s
+{
+ uint8_t opcode; /* 0: 0x28 */
+ uint8_t flags; /* 1: See SCSICMD_READ10FLAGS_* */
+ uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */
+ uint8_t groupno; /* 6: Bits 5-7: reserved; Bits 0-6: group number */
+ uint8_t xfrlen[2]; /* 7-8: Transfer length (in contiguous logical blocks) */
+ uint8_t control; /* 9: Control */
+};
+#define SCSICMD_READ10_SIZEOF 10
+
+struct scsicmd_write10_s
+{
+ uint8_t opcode; /* 0: 0x2a */
+ uint8_t flags; /* 1: See SCSICMD_WRITE10FLAGS_* */
+ uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */
+ uint8_t groupno; /* 6: Bits 5-7: reserved; Bits 0-6: group number */
+ uint8_t xfrlen[2]; /* 7-8: Transfer length (in contiguous logical blocks) */
+ uint8_t control; /* 9: Control */
+};
+#define SCSICMD_WRITE10_SIZEOF 10
+
+struct scsicmd_verify10_s
+{
+ uint8_t opcode; /* 0: 0x2f */
+ uint8_t flags; /* 1: See SCSICMD_VERIFY10_* definitions */
+ uint8_t lba[4]; /* 2-5: Logical block address (LBA) */
+ uint8_t groupno; /* 6: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */
+ uint8_t len[2]; /* 7-8: Verification length (in blocks) */
+ uint8_t control; /* 9: Control */
+};
+#define SCSICMD_VERIFY10_SIZEOF 10
+
+struct scsicmd_synchronizecache10_s
+{
+ uint8_t opcode; /* 0: 0x35 */
+ uint8_t flags; /* 1: See SCSICMD_SYNCHRONIZECACHE10_* definitions */
+ uint8_t lba[4]; /* 2-5: Logical block address (LBA) */
+ uint8_t groupno; /* 6: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */
+ uint8_t len[2]; /* 7-8: Number of logical blocks */
+ uint8_t control; /* 9: Control */
+};
+#define SCSICMD_SYNCHRONIZECACHE10_SIZEOF 10
+
+struct scsicmd_modeselect10_s
+{
+ uint8_t opcode; /* 0: 0x55 */
+ uint8_t flags; /* 1: See SCSICMD_MODESELECT10_FLAGS_* */
+ uint8_t reserved[5]; /* 2-6: Reserved */
+ uint8_t parmlen[2]; /* 7-8: Parameter list length */
+ uint8_t control; /* 9: Control */
+};
+#define SCSICMD_MODESELECT10_SIZEOF 10
+
+struct scsiresp_modeparameterhdr10_s
+{
+ uint8_t mdlen[2]; /* 0-1: Mode data length */
+ uint8_t type; /* 2: Medium type */
+ uint8_t param; /* 3: Device-specific parameter */
+ uint8_t reserved[2]; /* 4-5: reserved */
+ uint8_t bdlen[2]; /* 6-7: Block descriptor length */
+};
+#define SCSIRESP_MODEPARAMETERHDR10_SIZEOF 8
+
+struct scsicmd_modesense10_s
+{
+ uint8_t opcode; /* O: 0x5a */
+ uint8_t flags; /* 1: See SCSICMD_MODESENSE10_FLAGS_* */
+ uint8_t pcpgcode; /* 2: Bits 6-7: PC, bits 0-5: page code */
+ uint8_t subpgcode; /* 3: subpage code */
+ uint8_t reserved[3]; /* 4-6: reserved */
+ uint8_t alloclen[2]; /* 7-8: Allocation length */
+ uint8_t control; /* 9: Control */
+};
+#define SCSICMD_MODESENSE10_SIZEOF 10
+
+struct scsicmd_readcapacity16_s
+{
+ uint8_t opcode; /* 0: 0x9e */
+ uint8_t action; /* 1: Bits 5-7: Reserved, Bits 0-4: Service action */
+ uint8_t lba[8]; /* 2-9: Logical block address (LBA) */
+ uint8_t len[4]; /* 10-13: Allocation length */
+ uint8_t reserved; /* 14: Reserved */
+ uint8_t control; /* 15: Control */
+};
+#define SCSICMD_READCAPACITY16_SIZEOF 16
+
+struct scsicmd_read12_s
+{
+ uint8_t opcode; /* 0: 0xa8 */
+ uint8_t flags; /* 1: See SCSICMD_READ12FLAGS_* */
+ uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */
+ uint8_t xfrlen[4]; /* 6-9: Transfer length (in contiguous logical blocks) */
+ uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: reserved; Bits 0-6: group number */
+ uint8_t control; /* 11: Control */
+};
+#define SCSICMD_READ12_SIZEOF 12
+
+struct scsicmd_write12_s
+{
+ uint8_t opcode; /* 0: 0xaa */
+ uint8_t flags; /* 1: See SCSICMD_WRITE12FLAGS_* */
+ uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */
+ uint8_t xfrlen[4]; /* 6-9: Transfer length (in contiguous logical blocks) */
+ uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: reserved; Bits 0-6: group number */
+ uint8_t control; /* 11: Control */
+};
+#define SCSICMD_WRITE12_SIZEOF 12
+
+struct scsicmd_verify12_s
+{
+ uint8_t opcode; /* 0: 0xaf */
+ uint8_t flags; /* 1: See SCSICMD_VERIFY12_* definitions */
+ uint8_t lba[4]; /* 2-5: Logical block address (LBA) */
+ uint8_t len[4]; /* 6-9: Verification length */
+ uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */
+ uint8_t control; /* 11: Control */
+};
+#define SCSICMD_VERIFY12_SIZEOF 12
+
+/****************************************************************************
+ * Public Functions Definitions
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_SCSI_H */
diff --git a/third-party/cherryusb-0.6.0/class/msc/usbd_msc.c b/third-party/cherryusb-0.6.0/class/msc/usbd_msc.c
new file mode 100644
index 0000000000000000000000000000000000000000..708f8d099ce27798cdfe4020926fcf40b06555bc
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/msc/usbd_msc.c
@@ -0,0 +1,963 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "usbd_msc.h"
+#include "usb_scsi.h"
+#ifdef CONFIG_USBDEV_MSC_THREAD
+#include "usb_osal.h"
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE
+#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512
+#endif
+
+#define MSC_THREAD_OP_READ_MEM 1
+#define MSC_THREAD_OP_WRITE_MEM 2
+#define MSC_THREAD_OP_WRITE_DONE 3
+
+#define MSD_OUT_EP_IDX 0
+#define MSD_IN_EP_IDX 1
+
+/* Describe EndPoints configuration */
+static struct usbd_endpoint mass_ep_data[2];
+
+/* MSC Bulk-only Stage */
+enum Stage {
+ MSC_READ_CBW = 0, /* Command Block Wrapper */
+ MSC_DATA_OUT = 1, /* Data Out Phase */
+ MSC_DATA_IN = 2, /* Data In Phase */
+ MSC_SEND_CSW = 3, /* Command Status Wrapper */
+ MSC_WAIT_CSW = 4, /* Command Status Wrapper */
+};
+
+/* Device data structure */
+USB_NOCACHE_RAM_SECTION struct usbd_msc_cfg_priv {
+ /* state of the bulk-only state machine */
+ enum Stage stage;
+ USB_MEM_ALIGNX struct CBW cbw;
+ USB_MEM_ALIGNX struct CSW csw;
+
+ bool readonly;
+ uint8_t sKey; /* Sense key */
+ uint8_t ASC; /* Additional Sense Code */
+ uint8_t ASQ; /* Additional Sense Qualifier */
+ uint8_t max_lun;
+ uint32_t start_sector;
+ uint32_t nsectors;
+ uint16_t scsi_blk_size;
+ uint32_t scsi_blk_nbr;
+
+ uint8_t block_buffer[CONFIG_USBDEV_MSC_BLOCK_SIZE];
+} usbd_msc_cfg;
+
+#ifdef CONFIG_USBDEV_MSC_THREAD
+static volatile uint8_t thread_op;
+static usb_osal_sem_t msc_sem;
+static usb_osal_thread_t msc_thread;
+static volatile uint32_t current_byte_read;
+#endif
+
+static void usbd_msc_reset(void)
+{
+ usbd_msc_cfg.stage = MSC_READ_CBW;
+ usbd_msc_cfg.readonly = false;
+}
+
+static int msc_storage_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ USB_LOG_DBG("MSC Class request: "
+ "bRequest 0x%02x\r\n",
+ setup->bRequest);
+
+ switch (setup->bRequest) {
+ case MSC_REQUEST_RESET:
+ usbd_msc_reset();
+ break;
+
+ case MSC_REQUEST_GET_MAX_LUN:
+ *data = (uint8_t *)(&usbd_msc_cfg.max_lun);
+ *len = 1;
+ break;
+
+ default:
+ USB_LOG_WRN("Unhandled MSC Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+
+ return 0;
+}
+
+void msc_storage_notify_handler(uint8_t event, void *arg)
+{
+ switch (event) {
+ case USBD_EVENT_RESET:
+ usbd_msc_reset();
+ break;
+ case USBD_EVENT_CONFIGURED:
+ USB_LOG_DBG("Start reading cbw\r\n");
+ usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void usbd_msc_bot_abort(void)
+{
+ if ((usbd_msc_cfg.cbw.bmFlags == 0) && (usbd_msc_cfg.cbw.dDataLength != 0)) {
+ usbd_ep_set_stall(mass_ep_data[MSD_OUT_EP_IDX].ep_addr);
+ }
+ usbd_ep_set_stall(mass_ep_data[MSD_IN_EP_IDX].ep_addr);
+ usbd_ep_start_read(mass_ep_data[0].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
+}
+
+static void usbd_msc_send_csw(uint8_t CSW_Status)
+{
+ usbd_msc_cfg.csw.dSignature = MSC_CSW_Signature;
+ usbd_msc_cfg.csw.bStatus = CSW_Status;
+
+ /* updating the State Machine , so that we wait CSW when this
+ * transfer is complete, ie when we get a bulk in callback
+ */
+ usbd_msc_cfg.stage = MSC_WAIT_CSW;
+
+ USB_LOG_DBG("Send csw\r\n");
+ usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.csw, sizeof(struct CSW));
+}
+
+static void usbd_msc_send_info(uint8_t *buffer, uint8_t size)
+{
+ size = MIN(size, usbd_msc_cfg.cbw.dDataLength);
+
+ /* updating the State Machine , so that we send CSW when this
+ * transfer is complete, ie when we get a bulk in callback
+ */
+ usbd_msc_cfg.stage = MSC_SEND_CSW;
+
+ usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, buffer, size);
+
+ usbd_msc_cfg.csw.dDataResidue -= size;
+ usbd_msc_cfg.csw.bStatus = CSW_STATUS_CMD_PASSED;
+}
+
+static bool SCSI_processWrite(uint32_t nbytes);
+static bool SCSI_processRead(void);
+
+/**
+* @brief SCSI_SetSenseData
+* Load the last error code in the error list
+* @param sKey: Sense Key
+* @param ASC: Additional Sense Code
+* @retval none
+
+*/
+static void SCSI_SetSenseData(uint32_t KCQ)
+{
+ usbd_msc_cfg.sKey = (uint8_t)(KCQ >> 16);
+ usbd_msc_cfg.ASC = (uint8_t)(KCQ >> 8);
+ usbd_msc_cfg.ASQ = (uint8_t)(KCQ);
+}
+
+/**
+ * @brief SCSI Command list
+ *
+ */
+
+static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len)
+{
+ if (usbd_msc_cfg.cbw.dDataLength != 0U) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+ *data = NULL;
+ *len = 0;
+ return true;
+}
+
+static bool SCSI_requestSense(uint8_t **data, uint32_t *len)
+{
+ uint8_t data_len = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
+ if (usbd_msc_cfg.cbw.dDataLength == 0U) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+
+ if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_FIXEDSENSEDATA_SIZEOF) {
+ data_len = usbd_msc_cfg.cbw.CB[4];
+ }
+
+ uint8_t request_sense[SCSIRESP_FIXEDSENSEDATA_SIZEOF] = {
+ 0x70,
+ 0x00,
+ 0x00, /* Sense Key */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ SCSIRESP_FIXEDSENSEDATA_SIZEOF - 8,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00, /* Additional Sense Code */
+ 0x00, /* Additional Sense Request */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ };
+
+ request_sense[2] = usbd_msc_cfg.sKey;
+ request_sense[12] = usbd_msc_cfg.ASC;
+ request_sense[13] = usbd_msc_cfg.ASQ;
+#if 0
+ request_sense[ 2] = 0x06; /* UNIT ATTENTION */
+ request_sense[12] = 0x28; /* Additional Sense Code: Not ready to ready transition */
+ request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
+#endif
+#if 0
+ request_sense[ 2] = 0x02; /* NOT READY */
+ request_sense[12] = 0x3A; /* Additional Sense Code: Medium not present */
+ request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
+#endif
+#if 0
+ request_sense[ 2] = 0x05; /* ILLEGAL REQUEST */
+ request_sense[12] = 0x20; /* Additional Sense Code: Invalid command */
+ request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
+#endif
+#if 0
+ request_sense[ 2] = 0x00; /* NO SENSE */
+ request_sense[12] = 0x00; /* Additional Sense Code: No additional code */
+ request_sense[13] = 0x00; /* Additional Sense Code Qualifier */
+#endif
+
+ memcpy(*data, (uint8_t *)request_sense, data_len);
+ *len = data_len;
+ return true;
+}
+
+static bool SCSI_inquiry(uint8_t **data, uint32_t *len)
+{
+ uint8_t data_len = SCSIRESP_INQUIRY_SIZEOF;
+
+ uint8_t inquiry00[6] = {
+ 0x00,
+ 0x00,
+ 0x00,
+ (0x06 - 4U),
+ 0x00,
+ 0x80
+ };
+
+ /* USB Mass storage VPD Page 0x80 Inquiry Data for Unit Serial Number */
+ uint8_t inquiry80[8] = {
+ 0x00,
+ 0x80,
+ 0x00,
+ 0x08,
+ 0x20, /* Put Product Serial number */
+ 0x20,
+ 0x20,
+ 0x20
+ };
+
+ uint8_t inquiry[SCSIRESP_INQUIRY_SIZEOF] = {
+ /* 36 */
+
+ /* LUN 0 */
+ 0x00,
+ 0x80,
+ 0x02,
+ 0x02,
+ (SCSIRESP_INQUIRY_SIZEOF - 5),
+ 0x00,
+ 0x00,
+ 0x00,
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', /* Product : 16 Bytes */
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ' /* Version : 4 Bytes */
+ };
+
+ memcpy(&inquiry[8], CONFIG_USBDEV_MSC_MANUFACTURER_STRING, strlen(CONFIG_USBDEV_MSC_MANUFACTURER_STRING));
+ memcpy(&inquiry[16], CONFIG_USBDEV_MSC_PRODUCT_STRING, strlen(CONFIG_USBDEV_MSC_PRODUCT_STRING));
+ memcpy(&inquiry[32], CONFIG_USBDEV_MSC_VERSION_STRING, strlen(CONFIG_USBDEV_MSC_VERSION_STRING));
+
+ if (usbd_msc_cfg.cbw.dDataLength == 0U) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+
+ if ((usbd_msc_cfg.cbw.CB[1] & 0x01U) != 0U) { /* Evpd is set */
+ if (usbd_msc_cfg.cbw.CB[2] == 0U) { /* Request for Supported Vital Product Data Pages*/
+ data_len = 0x06;
+ memcpy(*data, (uint8_t *)inquiry00, data_len);
+ } else if (usbd_msc_cfg.cbw.CB[2] == 0x80U) { /* Request for VPD page 0x80 Unit Serial Number */
+ data_len = 0x08;
+ memcpy(*data, (uint8_t *)inquiry80, data_len);
+ } else { /* Request Not supported */
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDFIELDINCBA);
+ return false;
+ }
+ } else {
+ if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_INQUIRY_SIZEOF) {
+ data_len = usbd_msc_cfg.cbw.CB[4];
+ }
+ memcpy(*data, (uint8_t *)inquiry, data_len);
+ }
+
+ *len = data_len;
+ return true;
+}
+
+static bool SCSI_startStopUnit(uint8_t **data, uint32_t *len)
+{
+ if (usbd_msc_cfg.cbw.dDataLength != 0U) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+
+ if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x1U) /* START=1 */
+ {
+ //SCSI_MEDIUM_UNLOCKED;
+ } else if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */
+ {
+ //SCSI_MEDIUM_EJECTED;
+ } else if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */
+ {
+ //SCSI_MEDIUM_UNLOCKED;
+ } else {
+ }
+
+ *data = NULL;
+ *len = 0;
+ return true;
+}
+
+static bool SCSI_preventAllowMediaRemoval(uint8_t **data, uint32_t *len)
+{
+ if (usbd_msc_cfg.cbw.dDataLength != 0U) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+ if (usbd_msc_cfg.cbw.CB[4] == 0U) {
+ //SCSI_MEDIUM_UNLOCKED;
+ } else {
+ //SCSI_MEDIUM_LOCKED;
+ }
+ *data = NULL;
+ *len = 0;
+ return true;
+}
+
+static bool SCSI_modeSense6(uint8_t **data, uint32_t *len)
+{
+ uint8_t data_len = 4;
+ if (usbd_msc_cfg.cbw.dDataLength == 0U) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+ if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_MODEPARAMETERHDR6_SIZEOF) {
+ data_len = usbd_msc_cfg.cbw.CB[4];
+ }
+
+ uint8_t sense6[SCSIRESP_MODEPARAMETERHDR6_SIZEOF] = { 0x03, 0x00, 0x00, 0x00 };
+
+ if (usbd_msc_cfg.readonly) {
+ sense6[2] = 0x80;
+ }
+ memcpy(*data, (uint8_t *)sense6, data_len);
+ *len = data_len;
+ return true;
+}
+
+static bool SCSI_modeSense10(uint8_t **data, uint32_t *len)
+{
+ uint8_t data_len = 27;
+ if (usbd_msc_cfg.cbw.dDataLength == 0U) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+
+ if (usbd_msc_cfg.cbw.CB[8] < 27) {
+ data_len = usbd_msc_cfg.cbw.CB[8];
+ }
+
+ uint8_t sense10[27] = {
+ 0x00,
+ 0x26,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08,
+ 0x12,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+ };
+
+ memcpy(*data, (uint8_t *)sense10, data_len);
+ *len = data_len;
+ return true;
+}
+
+static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len)
+{
+ if (usbd_msc_cfg.cbw.dDataLength == 0U) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+ uint8_t format_capacity[SCSIRESP_READFORMATCAPACITIES_SIZEOF] = {
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x08, /* Capacity List Length */
+ (uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 24) & 0xff),
+ (uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 16) & 0xff),
+ (uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 8) & 0xff),
+ (uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 0) & 0xff),
+
+ 0x02, /* Descriptor Code: Formatted Media */
+ 0x00,
+ (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 8) & 0xff),
+ (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 0) & 0xff),
+ };
+
+ memcpy(*data, (uint8_t *)format_capacity, SCSIRESP_READFORMATCAPACITIES_SIZEOF);
+ *len = SCSIRESP_READFORMATCAPACITIES_SIZEOF;
+ return true;
+}
+
+static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len)
+{
+ if (usbd_msc_cfg.cbw.dDataLength == 0U) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+
+ uint8_t capacity10[SCSIRESP_READCAPACITY10_SIZEOF] = {
+ (uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 24) & 0xff),
+ (uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 16) & 0xff),
+ (uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 8) & 0xff),
+ (uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 0) & 0xff),
+
+ (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 24) & 0xff),
+ (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 16) & 0xff),
+ (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 8) & 0xff),
+ (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 0) & 0xff),
+ };
+
+ memcpy(*data, (uint8_t *)capacity10, SCSIRESP_READCAPACITY10_SIZEOF);
+ *len = SCSIRESP_READCAPACITY10_SIZEOF;
+ return true;
+}
+
+static bool SCSI_read10(uint8_t **data, uint32_t *len)
+{
+ if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x80U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+
+ usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
+ USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
+
+ usbd_msc_cfg.nsectors = GET_BE16(&usbd_msc_cfg.cbw.CB[7]); /* Number of Blocks to transfer */
+ USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
+
+ if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
+ SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE);
+ USB_LOG_ERR("LBA out of range\r\n");
+ return false;
+ }
+
+ if (usbd_msc_cfg.cbw.dDataLength != (usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size)) {
+ USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
+ return false;
+ }
+ usbd_msc_cfg.stage = MSC_DATA_IN;
+ return SCSI_processRead();
+}
+
+static bool SCSI_read12(uint8_t **data, uint32_t *len)
+{
+ if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x80U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+
+ usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
+ USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
+
+ usbd_msc_cfg.nsectors = GET_BE32(&usbd_msc_cfg.cbw.CB[6]); /* Number of Blocks to transfer */
+ USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
+
+ if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
+ SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE);
+ USB_LOG_ERR("LBA out of range\r\n");
+ return false;
+ }
+
+ if (usbd_msc_cfg.cbw.dDataLength != (usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size)) {
+ USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n");
+ return false;
+ }
+ usbd_msc_cfg.stage = MSC_DATA_IN;
+ return SCSI_processRead();
+}
+
+static bool SCSI_write10(uint8_t **data, uint32_t *len)
+{
+ uint32_t data_len = 0;
+ if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+
+ usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
+ USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
+
+ usbd_msc_cfg.nsectors = GET_BE16(&usbd_msc_cfg.cbw.CB[7]); /* Number of Blocks to transfer */
+ USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
+
+ data_len = usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size;
+ if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
+ USB_LOG_ERR("LBA out of range\r\n");
+ return false;
+ }
+
+ if (usbd_msc_cfg.cbw.dDataLength != data_len) {
+ return false;
+ }
+ usbd_msc_cfg.stage = MSC_DATA_OUT;
+ data_len = MIN(data_len, CONFIG_USBDEV_MSC_BLOCK_SIZE);
+ usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
+ return true;
+}
+
+static bool SCSI_write12(uint8_t **data, uint32_t *len)
+{
+ uint32_t data_len = 0;
+ if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+
+ usbd_msc_cfg.start_sector = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); /* Logical Block Address of First Block */
+ USB_LOG_DBG("lba: 0x%04x\r\n", usbd_msc_cfg.start_sector);
+
+ usbd_msc_cfg.nsectors = GET_BE32(&usbd_msc_cfg.cbw.CB[6]); /* Number of Blocks to transfer */
+ USB_LOG_DBG("nsectors: 0x%02x\r\n", usbd_msc_cfg.nsectors);
+
+ data_len = usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size;
+ if ((usbd_msc_cfg.start_sector + usbd_msc_cfg.nsectors) > usbd_msc_cfg.scsi_blk_nbr) {
+ USB_LOG_ERR("LBA out of range\r\n");
+ return false;
+ }
+
+ if (usbd_msc_cfg.cbw.dDataLength != data_len) {
+ return false;
+ }
+ usbd_msc_cfg.stage = MSC_DATA_OUT;
+ data_len = MIN(data_len, CONFIG_USBDEV_MSC_BLOCK_SIZE);
+ usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
+ return true;
+}
+/* do not use verify to reduce code size */
+#if 0
+static bool SCSI_verify10(uint8_t **data, uint32_t *len)
+{
+ /* Logical Block Address of First Block */
+ uint32_t lba = 0;
+ uint32_t blk_num = 0;
+
+ if ((usbd_msc_cfg.cbw.CB[1] & 0x02U) == 0x00U) {
+ return true;
+ }
+
+ if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+
+ if ((usbd_msc_cfg.cbw.CB[1] & 0x02U) == 0x02U) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDFIELDINCBA);
+ return false; /* Error, Verify Mode Not supported*/
+ }
+
+ lba = GET_BE32(&usbd_msc_cfg.cbw.CB[2]);
+ USB_LOG_DBG("lba: 0x%x\r\n", lba);
+
+ usbd_msc_cfg.scsi_blk_addr = lba * usbd_msc_cfg.scsi_blk_size;
+
+ /* Number of Blocks to transfer */
+ blk_num = GET_BE16(&usbd_msc_cfg.cbw.CB[7]);
+
+ USB_LOG_DBG("num (block) : 0x%x\r\n", blk_num);
+ usbd_msc_cfg.scsi_blk_len = blk_num * usbd_msc_cfg.scsi_blk_size;
+
+ if ((lba + blk_num) > usbd_msc_cfg.scsi_blk_nbr) {
+ USB_LOG_ERR("LBA out of range\r\n");
+ return false;
+ }
+
+ if (usbd_msc_cfg.cbw.dDataLength != usbd_msc_cfg.scsi_blk_len) {
+ return false;
+ }
+
+ usbd_msc_cfg.stage = MSC_DATA_OUT;
+ return true;
+}
+#endif
+
+static bool SCSI_processRead(void)
+{
+ uint32_t transfer_len;
+
+ USB_LOG_DBG("read lba:%d\r\n", usbd_msc_cfg.start_sector);
+
+ transfer_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
+
+ /* Start reading one sector */
+#ifdef CONFIG_USBDEV_MSC_THREAD
+ thread_op = MSC_THREAD_OP_READ_MEM;
+ usb_osal_sem_give(msc_sem);
+ return true;
+#else
+ if (usbd_msc_sector_read(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, transfer_len) != 0) {
+ SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA);
+ return false;
+ }
+#endif
+ usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, transfer_len);
+
+ usbd_msc_cfg.start_sector += (transfer_len / usbd_msc_cfg.scsi_blk_size);
+ usbd_msc_cfg.nsectors -= (transfer_len / usbd_msc_cfg.scsi_blk_size);
+ usbd_msc_cfg.csw.dDataResidue -= transfer_len;
+
+ if (usbd_msc_cfg.nsectors == 0) {
+ usbd_msc_cfg.stage = MSC_SEND_CSW;
+ }
+
+ return true;
+}
+
+#ifdef CONFIG_USBDEV_MSC_THREAD
+static void usbd_msc_thread_memory_read_done(void)
+{
+ size_t flags;
+ uint32_t transfer_len;
+
+ flags = usb_osal_enter_critical_section();
+
+ transfer_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
+
+ usbd_ep_start_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr,
+ usbd_msc_cfg.block_buffer, transfer_len);
+
+ usbd_msc_cfg.start_sector += (transfer_len / usbd_msc_cfg.scsi_blk_size);
+ usbd_msc_cfg.nsectors -= (transfer_len / usbd_msc_cfg.scsi_blk_size);
+ usbd_msc_cfg.csw.dDataResidue -= transfer_len;
+
+ if (usbd_msc_cfg.nsectors == 0) {
+ usbd_msc_cfg.stage = MSC_SEND_CSW;
+ }
+ usb_osal_leave_critical_section(flags);
+}
+#endif
+
+static bool SCSI_processWrite(uint32_t nbytes)
+{
+ uint32_t data_len = 0;
+ USB_LOG_DBG("write lba:%d\r\n", usbd_msc_cfg.start_sector);
+
+ /* Start writing one sector */
+#ifdef CONFIG_USBDEV_MSC_THREAD
+ thread_op = MSC_THREAD_OP_WRITE_MEM;
+ current_byte_read = nbytes;
+ usb_osal_sem_give(msc_sem);
+ return true;
+#else
+ if (usbd_msc_sector_write(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, nbytes) != 0) {
+ SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT);
+ return false;
+ }
+#endif
+
+ usbd_msc_cfg.start_sector += (nbytes / usbd_msc_cfg.scsi_blk_size);
+ usbd_msc_cfg.nsectors -= (nbytes / usbd_msc_cfg.scsi_blk_size);
+ usbd_msc_cfg.csw.dDataResidue -= nbytes;
+
+ if (usbd_msc_cfg.nsectors == 0) {
+ usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
+ } else {
+ data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
+ usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
+ }
+
+ return true;
+}
+
+#ifdef CONFIG_USBDEV_MSC_THREAD
+static void usbd_msc_thread_memory_write_done()
+{
+ size_t flags;
+ uint32_t data_len = 0;
+
+ flags = usb_osal_enter_critical_section();
+
+ usbd_msc_cfg.start_sector += (current_byte_read / usbd_msc_cfg.scsi_blk_size);
+ usbd_msc_cfg.nsectors -= (current_byte_read / usbd_msc_cfg.scsi_blk_size);
+ usbd_msc_cfg.csw.dDataResidue -= current_byte_read;
+
+ if (usbd_msc_cfg.nsectors == 0) {
+ usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
+ } else {
+ data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
+ usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, usbd_msc_cfg.block_buffer, data_len);
+ }
+
+ usb_osal_leave_critical_section(flags);
+}
+#endif
+
+static bool SCSI_CBWDecode(uint32_t nbytes)
+{
+ uint8_t *buf2send = usbd_msc_cfg.block_buffer;
+ uint32_t len2send = 0;
+ bool ret = false;
+
+ if (nbytes != sizeof(struct CBW)) {
+ USB_LOG_ERR("size != sizeof(cbw)\r\n");
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ }
+
+ usbd_msc_cfg.csw.dTag = usbd_msc_cfg.cbw.dTag;
+ usbd_msc_cfg.csw.dDataResidue = usbd_msc_cfg.cbw.dDataLength;
+
+ if ((usbd_msc_cfg.cbw.bLUN > 1) || (usbd_msc_cfg.cbw.dSignature != MSC_CBW_Signature) || (usbd_msc_cfg.cbw.bCBLength < 1) || (usbd_msc_cfg.cbw.bCBLength > 16)) {
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ return false;
+ } else {
+ USB_LOG_DBG("Decode CB:0x%02x\r\n", usbd_msc_cfg.cbw.CB[0]);
+ switch (usbd_msc_cfg.cbw.CB[0]) {
+ case SCSI_CMD_TESTUNITREADY:
+ ret = SCSI_testUnitReady(&buf2send, &len2send);
+ break;
+ case SCSI_CMD_REQUESTSENSE:
+ ret = SCSI_requestSense(&buf2send, &len2send);
+ break;
+ case SCSI_CMD_INQUIRY:
+ ret = SCSI_inquiry(&buf2send, &len2send);
+ break;
+ case SCSI_CMD_STARTSTOPUNIT:
+ ret = SCSI_startStopUnit(&buf2send, &len2send);
+ break;
+ case SCSI_CMD_PREVENTMEDIAREMOVAL:
+ ret = SCSI_preventAllowMediaRemoval(&buf2send, &len2send);
+ break;
+ case SCSI_CMD_MODESENSE6:
+ ret = SCSI_modeSense6(&buf2send, &len2send);
+ break;
+ case SCSI_CMD_MODESENSE10:
+ ret = SCSI_modeSense10(&buf2send, &len2send);
+ break;
+ case SCSI_CMD_READFORMATCAPACITIES:
+ ret = SCSI_readFormatCapacity(&buf2send, &len2send);
+ break;
+ case SCSI_CMD_READCAPACITY10:
+ ret = SCSI_readCapacity10(&buf2send, &len2send);
+ break;
+ case SCSI_CMD_READ10:
+ ret = SCSI_read10(NULL, 0);
+ break;
+ case SCSI_CMD_READ12:
+ ret = SCSI_read12(NULL, 0);
+ break;
+ case SCSI_CMD_WRITE10:
+ ret = SCSI_write10(NULL, 0);
+ break;
+ case SCSI_CMD_WRITE12:
+ ret = SCSI_write12(NULL, 0);
+ break;
+ case SCSI_CMD_VERIFY10:
+ //ret = SCSI_verify10(NULL, 0);
+ ret = false;
+ break;
+
+ default:
+ SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND);
+ USB_LOG_WRN("unsupported cmd:0x%02x\r\n", usbd_msc_cfg.cbw.CB[0]);
+ ret = false;
+ break;
+ }
+ }
+ if (ret) {
+ if (usbd_msc_cfg.stage == MSC_READ_CBW) {
+ if (len2send) {
+ USB_LOG_DBG("Send info len:%d\r\n", len2send);
+ usbd_msc_send_info(buf2send, len2send);
+ } else {
+ usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
+ }
+ }
+ }
+ return ret;
+}
+
+void mass_storage_bulk_out(uint8_t ep, uint32_t nbytes)
+{
+ switch (usbd_msc_cfg.stage) {
+ case MSC_READ_CBW:
+ if (SCSI_CBWDecode(nbytes) == false) {
+ USB_LOG_ERR("Command:0x%02x decode err\r\n", usbd_msc_cfg.cbw.CB[0]);
+ usbd_msc_bot_abort();
+ return;
+ }
+ break;
+ case MSC_DATA_OUT:
+ switch (usbd_msc_cfg.cbw.CB[0]) {
+ case SCSI_CMD_WRITE10:
+ case SCSI_CMD_WRITE12:
+ if (SCSI_processWrite(nbytes) == false) {
+ usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void mass_storage_bulk_in(uint8_t ep, uint32_t nbytes)
+{
+ switch (usbd_msc_cfg.stage) {
+ case MSC_DATA_IN:
+ switch (usbd_msc_cfg.cbw.CB[0]) {
+ case SCSI_CMD_READ10:
+ case SCSI_CMD_READ12:
+ if (SCSI_processRead() == false) {
+ usbd_msc_send_csw(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ /*the device has to send a CSW*/
+ case MSC_SEND_CSW:
+ usbd_msc_send_csw(CSW_STATUS_CMD_PASSED);
+ break;
+
+ /*the host has received the CSW*/
+ case MSC_WAIT_CSW:
+ usbd_msc_cfg.stage = MSC_READ_CBW;
+ USB_LOG_DBG("Start reading cbw\r\n");
+ usbd_ep_start_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW);
+ break;
+
+ default:
+ break;
+ }
+}
+
+#ifdef CONFIG_USBDEV_MSC_THREAD
+static void usbd_msc_thread(void *argument)
+{
+ uint32_t data_len = 0;
+ while (1) {
+ usb_osal_sem_take(msc_sem, 0xffffffff);
+
+ switch (thread_op) {
+ case MSC_THREAD_OP_READ_MEM:
+ data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
+ if (usbd_msc_sector_read(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, data_len) != 0) {
+ SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA);
+ }
+ usbd_msc_thread_memory_read_done();
+ break;
+ case MSC_THREAD_OP_WRITE_MEM:
+ data_len = MIN(usbd_msc_cfg.nsectors * usbd_msc_cfg.scsi_blk_size, CONFIG_USBDEV_MSC_BLOCK_SIZE);
+ if (usbd_msc_sector_write(usbd_msc_cfg.start_sector, usbd_msc_cfg.block_buffer, data_len) != 0) {
+ SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT);
+ }
+ usbd_msc_thread_memory_write_done();
+ break;
+ default:
+ break;
+ }
+ }
+}
+#endif
+
+struct usbd_interface *usbd_msc_alloc_intf(const uint8_t out_ep, const uint8_t in_ep)
+{
+ struct usbd_interface *intf = usb_malloc(sizeof(struct usbd_interface));
+ if (intf == NULL) {
+ USB_LOG_ERR("no mem to alloc intf\r\n");
+ return NULL;
+ }
+
+ intf->class_interface_handler = msc_storage_class_interface_request_handler;
+ intf->class_endpoint_handler = NULL;
+ intf->vendor_handler = NULL;
+ intf->notify_handler = msc_storage_notify_handler;
+
+ mass_ep_data[MSD_OUT_EP_IDX].ep_addr = out_ep;
+ mass_ep_data[MSD_OUT_EP_IDX].ep_cb = mass_storage_bulk_out;
+ mass_ep_data[MSD_IN_EP_IDX].ep_addr = in_ep;
+ mass_ep_data[MSD_IN_EP_IDX].ep_cb = mass_storage_bulk_in;
+
+ usbd_add_endpoint(&mass_ep_data[MSD_OUT_EP_IDX]);
+ usbd_add_endpoint(&mass_ep_data[MSD_IN_EP_IDX]);
+
+ memset((uint8_t *)&usbd_msc_cfg, 0, sizeof(struct usbd_msc_cfg_priv));
+
+ usbd_msc_get_cap(0, &usbd_msc_cfg.scsi_blk_nbr, &usbd_msc_cfg.scsi_blk_size);
+
+ if (usbd_msc_cfg.scsi_blk_size > CONFIG_USBDEV_MSC_BLOCK_SIZE) {
+ USB_LOG_ERR("msc block buffer overflow\r\n");
+ return NULL;
+ }
+#ifdef CONFIG_USBDEV_MSC_THREAD
+ msc_sem = usb_osal_sem_create(1);
+ msc_thread = usb_osal_thread_create("usbd_msc", CONFIG_USBDEV_MSC_STACKSIZE, CONFIG_USBDEV_MSC_PRIO, usbd_msc_thread, NULL);
+ if (msc_thread == NULL) {
+ USB_LOG_ERR("no enough memory to alloc msc thread\r\n");
+ return NULL;
+ }
+#endif
+
+ return intf;
+}
+
+void usbd_msc_set_readonly(bool readonly)
+{
+ usbd_msc_cfg.readonly = readonly;
+}
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/class/msc/usbd_msc.h b/third-party/cherryusb-0.6.0/class/msc/usbd_msc.h
new file mode 100644
index 0000000000000000000000000000000000000000..53ec4692164c200fc3666ee01485e9ae0924a97c
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/msc/usbd_msc.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBD_MSC_H
+#define USBD_MSC_H
+
+#include "usb_msc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Alloc msc interface driver */
+struct usbd_interface *usbd_msc_alloc_intf(const uint8_t out_ep, const uint8_t in_ep);
+
+void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
+int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length);
+int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length);
+
+void usbd_msc_set_readonly(bool readonly);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBD_MSC_H */
diff --git a/third-party/cherryusb-0.6.0/class/msc/usbh_msc.c b/third-party/cherryusb-0.6.0/class/msc/usbh_msc.c
new file mode 100644
index 0000000000000000000000000000000000000000..2f77a067d3b7e7eee6b7c7f5f170e39aab89f861
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/msc/usbh_msc.c
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbh_core.h"
+#include "usbh_msc.h"
+#include "usb_scsi.h"
+
+#define DEV_FORMAT "/dev/sd%c"
+
+static uint32_t g_devinuse = 0;
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_msc_buf[32];
+
+static int usbh_msc_devno_alloc(struct usbh_msc *msc_class)
+{
+ int devno;
+
+ for (devno = 0; devno < 26; devno++) {
+ uint32_t bitno = 1 << devno;
+ if ((g_devinuse & bitno) == 0) {
+ g_devinuse |= bitno;
+ msc_class->sdchar = 'a' + devno;
+ return 0;
+ }
+ }
+
+ return -EMFILE;
+}
+
+static void usbh_msc_devno_free(struct usbh_msc *msc_class)
+{
+ int devno = msc_class->sdchar - 'a';
+
+ if (devno >= 0 && devno < 26) {
+ g_devinuse &= ~(1 << devno);
+ }
+}
+
+static int usbh_msc_get_maxlun(struct usbh_msc *msc_class, uint8_t *buffer)
+{
+ struct usb_setup_packet *setup = &msc_class->hport->setup;
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = MSC_REQUEST_GET_MAX_LUN;
+ setup->wValue = 0;
+ setup->wIndex = msc_class->intf;
+ setup->wLength = 1;
+
+ return usbh_control_transfer(msc_class->hport->ep0, setup, buffer);
+}
+
+static void usbh_msc_cbw_dump(struct CBW *cbw)
+{
+#if 0
+ int i;
+
+ USB_LOG_INFO("CBW:\r\n");
+ USB_LOG_INFO(" signature: 0x%08x\r\n", (unsigned int)cbw->dSignature);
+ USB_LOG_INFO(" tag: 0x%08x\r\n", (unsigned int)cbw->dTag);
+ USB_LOG_INFO(" datlen: 0x%08x\r\n", (unsigned int)cbw->dDataLength);
+ USB_LOG_INFO(" flags: 0x%02x\r\n", cbw->bmFlags);
+ USB_LOG_INFO(" lun: 0x%02x\r\n", cbw->bLUN);
+ USB_LOG_INFO(" cblen: 0x%02x\r\n", cbw->bCBLength);
+
+ USB_LOG_INFO("CB:\r\n");
+ for (i = 0; i < cbw->bCBLength; i += 8) {
+ USB_LOG_INFO(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\r\n",
+ cbw->CB[i], cbw->CB[i + 1], cbw->CB[i + 2],
+ cbw->CB[i + 3], cbw->CB[i + 4], cbw->CB[i + 5],
+ cbw->CB[i + 6], cbw->CB[i + 7]);
+ }
+#endif
+}
+
+static void usbh_msc_csw_dump(struct CSW *csw)
+{
+#if 0
+ USB_LOG_INFO("CSW:\r\n");
+ USB_LOG_INFO(" signature: 0x%08x\r\n", (unsigned int)csw->dSignature);
+ USB_LOG_INFO(" tag: 0x%08x\r\n", (unsigned int)csw->dTag);
+ USB_LOG_INFO(" residue: 0x%08x\r\n", (unsigned int)csw->dDataResidue);
+ USB_LOG_INFO(" status: 0x%02x\r\n", csw->bStatus);
+#endif
+}
+
+static inline int usbh_msc_bulk_in_transfer(struct usbh_msc *msc_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
+{
+ int ret;
+ struct usbh_urb *urb = &msc_class->bulkin_urb;
+ memset(urb, 0, sizeof(struct usbh_urb));
+
+ usbh_bulk_urb_fill(urb, msc_class->bulkin, buffer, buflen, timeout, NULL, NULL);
+ ret = usbh_submit_urb(urb);
+ if (ret == 0) {
+ ret = urb->actual_length;
+ }
+ return ret;
+}
+
+static inline int usbh_msc_bulk_out_transfer(struct usbh_msc *msc_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout)
+{
+ int ret;
+ struct usbh_urb *urb = &msc_class->bulkout_urb;
+ memset(urb, 0, sizeof(struct usbh_urb));
+
+ usbh_bulk_urb_fill(urb, msc_class->bulkout, buffer, buflen, timeout, NULL, NULL);
+ ret = usbh_submit_urb(urb);
+ if (ret == 0) {
+ ret = urb->actual_length;
+ }
+ return ret;
+}
+
+static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class)
+{
+ int nbytes;
+ struct CBW *cbw;
+
+ /* Construct the CBW */
+ cbw = (struct CBW *)g_msc_buf;
+ memset(cbw, 0, USB_SIZEOF_MSC_CBW);
+ cbw->dSignature = MSC_CBW_Signature;
+
+ cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF;
+ cbw->CB[0] = SCSI_CMD_TESTUNITREADY;
+
+ usbh_msc_cbw_dump(cbw);
+ /* Send the CBW */
+ nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ /* Receive the CSW */
+ nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ usbh_msc_csw_dump((struct CSW *)g_msc_buf);
+ }
+ }
+ return nbytes < 0 ? (int)nbytes : 0;
+}
+
+static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class)
+{
+ int nbytes;
+ struct CBW *cbw;
+
+ /* Construct the CBW */
+ cbw = (struct CBW *)g_msc_buf;
+ memset(cbw, 0, USB_SIZEOF_MSC_CBW);
+ cbw->dSignature = MSC_CBW_Signature;
+
+ cbw->bmFlags = 0x80;
+ cbw->bCBLength = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
+ cbw->dDataLength = SCSICMD_REQUESTSENSE_SIZEOF;
+ cbw->CB[0] = SCSI_CMD_REQUESTSENSE;
+ cbw->CB[4] = SCSIRESP_FIXEDSENSEDATA_SIZEOF;
+
+ usbh_msc_cbw_dump(cbw);
+ /* Send the CBW */
+ nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ /* Receive the sense data response */
+ nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, SCSIRESP_FIXEDSENSEDATA_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ /* Receive the CSW */
+ nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ usbh_msc_csw_dump((struct CSW *)g_msc_buf);
+ }
+ }
+ }
+ return nbytes < 0 ? (int)nbytes : 0;
+}
+
+static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class)
+{
+ int nbytes;
+ struct CBW *cbw;
+
+ /* Construct the CBW */
+ cbw = (struct CBW *)g_msc_buf;
+ memset(cbw, 0, USB_SIZEOF_MSC_CBW);
+ cbw->dSignature = MSC_CBW_Signature;
+
+ cbw->dDataLength = SCSIRESP_INQUIRY_SIZEOF;
+ cbw->bmFlags = 0x80;
+ cbw->bCBLength = SCSICMD_INQUIRY_SIZEOF;
+ cbw->CB[0] = SCSI_CMD_INQUIRY;
+ cbw->CB[4] = SCSIRESP_INQUIRY_SIZEOF;
+
+ usbh_msc_cbw_dump(cbw);
+ /* Send the CBW */
+ nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ /* Receive the sense data response */
+ nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, SCSIRESP_INQUIRY_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ /* Receive the CSW */
+ nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ usbh_msc_csw_dump((struct CSW *)g_msc_buf);
+ }
+ }
+ }
+ return nbytes < 0 ? (int)nbytes : 0;
+}
+
+static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class)
+{
+ int nbytes;
+ struct CBW *cbw;
+
+ /* Construct the CBW */
+ cbw = (struct CBW *)g_msc_buf;
+ memset(cbw, 0, USB_SIZEOF_MSC_CBW);
+ cbw->dSignature = MSC_CBW_Signature;
+
+ cbw->dDataLength = SCSIRESP_READCAPACITY10_SIZEOF;
+ cbw->bmFlags = 0x80;
+ cbw->bCBLength = SCSICMD_READCAPACITY10_SIZEOF;
+ cbw->CB[0] = SCSI_CMD_READCAPACITY10;
+
+ usbh_msc_cbw_dump(cbw);
+ /* Send the CBW */
+ nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ /* Receive the sense data response */
+ nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, SCSIRESP_READCAPACITY10_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ /* Save the capacity information */
+ msc_class->blocknum = GET_BE32(&g_msc_buf[0]) + 1;
+ msc_class->blocksize = GET_BE32(&g_msc_buf[4]);
+ /* Receive the CSW */
+ nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ usbh_msc_csw_dump((struct CSW *)g_msc_buf);
+ }
+ }
+ }
+ return nbytes < 0 ? (int)nbytes : 0;
+}
+
+int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
+{
+ int nbytes;
+ struct CBW *cbw;
+
+ /* Construct the CBW */
+ cbw = (struct CBW *)g_msc_buf;
+ memset(cbw, 0, USB_SIZEOF_MSC_CBW);
+ cbw->dSignature = MSC_CBW_Signature;
+
+ cbw->dDataLength = (msc_class->blocksize * nsectors);
+ cbw->bCBLength = SCSICMD_WRITE10_SIZEOF;
+ cbw->CB[0] = SCSI_CMD_WRITE10;
+
+ SET_BE32(&cbw->CB[2], start_sector);
+ SET_BE16(&cbw->CB[7], nsectors);
+
+ usbh_msc_cbw_dump(cbw);
+ /* Send the CBW */
+ nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ /* Send the user data */
+ nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ /* Receive the CSW */
+ nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ usbh_msc_csw_dump((struct CSW *)g_msc_buf);
+ }
+ }
+ }
+ return nbytes < 0 ? (int)nbytes : 0;
+}
+
+int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors)
+{
+ int nbytes;
+ struct CBW *cbw;
+
+ /* Construct the CBW */
+ cbw = (struct CBW *)g_msc_buf;
+ memset(cbw, 0, USB_SIZEOF_MSC_CBW);
+ cbw->dSignature = MSC_CBW_Signature;
+
+ cbw->dDataLength = (msc_class->blocksize * nsectors);
+ cbw->bmFlags = 0x80;
+ cbw->bCBLength = SCSICMD_READ10_SIZEOF;
+ cbw->CB[0] = SCSI_CMD_READ10;
+
+ SET_BE32(&cbw->CB[2], start_sector);
+ SET_BE16(&cbw->CB[7], nsectors);
+
+ usbh_msc_cbw_dump(cbw);
+ /* Send the CBW */
+ nbytes = usbh_msc_bulk_out_transfer(msc_class, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ /* Receive the user data */
+ nbytes = usbh_msc_bulk_in_transfer(msc_class, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ /* Receive the CSW */
+ nbytes = usbh_msc_bulk_in_transfer(msc_class, g_msc_buf, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
+ if (nbytes >= 0) {
+ usbh_msc_csw_dump((struct CSW *)g_msc_buf);
+ }
+ }
+ }
+ return nbytes < 0 ? (int)nbytes : 0;
+}
+
+static int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf)
+{
+ struct usb_endpoint_descriptor *ep_desc;
+ int ret;
+
+ struct usbh_msc *msc_class = usb_malloc(sizeof(struct usbh_msc));
+ if (msc_class == NULL) {
+ USB_LOG_ERR("Fail to alloc msc_class\r\n");
+ return -ENOMEM;
+ }
+
+ memset(msc_class, 0, sizeof(struct usbh_msc));
+ usbh_msc_devno_alloc(msc_class);
+ msc_class->hport = hport;
+ msc_class->intf = intf;
+
+ hport->config.intf[intf].priv = msc_class;
+
+ ret = usbh_msc_get_maxlun(msc_class, g_msc_buf);
+ if (ret < 0) {
+ return ret;
+ }
+
+ USB_LOG_INFO("Get max LUN:%u\r\n", g_msc_buf[0] + 1);
+
+ 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_hport_activate_epx(&msc_class->bulkin, hport, ep_desc);
+ } else {
+ usbh_hport_activate_epx(&msc_class->bulkout, hport, ep_desc);
+ }
+ }
+
+ ret = usbh_msc_scsi_testunitready(msc_class);
+ if (ret < 0) {
+ USB_LOG_ERR("Fail to scsi_testunitready\r\n");
+ return ret;
+ }
+ ret = usbh_msc_scsi_inquiry(msc_class);
+ if (ret < 0) {
+ USB_LOG_ERR("Fail to scsi_inquiry\r\n");
+ return ret;
+ }
+ ret = usbh_msc_scsi_readcapacity10(msc_class);
+ if (ret < 0) {
+ USB_LOG_ERR("Fail to scsi_readcapacity10\r\n");
+ return ret;
+ }
+
+ if (msc_class->blocksize > 0) {
+ USB_LOG_INFO("Capacity info:\r\n");
+ USB_LOG_INFO("Block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize);
+ } else {
+ USB_LOG_ERR("Invalid block size\r\n");
+ return -ERANGE;
+ }
+
+ snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
+
+ USB_LOG_INFO("Register MSC Class:%s\r\n", hport->config.intf[intf].devname);
+
+ return ret;
+}
+
+static int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf)
+{
+ int ret = 0;
+
+ struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv;
+
+ if (msc_class) {
+ usbh_msc_devno_free(msc_class);
+
+ if (msc_class->bulkin) {
+ usbh_pipe_free(msc_class->bulkin);
+ }
+
+ if (msc_class->bulkout) {
+ usbh_pipe_free(msc_class->bulkout);
+ }
+
+ memset(msc_class, 0, sizeof(struct usbh_msc));
+ usb_free(msc_class);
+
+ if (hport->config.intf[intf].devname[0] != '\0'){
+ USB_LOG_INFO("Unregister MSC Class:%s\r\n", hport->config.intf[intf].devname);
+ }
+ }
+
+ return ret;
+}
+
+const struct usbh_class_driver msc_class_driver = {
+ .driver_name = "msc",
+ .connect = usbh_msc_connect,
+ .disconnect = usbh_msc_disconnect
+};
+
+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,
+ .vid = 0x00,
+ .pid = 0x00,
+ .class_driver = &msc_class_driver
+};
diff --git a/third-party/cherryusb-0.6.0/class/msc/usbh_msc.h b/third-party/cherryusb-0.6.0/class/msc/usbh_msc.h
new file mode 100644
index 0000000000000000000000000000000000000000..5a61de7d0e8efa397414dcf3d5e1b65e89251828
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/msc/usbh_msc.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBH_MSC_H
+#define USBH_MSC_H
+
+#include "usb_msc.h"
+#include "usb_scsi.h"
+
+struct usbh_msc {
+ struct usbh_hubport *hport;
+
+ uint8_t intf; /* Data interface number */
+ uint8_t sdchar;
+ usbh_pipe_t bulkin; /* Bulk IN endpoint */
+ usbh_pipe_t bulkout; /* Bulk OUT endpoint */
+ struct usbh_urb bulkin_urb; /* Bulk IN urb */
+ struct usbh_urb bulkout_urb; /* Bulk OUT urb */
+ uint32_t blocknum; /* Number of blocks on the USB mass storage device */
+ uint16_t blocksize; /* Block size of USB mass storage device */
+};
+
+int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
+int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, const uint8_t *buffer, uint32_t nsectors);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBH_MSC_H */
diff --git a/third-party/cherryusb-0.6.0/class/template/usb_xxx.h b/third-party/cherryusb-0.6.0/class/template/usb_xxx.h
new file mode 100644
index 0000000000000000000000000000000000000000..d883c8b2e23a4e1ca178828927ccca908bfb9a16
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/template/usb_xxx.h
@@ -0,0 +1,4 @@
+#ifndef _USB_XXX_H
+#define _USB_XXX_H
+
+#endif
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/class/template/usbd_xxx.c b/third-party/cherryusb-0.6.0/class/template/usbd_xxx.c
new file mode 100644
index 0000000000000000000000000000000000000000..f35911c55426506749ea5732bd403273b3c7e632
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/template/usbd_xxx.c
@@ -0,0 +1,39 @@
+#include "usbd_core.h"
+#include "usbd_xxx.h"
+
+static int xxx_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ USB_LOG_WRN("XXX Class request: "
+ "bRequest 0x%02x\r\n",
+ setup->bRequest);
+
+ switch (setup->bRequest) {
+ default:
+ USB_LOG_WRN("Unhandled XXX Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void xxx_notify_handler(uint8_t event, void *arg)
+{
+ switch (event) {
+ case USBD_EVENT_RESET:
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+void usbd_xxx_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
+{
+ intf->class_interface_handler = xxx_class_interface_request_handler;
+ intf->class_endpoint_handler = NULL;
+ intf->vendor_handler = NULL;
+ intf->notify_handler = xxx_notify_handler;
+
+ usbd_class_add_interface(devclass, intf);
+}
diff --git a/third-party/cherryusb-0.6.0/class/template/usbd_xxx.h b/third-party/cherryusb-0.6.0/class/template/usbd_xxx.h
new file mode 100644
index 0000000000000000000000000000000000000000..26f4b279d37ca33cb53b1320d45f452f47798413
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/template/usbd_xxx.h
@@ -0,0 +1,16 @@
+#ifndef _USBD_XXX_H_
+#define _USBD_XXX_H_
+
+#include "usb_xxx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void usbd_xxx_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _USBD_XXX_H_ */
diff --git a/third-party/cherryusb-0.6.0/class/template/usbh_xxx.c b/third-party/cherryusb-0.6.0/class/template/usbh_xxx.c
new file mode 100644
index 0000000000000000000000000000000000000000..4726a11788c7df5f3b11895ddd385d694ce1f4c3
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/template/usbh_xxx.c
@@ -0,0 +1,87 @@
+#include "usbh_core.h"
+#include "usbh_xxx.h"
+
+#define DEV_FORMAT "/dev/xxx"
+
+static int usbh_xxx_connect(struct usbh_hubport *hport, uint8_t intf)
+{
+ struct usbh_endpoint_cfg ep_cfg = { 0 };
+ struct usb_endpoint_descriptor *ep_desc;
+ int ret;
+
+ struct usbh_xxx *xxx_class = usb_malloc(sizeof(struct usbh_xxx));
+ if (xxx_class == NULL) {
+ USB_LOG_ERR("Fail to alloc xxx_class\r\n");
+ return -ENOMEM;
+ }
+
+ memset(xxx_class, 0, sizeof(struct usbh_xxx));
+
+ xxx_class->hport = hport;
+ xxx_class->intf = intf;
+
+ hport->config.intf[intf].priv = xxx_class;
+ strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
+
+ for (uint8_t i = 0; i < hport->config.intf[intf + 1].intf_desc.bNumEndpoints; i++) {
+ ep_desc = &hport->config.intf[intf + 1].ep[i].ep_desc;
+
+ ep_cfg.ep_addr = ep_desc->bEndpointAddress;
+ ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
+ ep_cfg.ep_mps = ep_desc->wMaxPacketSize;
+ ep_cfg.ep_interval = ep_desc->bInterval;
+ ep_cfg.hport = hport;
+ if (ep_desc->bEndpointAddress & 0x80) {
+ usbh_pipe_alloc(&rndis_class->bulkin, &ep_cfg);
+ } else {
+ usbh_pipe_alloc(&rndis_class->bulkout, &ep_cfg);
+ }
+ }
+
+ return ret;
+
+}
+
+
+static int usbh_xxx_disconnect(struct usbh_hubport *hport, uint8_t intf)
+{
+ int ret = 0;
+
+ struct usbh_xxx *xxx_class = (struct usbh_xxx *)hport->config.intf[intf].priv;
+
+ if (xxx_class) {
+ if (xxx_class->bulkin) {
+ usbh_pipe_free(xxx_class->bulkin);
+ }
+
+ if (xxx_class->bulkout) {
+ usbh_pipe_free(xxx_class->bulkout);
+ }
+
+ usb_free(xxx_class);
+
+ USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname);
+ memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN);
+
+ hport->config.intf[intf].priv = NULL;
+ }
+
+ return ret;
+}
+
+
+static const struct usbh_class_driver xxx_class_driver = {
+ .driver_name = "xxx",
+ .connect = usbh_xxx_connect,
+ .disconnect = usbh_xxx_disconnect
+};
+
+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,
+ .vid = 0x00,
+ .pid = 0x00,
+ .class_driver = &xxx_class_driver
+};
diff --git a/third-party/cherryusb-0.6.0/class/template/usbh_xxx.h b/third-party/cherryusb-0.6.0/class/template/usbh_xxx.h
new file mode 100644
index 0000000000000000000000000000000000000000..3bcb6991925b7e340a9812ce2dc4af9887f3b4f5
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/template/usbh_xxx.h
@@ -0,0 +1,14 @@
+#ifndef _USBH_XXX_H
+#define _USBH_XXX_H
+
+#include "usb_xxx.h"
+
+struct usbh_xxx {
+ struct usbh_hubport *hport;
+
+ uint8_t intf; /* interface number */
+ usbh_pipe_t intin; /* INTR IN endpoint */
+ usbh_pipe_t intout; /* INTR OUT endpoint */
+};
+
+#endif
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/class/video/usb_video.h b/third-party/cherryusb-0.6.0/class/video/usb_video.h
new file mode 100644
index 0000000000000000000000000000000000000000..4997526baab2355d201aa756c4aac683b1247202
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/video/usb_video.h
@@ -0,0 +1,1198 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_VIDEO_H
+#define USB_VIDEO_H
+
+#define USB_DEVICE_VIDEO_CLASS_VERSION_1_5 0
+
+/*! @brief Video device subclass code */
+#define VIDEO_SC_UNDEFINED 0x00U
+#define VIDEO_SC_VIDEOCONTROL 0x01U
+#define VIDEO_SC_VIDEOSTREAMING 0x02U
+#define VIDEO_SC_VIDEO_INTERFACE_COLLECTION 0x03U
+
+/*! @brief Video device protocol code */
+#define VIDEO_PC_PROTOCOL_UNDEFINED 0x00U
+#define VIDEO_PC_PROTOCOL_15 0x01U
+
+/*! @brief Video device class-specific descriptor type */
+#define VIDEO_CS_UNDEFINED_DESCRIPTOR_TYPE 0x20U
+#define VIDEO_CS_DEVICE_DESCRIPTOR_TYPE 0x21U
+#define VIDEO_CS_CONFIGURATION_DESCRIPTOR_TYPE 0x22U
+#define VIDEO_CS_STRING_DESCRIPTOR_TYPE 0x23U
+#define VIDEO_CS_INTERFACE_DESCRIPTOR_TYPE 0x24U
+#define VIDEO_CS_ENDPOINT_DESCRIPTOR_TYPE 0x25U
+
+/*! @brief Video device class-specific VC interface descriptor subtype */
+#define VIDEO_VC_DESCRIPTOR_UNDEFINED_DESCRIPTOR_SUBTYPE 0x00U
+#define VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE 0x01U
+#define VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE 0x02U
+#define VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE 0x03U
+#define VIDEO_VC_SELECTOR_UNIT_DESCRIPTOR_SUBTYPE 0x04U
+#define VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE 0x05U
+#define VIDEO_VC_EXTENSION_UNIT_DESCRIPTOR_SUBTYPE 0x06U
+#define VIDEO_VC_ENCODING_UNIT_DESCRIPTOR_SUBTYPE 0x07U
+
+/*! @brief Video device class-specific VS interface descriptor subtype */
+#define VIDEO_VS_UNDEFINED_DESCRIPTOR_SUBTYPE 0x00U
+#define VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE 0x01U
+#define VIDEO_VS_OUTPUT_HEADER_DESCRIPTOR_SUBTYPE 0x02U
+#define VIDEO_VS_STILL_IMAGE_FRAME_DESCRIPTOR_SUBTYPE 0x03U
+#define VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_SUBTYPE 0x04U
+#define VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE 0x05U
+#define VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_SUBTYPE 0x06U
+#define VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE 0x07U
+#define VIDEO_VS_FORMAT_MPEG2TS_DESCRIPTOR_SUBTYPE 0x0AU
+#define VIDEO_VS_FORMAT_DV_DESCRIPTOR_SUBTYPE 0x0CU
+#define VIDEO_VS_COLORFORMAT_DESCRIPTOR_SUBTYPE 0x0DU
+#define VIDEO_VS_FORMAT_FRAME_BASED_DESCRIPTOR_SUBTYPE 0x10U
+#define VIDEO_VS_FRAME_FRAME_BASED_DESCRIPTOR_SUBTYPE 0x11U
+#define VIDEO_VS_FORMAT_STREAM_BASED_DESCRIPTOR_SUBTYPE 0x12U
+#define VIDEO_VS_FORMAT_H264_DESCRIPTOR_SUBTYPE 0x13U
+#define VIDEO_VS_FRAME_H264_DESCRIPTOR_SUBTYPE 0x14U
+#define VIDEO_VS_FORMAT_H264_SIMULCAST_DESCRIPTOR_SUBTYPE 0x15U
+#define VIDEO_VS_FORMAT_VP8_DESCRIPTOR_SUBTYPE 0x16U
+#define VIDEO_VS_FRAME_VP8_DESCRIPTOR_SUBTYPE 0x17U
+#define VIDEO_VS_FORMAT_VP8_SIMULCAST_DESCRIPTOR_SUBTYPE 0x18U
+
+/*! @brief Video device class-specific VC endpoint descriptor subtype */
+#define VIDEO_EP_UNDEFINED_DESCRIPTOR_SUBTYPE 0x00U
+#define VIDEO_EP_GENERAL_DESCRIPTOR_SUBTYPE 0x01U
+#define VIDEO_EP_ENDPOINT_DESCRIPTOR_SUBTYPE 0x02U
+#define VIDEO_EP_INTERRUPT_DESCRIPTOR_SUBTYPE 0x03U
+
+/*! @brief Video device class-specific request code */
+#define VIDEO_REQUEST_UNDEFINED 0x00U
+#define VIDEO_REQUEST_SET_CUR 0x01U
+#define VIDEO_REQUEST_SET_CUR_ALL 0x11U
+#define VIDEO_REQUEST_GET_CUR 0x81U
+#define VIDEO_REQUEST_GET_MIN 0x82U
+#define VIDEO_REQUEST_GET_MAX 0x83U
+#define VIDEO_REQUEST_GET_RES 0x84U
+#define VIDEO_REQUEST_GET_LEN 0x85U
+#define VIDEO_REQUEST_GET_INFO 0x86U
+#define VIDEO_REQUEST_GET_DEF 0x87U
+#define VIDEO_REQUEST_GET_CUR_ALL 0x91U
+#define VIDEO_REQUEST_GET_MIN_ALL 0x92U
+#define VIDEO_REQUEST_GET_MAX_ALL 0x93U
+#define VIDEO_REQUEST_GET_RES_ALL 0x94U
+#define VIDEO_REQUEST_GET_DEF_ALL 0x97U
+
+/*! @brief Video device class-specific VideoControl interface control selector */
+#define VIDEO_VC_CONTROL_UNDEFINED 0x00U
+#define VIDEO_VC_VIDEO_POWER_MODE_CONTROL 0x01U
+#define VIDEO_VC_REQUEST_ERROR_CODE_CONTROL 0x02U
+
+/*! @brief Video device class-specific Terminal control selector */
+#define VIDEO_TE_CONTROL_UNDEFINED 0x00U
+
+/*! @brief Video device class-specific Selector Unit control selector */
+#define VIDEO_SU_CONTROL_UNDEFINED 0x00U
+#define VIDEO_SU_INPUT_SELECT_CONTROL 0x01U
+
+/*! @brief Video device class-specific Camera Terminal control selector */
+#define VIDEO_CT_CONTROL_UNDEFINED 0x00U
+#define VIDEO_CT_SCANNING_MODE_CONTROL 0x01U
+#define VIDEO_CT_AE_MODE_CONTROL 0x02U
+#define VIDEO_CT_AE_PRIORITY_CONTROL 0x03U
+#define VIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04U
+#define VIDEO_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05U
+#define VIDEO_CT_FOCUS_ABSOLUTE_CONTROL 0x06U
+#define VIDEO_CT_FOCUS_RELATIVE_CONTROL 0x07U
+#define VIDEO_CT_FOCUS_AUTO_CONTROL 0x08U
+#define VIDEO_CT_IRIS_ABSOLUTE_CONTROL 0x09U
+#define VIDEO_CT_IRIS_RELATIVE_CONTROL 0x0AU
+#define VIDEO_CT_ZOOM_ABSOLUTE_CONTROL 0x0BU
+#define VIDEO_CT_ZOOM_RELATIVE_CONTROL 0x0CU
+#define VIDEO_CT_PANTILT_ABSOLUTE_CONTROL 0x0DU
+#define VIDEO_CT_PANTILT_RELATIVE_CONTROL 0x0EU
+#define VIDEO_CT_ROLL_ABSOLUTE_CONTROL 0x0FU
+#define VIDEO_CT_ROLL_RELATIVE_CONTROL 0x10U
+#define VIDEO_CT_PRIVACY_CONTROL 0x11U
+#define VIDEO_CT_FOCUS_SIMPLE_CONTROL 0x12U
+#define VIDEO_CT_WINDOW_CONTROL 0x13U
+#define VIDEO_CT_REGION_OF_INTEREST_CONTROL 0x14U
+
+/*! @brief Video device class-specific Processing Unit control selector */
+#define VIDEO_PU_CONTROL_UNDEFINED 0x00U
+#define VIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL 0x01U
+#define VIDEO_PU_BRIGHTNESS_CONTROL 0x02U
+#define VIDEO_PU_CONTRAST_CONTROL 0x03U
+#define VIDEO_PU_GAIN_CONTROL 0x04U
+#define VIDEO_PU_POWER_LINE_FREQUENCY_CONTROL 0x05U
+#define VIDEO_PU_HUE_CONTROL 0x06U
+#define VIDEO_PU_SATURATION_CONTROL 0x07U
+#define VIDEO_PU_SHARPNESS_CONTROL 0x08U
+#define VIDEO_PU_GAMMA_CONTROL 0x09U
+#define VIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0AU
+#define VIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0BU
+#define VIDEO_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0CU
+#define VIDEO_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0DU
+#define VIDEO_PU_DIGITAL_MULTIPLIER_CONTROL 0x0EU
+#define VIDEO_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0FU
+#define VIDEO_PU_HUE_AUTO_CONTROL 0x10U
+#define VIDEO_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11U
+#define VIDEO_PU_ANALOG_LOCK_STATUS_CONTROL 0x12U
+#define VIDEO_PU_CONTRAST_AUTO_CONTROL 0x13U
+
+/*! @brief Video device class-specific Encoding Unit control selector */
+#define VIDEO_EU_CONTROL_UNDEFINED 0x00U
+#define VIDEO_EU_SELECT_LAYER_CONTROL 0x01U
+#define VIDEO_EU_PROFILE_TOOLSET_CONTROL 0x02U
+#define VIDEO_EU_VIDEO_RESOLUTION_CONTROL 0x03U
+#define VIDEO_EU_MIN_FRAME_INTERVAL_CONTROL 0x04U
+#define VIDEO_EU_SLICE_MODE_CONTROL 0x05U
+#define VIDEO_EU_RATE_CONTROL_MODE_CONTROL 0x06U
+#define VIDEO_EU_AVERAGE_BITRATE_CONTROL 0x07U
+#define VIDEO_EU_CPB_SIZE_CONTROL 0x08U
+#define VIDEO_EU_PEAK_BIT_RATE_CONTROL 0x09U
+#define VIDEO_EU_QUANTIZATION_PARAMS_CONTROL 0x0AU
+#define VIDEO_EU_SYNC_REF_FRAME_CONTROL 0x0BU
+#define VIDEO_EU_LTR_BUFFER_CONTROL 0x0CU
+#define VIDEO_EU_LTR_PICTURE_CONTROL 0x0DU
+#define VIDEO_EU_LTR_VALIDATION_CONTROL 0x0EU
+#define VIDEO_EU_LEVEL_IDC_LIMIT_CONTROL 0x0FU
+#define VIDEO_EU_SEI_PAYLOADTYPE_CONTROL 0x10U
+#define VIDEO_EU_QP_RANGE_CONTROL 0x11U
+#define VIDEO_EU_PRIORITY_CONTROL 0x12U
+#define VIDEO_EU_START_OR_STOP_LAYER_CONTROL 0x13U
+#define VIDEO_EU_ERROR_RESILIENCY_CONTROL 0x14U
+
+/*! @brief Video device class-specific Extension Unit control selector */
+#define VIDEO_XU_CONTROL_UNDEFINED 0x00U
+
+/*! @brief Video device class-specific VideoStreaming Interface control selector */
+#define VIDEO_VS_CONTROL_UNDEFINED 0x00U
+#define VIDEO_VS_PROBE_CONTROL 0x01U
+#define VIDEO_VS_COMMIT_CONTROL 0x02U
+#define VIDEO_VS_STILL_PROBE_CONTROL 0x03U
+#define VIDEO_VS_STILL_COMMIT_CONTROL 0x04U
+#define VIDEO_VS_STILL_IMAGE_TRIGGER_CONTROL 0x05U
+#define VIDEO_VS_STREAM_ERROR_CODE_CONTROL 0x06U
+#define VIDEO_VS_GENERATE_KEY_FRAME_CONTROL 0x07U
+#define VIDEO_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08U
+#define VIDEO_VS_SYNCH_DELAY_CONTROL 0x09U
+
+/*! @}*/
+
+/*!
+ * @name USB Video class terminal types
+ * @{
+ */
+
+/*! @brief Video device USB terminal type */
+#define VIDEO_TT_VENDOR_SPECIFIC 0x0100U
+#define VIDEO_TT_STREAMING 0x0101U
+
+/*! @brief Video device input terminal type */
+#define VIDEO_ITT_VENDOR_SPECIFIC 0x0200U
+#define VIDEO_ITT_CAMERA 0x0201U
+#define VIDEO_ITT_MEDIA_TRANSPORT_INPUT 0x0202U
+
+/*! @brief Video device output terminal type */
+#define VIDEO_OTT_VENDOR_SPECIFIC 0x0300U
+#define VIDEO_OTT_DISPLAY 0x0301U
+#define VIDEO_OTT_MEDIA_TRANSPORT_OUTPUT 0x0302U
+
+/*! @brief Video device external terminal type */
+#define VIDEO_ET_VENDOR_SPECIFIC 0x0400U
+#define VIDEO_ET_COMPOSITE_CONNECTOR 0x0401U
+#define VIDEO_ET_SVIDEO_CONNECTOR 0x0402U
+#define VIDEO_ET_COMPONENT_CONNECTOR 0x0403U
+
+/*! @}*/
+
+/*!
+ * @name USB Video class setup request types
+ * @{
+ */
+
+/*! @brief Video device class setup request set type */
+#define VIDEO_SET_REQUEST_INTERFACE 0x21U
+#define VIDEO_SET_REQUEST_ENDPOINT 0x22U
+
+/*! @brief Video device class setup request get type */
+#define VIDEO_GET_REQUEST_INTERFACE 0xA1U
+#define VIDEO_GET_REQUEST_ENDPOINT 0xA2U
+
+/*! @}*/
+
+/*! @brief Video device still image trigger control */
+#define VIDEO_STILL_IMAGE_TRIGGER_NORMAL_OPERATION 0x00U
+#define VIDEO_STILL_IMAGE_TRIGGER_TRANSMIT_STILL_IMAGE 0x01U
+#define VIDEO_STILL_IMAGE_TRIGGER_TRANSMIT_STILL_IMAGE_VS_DEDICATED_BULK_PIPE 0x02U
+#define VIDEO_STILL_IMAGE_TRIGGER_ABORT_STILL_IMAGE_TRANSMISSION 0x03U
+
+/*!
+ * @name USB Video device class-specific request commands
+ * @{
+ */
+
+/*! @brief Video device class-specific request GET CUR COMMAND */
+#define VIDEO_GET_CUR_VC_POWER_MODE_CONTROL 0x8101U
+#define VIDEO_GET_CUR_VC_ERROR_CODE_CONTROL 0x8102U
+
+#define VIDEO_GET_CUR_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8121U
+#define VIDEO_GET_CUR_PU_BRIGHTNESS_CONTROL 0x8122U
+#define VIDEO_GET_CUR_PU_CONTRACT_CONTROL 0x8123U
+#define VIDEO_GET_CUR_PU_GAIN_CONTROL 0x8124U
+#define VIDEO_GET_CUR_PU_POWER_LINE_FREQUENCY_CONTROL 0x8125U
+#define VIDEO_GET_CUR_PU_HUE_CONTROL 0x8126U
+#define VIDEO_GET_CUR_PU_SATURATION_CONTROL 0x8127U
+#define VIDEO_GET_CUR_PU_SHARRNESS_CONTROL 0x8128U
+#define VIDEO_GET_CUR_PU_GAMMA_CONTROL 0x8129U
+#define VIDEO_GET_CUR_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x812AU
+#define VIDEO_GET_CUR_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x812BU
+#define VIDEO_GET_CUR_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x812CU
+#define VIDEO_GET_CUR_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x812DU
+#define VIDEO_GET_CUR_PU_DIGITAL_MULTIPLIER_CONTROL 0x812EU
+#define VIDEO_GET_CUR_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x812FU
+#define VIDEO_GET_CUR_PU_HUE_AUTO_CONTROL 0x8130U
+#define VIDEO_GET_CUR_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x8131U
+#define VIDEO_GET_CUR_PU_ANALOG_LOCK_STATUS_CONTROL 0x8132U
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_CUR_PU_CONTRAST_AUTO_CONTROL 0x8133U
+#endif
+
+#define VIDEO_GET_CUR_CT_SCANNING_MODE_CONTROL 0x8141U
+#define VIDEO_GET_CUR_CT_AE_MODE_CONTROL 0x8142U
+#define VIDEO_GET_CUR_CT_AE_PRIORITY_CONTROL 0x8143U
+#define VIDEO_GET_CUR_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8144U
+#define VIDEO_GET_CUR_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x8145U
+#define VIDEO_GET_CUR_CT_FOCUS_ABSOLUTE_CONTROL 0x8146U
+#define VIDEO_GET_CUR_CT_FOCUS_RELATIVE_CONTROL 0x8147U
+#define VIDEO_GET_CUR_CT_FOCUS_AUTO_CONTROL 0x8148U
+#define VIDEO_GET_CUR_CT_IRIS_ABSOLUTE_CONTROL 0x8149U
+#define VIDEO_GET_CUR_CT_IRIS_RELATIVE_CONTROL 0x814AU
+#define VIDEO_GET_CUR_CT_ZOOM_ABSOLUTE_CONTROL 0x814BU
+#define VIDEO_GET_CUR_CT_ZOOM_RELATIVE_CONTROL 0x814CU
+#define VIDEO_GET_CUR_CT_PANTILT_ABSOLUTE_CONTROL 0x814DU
+#define VIDEO_GET_CUR_CT_PANTILT_RELATIVE_CONTROL 0x814EU
+#define VIDEO_GET_CUR_CT_ROLL_ABSOLUTE_CONTROL 0x814FU
+#define VIDEO_GET_CUR_CT_ROLL_RELATIVE_CONTROL 0x8150U
+#define VIDEO_GET_CUR_CT_PRIVACY_CONTROL 0x8151U
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_CUR_CT_FOCUS_SIMPLE_CONTROL 0x8152U
+#define VIDEO_GET_CUR_CT_DIGITAL_WINDOW_CONTROL 0x8153U
+#define VIDEO_GET_CUR_CT_REGION_OF_INTEREST_CONTROL 0x8154U
+#endif
+
+#define VIDEO_GET_CUR_VS_PROBE_CONTROL 0x8161U
+#define VIDEO_GET_CUR_VS_COMMIT_CONTROL 0x8162U
+#define VIDEO_GET_CUR_VS_STILL_PROBE_CONTROL 0x8163U
+#define VIDEO_GET_CUR_VS_STILL_COMMIT_CONTROL 0x8164U
+#define VIDEO_GET_CUR_VS_STILL_IMAGE_TRIGGER_CONTROL 0x8165U
+#define VIDEO_GET_CUR_VS_STREAM_ERROR_CODE_CONTROL 0x8166U
+#define VIDEO_GET_CUR_VS_GENERATE_KEY_FRAME_CONTROL 0x8167U
+#define VIDEO_GET_CUR_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8168U
+#define VIDEO_GET_CUR_VS_SYNCH_DELAY_CONTROL 0x8169U
+
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_CUR_EU_SELECT_LAYER_CONTROL 0x8181U
+#define VIDEO_GET_CUR_EU_PROFILE_TOOLSET_CONTROL 0x8182U
+#define VIDEO_GET_CUR_EU_VIDEO_RESOLUTION_CONTROL 0x8183U
+#define VIDEO_GET_CUR_EU_MIN_FRAME_INTERVAL_CONTROL 0x8184U
+#define VIDEO_GET_CUR_EU_SLICE_MODE_CONTROL 0x8185U
+#define VIDEO_GET_CUR_EU_RATE_CONTROL_MODE_CONTROL 0x8186U
+#define VIDEO_GET_CUR_EU_AVERAGE_BITRATE_CONTROL 0x8187U
+#define VIDEO_GET_CUR_EU_CPB_SIZE_CONTROL 0x8188U
+#define VIDEO_GET_CUR_EU_PEAK_BIT_RATE_CONTROL 0x8189U
+#define VIDEO_GET_CUR_EU_QUANTIZATION_PARAMS_CONTROL 0x818AU
+#define VIDEO_GET_CUR_EU_SYNC_REF_FRAME_CONTROL 0x818BU
+#define VIDEO_GET_CUR_EU_LTR_BUFFER_CONTROL 0x818CU
+#define VIDEO_GET_CUR_EU_LTR_PICTURE_CONTROL 0x818DU
+#define VIDEO_GET_CUR_EU_LTR_VALIDATION_CONTROL 0x818EU
+#define VIDEO_GET_CUR_EU_LEVEL_IDC_LIMIT_CONTROL 0x818FU
+#define VIDEO_GET_CUR_EU_SEI_PAYLOADTYPE_CONTROL 0x8190U
+#define VIDEO_GET_CUR_EU_QP_RANGE_CONTROL 0x8191U
+#define VIDEO_GET_CUR_EU_PRIORITY_CONTROL 0x8192U
+#define VIDEO_GET_CUR_EU_START_OR_STOP_LAYER_CONTROL 0x8193U
+#define VIDEO_GET_CUR_EU_ERROR_RESILIENCY_CONTROL 0x8194U
+#endif
+
+/*! @brief Video device class-specific request GET MIN COMMAND */
+#define VIDEO_GET_MIN_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8221U
+#define VIDEO_GET_MIN_PU_BRIGHTNESS_CONTROL 0x8222U
+#define VIDEO_GET_MIN_PU_CONTRACT_CONTROL 0x8223U
+#define VIDEO_GET_MIN_PU_GAIN_CONTROL 0x8224U
+#define VIDEO_GET_MIN_PU_HUE_CONTROL 0x8226U
+#define VIDEO_GET_MIN_PU_SATURATION_CONTROL 0x8227U
+#define VIDEO_GET_MIN_PU_SHARRNESS_CONTROL 0x8228U
+#define VIDEO_GET_MIN_PU_GAMMA_CONTROL 0x8229U
+#define VIDEO_GET_MIN_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x822AU
+#define VIDEO_GET_MIN_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x822CU
+#define VIDEO_GET_MIN_PU_DIGITAL_MULTIPLIER_CONTROL 0x822EU
+#define VIDEO_GET_MIN_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x822FU
+
+#define VIDEO_GET_MIN_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8244U
+#define VIDEO_GET_MIN_CT_FOCUS_ABSOLUTE_CONTROL 0x8246U
+#define VIDEO_GET_MIN_CT_FOCUS_RELATIVE_CONTROL 0x8247U
+#define VIDEO_GET_MIN_CT_IRIS_ABSOLUTE_CONTROL 0x8249U
+#define VIDEO_GET_MIN_CT_ZOOM_ABSOLUTE_CONTROL 0x824BU
+#define VIDEO_GET_MIN_CT_ZOOM_RELATIVE_CONTROL 0x824CU
+#define VIDEO_GET_MIN_CT_PANTILT_ABSOLUTE_CONTROL 0x824DU
+#define VIDEO_GET_MIN_CT_PANTILT_RELATIVE_CONTROL 0x824EU
+#define VIDEO_GET_MIN_CT_ROLL_ABSOLUTE_CONTROL 0x824FU
+#define VIDEO_GET_MIN_CT_ROLL_RELATIVE_CONTROL 0x8250U
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_MIN_CT_DIGITAL_WINDOW_CONTROL 0x8251U
+#define VIDEO_GET_MIN_CT_REGION_OF_INTEREST_CONTROL 0x8252U
+#endif
+
+#define VIDEO_GET_MIN_VS_PROBE_CONTROL 0x8261U
+#define VIDEO_GET_MIN_VS_STILL_PROBE_CONTROL 0x8263U
+#define VIDEO_GET_MIN_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8268U
+#define VIDEO_GET_MIN_VS_SYNCH_DELAY_CONTROL 0x8269U
+
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_MIN_EU_VIDEO_RESOLUTION_CONTROL 0x8283U
+#define VIDEO_GET_MIN_EU_MIN_FRAME_INTERVAL_CONTROL 0x8284U
+#define VIDEO_GET_MIN_EU_SLICE_MODE_CONTROL 0x8285U
+#define VIDEO_GET_MIN_EU_AVERAGE_BITRATE_CONTROL 0x8287U
+#define VIDEO_GET_MIN_EU_CPB_SIZE_CONTROL 0x8288U
+#define VIDEO_GET_MIN_EU_PEAK_BIT_RATE_CONTROL 0x8289U
+#define VIDEO_GET_MIN_EU_QUANTIZATION_PARAMS_CONTROL 0x828AU
+#define VIDEO_GET_MIN_EU_SYNC_REF_FRAME_CONTROL 0x828BU
+#define VIDEO_GET_MIN_EU_LEVEL_IDC_LIMIT_CONTROL 0x828FU
+#define VIDEO_GET_MIN_EU_SEI_PAYLOADTYPE_CONTROL 0x8290U
+#define VIDEO_GET_MIN_EU_QP_RANGE_CONTROL 0x8291U
+#endif
+
+/*! @brief Video device class-specific request GET MAX COMMAND */
+#define VIDEO_GET_MAX_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8321U
+#define VIDEO_GET_MAX_PU_BRIGHTNESS_CONTROL 0x8322U
+#define VIDEO_GET_MAX_PU_CONTRACT_CONTROL 0x8323U
+#define VIDEO_GET_MAX_PU_GAIN_CONTROL 0x8324U
+#define VIDEO_GET_MAX_PU_HUE_CONTROL 0x8326U
+#define VIDEO_GET_MAX_PU_SATURATION_CONTROL 0x8327U
+#define VIDEO_GET_MAX_PU_SHARRNESS_CONTROL 0x8328U
+#define VIDEO_GET_MAX_PU_GAMMA_CONTROL 0x8329U
+#define VIDEO_GET_MAX_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x832AU
+#define VIDEO_GET_MAX_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x832CU
+#define VIDEO_GET_MAX_PU_DIGITAL_MULTIPLIER_CONTROL 0x832EU
+#define VIDEO_GET_MAX_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x832FU
+
+#define VIDEO_GET_MAX_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8344U
+#define VIDEO_GET_MAX_CT_FOCUS_ABSOLUTE_CONTROL 0x8346U
+#define VIDEO_GET_MAX_CT_FOCUS_RELATIVE_CONTROL 0x8347U
+#define VIDEO_GET_MAX_CT_IRIS_ABSOLUTE_CONTROL 0x8349U
+#define VIDEO_GET_MAX_CT_ZOOM_ABSOLUTE_CONTROL 0x834BU
+#define VIDEO_GET_MAX_CT_ZOOM_RELATIVE_CONTROL 0x834CU
+#define VIDEO_GET_MAX_CT_PANTILT_ABSOLUTE_CONTROL 0x834DU
+#define VIDEO_GET_MAX_CT_PANTILT_RELATIVE_CONTROL 0x834EU
+#define VIDEO_GET_MAX_CT_ROLL_ABSOLUTE_CONTROL 0x834FU
+#define VIDEO_GET_MAX_CT_ROLL_RELATIVE_CONTROL 0x8350U
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_MAX_CT_DIGITAL_WINDOW_CONTROL 0x8351U
+#define VIDEO_GET_MAX_CT_REGION_OF_INTEREST_CONTROL 0x8352U
+#endif
+
+#define VIDEO_GET_MAX_VS_PROBE_CONTROL 0x8361U
+#define VIDEO_GET_MAX_VS_STILL_PROBE_CONTROL 0x8363U
+#define VIDEO_GET_MAX_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8368U
+#define VIDEO_GET_MAX_VS_SYNCH_DELAY_CONTROL 0x8369U
+
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_MAX_EU_VIDEO_RESOLUTION_CONTROL 0x8383U
+#define VIDEO_GET_MAX_EU_MIN_FRAME_INTERVAL_CONTROL 0x8384U
+#define VIDEO_GET_MAX_EU_SLICE_MODE_CONTROL 0x8385U
+#define VIDEO_GET_MAX_EU_AVERAGE_BITRATE_CONTROL 0x8387U
+#define VIDEO_GET_MAX_EU_CPB_SIZE_CONTROL 0x8388U
+#define VIDEO_GET_MAX_EU_PEAK_BIT_RATE_CONTROL 0x8389U
+#define VIDEO_GET_MAX_EU_QUANTIZATION_PARAMS_CONTROL 0x838AU
+#define VIDEO_GET_MAX_EU_SYNC_REF_FRAME_CONTROL 0x838BU
+#define VIDEO_GET_MAX_EU_LTR_BUFFER_CONTROL 0x838CU
+#define VIDEO_GET_MAX_EU_LEVEL_IDC_LIMIT_CONTROL 0x838FU
+#define VIDEO_GET_MAX_EU_SEI_PAYLOADTYPE_CONTROL 0x8390U
+#define VIDEO_GET_MAX_EU_QP_RANGE_CONTROL 0x8391U
+#endif
+
+/*! @brief Video device class-specific request GET RES COMMAND */
+#define VIDEO_GET_RES_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8421U
+#define VIDEO_GET_RES_PU_BRIGHTNESS_CONTROL 0x8422U
+#define VIDEO_GET_RES_PU_CONTRACT_CONTROL 0x8423U
+#define VIDEO_GET_RES_PU_GAIN_CONTROL 0x8424U
+#define VIDEO_GET_RES_PU_HUE_CONTROL 0x8426U
+#define VIDEO_GET_RES_PU_SATURATION_CONTROL 0x8427U
+#define VIDEO_GET_RES_PU_SHARRNESS_CONTROL 0x8428U
+#define VIDEO_GET_RES_PU_GAMMA_CONTROL 0x8429U
+#define VIDEO_GET_RES_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x842AU
+#define VIDEO_GET_RES_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x842CU
+#define VIDEO_GET_RES_PU_DIGITAL_MULTIPLIER_CONTROL 0x842EU
+#define VIDEO_GET_RES_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x842FU
+
+#define VIDEO_GET_RES_CT_AE_MODE_CONTROL 0x8442U
+#define VIDEO_GET_RES_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8444U
+#define VIDEO_GET_RES_CT_FOCUS_ABSOLUTE_CONTROL 0x8446U
+#define VIDEO_GET_RES_CT_FOCUS_RELATIVE_CONTROL 0x8447U
+#define VIDEO_GET_RES_CT_IRIS_ABSOLUTE_CONTROL 0x8449U
+#define VIDEO_GET_RES_CT_ZOOM_ABSOLUTE_CONTROL 0x844BU
+#define VIDEO_GET_RES_CT_ZOOM_RELATIVE_CONTROL 0x844CU
+#define VIDEO_GET_RES_CT_PANTILT_ABSOLUTE_CONTROL 0x844DU
+#define VIDEO_GET_RES_CT_PANTILT_RELATIVE_CONTROL 0x844EU
+#define VIDEO_GET_RES_CT_ROLL_ABSOLUTE_CONTROL 0x844FU
+#define VIDEO_GET_RES_CT_ROLL_RELATIVE_CONTROL 0x8450U
+
+#define VIDEO_GET_RES_VS_PROBE_CONTROL 0x8461U
+#define VIDEO_GET_RES_VS_STILL_PROBE_CONTROL 0x8463U
+#define VIDEO_GET_RES_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8468U
+#define VIDEO_GET_RES_VS_SYNCH_DELAY_CONTROL 0x8469U
+
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_RES_EU_AVERAGE_BITRATE_CONTROL 0x8487U
+#define VIDEO_GET_RES_EU_CPB_SIZE_CONTROL 0x8488U
+#define VIDEO_GET_RES_EU_PEAK_BIT_RATE_CONTROL 0x8489U
+#define VIDEO_GET_RES_EU_QUANTIZATION_PARAMS_CONTROL 0x848AU
+#define VIDEO_GET_RES_EU_ERROR_RESILIENCY_CONTROL 0x8494U
+#endif
+
+/*! @brief Video device class-specific request GET LEN COMMAND */
+
+#define VIDEO_GET_LEN_VS_PROBE_CONTROL 0x8561U
+#define VIDEO_GET_LEN_VS_COMMIT_CONTROL 0x8562U
+#define VIDEO_GET_LEN_VS_STILL_PROBE_CONTROL 0x8563U
+#define VIDEO_GET_LEN_VS_STILL_COMMIT_CONTROL 0x8564U
+
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_LEN_EU_SELECT_LAYER_CONTROL 0x8581U
+#define VIDEO_GET_LEN_EU_PROFILE_TOOLSET_CONTROL 0x8582U
+#define VIDEO_GET_LEN_EU_VIDEO_RESOLUTION_CONTROL 0x8583U
+#define VIDEO_GET_LEN_EU_MIN_FRAME_INTERVAL_CONTROL 0x8584U
+#define VIDEO_GET_LEN_EU_SLICE_MODE_CONTROL 0x8585U
+#define VIDEO_GET_LEN_EU_RATE_CONTROL_MODE_CONTROL 0x8586U
+#define VIDEO_GET_LEN_EU_AVERAGE_BITRATE_CONTROL 0x8587U
+#define VIDEO_GET_LEN_EU_CPB_SIZE_CONTROL 0x8588U
+#define VIDEO_GET_LEN_EU_PEAK_BIT_RATE_CONTROL 0x8589U
+#define VIDEO_GET_LEN_EU_QUANTIZATION_PARAMS_CONTROL 0x858AU
+#define VIDEO_GET_LEN_EU_SYNC_REF_FRAME_CONTROL 0x858BU
+#define VIDEO_GET_LEN_EU_LTR_BUFFER_CONTROL 0x858CU
+#define VIDEO_GET_LEN_EU_LTR_PICTURE_CONTROL 0x858DU
+#define VIDEO_GET_LEN_EU_LTR_VALIDATION_CONTROL 0x858EU
+#define VIDEO_GET_LEN_EU_QP_RANGE_CONTROL 0x8591U
+#define VIDEO_GET_LEN_EU_PRIORITY_CONTROL 0x8592U
+#define VIDEO_GET_LEN_EU_START_OR_STOP_LAYER_CONTROL 0x8593U
+#endif
+
+/*! @brief Video device class-specific request GET INFO COMMAND */
+#define VIDEO_GET_INFO_VC_POWER_MODE_CONTROL 0x8601U
+#define VIDEO_GET_INFO_VC_ERROR_CODE_CONTROL 0x8602U
+
+#define VIDEO_GET_INFO_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8621U
+#define VIDEO_GET_INFO_PU_BRIGHTNESS_CONTROL 0x8622U
+#define VIDEO_GET_INFO_PU_CONTRACT_CONTROL 0x8623U
+#define VIDEO_GET_INFO_PU_GAIN_CONTROL 0x8624U
+#define VIDEO_GET_INFO_PU_POWER_LINE_FREQUENCY_CONTROL 0x8625U
+#define VIDEO_GET_INFO_PU_HUE_CONTROL 0x8626U
+#define VIDEO_GET_INFO_PU_SATURATION_CONTROL 0x8627U
+#define VIDEO_GET_INFO_PU_SHARRNESS_CONTROL 0x8628U
+#define VIDEO_GET_INFO_PU_GAMMA_CONTROL 0x8629U
+#define VIDEO_GET_INFO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x862AU
+#define VIDEO_GET_INFO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x862BU
+#define VIDEO_GET_INFO_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x862CU
+#define VIDEO_GET_INFO_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x862DU
+#define VIDEO_GET_INFO_PU_DIGITAL_MULTIPLIER_CONTROL 0x862EU
+#define VIDEO_GET_INFO_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x862FU
+#define VIDEO_GET_INFO_PU_HUE_AUTO_CONTROL 0x8630U
+#define VIDEO_GET_INFO_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x8631U
+#define VIDEO_GET_INFO_PU_ANALOG_LOCK_STATUS_CONTROL 0x8632U
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_INFO_PU_CONTRAST_AUTO_CONTROL 0x8633U
+#endif
+
+#define VIDEO_GET_INFO_CT_SCANNING_MODE_CONTROL 0x8641U
+#define VIDEO_GET_INFO_CT_AE_MODE_CONTROL 0x8642U
+#define VIDEO_GET_INFO_CT_AE_PRIORITY_CONTROL 0x8643U
+#define VIDEO_GET_INFO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8644U
+#define VIDEO_GET_INFO_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x8645U
+#define VIDEO_GET_INFO_CT_FOCUS_ABSOLUTE_CONTROL 0x8646U
+#define VIDEO_GET_INFO_CT_FOCUS_RELATIVE_CONTROL 0x8647U
+#define VIDEO_GET_INFO_CT_FOCUS_AUTO_CONTROL 0x8648U
+#define VIDEO_GET_INFO_CT_IRIS_ABSOLUTE_CONTROL 0x8649U
+#define VIDEO_GET_INFO_CT_IRIS_RELATIVE_CONTROL 0x864AU
+#define VIDEO_GET_INFO_CT_ZOOM_ABSOLUTE_CONTROL 0x864BU
+#define VIDEO_GET_INFO_CT_ZOOM_RELATIVE_CONTROL 0x864CU
+#define VIDEO_GET_INFO_CT_PANTILT_ABSOLUTE_CONTROL 0x864DU
+#define VIDEO_GET_INFO_CT_PANTILT_RELATIVE_CONTROL 0x864EU
+#define VIDEO_GET_INFO_CT_ROLL_ABSOLUTE_CONTROL 0x864FU
+#define VIDEO_GET_INFO_CT_ROLL_RELATIVE_CONTROL 0x8650U
+#define VIDEO_GET_INFO_CT_PRIVACY_CONTROL 0x8651U
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_INFO_CT_FOCUS_SIMPLE_CONTROL 0x8652U
+#endif
+
+#define VIDEO_GET_INFO_VS_PROBE_CONTROL 0x8661U
+#define VIDEO_GET_INFO_VS_COMMIT_CONTROL 0x8662U
+#define VIDEO_GET_INFO_VS_STILL_PROBE_CONTROL 0x8663U
+#define VIDEO_GET_INFO_VS_STILL_COMMIT_CONTROL 0x8664U
+#define VIDEO_GET_INFO_VS_STILL_IMAGE_TRIGGER_CONTROL 0x8665U
+#define VIDEO_GET_INFO_VS_STREAM_ERROR_CODE_CONTROL 0x8666U
+#define VIDEO_GET_INFO_VS_GENERATE_KEY_FRAME_CONTROL 0x8667U
+#define VIDEO_GET_INFO_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8668U
+#define VIDEO_GET_INFO_VS_SYNCH_DELAY_CONTROL 0x8669U
+
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_INFO_EU_SELECT_LAYER_CONTROL 0x8681U
+#define VIDEO_GET_INFO_EU_PROFILE_TOOLSET_CONTROL 0x8682U
+#define VIDEO_GET_INFO_EU_VIDEO_RESOLUTION_CONTROL 0x8683U
+#define VIDEO_GET_INFO_EU_MIN_FRAME_INTERVAL_CONTROL 0x8684U
+#define VIDEO_GET_INFO_EU_SLICE_MODE_CONTROL 0x8685U
+#define VIDEO_GET_INFO_EU_RATE_CONTROL_MODE_CONTROL 0x8686U
+#define VIDEO_GET_INFO_EU_AVERAGE_BITRATE_CONTROL 0x8687U
+#define VIDEO_GET_INFO_EU_CPB_SIZE_CONTROL 0x8688U
+#define VIDEO_GET_INFO_EU_PEAK_BIT_RATE_CONTROL 0x8689U
+#define VIDEO_GET_INFO_EU_QUANTIZATION_PARAMS_CONTROL 0x868AU
+#define VIDEO_GET_INFO_EU_SYNC_REF_FRAME_CONTROL 0x868BU
+#define VIDEO_GET_INFO_EU_LTR_BUFFER_CONTROL 0x868CU
+#define VIDEO_GET_INFO_EU_LTR_PICTURE_CONTROL 0x868DU
+#define VIDEO_GET_INFO_EU_LTR_VALIDATION_CONTROL 0x868EU
+#define VIDEO_GET_INFO_EU_SEI_PAYLOADTYPE_CONTROL 0x8690U
+#define VIDEO_GET_INFO_EU_QP_RANGE_CONTROL 0x8691U
+#define VIDEO_GET_INFO_EU_PRIORITY_CONTROL 0x8692U
+#define VIDEO_GET_INFO_EU_START_OR_STOP_LAYER_CONTROL 0x8693U
+#endif
+
+/*! @brief Video device class-specific request GET DEF COMMAND */
+#define VIDEO_GET_DEF_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8721U
+#define VIDEO_GET_DEF_PU_BRIGHTNESS_CONTROL 0x8722U
+#define VIDEO_GET_DEF_PU_CONTRACT_CONTROL 0x8723U
+#define VIDEO_GET_DEF_PU_GAIN_CONTROL 0x8724U
+#define VIDEO_GET_DEF_PU_POWER_LINE_FREQUENCY_CONTROL 0x8725U
+#define VIDEO_GET_DEF_PU_HUE_CONTROL 0x8726U
+#define VIDEO_GET_DEF_PU_SATURATION_CONTROL 0x8727U
+#define VIDEO_GET_DEF_PU_SHARRNESS_CONTROL 0x8728U
+#define VIDEO_GET_DEF_PU_GAMMA_CONTROL 0x8729U
+#define VIDEO_GET_DEF_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x872AU
+#define VIDEO_GET_DEF_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x872BU
+#define VIDEO_GET_DEF_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x872CU
+#define VIDEO_GET_DEF_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x872DU
+#define VIDEO_GET_DEF_PU_DIGITAL_MULTIPLIER_CONTROL 0x872EU
+#define VIDEO_GET_DEF_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x872FU
+#define VIDEO_GET_DEF_PU_HUE_AUTO_CONTROL 0x8730U
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_DEF_PU_CONTRAST_AUTO_CONTROL 0x8731U
+#endif
+
+#define VIDEO_GET_DEF_CT_AE_MODE_CONTROL 0x8742U
+#define VIDEO_GET_DEF_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8744U
+#define VIDEO_GET_DEF_CT_FOCUS_ABSOLUTE_CONTROL 0x8746U
+#define VIDEO_GET_DEF_CT_FOCUS_RELATIVE_CONTROL 0x8747U
+#define VIDEO_GET_DEF_CT_FOCUS_AUTO_CONTROL 0x8748U
+#define VIDEO_GET_DEF_CT_IRIS_ABSOLUTE_CONTROL 0x8749U
+#define VIDEO_GET_DEF_CT_ZOOM_ABSOLUTE_CONTROL 0x874BU
+#define VIDEO_GET_DEF_CT_ZOOM_RELATIVE_CONTROL 0x874CU
+#define VIDEO_GET_DEF_CT_PANTILT_ABSOLUTE_CONTROL 0x874DU
+#define VIDEO_GET_DEF_CT_PANTILT_RELATIVE_CONTROL 0x874EU
+#define VIDEO_GET_DEF_CT_ROLL_ABSOLUTE_CONTROL 0x874FU
+#define VIDEO_GET_DEF_CT_ROLL_RELATIVE_CONTROL 0x8750U
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_DEF_CT_FOCUS_SIMPLE_CONTROL 0x8751U
+#define VIDEO_GET_DEF_CT_DIGITAL_WINDOW_CONTROL 0x8752U
+#define VIDEO_GET_DEF_CT_REGION_OF_INTEREST_CONTROL 0x8753U
+#endif
+
+#define VIDEO_GET_DEF_VS_PROBE_CONTROL 0x8761U
+#define VIDEO_GET_DEF_VS_STILL_PROBE_CONTROL 0x8763U
+#define VIDEO_GET_DEF_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8768U
+#define VIDEO_GET_DEF_VS_SYNCH_DELAY_CONTROL 0x8769U
+
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_GET_DEF_EU_PROFILE_TOOLSET_CONTROL 0x8782U
+#define VIDEO_GET_DEF_EU_VIDEO_RESOLUTION_CONTROL 0x8783U
+#define VIDEO_GET_DEF_EU_MIN_FRAME_INTERVAL_CONTROL 0x8784U
+#define VIDEO_GET_DEF_EU_SLICE_MODE_CONTROL 0x8785U
+#define VIDEO_GET_DEF_EU_RATE_CONTROL_MODE_CONTROL 0x8786U
+#define VIDEO_GET_DEF_EU_AVERAGE_BITRATE_CONTROL 0x8787U
+#define VIDEO_GET_DEF_EU_CPB_SIZE_CONTROL 0x8788U
+#define VIDEO_GET_DEF_EU_PEAK_BIT_RATE_CONTROL 0x8789U
+#define VIDEO_GET_DEF_EU_QUANTIZATION_PARAMS_CONTROL 0x878AU
+#define VIDEO_GET_DEF_EU_LTR_BUFFER_CONTROL 0x878CU
+#define VIDEO_GET_DEF_EU_LTR_PICTURE_CONTROL 0x878DU
+#define VIDEO_GET_DEF_EU_LTR_VALIDATION_CONTROL 0x878EU
+#define VIDEO_GET_DEF_EU_LEVEL_IDC_LIMIT_CONTROL 0x878FU
+#define VIDEO_GET_DEF_EU_SEI_PAYLOADTYPE_CONTROL 0x8790U
+#define VIDEO_GET_DEF_EU_QP_RANGE_CONTROL 0x8791U
+#define VIDEO_GET_DEF_EU_ERROR_RESILIENCY_CONTROL 0x8794U
+#endif
+
+/*! @brief Video device class-specific request SET CUR COMMAND */
+#define VIDEO_SET_CUR_VC_POWER_MODE_CONTROL 0x0101U
+
+#define VIDEO_SET_CUR_PU_BACKLIGHT_COMPENSATION_CONTROL 0x0121U
+#define VIDEO_SET_CUR_PU_BRIGHTNESS_CONTROL 0x0122U
+#define VIDEO_SET_CUR_PU_CONTRACT_CONTROL 0x0123U
+#define VIDEO_SET_CUR_PU_GAIN_CONTROL 0x0124U
+#define VIDEO_SET_CUR_PU_POWER_LINE_FREQUENCY_CONTROL 0x0125U
+#define VIDEO_SET_CUR_PU_HUE_CONTROL 0x0126U
+#define VIDEO_SET_CUR_PU_SATURATION_CONTROL 0x0127U
+#define VIDEO_SET_CUR_PU_SHARRNESS_CONTROL 0x0128U
+#define VIDEO_SET_CUR_PU_GAMMA_CONTROL 0x0129U
+#define VIDEO_SET_CUR_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x012AU
+#define VIDEO_SET_CUR_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x012BU
+#define VIDEO_SET_CUR_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x012CU
+#define VIDEO_SET_CUR_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x012DU
+#define VIDEO_SET_CUR_PU_DIGITAL_MULTIPLIER_CONTROL 0x012EU
+#define VIDEO_SET_CUR_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x012FU
+#define VIDEO_SET_CUR_PU_HUE_AUTO_CONTROL 0x0130U
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_SET_CUR_PU_CONTRAST_AUTO_CONTROL 0x0131U
+#endif
+
+#define VIDEO_SET_CUR_CT_SCANNING_MODE_CONTROL 0x0141U
+#define VIDEO_SET_CUR_CT_AE_MODE_CONTROL 0x0142U
+#define VIDEO_SET_CUR_CT_AE_PRIORITY_CONTROL 0x0143U
+#define VIDEO_SET_CUR_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x0144U
+#define VIDEO_SET_CUR_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x0145U
+#define VIDEO_SET_CUR_CT_FOCUS_ABSOLUTE_CONTROL 0x0146U
+#define VIDEO_SET_CUR_CT_FOCUS_RELATIVE_CONTROL 0x0147U
+#define VIDEO_SET_CUR_CT_FOCUS_AUTO_CONTROL 0x0148U
+#define VIDEO_SET_CUR_CT_IRIS_ABSOLUTE_CONTROL 0x0149U
+#define VIDEO_SET_CUR_CT_IRIS_RELATIVE_CONTROL 0x014AU
+#define VIDEO_SET_CUR_CT_ZOOM_ABSOLUTE_CONTROL 0x014BU
+#define VIDEO_SET_CUR_CT_ZOOM_RELATIVE_CONTROL 0x014CU
+#define VIDEO_SET_CUR_CT_PANTILT_ABSOLUTE_CONTROL 0x014DU
+#define VIDEO_SET_CUR_CT_PANTILT_RELATIVE_CONTROL 0x014EU
+#define VIDEO_SET_CUR_CT_ROLL_ABSOLUTE_CONTROL 0x014FU
+#define VIDEO_SET_CUR_CT_ROLL_RELATIVE_CONTROL 0x0150U
+#define VIDEO_SET_CUR_CT_PRIVACY_CONTROL 0x0151U
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_SET_CUR_CT_FOCUS_SIMPLE_CONTROL 0x0152U
+#define VIDEO_SET_CUR_CT_DIGITAL_WINDOW_CONTROL 0x0153U
+#define VIDEO_SET_CUR_CT_REGION_OF_INTEREST_CONTROL 0x0154U
+#endif
+
+#define VIDEO_SET_CUR_VS_PROBE_CONTROL 0x0161U
+#define VIDEO_SET_CUR_VS_COMMIT_CONTROL 0x0162U
+#define VIDEO_SET_CUR_VS_STILL_PROBE_CONTROL 0x0163U
+#define VIDEO_SET_CUR_VS_STILL_COMMIT_CONTROL 0x0164U
+#define VIDEO_SET_CUR_VS_STILL_IMAGE_TRIGGER_CONTROL 0x0165U
+#define VIDEO_SET_CUR_VS_STREAM_ERROR_CODE_CONTROL 0x0166U
+#define VIDEO_SET_CUR_VS_GENERATE_KEY_FRAME_CONTROL 0x0167U
+#define VIDEO_SET_CUR_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x0168U
+#define VIDEO_SET_CUR_VS_SYNCH_DELAY_CONTROL 0x0169U
+
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+#define VIDEO_SET_CUR_EU_SELECT_LAYER_CONTROL 0x0181U
+#define VIDEO_SET_CUR_EU_PROFILE_TOOLSET_CONTROL 0x0182U
+#define VIDEO_SET_CUR_EU_VIDEO_RESOLUTION_CONTROL 0x0183U
+#define VIDEO_SET_CUR_EU_MIN_FRAME_INTERVAL_CONTROL 0x0184U
+#define VIDEO_SET_CUR_EU_SLICE_MODE_CONTROL 0x0185U
+#define VIDEO_SET_CUR_EU_RATE_CONTROL_MODE_CONTROL 0x0186U
+#define VIDEO_SET_CUR_EU_AVERAGE_BITRATE_CONTROL 0x0187U
+#define VIDEO_SET_CUR_EU_CPB_SIZE_CONTROL 0x0188U
+#define VIDEO_SET_CUR_EU_PEAK_BIT_RATE_CONTROL 0x0189U
+#define VIDEO_SET_CUR_EU_QUANTIZATION_PARAMS_CONTROL 0x018AU
+#define VIDEO_SET_CUR_EU_SYNC_REF_FRAME_CONTROL 0x018BU
+#define VIDEO_SET_CUR_EU_LTR_BUFFER_CONTROL 0x018CU
+#define VIDEO_SET_CUR_EU_LTR_PICTURE_CONTROL 0x018DU
+#define VIDEO_SET_CUR_EU_LTR_VALIDATION_CONTROL 0x018EU
+#define VIDEO_SET_CUR_EU_LEVEL_IDC_LIMIT_CONTROL 0x018FU
+#define VIDEO_SET_CUR_EU_SEI_PAYLOADTYPE_CONTROL 0x0190U
+#define VIDEO_SET_CUR_EU_QP_RANGE_CONTROL 0x0191U
+#define VIDEO_SET_CUR_EU_PRIORITY_CONTROL 0x0192U
+#define VIDEO_SET_CUR_EU_START_OR_STOP_LAYER_CONTROL 0x0193U
+#define VIDEO_SET_CUR_EU_ERROR_RESILIENCY_CONTROL 0x0194U
+#endif
+
+/*! @brief The payload header structure. */
+struct video_payload_header {
+ uint8_t bHeaderLength; /*!< The payload header length. */
+ union {
+ uint8_t bmheaderInfo; /*!< The payload header bitmap field. */
+ struct
+ {
+ uint8_t frameIdentifier : 1U; /*!< Frame Identifier. This bit toggles at each frame start boundary and stays
+ constant for the rest of the frame.*/
+ uint8_t endOfFrame : 1U; /*!< End of Frame. This bit indicates the end of a video frame and is set in the
+ last video sample that belongs to a frame.*/
+ uint8_t
+ presentationTimeStamp : 1U; /*!< Presentation Time Stamp. This bit, when set, indicates the presence of
+ a PTS field.*/
+ uint8_t sourceClockReference : 1U; /*!< Source Clock Reference. This bit, when set, indicates the presence
+ of a SCR field.*/
+ uint8_t reserved : 1U; /*!< Reserved. Set to 0. */
+ uint8_t stillImage : 1U; /*!< Still Image. This bit, when set, identifies a video sample that belongs to a
+ still image.*/
+ uint8_t errorBit : 1U; /*!< Error Bit. This bit, when set, indicates an error in the device streaming.*/
+ uint8_t endOfHeader : 1U; /*!< End of Header. This bit, when set, indicates the end of the BFH fields.*/
+ } headerInfoBits;
+ struct
+ {
+ uint8_t FID : 1U; /*!< Frame Identifier. This bit toggles at each frame start boundary and stays constant
+ for the rest of the frame.*/
+ uint8_t EOI : 1U; /*!< End of Frame. This bit indicates the end of a video frame and is set in the last
+ video sample that belongs to a frame.*/
+ uint8_t PTS : 1U; /*!< Presentation Time Stamp. This bit, when set, indicates the presence of a PTS field.*/
+ uint8_t SCR : 1U; /*!< Source Clock Reference. This bit, when set, indicates the presence of a SCR field.*/
+ uint8_t RES : 1U; /*!< Reserved. Set to 0. */
+ uint8_t STI : 1U; /*!< Still Image. This bit, when set, identifies a video sample that belongs to a still
+ image.*/
+ uint8_t ERR : 1U; /*!< Error Bit. This bit, when set, indicates an error in the device streaming.*/
+ uint8_t EOH : 1U; /*!< End of Header. This bit, when set, indicates the end of the BFH fields.*/
+ } headerInfoBitmap;
+ } headerInfoUnion;
+ uint32_t dwPresentationTime; /*!< Presentation time stamp (PTS) field.*/
+ uint8_t bSourceClockReference[6]; /*!< Source clock reference (SCR) field.*/
+} __PACKED;
+
+/*! @brief The Video probe and commit controls structure.*/
+struct video_probe_and_commit_controls {
+ union {
+ uint8_t bmHint; /*!< Bit-field control indicating to the function what fields shall be kept fixed. */
+ struct
+ {
+ uint8_t dwFrameInterval : 1U; /*!< dwFrameInterval field.*/
+ uint8_t wKeyFrameRate : 1U; /*!< wKeyFrameRate field.*/
+ uint8_t wPFrameRate : 1U; /*!< wPFrameRate field.*/
+ uint8_t wCompQuality : 1U; /*!< wCompQuality field.*/
+ uint8_t wCompWindowSize : 1U; /*!< wCompWindowSize field.*/
+ uint8_t reserved : 3U; /*!< Reserved field.*/
+ } hintBitmap;
+ } hintUnion;
+ union {
+ uint8_t bmHint; /*!< Bit-field control indicating to the function what fields shall be kept fixed. */
+ struct
+ {
+ uint8_t reserved : 8U; /*!< Reserved field.*/
+ } hintBitmap;
+ } hintUnion1;
+ uint8_t bFormatIndex; /*!< Video format index from a format descriptor.*/
+ uint8_t bFrameIndex; /*!< Video frame index from a frame descriptor.*/
+ uint32_t dwFrameInterval; /*!< Frame interval in 100ns units.*/
+ uint16_t wKeyFrameRate; /*!< Key frame rate in key-frame per video-frame units.*/
+ uint16_t wPFrameRate; /*!< PFrame rate in PFrame/key frame units.*/
+ uint16_t wCompQuality; /*!< Compression quality control in abstract units 0U (lowest) to 10000U (highest).*/
+ uint16_t wCompWindowSize; /*!< Window size for average bit rate control.*/
+ uint16_t wDelay; /*!< Internal video streaming interface latency in ms from video data capture to presentation on
+ the USB.*/
+ uint32_t dwMaxVideoFrameSize; /*!< Maximum video frame or codec-specific segment size in bytes.*/
+ uint32_t dwMaxPayloadTransferSize; /*!< Specifies the maximum number of bytes that the device can transmit or
+ receive in a single payload transfer.*/
+ uint32_t dwClockFrequency; /*!< The device clock frequency in Hz for the specified format. This specifies the
+ units used for the time information fields in the Video Payload Headers in the data
+ stream.*/
+ uint8_t bmFramingInfo; /*!< Bit-field control supporting the following values: D0 Frame ID, D1 EOF.*/
+ uint8_t bPreferedVersion; /*!< The preferred payload format version supported by the host or device for the
+ specified bFormatIndex value.*/
+ uint8_t bMinVersion; /*!< The minimum payload format version supported by the device for the specified bFormatIndex
+ value.*/
+ uint8_t bMaxVersion; /*!< The maximum payload format version supported by the device for the specified bFormatIndex
+ value.*/
+#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5
+ uint8_t bUsage; /*!< This bitmap enables features reported by the bmUsages field of the Video Frame Descriptor.*/
+ uint8_t
+ bBitDepthLuma; /*!< Represents bit_depth_luma_minus8 + 8U, which must be the same as bit_depth_chroma_minus8 +
+ 8.*/
+ uint8_t bmSettings; /*!< A bitmap of flags that is used to discover and control specific features of a temporally
+ encoded video stream.*/
+ uint8_t bMaxNumberOfRefFramesPlus1; /*!< Host indicates the maximum number of frames stored for use as references.*/
+ uint16_t bmRateControlModes; /*!< This field contains 4U sub-fields, each of which is a 4U bit number.*/
+ uint64_t bmLayoutPerStream; /*!< This field contains 4U sub-fields, each of which is a 2U byte number.*/
+#endif
+} __PACKED;
+
+/*! @brief The Video still probe and still commit controls structure.*/
+struct video_still_probe_and_commit_controls {
+ uint8_t bFormatIndex; /*!< Video format index from a format descriptor.*/
+ uint8_t bFrameIndex; /*!< Video frame index from a frame descriptor.*/
+ uint8_t bCompressionIndex; /*!< Compression index from a frame descriptor.*/
+ uint32_t dwMaxVideoFrameSize; /*!< Maximum still image size in bytes.*/
+ uint32_t dwMaxPayloadTransferSize; /*!< Specifies the maximum number of bytes that the device can transmit or
+ receive in a single payload transfer.*/
+} __PACKED;
+
+struct video_cs_if_vc_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bcdVDC;
+ uint16_t wTotalLength;
+ uint32_t dwClockFrequency;
+ uint8_t bInCollection;
+ uint8_t baInterfaceNr[];
+} __PACKED;
+
+#define VIDEO_SIZEOF_VC_HEADER_DESC(n) (11 + n)
+
+struct video_cs_if_vc_input_terminal_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t iTerminal;
+ uint16_t wObjectiveFocalLenMin;
+ uint16_t wObjectiveFocalLenMax;
+ uint16_t wOcularFocalLength;
+ uint8_t bControlSize;
+ uint8_t bmaControls[];
+} __PACKED;
+
+#define VIDEO_SIZEOF_VC_INPUT_TERMINAL_DESC(n) (15 + n)
+
+struct video_cs_if_vc_processing_unit_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bUnitID;
+ uint8_t bSourceID;
+ uint16_t wMaxMultiplier;
+ uint8_t bControlSize;
+ // uint8_t bmaControls[];
+ uint8_t iProcessing;
+ uint8_t bmVideoStandards;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VC_PROCESSING_UNIT_DESC(n) (10 + n)
+
+struct video_cs_if_vc_output_terminal_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bTerminalID;
+ uint16_t wTerminalType;
+ uint8_t bAssocTerminal;
+ uint8_t bSourceID;
+ uint8_t iTerminal;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VC_OUTPUT_TERMINAL_DESC 9
+
+struct video_cs_ep_vc_ep_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint16_t wMaxTransferSize;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VC_EP_DESC 5
+
+struct video_cs_if_vs_input_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bNumFormats;
+ uint16_t wTotalLength;
+ uint8_t bEndpointAddress;
+ uint8_t bmInfo;
+ uint8_t bTerminalLink;
+ uint8_t bStillCaptureMethod;
+ uint8_t bTriggerSupport;
+ uint8_t bTriggerUsage;
+ uint8_t bControlSize;
+ uint8_t bmaControls[];
+} __PACKED;
+
+#define VIDEO_SIZEOF_VS_INPUT_HEADER_DESC(p, n) (13 + p * n)
+
+struct video_cs_if_vs_output_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bNumFormats;
+ uint16_t wTotalLength;
+ uint8_t bEndpointAddress;
+ uint8_t bTerminalLink;
+ uint8_t bControlSize;
+ uint8_t bmaControls[];
+} __PACKED;
+
+#define VIDEO_SIZEOF_VS_OUTPUT_TERMINAL_DESC(p, n) (9 + p * n)
+
+struct video_cs_if_vs_format_uncompressed_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bFormatIndex;
+ uint8_t bNumFrameDescriptors;
+ uint8_t guidFormat[16];
+ uint8_t bBitsPerPixel;
+ uint8_t bDefaultFrameIndex;
+ uint8_t bAspectRatioX;
+ uint8_t bAspectRatioY;
+ uint8_t bmInterlaceFlags;
+ uint8_t bCopyProtect;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VS_FORMAT_UNCOMPRESSED_DESC (27)
+
+struct video_cs_if_vs_frame_uncompressed_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bFormatIndex;
+ uint8_t bmCapabilities;
+ uint16_t wWidth;
+ uint16_t wHeight;
+ uint32_t dwMinBitRate;
+ uint32_t dwMaxBitRate;
+ uint32_t dwMaxVideoFrameBufferSize;
+ uint32_t dwDefaultFrameInterval;
+ uint8_t bFrameIntervalType;
+ uint32_t dwFrameInterval;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VS_FRAME_UNCOMPRESSED_DESC 30
+
+struct video_cs_if_vs_format_mjpeg_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bFormatIndex;
+ uint8_t bNumFrameDescriptors;
+ uint8_t bmFlags;
+ uint8_t bDefaultFrameIndex;
+ uint8_t bAspectRatioX;
+ uint8_t bAspectRatioY;
+ uint8_t bmInterlaceFlags;
+ uint8_t bCopyProtect;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VS_FORMAT_MJPEG_DESC 11
+
+struct video_cs_if_vs_frame_mjpeg_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bFormatIndex;
+ uint8_t bmCapabilities;
+ uint16_t wWidth;
+ uint16_t wHeight;
+ uint32_t dwMinBitRate;
+ uint32_t dwMaxBitRate;
+ uint32_t dwMaxVideoFrameBufferSize;
+ uint32_t dwDefaultFrameInterval;
+ uint8_t bFrameIntervalType;
+ uint32_t dwFrameInterval1;
+ uint32_t dwFrameInterval2;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(n) (26 + n)
+
+struct video_cs_if_vs_colorformat_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubType;
+ uint8_t bColorPrimaries;
+ uint8_t bXferCharacteristics;
+ uint8_t bMatrixCoefficients;
+} __PACKED;
+
+#define VIDEO_SIZEOF_VS_COLORFORMAT_DESC 6
+
+struct video_vc_input_terminal_bmcontrol_bitmap {
+ uint32_t scanning_mode : 1;
+ uint32_t auto_exposure_mode : 1;
+ uint32_t auto_exposure_priority : 1;
+ uint32_t exposure_time_absolute : 1;
+ uint32_t exposure_time_relative : 1;
+ uint32_t focus_absolute : 1;
+ uint32_t focus_relative : 1;
+ uint32_t iris_absolute : 1;
+ uint32_t iris_relative : 1;
+ uint32_t zoom_absolute : 1;
+ uint32_t zoom_relative : 1;
+ uint32_t pantilt_absolute : 1;
+ uint32_t pantilt_relative : 1;
+ uint32_t roll_absolute : 1;
+ uint32_t roll_relative : 1;
+ uint32_t reserved : 2;
+ uint32_t focus_auto : 1;
+ uint32_t pricvcy : 1;
+};
+
+struct video_vc_processing_unit_bmcontrol_bitmap {
+ uint16_t brightness : 1;
+ uint16_t contrast : 1;
+ uint16_t hue : 1;
+ uint16_t saturation : 1;
+ uint16_t sharpness : 1;
+ uint16_t gamma : 1;
+ uint16_t white_bal_temp : 1;
+ uint16_t white_bal_comp : 1;
+ uint16_t backlight_comp : 1;
+ uint16_t gain : 1;
+ uint16_t power_line_freq : 1;
+ uint16_t hue_auto : 1;
+ uint16_t white_bal_temp_auto : 1;
+ uint16_t white_bal_comp_auto : 1;
+ uint16_t digital_mult : 1;
+ uint16_t digital_mult_limit : 1;
+};
+
+struct video_camera_capabilities {
+ uint8_t support_get_request : 1;
+ uint8_t support_set_request : 1;
+ uint8_t disabled_by_automatic_mode : 1;
+ uint8_t auto_update_control : 1;
+ uint8_t async_control : 1;
+ uint8_t reserved : 3;
+};
+
+struct video_autoexposure_mode {
+ uint8_t manual_mode : 1;
+ uint8_t auto_mode : 1;
+ uint8_t shutter_priority_mode : 1;
+ uint8_t aperture_priority_mode : 1;
+ uint8_t reserved : 4;
+};
+
+#define VIDEO_GUID_YUY2 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
+#define VIDEO_GUID_NV12 0x4E, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
+#define VIDEO_GUID_M420 0x4D, 0x34, 0x32, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
+#define VIDEO_GUID_I420 0x49, 0x34, 0x32, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
+
+// clang-format off
+#define VIDEO_VC_DESCRIPTOR_INIT(bFirstInterface, bNumEndpoints, bcdUVC, wTotalLength, dwClockFrequency, stridx) \
+ /* Interface Association Descriptor */ \
+ 0x08, \
+ USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \
+ bFirstInterface, \
+ 0x02, \
+ USB_DEVICE_CLASS_VIDEO, \
+ VIDEO_SC_VIDEO_INTERFACE_COLLECTION, \
+ 0x00, \
+ 0x00, \
+ /* VideoControl Interface Descriptor */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ 0x00, /* bInterfaceNumber */ \
+ 0x00, /* bAlternateSetting */ \
+ bNumEndpoints, /* bNumEndpoints:1 endpoint (interrupt endpoint) */ \
+ USB_DEVICE_CLASS_VIDEO, /* bInterfaceClass : CC_VIDEO */ \
+ VIDEO_SC_VIDEOCONTROL, /* bInterfaceSubClass : SC_VIDEOCONTROL */ \
+ VIDEO_PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
+ stridx, /* iInterface:Index to string descriptor that contains the string */ \
+ /*Class-specific VideoControl Interface Descriptor */ \
+ 0x0d, /* bLength */ \
+ 0x24, /* bDescriptorType : CS_INTERFACE */ \
+ VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VC_HEADER subtype */ \
+ WBVAL(bcdUVC), /* bcdUVC : Revision of class specification that this device is based upon.*/ \
+ WBVAL(wTotalLength), /* wTotalLength */ \
+ DBVAL(dwClockFrequency), /* dwClockFrequency : 0x005b8d80 -> 6,000,000 == 6MHz*/ \
+ 0x01, /* bInCollection : Number of streaming interfaces. */ \
+ (uint8_t)(bFirstInterface + 1), /* baInterfaceNr(0) : VideoStreaming interface 1 belongs to this VideoControl interface.*/ \
+ /* Input Terminal 1 -> Processing Unit 2 -> Output Terminal 3 */ \
+ 0x12, \
+ 0x24, \
+ VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
+ 0x01, /* bTerminalID */ \
+ WBVAL(VIDEO_ITT_CAMERA), /* wTerminalType : 0x0201 Camera Sensor*/ \
+ 0x00, /* bAssocTerminal */ \
+ 0x00, /* iTerminal */ \
+ WBVAL(0x0000), /* wObjectiveFocalLengthMin */ \
+ WBVAL(0x0000), /* wObjectiveFocalLengthMax */ \
+ WBVAL(0x0000), /* wOcularFocalLength */ \
+ 0x03, /* bControlSize */ \
+ 0x00, 0x00, 0x00, /* bmControls */ \
+ 0x0c, \
+ 0x24, \
+ VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, \
+ 0x02, /* bUnitID */ \
+ 0x01, /* bSourceID */ \
+ 0x00, 0x00, /* wMaxMultiplier */ \
+ 0x02, /* bControlSize */ \
+ 0x00, 0x00, /* bmControls */ \
+ 0x00, /* iProcessing */ \
+ 0x00, /* bmVideoStandards */ \
+ 0x09, \
+ 0x24, \
+ VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \
+ 0x03, /* bTerminalID */ \
+ WBVAL(VIDEO_TT_STREAMING), \
+ 0x00, /* bAssocTerminal */ \
+ 0x02, /* bSourceID */ \
+ 0x00 /* iTerminal */
+
+#define VIDEO_VS_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints) \
+ /* Video Streaming (VS) Interface Descriptor */ \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType : INTERFACE */ \
+ bInterfaceNumber, /* bInterfaceNumber: Index of this interface */ \
+ bAlternateSetting, /* bAlternateSetting: Index of this alternate setting */ \
+ bNumEndpoints, /* bNumEndpoints : 0 endpoints – no bandwidth used*/ \
+ 0x0e, /* bInterfaceClass : CC_VIDEO */ \
+ 0x02, /* bInterfaceSubClass : SC_VIDEOSTREAMING */ \
+ 0x00, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
+ 0x00 /* iInterface : unused */
+
+#define VIDEO_VS_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, ...) \
+ /*Class-specific VideoStream Header Descriptor (Input) */ \
+ 0x0d + PP_NARG(__VA_ARGS__), \
+ 0x24, \
+ VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE, \
+ bNumFormats, /* bNumFormats : One format descriptor follows. */ \
+ WBVAL(wTotalLength), \
+ bEndpointAddress, \
+ 0x00, /* bmInfo : No dynamic format change supported. */ \
+ 0x03, /* bTerminalLink : This VideoStreaming interface supplies terminal ID 2 (Output Terminal). */ \
+ 0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
+ 0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
+ 0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
+ PP_NARG(__VA_ARGS__), /* bControlSize : Size of the bmaControls field */ \
+ __VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
+
+#define VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors, GUIDFormat) \
+ /*Payload Format(UNCOMPRESSED) Descriptor */ \
+ 0x1b, \
+ 0x24, \
+ VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FORMAT_UNCOMPRESSED subtype */ \
+ bFormatIndex, /* bFormatIndex : First (and only) format descriptor */ \
+ bNumFrameDescriptors, /* bNumFrameDescriptors : One frame descriptor for this format follows. */ \
+ GUIDFormat, /* GUID Format YUY2 {32595559-0000-0010-8000-00AA00389B71} */ \
+ 0x0c, /* bBitsPerPixel : Number of bits per pixel used to specify color in the decoded video frame - 16 for yuy2*/ \
+ 0x01, /* bDefaultFrameIndex : Default frame index is 1. */ \
+ 0x00, /* bAspectRatioX : Non-interlaced stream not required. */ \
+ 0x00, /* bAspectRatioY : Non-interlaced stream not required. */ \
+ 0x00, /* bmInterlaceFlags : Non-interlaced stream */ \
+ 0x00 /* bCopyProtect : No restrictions imposed on the duplication of this video stream. */
+
+#define VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
+ dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, dwFrameInterval) \
+ 0x1e, \
+ 0x24, \
+ VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE, \
+ bFrameIndex, \
+ 0x00, \
+ WBVAL(wWidth), \
+ WBVAL(wHeight), \
+ DBVAL(dwMinBitRate), \
+ DBVAL(dwMaxBitRate), \
+ DBVAL(dwMaxVideoFrameBufferSize), \
+ DBVAL(dwDefaultFrameInterval), \
+ 0x01, \
+ DBVAL(dwFrameInterval)
+
+#define VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors) \
+ /*Payload Format(MJPEG) Descriptor */ \
+ 0x0b, /* bLength */ \
+ 0x24, /* bDescriptorType : CS_INTERFACE */ \
+ 0x06, /* bDescriptorSubType : VS_FORMAT_MJPEG subtype */ \
+ bFormatIndex, /* bFormatIndex : First (and only) format descriptor */ \
+ bNumFrameDescriptors, /* bNumFrameDescriptors : One frame descriptor for this format follows. */ \
+ 0x00, /* bmFlags : Uses fixed size samples.. */ \
+ 0x01, /* bDefaultFrameIndex : Default frame index is 1. */ \
+ 0x00, /* bAspectRatioX : Non-interlaced stream – not required. */ \
+ 0x00, /* bAspectRatioY : Non-interlaced stream – not required. */ \
+ 0x00, /* bmInterlaceFlags : Non-interlaced stream */ \
+ 0x00 /* bCopyProtect : No restrictions imposed on the duplication of this video stream. */
+
+#define VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \
+ dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, bFrameIntervalType, ...) \
+ 0x1a + PP_NARG(__VA_ARGS__), /* bLength */ \
+ 0x24, /* bDescriptorType : CS_INTERFACE */ \
+ VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FRAME_MJPEG */ \
+ bFrameIndex, /* bFrameIndex : First (and only) frame descriptor */ \
+ 0x00, /* bmCapabilities : Still images using capture method 0 are supported at this frame setting.D1: Fixed frame-rate. */ \
+ WBVAL(wWidth), /* wWidth (2bytes): Width of frame is 128 pixels. */ \
+ WBVAL(wHeight), /* wHeight (2bytes): Height of frame is 64 pixels. */ \
+ DBVAL(dwMinBitRate), /* dwMinBitRate (4bytes): Min bit rate in bits/s */ \
+ DBVAL(dwMaxBitRate), /* dwMaxBitRate (4bytes): Max bit rate in bits/s */ \
+ DBVAL(dwMaxVideoFrameBufferSize), /* dwMaxVideoFrameBufSize (4bytes): Maximum video or still frame size, in bytes. */ \
+ dwDefaultFrameInterval, /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
+ bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
+ __VA_ARGS__
+// clang-format on
+#endif /*USB_VIDEO_H */
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/class/video/usbd_video.c b/third-party/cherryusb-0.6.0/class/video/usbd_video.c
new file mode 100644
index 0000000000000000000000000000000000000000..fbb2beec35ba91e95daaf8d2f6cc9ca138c205a2
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/video/usbd_video.c
@@ -0,0 +1,786 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "usbd_video.h"
+
+struct video_entity_info {
+ uint8_t bDescriptorSubtype;
+ uint8_t bEntityId;
+ uint16_t wTerminalType;
+};
+
+struct usbd_video_cfg_priv {
+ struct video_probe_and_commit_controls probe;
+ struct video_probe_and_commit_controls commit;
+ uint8_t power_mode;
+ uint8_t error_code;
+ struct video_entity_info info[3];
+} usbd_video_cfg = {
+ .info[0] = { .bDescriptorSubtype = VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, .bEntityId = 0x01, .wTerminalType = VIDEO_ITT_CAMERA },
+ .info[1] = { .bDescriptorSubtype = VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, .bEntityId = 0x03, .wTerminalType = 0x00 },
+ .info[2] = { .bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, .bEntityId = 0x02, .wTerminalType = 0x00 },
+};
+
+static int usbd_video_control_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
+
+ switch (control_selector) {
+ case VIDEO_VC_VIDEO_POWER_MODE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_SET_CUR:
+ break;
+ case VIDEO_REQUEST_GET_CUR:
+ break;
+ case VIDEO_REQUEST_GET_INFO:
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+
+ break;
+ case VIDEO_VC_REQUEST_ERROR_CODE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR:
+ (*data)[0] = 0x06;
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_INFO:
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ uint8_t entity_id = (uint8_t)(setup->wIndex >> 8);
+ uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
+
+ for (uint8_t i = 0; i < 3; i++) {
+ struct video_entity_info *entity_info = &usbd_video_cfg.info[i];
+ if (entity_info->bEntityId == entity_id) {
+ switch (entity_info->bDescriptorSubtype) {
+ case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
+ break;
+ case VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE:
+ if (entity_info->wTerminalType == VIDEO_ITT_CAMERA) {
+ switch (control_selector) {
+ case VIDEO_CT_AE_MODE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR:
+ (*data)[0] = 0x08;
+ *len = 1;
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint32_t dwExposureTimeAbsolute = 2500;
+ memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
+ *len = 4;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint32_t dwExposureTimeAbsolute = 5; //0.0005sec
+ memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
+ *len = 4;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint32_t dwExposureTimeAbsolute = 2500; //0.2500sec
+ memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
+ *len = 4;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint32_t dwExposureTimeAbsolute = 5; //0.0005sec
+ memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
+ *len = 4;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint32_t dwExposureTimeAbsolute = 2500; //0.2500sec
+ memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4);
+ *len = 4;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_CT_FOCUS_ABSOLUTE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wFocusAbsolute = 0x0080;
+ memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wFocusAbsolute = 0;
+ memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wFocusAbsolute = 0x00ff;
+ memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wFocusAbsolute = 0x0001;
+ memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wFocusAbsolute = 0x0080;
+ memcpy(*data, (uint8_t *)&wFocusAbsolute, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_CT_ZOOM_ABSOLUTE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wObjectiveFocalLength = 0x0064;
+ memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wObjectiveFocalLength = 0x0064;
+ memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wObjectiveFocalLength = 0x00c8;
+ memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wObjectiveFocalLength = 0x0001;
+ memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wObjectiveFocalLength = 0x0064;
+ memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_CT_ROLL_ABSOLUTE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wRollAbsolute = 0x0000;
+ memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wRollAbsolute = 0x0000;
+ memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wRollAbsolute = 0x00ff;
+ memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wRollAbsolute = 0x0001;
+ memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wRollAbsolute = 0x0000;
+ memcpy(*data, (uint8_t *)&wRollAbsolute, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_CT_FOCUS_AUTO_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wFocusAuto = 0x0000;
+ memcpy(*data, (uint8_t *)&wFocusAuto, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
+ return -1;
+ }
+ } else {
+ USB_LOG_WRN("Unhandled Video Class wTerminalType 0x%02x\r\n", entity_info->wTerminalType);
+ return -2;
+ }
+ break;
+ case VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE:
+ break;
+ case VIDEO_VC_SELECTOR_UNIT_DESCRIPTOR_SUBTYPE:
+ break;
+ case VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE:
+ switch (control_selector) {
+ case VIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wBacklightCompensation = 0x0004;
+ memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wBacklightCompensation = 0;
+ memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wBacklightCompensation = 8;
+ memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wBacklightCompensation = 1;
+ memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wBacklightCompensation = 4;
+ memcpy(*data, (uint8_t *)&wBacklightCompensation, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_BRIGHTNESS_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_SET_CUR: {
+ uint16_t wBrightness = (uint16_t)(*data)[1] << 8 | (uint16_t)(*data)[0];
+ USB_LOG_INFO("Video set brightness:%d\r\n", wBrightness);
+ } break;
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wBrightness = 0x0080;
+ memcpy(*data, (uint8_t *)&wBrightness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wBrightness = 0x0001;
+ memcpy(*data, (uint8_t *)&wBrightness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wBrightness = 0x00ff;
+ memcpy(*data, (uint8_t *)&wBrightness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wBrightness = 0x0001;
+ memcpy(*data, (uint8_t *)&wBrightness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wBrightness = 0x0080;
+ memcpy(*data, (uint8_t *)&wBrightness, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_CONTRAST_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wContrast = 0x0080;
+ memcpy(*data, (uint8_t *)&wContrast, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wContrast = 0x0001;
+ memcpy(*data, (uint8_t *)&wContrast, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wContrast = 0x00ff;
+ memcpy(*data, (uint8_t *)&wContrast, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wContrast = 0x0001;
+ memcpy(*data, (uint8_t *)&wContrast, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wContrast = 0x0080;
+ memcpy(*data, (uint8_t *)&wContrast, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_HUE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wHue = 0x0080;
+ memcpy(*data, (uint8_t *)&wHue, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wHue = 0x0001;
+ memcpy(*data, (uint8_t *)&wHue, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wHue = 0x00ff;
+ memcpy(*data, (uint8_t *)&wHue, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wHue = 0x0001;
+ memcpy(*data, (uint8_t *)&wHue, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wHue = 0x0080;
+ memcpy(*data, (uint8_t *)&wHue, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_SATURATION_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wSaturation = 0x0001;
+ memcpy(*data, (uint8_t *)&wSaturation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wSaturation = 0x00ff;
+ memcpy(*data, (uint8_t *)&wSaturation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wSaturation = 0x0001;
+ memcpy(*data, (uint8_t *)&wSaturation, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wSaturation = 0x0080;
+ memcpy(*data, (uint8_t *)&wSaturation, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_SHARPNESS_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wSharpness = 0x0001;
+ memcpy(*data, (uint8_t *)&wSharpness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wSharpness = 0x00ff;
+ memcpy(*data, (uint8_t *)&wSharpness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wSharpness = 0x0001;
+ memcpy(*data, (uint8_t *)&wSharpness, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wSharpness = 0x0080;
+ memcpy(*data, (uint8_t *)&wSharpness, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_GAIN_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wGain = 0;
+ memcpy(*data, (uint8_t *)&wGain, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wGain = 255;
+ memcpy(*data, (uint8_t *)&wGain, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wGain = 1;
+ memcpy(*data, (uint8_t *)&wGain, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wGain = 255;
+ memcpy(*data, (uint8_t *)&wGain, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wWhiteBalance_Temprature = 417;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MIN: {
+ uint16_t wWhiteBalance_Temprature = 300;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_MAX: {
+ uint16_t wWhiteBalance_Temprature = 600;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_RES: {
+ uint16_t wWhiteBalance_Temprature = 1;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
+ *len = 2;
+ } break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03; //struct video_camera_capabilities
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_DEF: {
+ uint16_t wWhiteBalance_Temprature = 417;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2);
+ *len = 2;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR: {
+ uint16_t wWhiteBalance_Temprature_Auto = 1;
+ memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature_Auto, 1);
+ *len = 1;
+ } break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ default:
+ usbd_video_cfg.error_code = 0x06;
+ USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector);
+ return -1;
+ }
+ break;
+ case VIDEO_VC_EXTENSION_UNIT_DESCRIPTOR_SUBTYPE:
+ break;
+ case VIDEO_VC_ENCODING_UNIT_DESCRIPTOR_SUBTYPE:
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
+
+ switch (control_selector) {
+ case VIDEO_VS_PROBE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_SET_CUR:
+ //memcpy((uint8_t *)usbd_video_cfg.probe, *data, setup->wLength);
+ break;
+ case VIDEO_REQUEST_GET_CUR:
+ *data = (uint8_t *)&usbd_video_cfg.probe;
+ *len = sizeof(struct video_probe_and_commit_controls);
+ break;
+
+ case VIDEO_REQUEST_GET_MIN:
+ case VIDEO_REQUEST_GET_MAX:
+ case VIDEO_REQUEST_GET_RES:
+ case VIDEO_REQUEST_GET_DEF:
+ *data = (uint8_t *)&usbd_video_cfg.probe;
+ *len = sizeof(struct video_probe_and_commit_controls);
+ break;
+ case VIDEO_REQUEST_GET_LEN:
+ (*data)[0] = sizeof(struct video_probe_and_commit_controls);
+ *len = 1;
+ break;
+
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03;
+ *len = 1;
+ break;
+
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_VS_COMMIT_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_SET_CUR:
+ //memcpy((uint8_t *)usbd_video_cfg.commit, *data, setup->wLength);
+ break;
+ case VIDEO_REQUEST_GET_CUR:
+ *data = (uint8_t *)&usbd_video_cfg.commit;
+ *len = sizeof(struct video_probe_and_commit_controls);
+ break;
+ case VIDEO_REQUEST_GET_MIN:
+ case VIDEO_REQUEST_GET_MAX:
+ case VIDEO_REQUEST_GET_RES:
+ case VIDEO_REQUEST_GET_DEF:
+ *data = (uint8_t *)&usbd_video_cfg.commit;
+ *len = sizeof(struct video_probe_and_commit_controls);
+ break;
+
+ case VIDEO_REQUEST_GET_LEN:
+ (*data)[0] = sizeof(struct video_probe_and_commit_controls);
+ *len = 1;
+ break;
+
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x03;
+ *len = 1;
+ break;
+
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ case VIDEO_VS_STREAM_ERROR_CODE_CONTROL:
+ switch (setup->bRequest) {
+ case VIDEO_REQUEST_GET_CUR:
+ *data = &usbd_video_cfg.error_code;
+ *len = 1;
+ break;
+ case VIDEO_REQUEST_GET_INFO:
+ (*data)[0] = 0x01;
+ *len = 1;
+ break;
+ default:
+ USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest);
+ return -1;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int video_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ USB_LOG_DBG("Video Class request: "
+ "bRequest 0x%02x\r\n",
+ setup->bRequest);
+
+ uint8_t intf_num = (uint8_t)setup->wIndex;
+ uint8_t entity_id = (uint8_t)(setup->wIndex >> 8);
+
+ if (intf_num == 0) { /* Video Control Interface */
+ if (entity_id == 0) {
+ return usbd_video_control_request_handler(setup, data, len); /* Interface Control Requests */
+ } else {
+ return usbd_video_control_unit_terminal_request_handler(setup, data, len); /* Unit and Terminal Requests */
+ }
+ } else if (intf_num == 1) { /* Video Stream Inteface */
+ return usbd_video_stream_request_handler(setup, data, len); /* Interface Stream Requests */
+ }
+ return -1;
+}
+
+static void video_notify_handler(uint8_t event, void *arg)
+{
+ switch (event) {
+ case USBD_EVENT_RESET:
+ usbd_video_cfg.error_code = 0;
+ usbd_video_cfg.power_mode = 0;
+ break;
+
+ case USBD_EVENT_SET_INTERFACE: {
+ struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg;
+ if (intf->bAlternateSetting == 1) {
+ usbd_video_open(intf->bInterfaceNumber);
+ } else {
+ usbd_video_close(intf->bInterfaceNumber);
+ }
+ }
+
+ break;
+ default:
+ break;
+ }
+}
+
+void usbd_video_probe_and_commit_controls_init(uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
+{
+ usbd_video_cfg.probe.hintUnion.bmHint = 0x01;
+ usbd_video_cfg.probe.hintUnion1.bmHint = 0;
+ usbd_video_cfg.probe.bFormatIndex = 1;
+ usbd_video_cfg.probe.bFrameIndex = 1;
+ usbd_video_cfg.probe.dwFrameInterval = dwFrameInterval;
+ usbd_video_cfg.probe.wKeyFrameRate = 0;
+ usbd_video_cfg.probe.wPFrameRate = 0;
+ usbd_video_cfg.probe.wCompQuality = 0;
+ usbd_video_cfg.probe.wCompWindowSize = 0;
+ usbd_video_cfg.probe.wDelay = 0;
+ usbd_video_cfg.probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
+ usbd_video_cfg.probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
+ usbd_video_cfg.probe.dwClockFrequency = 0;
+ usbd_video_cfg.probe.bmFramingInfo = 0;
+ usbd_video_cfg.probe.bPreferedVersion = 0;
+ usbd_video_cfg.probe.bMinVersion = 0;
+ usbd_video_cfg.probe.bMaxVersion = 0;
+
+ usbd_video_cfg.commit.hintUnion.bmHint = 0x01;
+ usbd_video_cfg.commit.hintUnion1.bmHint = 0;
+ usbd_video_cfg.commit.bFormatIndex = 1;
+ usbd_video_cfg.commit.bFrameIndex = 1;
+ usbd_video_cfg.commit.dwFrameInterval = dwFrameInterval;
+ usbd_video_cfg.commit.wKeyFrameRate = 0;
+ usbd_video_cfg.commit.wPFrameRate = 0;
+ usbd_video_cfg.commit.wCompQuality = 0;
+ usbd_video_cfg.commit.wCompWindowSize = 0;
+ usbd_video_cfg.commit.wDelay = 0;
+ usbd_video_cfg.commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
+ usbd_video_cfg.commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
+ usbd_video_cfg.commit.dwClockFrequency = 0;
+ usbd_video_cfg.commit.bmFramingInfo = 0;
+ usbd_video_cfg.commit.bPreferedVersion = 0;
+ usbd_video_cfg.commit.bMinVersion = 0;
+ usbd_video_cfg.commit.bMaxVersion = 0;
+}
+
+struct usbd_interface *usbd_video_alloc_intf(uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
+{
+ struct usbd_interface *intf = usb_malloc(sizeof(struct usbd_interface));
+ if (intf == NULL) {
+ USB_LOG_ERR("no mem to alloc intf\r\n");
+ return NULL;
+ }
+
+ intf->class_interface_handler = video_class_interface_request_handler;
+ intf->class_endpoint_handler = NULL;
+ intf->vendor_handler = NULL;
+ intf->notify_handler = video_notify_handler;
+
+ usbd_video_probe_and_commit_controls_init(dwFrameInterval, dwMaxVideoFrameSize, dwMaxPayloadTransferSize);
+ return intf;
+}
+
+uint32_t usbd_video_mjpeg_payload_fill(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 / usbd_video_cfg.probe.dwMaxPayloadTransferSize + 1;
+ last_packet_size = input_len - ((packets - 1) * (usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2)) + 2;
+
+ for (size_t i = 0; i < packets; i++) {
+ output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
+ output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
+ if (i == (packets - 1)) {
+ memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size - 2);
+ output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
+ } else {
+ memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2);
+ picture_pos += usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2;
+ }
+ }
+ uvc_header[1] ^=1;
+ *out_len = (input_len + 2 * packets);
+ return packets;
+}
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/class/video/usbd_video.h b/third-party/cherryusb-0.6.0/class/video/usbd_video.h
new file mode 100644
index 0000000000000000000000000000000000000000..cbb54d715b2be88cf24795cd2d883439e06d0086
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/video/usbd_video.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBD_VIDEO_H
+#define USBD_VIDEO_H
+
+#include "usb_video.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Alloc video interface driver */
+struct usbd_interface *usbd_video_alloc_intf(uint32_t dwFrameInterval,
+ uint32_t dwMaxVideoFrameSize,
+ uint32_t dwMaxPayloadTransferSize);
+
+void usbd_video_open(uint8_t intf);
+void usbd_video_close(uint8_t intf);
+uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBD_VIDEO_H */
diff --git a/third-party/cherryusb-0.6.0/class/video/usbh_video.c b/third-party/cherryusb-0.6.0/class/video/usbh_video.c
new file mode 100644
index 0000000000000000000000000000000000000000..e6952ca232b3e872835616d274f6b335be405db2
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/video/usbh_video.c
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbh_core.h"
+#include "usbh_video.h"
+
+#define DEV_FORMAT "/dev/video%d"
+
+/* general descriptor field offsets */
+#define DESC_bLength 0 /** Length offset */
+#define DESC_bDescriptorType 1 /** Descriptor type offset */
+#define DESC_bDescriptorSubType 2 /** Descriptor subtype offset */
+#define DESC_bNumFormats 3 /** Descriptor numformat offset */
+#define DESC_bNumFrameDescriptors 4 /** Descriptor numframe offset */
+#define DESC_bFormatIndex 3 /** Descriptor format index offset */
+#define DESC_bFrameIndex 3 /** Descriptor frame index offset */
+
+/* interface descriptor field offsets */
+#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
+#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
+
+static uint32_t g_devinuse = 0;
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_video_buf[128];
+
+static const char *format_type[] = { "uncompressed", "mjpeg" };
+
+static int __s_r_1370705v[256] = { 0 };
+static int __s_b_1732446u[256] = { 0 };
+static int __s_g_337633u[256] = { 0 };
+static int __s_g_698001v[256] = { 0 };
+
+static void inityuyv2rgb_table(void)
+{
+ for (int i = 0; i < 256; i++) {
+ __s_r_1370705v[i] = (1.370705 * (i - 128));
+ __s_b_1732446u[i] = (1.732446 * (i - 128));
+ __s_g_337633u[i] = (0.337633 * (i - 128));
+ __s_g_698001v[i] = (0.698001 * (i - 128));
+ }
+}
+
+static void yuyv2rgb565(void *input, void *output, uint32_t len)
+{
+ int y0, u, y1, v;
+ uint8_t r, g, b;
+ int val;
+
+ for (uint32_t i = 0; i < len / 4; i++) {
+ y0 = (int)(((uint8_t *)input)[i * 4 + 0]);
+ u = (int)(((uint8_t *)input)[i * 4 + 1]);
+ y1 = (int)(((uint8_t *)input)[i * 4 + 2]);
+ v = (int)(((uint8_t *)input)[i * 4 + 3]);
+ val = y0 + __s_r_1370705v[v];
+ r = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
+ val = y0 - __s_g_337633u[u] - __s_g_698001v[v];
+ g = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
+ val = y0 + __s_b_1732446u[u];
+ b = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
+ ((uint16_t *)output)[i * 2] = (uint16_t)(b >> 3) | ((uint16_t)(g >> 2) << 5) | ((uint16_t)(r >> 3) << 11);
+ val = y1 + __s_r_1370705v[v];
+ r = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
+ val = y1 - __s_g_337633u[u] - __s_g_698001v[v];
+ g = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
+ val = y1 + __s_b_1732446u[u];
+ b = (val < 0) ? 0 : ((val > 255) ? 255 : (uint8_t)val);
+ ((uint16_t *)output)[i * 2 + 1] = (uint16_t)(b >> 3) | ((uint16_t)(g >> 2) << 5) | ((uint16_t)(r >> 3) << 11);
+ }
+}
+
+static int usbh_video_devno_alloc(struct usbh_video *video_class)
+{
+ int devno;
+
+ for (devno = 0; devno < 32; devno++) {
+ uint32_t bitno = 1 << devno;
+ if ((g_devinuse & bitno) == 0) {
+ g_devinuse |= bitno;
+ video_class->minor = devno;
+ return 0;
+ }
+ }
+
+ return -EMFILE;
+}
+
+static void usbh_video_devno_free(struct usbh_video *video_class)
+{
+ int devno = video_class->minor;
+
+ if (devno >= 0 && devno < 32) {
+ g_devinuse &= ~(1 << devno);
+ }
+}
+
+int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
+{
+ struct usb_setup_packet *setup = &video_class->hport->setup;
+ int ret;
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = VIDEO_REQUEST_GET_CUR;
+ setup->wValue = cs << 8;
+ setup->wIndex = (entity_id << 8) | intf;
+ setup->wLength = len;
+
+ ret = usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
+ if (ret < 0) {
+ return ret;
+ }
+ memcpy(buf, g_video_buf, len);
+ return ret;
+}
+
+int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len)
+{
+ struct usb_setup_packet *setup = &video_class->hport->setup;
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = VIDEO_REQUEST_SET_CUR;
+ setup->wValue = cs << 8;
+ setup->wIndex = (entity_id << 8) | intf;
+ setup->wLength = len;
+
+ memcpy(g_video_buf, buf, len);
+
+ return usbh_control_transfer(video_class->hport->ep0, setup, g_video_buf);
+}
+
+int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class)
+{
+ return usbh_video_get_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
+}
+
+int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
+{
+ video_class->probe.bFormatIndex = formatindex;
+ video_class->probe.bFrameIndex = frameindex;
+ video_class->probe.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
+ video_class->probe.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
+ return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
+}
+
+int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
+{
+ video_class->commit.bFormatIndex = formatindex;
+ video_class->commit.bFrameIndex = frameindex;
+ video_class->commit.dwMaxVideoFrameSize = dwMaxVideoFrameSize;
+ video_class->commit.dwMaxPayloadTransferSize = dwMaxPayloadTransferSize;
+ return usbh_video_set_cur(video_class, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
+}
+
+int usbh_video_open(struct usbh_video *video_class, uint8_t altsetting)
+{
+ struct usb_setup_packet *setup = &video_class->hport->setup;
+ struct usb_endpoint_descriptor *ep_desc;
+ uint8_t mult;
+ uint16_t mps;
+ int ret;
+
+ if (video_class->is_opened) {
+ return -EMFILE;
+ }
+
+ if (altsetting > (video_class->num_of_intf_altsettings - 1)) {
+ return -EINVAL;
+ }
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = USB_REQUEST_SET_INTERFACE;
+ setup->wValue = altsetting;
+ setup->wIndex = video_class->data_intf;
+ setup->wLength = 0;
+
+ ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
+ if (ret < 0) {
+ return ret;
+ }
+
+ ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[altsetting].ep[0].ep_desc;
+ mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
+ mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
+ if (ep_desc->bEndpointAddress & 0x80) {
+ video_class->isoin_mps = mps * (mult + 1);
+ usbh_hport_activate_epx(&video_class->isoin, video_class->hport, ep_desc);
+ } else {
+ video_class->isoout_mps = mps * (mult + 1);
+ usbh_hport_activate_epx(&video_class->isoout, video_class->hport, ep_desc);
+ }
+ USB_LOG_INFO("Open video and select altsetting:%u\r\n", altsetting);
+ video_class->is_opened = true;
+ return ret;
+}
+
+int usbh_video_close(struct usbh_video *video_class)
+{
+ struct usb_setup_packet *setup = &video_class->hport->setup;
+ int ret;
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = USB_REQUEST_SET_INTERFACE;
+ setup->wValue = 0;
+ setup->wIndex = video_class->data_intf;
+ setup->wLength = 0;
+
+ ret = usbh_control_transfer(video_class->hport->ep0, setup, NULL);
+ if (ret < 0) {
+ return ret;
+ }
+ if (video_class->isoin) {
+ usbh_pipe_free(video_class->isoin);
+ video_class->isoin = NULL;
+ }
+
+ if (video_class->isoout) {
+ usbh_pipe_free(video_class->isoout);
+ video_class->isoout = NULL;
+ }
+
+ USB_LOG_INFO("Close video device\r\n");
+ video_class->is_opened = false;
+ return ret;
+}
+
+void usbh_video_list_info(struct usbh_video *video_class)
+{
+ struct usbh_hubport *hport;
+ struct usb_endpoint_descriptor *ep_desc;
+ uint8_t mult;
+ uint16_t mps;
+
+ USB_LOG_INFO("============= Video device information ===================\r\n");
+ USB_LOG_INFO("bcdVDC:%04x\r\n", video_class->bcdVDC);
+ USB_LOG_INFO("Num of altsettings:%02x\r\n", video_class->num_of_intf_altsettings);
+
+ hport = video_class->hport;
+
+ for (uint8_t i = 1; i < video_class->num_of_intf_altsettings; i++) {
+ ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[i].ep[0].ep_desc;
+
+ mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
+ mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
+
+ USB_LOG_INFO("Altsetting:%u, Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
+ i,
+ ep_desc->bEndpointAddress,
+ ep_desc->bmAttributes,
+ mps,
+ ep_desc->bInterval,
+ mult);
+ }
+
+ USB_LOG_INFO("bNumFormats:%u\r\n", video_class->num_of_formats);
+ for (uint8_t i = 0; i < video_class->num_of_formats; i++) {
+ USB_LOG_INFO(" FormatIndex:%u\r\n", i + 1);
+ USB_LOG_INFO(" FormatType:%s\r\n", format_type[video_class->format[i].format_type]);
+ USB_LOG_INFO(" bNumFrames:%u\r\n", video_class->format[i].num_of_frames);
+ USB_LOG_INFO(" Resolution:\r\n");
+ for (uint8_t j = 0; j < video_class->format[i].num_of_frames; j++) {
+ USB_LOG_INFO(" FrameIndex:%u\r\n", j + 1);
+ USB_LOG_INFO(" wWidth: %d, wHeight: %d\r\n",
+ video_class->format[i].frame[j].wWidth,
+ video_class->format[i].frame[j].wHeight);
+ }
+ }
+
+ usbh_videostreaming_get_cur_probe(video_class);
+
+ USB_LOG_INFO("dwMaxVideoFrameSize:%u,dwMaxPayloadTransferSize:%u\r\n", (int)video_class->probe.dwMaxVideoFrameSize, (int)video_class->probe.dwMaxPayloadTransferSize);
+
+ USB_LOG_INFO("============= Video device information ===================\r\n");
+}
+
+static int usbh_video_ctrl_intf_connect(struct usbh_hubport *hport, uint8_t intf)
+{
+ int ret;
+ uint8_t cur_iface = 0xff;
+ uint8_t cur_alt_setting = 0xff;
+ uint8_t frame_index = 0xff;
+ uint8_t format_index = 0xff;
+ uint8_t num_of_frames = 0xff;
+ uint8_t *p;
+
+ struct usbh_video *video_class = usb_malloc(sizeof(struct usbh_video));
+ if (video_class == NULL) {
+ USB_LOG_ERR("Fail to alloc video_class\r\n");
+ return -ENOMEM;
+ }
+
+ memset(video_class, 0, sizeof(struct usbh_video));
+ usbh_video_devno_alloc(video_class);
+ video_class->hport = hport;
+ video_class->ctrl_intf = intf;
+ video_class->data_intf = intf + 1;
+ video_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
+
+ hport->config.intf[intf].priv = video_class;
+
+ ret = usbh_video_close(video_class);
+ if (ret < 0) {
+ USB_LOG_ERR("Fail to close video device\r\n");
+ return ret;
+ }
+
+ p = hport->raw_config_desc;
+ while (p[DESC_bLength]) {
+ switch (p[DESC_bDescriptorType]) {
+ case USB_DESCRIPTOR_TYPE_INTERFACE:
+ cur_iface = p[INTF_DESC_bInterfaceNumber];
+ //cur_alt_setting = p[INTF_DESC_bAlternateSetting];
+ break;
+ case USB_DESCRIPTOR_TYPE_ENDPOINT:
+ //ep_desc = (struct usb_endpoint_descriptor *)p;
+ break;
+ case VIDEO_CS_INTERFACE_DESCRIPTOR_TYPE:
+ if (cur_iface == video_class->ctrl_intf) {
+ switch (p[DESC_bDescriptorSubType]) {
+ case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
+ video_class->bcdVDC = ((uint16_t)p[4] << 8) | (uint16_t)p[3];
+ break;
+ case VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE:
+ break;
+ case VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE:
+ break;
+ case VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE:
+ break;
+
+ default:
+ break;
+ }
+ } else if (cur_iface == video_class->data_intf) {
+ switch (p[DESC_bDescriptorSubType]) {
+ case VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE:
+ video_class->num_of_formats = p[DESC_bNumFormats];
+ break;
+ case VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_SUBTYPE:
+ format_index = p[DESC_bFormatIndex];
+ num_of_frames = p[DESC_bNumFrameDescriptors];
+
+ video_class->format[format_index - 1].num_of_frames = num_of_frames;
+ video_class->format[format_index - 1].format_type = USBH_VIDEO_FORMAT_UNCOMPRESSED;
+ break;
+ case VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_SUBTYPE:
+ format_index = p[DESC_bFormatIndex];
+ num_of_frames = p[DESC_bNumFrameDescriptors];
+
+ video_class->format[format_index - 1].num_of_frames = num_of_frames;
+ video_class->format[format_index - 1].format_type = USBH_VIDEO_FORMAT_MJPEG;
+ break;
+ case VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE:
+ frame_index = p[DESC_bFrameIndex];
+
+ video_class->format[format_index - 1].frame[frame_index - 1].wWidth = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->wWidth;
+ video_class->format[format_index - 1].frame[frame_index - 1].wHeight = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->wHeight;
+ break;
+ case VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE:
+ frame_index = p[DESC_bFrameIndex];
+
+ video_class->format[format_index - 1].frame[frame_index - 1].wWidth = ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->wWidth;
+ video_class->format[format_index - 1].frame[frame_index - 1].wHeight = ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->wHeight;
+ break;
+ default:
+ break;
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ /* skip to next descriptor */
+ p += p[DESC_bLength];
+ }
+
+ usbh_video_list_info(video_class);
+
+ snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, video_class->minor);
+
+ inityuyv2rgb_table();
+ USB_LOG_INFO("Register Video Class:%s\r\n", hport->config.intf[intf].devname);
+
+ return 0;
+}
+
+static int usbh_video_ctrl_intf_disconnect(struct usbh_hubport *hport, uint8_t intf)
+{
+ int ret = 0;
+
+ struct usbh_video *video_class = (struct usbh_video *)hport->config.intf[intf].priv;
+
+ if (video_class) {
+ usbh_video_devno_free(video_class);
+
+ if (video_class->isoin) {
+ usbh_pipe_free(video_class->isoin);
+ }
+
+ if (video_class->isoout) {
+ usbh_pipe_free(video_class->isoout);
+ }
+
+ memset(video_class, 0, sizeof(struct usbh_video));
+ usb_free(video_class);
+
+ if (hport->config.intf[intf].devname[0] != '\0')
+ USB_LOG_INFO("Unregister Video Class:%s\r\n", hport->config.intf[intf].devname);
+ }
+
+ return ret;
+}
+
+static int usbh_video_data_intf_connect(struct usbh_hubport *hport, uint8_t intf)
+{
+ USB_LOG_WRN("Ignore video data intf\r\n");
+ return 0;
+}
+
+static int usbh_video_data_intf_disconnect(struct usbh_hubport *hport, uint8_t intf)
+{
+ return 0;
+}
+
+void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream)
+{
+ struct usbh_iso_frame_packet *iso_packet;
+ uint32_t num_of_iso_packets;
+ uint8_t *tmp_buf;
+ uint8_t data_offset;
+ uint32_t data_len;
+
+ num_of_iso_packets = urb->num_of_iso_packets;
+ iso_packet = urb->iso_packet;
+
+ for (uint32_t i = 0; i < num_of_iso_packets; i++) {
+ /*
+ uint8_t frameIdentifier : 1U;
+ uint8_t endOfFrame : 1U;
+ uint8_t presentationTimeStamp : 1U;
+ uint8_t sourceClockReference : 1U;
+ uint8_t reserved : 1U;
+ uint8_t stillImage : 1U;
+ uint8_t errorBit : 1U;
+ uint8_t endOfHeader : 1U;
+ */
+ if (iso_packet[i].actual_length == 0) { /* skip no data */
+ continue;
+ }
+ if (iso_packet[i].actual_length < iso_packet[i].transfer_buffer[0]) { /* do not be illegal */
+ while (1) {
+ }
+ }
+ if ((iso_packet[i].transfer_buffer[0] > 12) || (iso_packet[i].transfer_buffer[0] == 0)) { /* do not be illegal */
+ while (1) {
+ }
+ }
+ if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
+ stream->bufoffset = 0;
+ continue;
+ }
+
+ data_offset = iso_packet[i].transfer_buffer[0];
+ data_len = iso_packet[i].actual_length - iso_packet[i].transfer_buffer[0];
+
+ tmp_buf = stream->bufbase + stream->bufoffset;
+ stream->bufoffset += data_len;
+
+ memcpy(tmp_buf, &iso_packet[i].transfer_buffer[data_offset], data_len);
+ if ((stream->bufbase[0] != 0xff) && (stream->bufbase[1] != 0xd8)) {
+ stream->bufoffset = 0;
+ continue;
+ }
+
+ if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
+ if ((stream->bufbase[stream->bufoffset - 2] != 0xff) && (stream->bufbase[stream->bufoffset - 1] != 0xd9)) {
+ stream->bufoffset = 0;
+ continue;
+ }
+ if (stream->video_one_frame_callback) {
+ stream->video_one_frame_callback(stream);
+ }
+ stream->bufoffset = 0;
+ }
+ }
+}
+
+void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_videostreaming *stream)
+{
+ struct usbh_iso_frame_packet *iso_packet;
+ uint32_t num_of_iso_packets;
+ uint8_t *tmp_buf;
+ uint8_t data_offset;
+ uint32_t data_len;
+
+ num_of_iso_packets = urb->num_of_iso_packets;
+ iso_packet = urb->iso_packet;
+
+ for (uint32_t i = 0; i < num_of_iso_packets; i++) {
+ /*
+ uint8_t frameIdentifier : 1U;
+ uint8_t endOfFrame : 1U;
+ uint8_t presentationTimeStamp : 1U;
+ uint8_t sourceClockReference : 1U;
+ uint8_t reserved : 1U;
+ uint8_t stillImage : 1U;
+ uint8_t errorBit : 1U;
+ uint8_t endOfHeader : 1U;
+ */
+
+ if (iso_packet[i].actual_length == 0) { /* skip no data */
+ continue;
+ }
+ if (iso_packet[i].actual_length < iso_packet[i].transfer_buffer[0]) { /* do not be illegal */
+ while (1) {
+ }
+ }
+ if ((iso_packet[i].transfer_buffer[0] > 12) || (iso_packet[i].transfer_buffer[0] == 0)) { /* do not be illegal */
+ while (1) {
+ }
+ }
+ if (iso_packet[i].transfer_buffer[1] & (1 << 6)) { /* error bit, re-receive */
+ stream->bufoffset = 0;
+ continue;
+ }
+
+ data_offset = iso_packet[i].transfer_buffer[0];
+ data_len = iso_packet[i].actual_length - iso_packet[i].transfer_buffer[0];
+
+ tmp_buf = stream->bufbase + stream->bufoffset;
+ stream->bufoffset += data_len;
+
+ yuyv2rgb565(&iso_packet[i].transfer_buffer[data_offset], tmp_buf, data_len);
+ if (iso_packet[i].transfer_buffer[1] & (1 << 1)) {
+ if (stream->video_one_frame_callback) {
+ stream->video_one_frame_callback(stream);
+ }
+ stream->bufoffset = 0;
+ }
+ }
+}
+
+const struct usbh_class_driver video_class_ctrl_intf_driver = {
+ .driver_name = "video",
+ .connect = usbh_video_ctrl_intf_connect,
+ .disconnect = usbh_video_ctrl_intf_disconnect
+};
+
+const struct usbh_class_driver video_class_data_intf_driver = {
+ .driver_name = "video",
+ .connect = usbh_video_data_intf_connect,
+ .disconnect = usbh_video_data_intf_disconnect
+};
+
+CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_intf_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,
+ .vid = 0x00,
+ .pid = 0x00,
+ .class_driver = &video_class_ctrl_intf_driver
+};
+
+CLASS_INFO_DEFINE const struct usbh_class_info video_data_intf_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,
+ .vid = 0x00,
+ .pid = 0x00,
+ .class_driver = &video_class_data_intf_driver
+};
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/class/video/usbh_video.h b/third-party/cherryusb-0.6.0/class/video/usbh_video.h
new file mode 100644
index 0000000000000000000000000000000000000000..4cc0933a806eb12afbbf0a28dde4fd0b254b8373
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/video/usbh_video.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBH_VIDEO_H
+#define USBH_VIDEO_H
+
+#include "usb_video.h"
+
+#define USBH_VIDEO_FORMAT_UNCOMPRESSED 0
+#define USBH_VIDEO_FORMAT_MJPEG 1
+
+struct usbh_video_resolution {
+ uint16_t wWidth;
+ uint16_t wHeight;
+};
+
+struct usbh_video_format {
+ struct usbh_video_resolution frame[8];
+ uint8_t format_type;
+ uint8_t num_of_frames;
+};
+
+struct usbh_videostreaming {
+ uint8_t *bufbase;
+ uint32_t bufoffset;
+ void (*video_one_frame_callback)(struct usbh_videostreaming *stream);
+};
+
+struct usbh_video {
+ struct usbh_hubport *hport;
+
+ uint8_t ctrl_intf; /* interface number */
+ uint8_t data_intf; /* interface number */
+ uint8_t minor;
+ usbh_pipe_t isoin; /* ISO IN endpoint */
+ usbh_pipe_t isoout; /* ISO OUT endpoint */
+ struct video_probe_and_commit_controls probe;
+ struct video_probe_and_commit_controls commit;
+ uint16_t isoin_mps;
+ uint16_t isoout_mps;
+ bool is_opened;
+ uint16_t bcdVDC;
+ uint8_t num_of_intf_altsettings;
+ uint8_t num_of_formats;
+ struct usbh_video_format format[3];
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int usbh_video_get_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
+int usbh_video_set_cur(struct usbh_video *video_class, uint8_t intf, uint8_t entity_id, uint8_t cs, uint8_t *buf, uint16_t len);
+int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class);
+int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize);
+int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize);
+
+int usbh_video_open(struct usbh_video *video_class, uint8_t altsetting);
+int usbh_video_close(struct usbh_video *video_class);
+
+void usbh_video_list_info(struct usbh_video *video_class);
+
+void usbh_videostreaming_parse_mjpeg(struct usbh_urb *urb, struct usbh_videostreaming *stream);
+void usbh_videostreaming_parse_yuyv2rgb565(struct usbh_urb *urb, struct usbh_videostreaming *stream);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBH_VIDEO_H */
diff --git a/third-party/cherryusb-0.6.0/class/wireless/ndis.h b/third-party/cherryusb-0.6.0/class/wireless/ndis.h
new file mode 100644
index 0000000000000000000000000000000000000000..80a6e66968f58e16f30ff9ebcc6a28ab7dfc40cf
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/wireless/ndis.h
@@ -0,0 +1,270 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file ndis.h ***************************************************************
+ *
+ * \brief
+ * This file contains the possible external configuration of the USB.
+ *
+ * \addtogroup usbstick
+ *
+ *
+ ******************************************************************************/
+
+/**
+ \ingroup usbstick
+ \defgroup RNDIS RNDIS Support
+ @{
+ */
+
+/*
+ * ndis.h
+ *
+ * Modified by Colin O'Flynn
+ * ntddndis.h modified by Benedikt Spranger
+ *
+ * Thanks to the cygwin development team,
+ * espacially to Casper S. Hornstrup
+ *
+ * THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ * This source code is offered for use in the public domain. You may
+ * use, modify or distribute it freely.
+ *
+ * This code is distributed in the hope that it will be useful but
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ * DISCLAIMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#ifndef _LINUX_NDIS_H
+#define _LINUX_NDIS_H
+
+#define NDIS_STATUS_MULTICAST_FULL 0xC0010009
+#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A
+#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B
+
+/* from drivers/net/sk98lin/h/skgepnmi.h */
+#define OID_PNP_CAPABILITIES 0xFD010100
+#define OID_PNP_SET_POWER 0xFD010101
+#define OID_PNP_QUERY_POWER 0xFD010102
+#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103
+#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104
+#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
+
+enum NDIS_DEVICE_POWER_STATE {
+ NdisDeviceStateUnspecified = 0,
+ NdisDeviceStateD0,
+ NdisDeviceStateD1,
+ NdisDeviceStateD2,
+ NdisDeviceStateD3,
+ NdisDeviceStateMaximum
+};
+
+struct NDIS_PM_WAKE_UP_CAPABILITIES {
+ enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp;
+ enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp;
+ enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp;
+};
+
+/* NDIS_PNP_CAPABILITIES.Flags constants */
+#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001
+#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002
+#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004
+
+/*
+struct NDIS_PNP_CAPABILITIES {
+ __le32 Flags;
+ struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities;
+};
+
+struct NDIS_PM_PACKET_PATTERN {
+ __le32 Priority;
+ __le32 Reserved;
+ __le32 MaskSize;
+ __le32 PatternOffset;
+ __le32 PatternSize;
+ __le32 PatternFlags;
+};
+*/
+
+/* Required Object IDs (OIDs) */
+#define OID_GEN_SUPPORTED_LIST 0x00010101
+#define OID_GEN_HARDWARE_STATUS 0x00010102
+#define OID_GEN_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_MEDIA_IN_USE 0x00010104
+#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
+#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
+#define OID_GEN_LINK_SPEED 0x00010107
+#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
+#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
+#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
+#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
+#define OID_GEN_VENDOR_ID 0x0001010C
+#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
+#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
+#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
+#define OID_GEN_DRIVER_VERSION 0x00010110
+#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
+#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
+#define OID_GEN_MAC_OPTIONS 0x00010113
+#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
+#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
+#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
+#define OID_GEN_SUPPORTED_GUIDS 0x00010117
+#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118
+#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119
+#define OID_GEN_MACHINE_NAME 0x0001021A
+#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B
+#define OID_GEN_VLAN_ID 0x0001021C
+
+/* Optional OIDs */
+#define OID_GEN_MEDIA_CAPABILITIES 0x00010201
+#define OID_GEN_PHYSICAL_MEDIUM 0x00010202
+
+/* Required statistics OIDs */
+#define OID_GEN_XMIT_OK 0x00020101
+#define OID_GEN_RCV_OK 0x00020102
+#define OID_GEN_XMIT_ERROR 0x00020103
+#define OID_GEN_RCV_ERROR 0x00020104
+#define OID_GEN_RCV_NO_BUFFER 0x00020105
+
+/* Optional statistics OIDs */
+#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
+#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
+#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
+#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
+#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
+#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
+#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
+#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
+#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
+#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
+#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
+#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
+#define OID_GEN_RCV_CRC_ERROR 0x0002020D
+#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
+#define OID_GEN_GET_TIME_CAPS 0x0002020F
+#define OID_GEN_GET_NETCARD_TIME 0x00020210
+#define OID_GEN_NETCARD_LOAD 0x00020211
+#define OID_GEN_DEVICE_PROFILE 0x00020212
+#define OID_GEN_INIT_TIME_MS 0x00020213
+#define OID_GEN_RESET_COUNTS 0x00020214
+#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215
+#define OID_GEN_FRIENDLY_NAME 0x00020216
+#define OID_GEN_MINIPORT_INFO 0x00020217
+#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218
+
+/* IEEE 802.3 (Ethernet) OIDs */
+#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
+
+#define OID_802_3_PERMANENT_ADDRESS 0x01010101
+#define OID_802_3_CURRENT_ADDRESS 0x01010102
+#define OID_802_3_MULTICAST_LIST 0x01010103
+#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
+#define OID_802_3_MAC_OPTIONS 0x01010105
+#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
+#define OID_802_3_XMIT_DEFERRED 0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
+#define OID_802_3_RCV_OVERRUN 0x01020203
+#define OID_802_3_XMIT_UNDERRUN 0x01020204
+#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
+#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
+
+/* Wireless LAN OIDs */
+/* Mandatory */
+#define OID_802_11_BSSID 0x0D010101 /* Q S */
+#define OID_802_11_SSID 0x0D010102 /* Q S */
+#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 /* Q S */
+#define OID_802_11_RSSI 0x0D010206 /* Q I */
+#define OID_802_11_BSSID_LIST 0x0D010217 /* Q */
+#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A /* S */
+#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 /* Q S */
+#define OID_802_11_SUPPORTED_RATES 0x0D01020E /* Q */
+#define OID_802_11_CONFIGURATION 0x0D010211 /* Q S */
+#define OID_802_11_ADD_WEP 0x0D010113 /* S */
+#define OID_802_11_WEP_STATUS 0x0D01011B /* Q S */
+#define OID_802_11_REMOVE_WEP 0x0D010114 /* S */
+#define OID_802_11_DISASSOCIATE 0x0D010115 /* S */
+#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 /* Q S */
+#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C /* S */
+
+/* OID_GEN_MINIPORT_INFO constants */
+#define NDIS_MINIPORT_BUS_MASTER 0x00000001
+#define NDIS_MINIPORT_WDM_DRIVER 0x00000002
+#define NDIS_MINIPORT_SG_LIST 0x00000004
+#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008
+#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010
+#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020
+#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040
+#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080
+#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100
+#define NDIS_MINIPORT_IS_NDIS_5 0x00000200
+#define NDIS_MINIPORT_IS_CO 0x00000400
+#define NDIS_MINIPORT_DESERIALIZE 0x00000800
+#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000
+#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000
+#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000
+#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000
+#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000
+#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000
+#define NDIS_MINIPORT_HIDDEN 0x00040000
+#define NDIS_MINIPORT_SWENUM 0x00080000
+#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000
+#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000
+#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000
+#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000
+#define NDIS_MINIPORT_64BITS_DMA 0x01000000
+
+#define NDIS_MEDIUM_802_3 0x00000000
+#define NDIS_MEDIUM_802_5 0x00000001
+#define NDIS_MEDIUM_FDDI 0x00000002
+#define NDIS_MEDIUM_WAN 0x00000003
+#define NDIS_MEDIUM_LOCAL_TALK 0x00000004
+#define NDIS_MEDIUM_DIX 0x00000005
+#define NDIS_MEDIUM_ARCENT_RAW 0x00000006
+#define NDIS_MEDIUM_ARCENT_878_2 0x00000007
+#define NDIS_MEDIUM_ATM 0x00000008
+#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009
+#define NDIS_MEDIUM_IRDA 0x0000000A
+#define NDIS_MEDIUM_BPC 0x0000000B
+#define NDIS_MEDIUM_CO_WAN 0x0000000C
+#define NDIS_MEDIUM_1394 0x0000000D
+
+#define NDIS_PACKET_TYPE_DIRECTED 0x00000001
+#define NDIS_PACKET_TYPE_MULTICAST 0x00000002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
+#define NDIS_PACKET_TYPE_BROADCAST 0x00000008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010
+#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020
+#define NDIS_PACKET_TYPE_SMT 0x00000040
+#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080
+#define NDIS_PACKET_TYPE_GROUP 0x00000100
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200
+#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400
+#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800
+
+#define NDIS_MEDIA_STATE_CONNECTED 0x00000000
+#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001
+
+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001
+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002
+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004
+#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008
+#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010
+#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020
+#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040
+#define NDIS_MAC_OPTION_RESERVED 0x80000000
+
+/** Hardware status of the underlying NIC */
+#define NDIS_HW_STS_READY 0x00000000UL
+#define NDIS_HW_STS_INITIALIZING 0x00000001UL
+#define NDIS_HW_STS_RESET 0x00000002UL
+#define NDIS_HW_STS_CLOSING 0x00000003UL
+#define NDIS_HW_STS_NOT_READY 0x00000004UL
+
+#endif /* _LINUX_NDIS_H */
+
+/** @} */
diff --git a/third-party/cherryusb-0.6.0/class/wireless/rndis_protocol.h b/third-party/cherryusb-0.6.0/class/wireless/rndis_protocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..54b4ebf6262bef2997d95fd6fe53a1952b1f2863
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/wireless/rndis_protocol.h
@@ -0,0 +1,302 @@
+/**
+ * \file rndis_protocol.h
+ * RNDIS Defines
+ *
+ * \author
+ * Colin O'Flynn
+ *
+ * \addtogroup usbstick
+ */
+
+/* Copyright (c) 2008 Colin O'Flynn
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _RNDIS_H
+#define _RNDIS_H
+
+/**
+ \addtogroup RNDIS
+ @{
+ */
+
+#include
+
+#define RNDIS_MAJOR_VERSION 1
+#define RNDIS_MINOR_VERSION 0
+
+#define RNDIS_STATUS_SUCCESS 0X00000000
+#define RNDIS_STATUS_FAILURE 0XC0000001
+#define RNDIS_STATUS_INVALID_DATA 0XC0010015
+#define RNDIS_STATUS_NOT_SUPPORTED 0XC00000BB
+#define RNDIS_STATUS_MEDIA_CONNECT 0X4001000B
+#define RNDIS_STATUS_MEDIA_DISCONNECT 0X4001000C
+
+/* Message set for Connectionless (802.3) Devices */
+#define REMOTE_NDIS_PACKET_MSG 0x00000001
+#define REMOTE_NDIS_INITIALIZE_MSG 0X00000002
+#define REMOTE_NDIS_HALT_MSG 0X00000003
+#define REMOTE_NDIS_QUERY_MSG 0X00000004
+#define REMOTE_NDIS_SET_MSG 0X00000005
+#define REMOTE_NDIS_RESET_MSG 0X00000006
+#define REMOTE_NDIS_INDICATE_STATUS_MSG 0X00000007
+#define REMOTE_NDIS_KEEPALIVE_MSG 0X00000008
+#define REMOTE_NDIS_INITIALIZE_CMPLT 0X80000002
+#define REMOTE_NDIS_QUERY_CMPLT 0X80000004
+#define REMOTE_NDIS_SET_CMPLT 0X80000005
+#define REMOTE_NDIS_RESET_CMPLT 0X80000006
+#define REMOTE_NDIS_KEEPALIVE_CMPLT 0X80000008
+
+typedef uint32_t rndis_MessageType_t;
+typedef uint32_t rndis_MessageLength_t;
+typedef uint32_t rndis_RequestId_t;
+typedef uint32_t rndis_MajorVersion_t;
+typedef uint32_t rndis_MinorVersion_t;
+typedef uint32_t rndis_MaxTransferSize_t;
+typedef uint32_t rndis_Status_t;
+
+/* Device Flags */
+#define RNDIS_DF_CONNECTIONLESS 0x00000001
+#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002
+typedef uint32_t rndis_DeviceFlags_t;
+
+/* Mediums */
+#define RNDIS_MEDIUM_802_3 0x00000000
+typedef uint32_t rndis_Medium_t;
+
+typedef uint32_t rndis_MaxPacketsPerTransfer_t;
+typedef uint32_t rndis_PacketAlignmentFactor_t;
+typedef uint32_t rndis_AfListOffset_t;
+typedef uint32_t rndis_AfListSize_t;
+
+/*** Remote NDIS Generic Message type ***/
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+} rndis_generic_msg_t;
+
+/*** Remote NDIS Initialize Message ***/
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_RequestId_t RequestId;
+ rndis_MajorVersion_t MajorVersion;
+ rndis_MinorVersion_t MinorVersion;
+ rndis_MaxTransferSize_t MaxTransferSize;
+} rndis_initialize_msg_t;
+
+/* Response: */
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_RequestId_t RequestId;
+ rndis_Status_t Status;
+ rndis_MajorVersion_t MajorVersion;
+ rndis_MinorVersion_t MinorVersion;
+ rndis_DeviceFlags_t DeviceFlags;
+ rndis_Medium_t Medium;
+ rndis_MaxPacketsPerTransfer_t MaxPacketsPerTransfer;
+ rndis_MaxTransferSize_t MaxTransferSize;
+ rndis_PacketAlignmentFactor_t PacketAlignmentFactor;
+ rndis_AfListOffset_t AfListOffset;
+ rndis_AfListSize_t AfListSize;
+} rndis_initialize_cmplt_t;
+
+/*** Remote NDIS Halt Message ***/
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_RequestId_t RequestId;
+} rndis_halt_msg_t;
+
+typedef uint32_t rndis_Oid_t;
+typedef uint32_t rndis_InformationBufferLength_t;
+typedef uint32_t rndis_InformationBufferOffset_t;
+typedef uint32_t rndis_DeviceVcHandle_t;
+
+/*** Remote NDIS Query Message ***/
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_RequestId_t RequestId;
+ rndis_Oid_t Oid;
+ rndis_InformationBufferLength_t InformationBufferLength;
+ rndis_InformationBufferOffset_t InformationBufferOffset;
+ rndis_DeviceVcHandle_t DeviceVcHandle;
+} rndis_query_msg_t;
+
+/* Response: */
+
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_RequestId_t RequestId;
+ rndis_Status_t Status;
+ rndis_InformationBufferLength_t InformationBufferLength;
+ rndis_InformationBufferOffset_t InformationBufferOffset;
+} rndis_query_cmplt_t;
+
+/*** Remote NDIS Set Message ***/
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_RequestId_t RequestId;
+ rndis_Oid_t Oid;
+ rndis_InformationBufferLength_t InformationBufferLength;
+ rndis_InformationBufferOffset_t InformationBufferOffset;
+ rndis_DeviceVcHandle_t DeviceVcHandle;
+} rndis_set_msg_t;
+
+/* Response */
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_RequestId_t RequestId;
+ rndis_Status_t Status;
+} rndis_set_cmplt_t;
+
+/* Information buffer layout for OID_GEN_RNDIS_CONFIG_PARAMETER */
+typedef uint32_t rndis_ParameterNameOffset_t;
+typedef uint32_t rndis_ParameterNameLength_t;
+typedef uint32_t rndis_ParameterType_t;
+typedef uint32_t rndis_ParameterValueOffset_t;
+typedef uint32_t rndis_ParameterValueLength_t;
+
+#define PARAMETER_TYPE_STRING 2
+#define PARAMETER_TYPE_NUMERICAL 0
+
+typedef struct {
+ rndis_ParameterNameOffset_t ParameterNameOffset;
+ rndis_ParameterNameLength_t ParameterNameLength;
+ rndis_ParameterType_t ParameterType;
+ rndis_ParameterValueOffset_t ParameterValueOffset;
+ rndis_ParameterValueLength_t ParameterValueLength;
+} rndis_config_parameter_t;
+
+typedef uint32_t rndis_Reserved_t;
+
+/*** Remote NDIS Soft Reset Message ***/
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_Reserved_t Reserved;
+} rndis_reset_msg_t;
+
+typedef uint32_t rndis_AddressingReset_t;
+
+/* Response: */
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_Status_t Status;
+ rndis_AddressingReset_t AddressingReset;
+} rndis_reset_cmplt_t;
+
+/*** Remote NDIS Indicate Status Message ***/
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_Status_t Status;
+ rndis_Status_t StatusBufferLength;
+ rndis_Status_t StatusBufferOffset;
+} rndis_indicate_status_t;
+
+typedef uint32_t rndis_DiagStatus_t;
+typedef uint32_t rndis_ErrorOffset_t;
+
+typedef struct {
+ rndis_DiagStatus_t DiagStatus;
+ rndis_ErrorOffset_t ErrorOffset;
+} rndis_diagnostic_info_t;
+
+/*** Remote NDIS Keepalive Message */
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_RequestId_t RequestId;
+} rndis_keepalive_msg_t;
+
+/* Response: */
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_RequestId_t RequestId;
+ rndis_Status_t Status;
+} rndis_keepalive_cmplt_t;
+
+/*** Remote NDIS Data Packet ***/
+
+typedef uint32_t rndis_DataOffset_t;
+typedef uint32_t rndis_DataLength_t;
+typedef uint32_t rndis_OOBDataOffset_t;
+typedef uint32_t rndis_OOBDataLength_t;
+typedef uint32_t rndis_NumOOBDataElements_t;
+typedef uint32_t rndis_PerPacketInfoOffset_t;
+typedef uint32_t rndis_PerPacketInfoLength_t;
+
+typedef struct {
+ rndis_MessageType_t MessageType;
+ rndis_MessageLength_t MessageLength;
+ rndis_DataOffset_t DataOffset;
+ rndis_DataLength_t DataLength;
+ rndis_OOBDataOffset_t OOBDataOffset;
+ rndis_OOBDataLength_t OOBDataLength;
+ rndis_NumOOBDataElements_t NumOOBDataElements;
+ rndis_PerPacketInfoOffset_t PerPacketInfoOffset;
+ rndis_PerPacketInfoLength_t PerPacketInfoLength;
+ rndis_DeviceVcHandle_t DeviceVcHandle;
+ rndis_Reserved_t Reserved;
+} rndis_data_packet_t;
+
+typedef uint32_t rndis_ClassInformationOffset_t;
+typedef uint32_t rndis_Size_t;
+typedef uint32_t rndis_Type_t;
+
+typedef struct {
+ rndis_Size_t Size;
+ rndis_Type_t Type;
+ rndis_ClassInformationOffset_t ClassInformationType;
+} rndis_OOB_packet_t;
+
+#include "ndis.h"
+
+typedef enum rnids_state_e {
+ rndis_uninitialized,
+ rndis_initialized,
+ rndis_data_initialized
+} rndis_state_t;
+
+typedef struct {
+ uint32_t txok;
+ uint32_t rxok;
+ uint32_t txbad;
+ uint32_t rxbad;
+} usb_eth_stat_t;
+
+#endif /* _RNDIS_H */
+
+/** @} */
diff --git a/third-party/cherryusb-0.6.0/class/wireless/usbd_rndis.c b/third-party/cherryusb-0.6.0/class/wireless/usbd_rndis.c
new file mode 100644
index 0000000000000000000000000000000000000000..2479bb0bfa819e4e577f3b2f1bd3d57f4a795394
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/wireless/usbd_rndis.c
@@ -0,0 +1,559 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+#include "usbd_rndis.h"
+#include "rndis_protocol.h"
+
+#define RNDIS_OUT_EP_IDX 0
+#define RNDIS_IN_EP_IDX 1
+#define RNDIS_INT_EP_IDX 2
+
+/* Describe EndPoints configuration */
+static struct usbd_endpoint rndis_ep_data[3];
+
+#define RNDIS_INQUIRY_PUT(src, len) (memcpy(infomation_buffer, src, len))
+#define RNDIS_INQUIRY_PUT_LE32(value) (*(uint32_t *)infomation_buffer = (value))
+
+#ifdef CONFIG_USB_HS
+#define RNDIS_MAX_PACKET_SIZE 512
+#else
+#define RNDIS_MAX_PACKET_SIZE 64
+#endif
+
+#ifndef CONFIG_USB_HS
+#define RNDIS_LINK_SPEED 12000000 /* Link baudrate (12Mbit/s for USB-FS) */
+#else
+#define RNDIS_LINK_SPEED 480000000 /* Link baudrate (480Mbit/s for USB-HS) */
+#endif
+
+/* Device data structure */
+struct usbd_rndis_cfg_priv {
+ uint32_t drv_version;
+ uint32_t link_status;
+ uint32_t speed;
+ uint32_t net_filter;
+ usb_eth_stat_t eth_state;
+ rndis_state_t init_state;
+ uint8_t mac[6];
+} usbd_rndis_cfg = { .drv_version = 0x0001,
+ .link_status = NDIS_MEDIA_STATE_DISCONNECTED,
+ .speed = RNDIS_LINK_SPEED,
+ .init_state = rndis_uninitialized,
+ .mac = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 } };
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + 44];
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE];
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+volatile uint8_t *g_rndis_rx_data_buffer;
+volatile uint32_t g_rndis_rx_data_length;
+volatile uint32_t g_rndis_tx_data_length;
+
+/* RNDIS options list */
+const uint32_t oid_supported_list[] = {
+ /* General OIDs */
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_VENDOR_DRIVER_VERSION,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_MEDIA_CONNECT_STATUS,
+
+ OID_GEN_PHYSICAL_MEDIUM,
+
+ /* General Statistic OIDs */
+ OID_GEN_XMIT_OK,
+ OID_GEN_RCV_OK,
+ OID_GEN_XMIT_ERROR,
+ OID_GEN_RCV_ERROR,
+ OID_GEN_RCV_NO_BUFFER,
+
+ /* Please configure us */
+ OID_GEN_RNDIS_CONFIG_PARAMETER,
+
+ /* 802.3 OIDs */
+ OID_802_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MULTICAST_LIST,
+ OID_802_3_MAXIMUM_LIST_SIZE,
+
+ /* 802.3 Statistic OIDs */
+ OID_802_3_RCV_ERROR_ALIGNMENT,
+ OID_802_3_XMIT_ONE_COLLISION,
+ OID_802_3_XMIT_MORE_COLLISIONS,
+
+ OID_802_3_MAC_OPTIONS,
+};
+
+static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len);
+
+static void rndis_notify_rsp(void)
+{
+ usbd_ep_start_write(rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr, NOTIFY_RESPONSE_AVAILABLE, 8);
+}
+
+static int rndis_class_interface_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ switch (setup->bRequest) {
+ case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
+ rndis_encapsulated_cmd_handler(*data, setup->wLength);
+ break;
+ case CDC_REQUEST_GET_ENCAPSULATED_RESPONSE:
+ *data = rndis_encapsulated_resp_buffer;
+ *len = ((rndis_generic_msg_t *)rndis_encapsulated_resp_buffer)->MessageLength;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int rndis_init_cmd_handler(uint8_t *data, uint32_t len);
+static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len);
+static int rndis_query_cmd_handler(uint8_t *data, uint32_t len);
+static int rndis_set_cmd_handler(uint8_t *data, uint32_t len);
+static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len);
+static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len);
+
+static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len)
+{
+ switch (((rndis_generic_msg_t *)data)->MessageType) {
+ case REMOTE_NDIS_INITIALIZE_MSG:
+ return rndis_init_cmd_handler(data, len);
+ case REMOTE_NDIS_HALT_MSG:
+ return rndis_halt_cmd_handler(data, len);
+ case REMOTE_NDIS_QUERY_MSG:
+ return rndis_query_cmd_handler(data, len);
+ case REMOTE_NDIS_SET_MSG:
+ return rndis_set_cmd_handler(data, len);
+ case REMOTE_NDIS_RESET_MSG:
+ return rndis_reset_cmd_handler(data, len);
+ case REMOTE_NDIS_KEEPALIVE_MSG:
+ return rndis_keepalive_cmd_handler(data, len);
+
+ default:
+ break;
+ }
+ return -1;
+}
+
+static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
+{
+ rndis_initialize_msg_t *cmd = (rndis_initialize_msg_t *)data;
+ rndis_initialize_cmplt_t *resp;
+
+ resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
+ resp->RequestId = cmd->RequestId;
+ resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
+ resp->MessageLength = sizeof(rndis_initialize_cmplt_t);
+ resp->MajorVersion = RNDIS_MAJOR_VERSION;
+ resp->MinorVersion = RNDIS_MINOR_VERSION;
+ resp->Status = RNDIS_STATUS_SUCCESS;
+ resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
+ resp->Medium = RNDIS_MEDIUM_802_3;
+ resp->MaxPacketsPerTransfer = 1;
+ resp->MaxTransferSize = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + sizeof(rndis_data_packet_t);
+ resp->PacketAlignmentFactor = 0;
+ resp->AfListOffset = 0;
+ resp->AfListSize = 0;
+
+ usbd_rndis_cfg.init_state = rndis_initialized;
+
+ rndis_notify_rsp();
+ return 0;
+}
+
+static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
+{
+ rndis_halt_msg_t *resp;
+
+ resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
+ resp->MessageLength = 0;
+
+ usbd_rndis_cfg.init_state = rndis_uninitialized;
+
+ return 0;
+}
+
+static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
+{
+ rndis_query_msg_t *cmd = (rndis_query_msg_t *)data;
+ rndis_query_cmplt_t *resp;
+ uint8_t *infomation_buffer;
+ uint32_t infomation_len = 0;
+
+ resp = ((rndis_query_cmplt_t *)rndis_encapsulated_resp_buffer);
+ resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
+ resp->RequestId = cmd->RequestId;
+ resp->InformationBufferOffset = sizeof(rndis_query_cmplt_t) - sizeof(rndis_generic_msg_t);
+ resp->Status = RNDIS_STATUS_SUCCESS;
+
+ infomation_buffer = (uint8_t *)resp + sizeof(rndis_query_cmplt_t);
+
+ switch (cmd->Oid) {
+ case OID_GEN_SUPPORTED_LIST:
+ RNDIS_INQUIRY_PUT(oid_supported_list, sizeof(oid_supported_list));
+ infomation_len = sizeof(oid_supported_list);
+ break;
+ case OID_GEN_HARDWARE_STATUS:
+ RNDIS_INQUIRY_PUT_LE32(NDIS_HW_STS_READY);
+ infomation_len = 4;
+ break;
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+ RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
+ infomation_len = 4;
+ break;
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE);
+ infomation_len = 4;
+ break;
+ case OID_GEN_VENDOR_ID:
+ RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_VENDOR_ID);
+ infomation_len = 4;
+ break;
+ case OID_GEN_VENDOR_DRIVER_VERSION:
+ RNDIS_INQUIRY_PUT_LE32(0x0001);
+ infomation_len = 4;
+ break;
+ case OID_GEN_VENDOR_DESCRIPTION:
+ RNDIS_INQUIRY_PUT(CONFIG_USBDEV_RNDIS_VENDOR_DESC, strlen(CONFIG_USBDEV_RNDIS_VENDOR_DESC));
+ infomation_len = (strlen(CONFIG_USBDEV_RNDIS_VENDOR_DESC) + 1);
+ break;
+ case OID_802_3_CURRENT_ADDRESS:
+ case OID_802_3_PERMANENT_ADDRESS:
+ RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
+ infomation_len = 6;
+ break;
+ case OID_GEN_PHYSICAL_MEDIUM:
+ RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
+ infomation_len = 4;
+ break;
+ case OID_GEN_LINK_SPEED:
+ RNDIS_INQUIRY_PUT_LE32(RNDIS_LINK_SPEED / 100);
+ infomation_len = 4;
+ break;
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.net_filter);
+ infomation_len = 4;
+ break;
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE + CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE);
+ infomation_len = 4;
+ break;
+ case OID_GEN_MEDIA_CONNECT_STATUS:
+ RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.link_status);
+ infomation_len = 4;
+ break;
+ case OID_GEN_RNDIS_CONFIG_PARAMETER:
+ RNDIS_INQUIRY_PUT_LE32(0);
+ infomation_len = 4;
+ break;
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ RNDIS_INQUIRY_PUT_LE32(1); /* one address */
+ infomation_len = 4;
+ break;
+ case OID_802_3_MULTICAST_LIST:
+ //RNDIS_INQUIRY_PUT_LE32(0xE0000000); /* 224.0.0.0 */
+ resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
+ RNDIS_INQUIRY_PUT_LE32(0);
+ infomation_len = 4;
+ break;
+ case OID_802_3_MAC_OPTIONS:
+ // infomation_len = 0;
+ resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
+ RNDIS_INQUIRY_PUT_LE32(0);
+ infomation_len = 4;
+ break;
+ case OID_GEN_MAC_OPTIONS:
+ RNDIS_INQUIRY_PUT_LE32(0);
+ infomation_len = 4;
+ break;
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ RNDIS_INQUIRY_PUT_LE32(0);
+ infomation_len = 4;
+ break;
+ case OID_802_3_XMIT_ONE_COLLISION:
+ RNDIS_INQUIRY_PUT_LE32(0);
+ infomation_len = 4;
+ break;
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+ RNDIS_INQUIRY_PUT_LE32(0);
+ infomation_len = 4;
+ break;
+ case OID_GEN_XMIT_OK:
+ RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txok);
+ infomation_len = 4;
+ break;
+ case OID_GEN_RCV_OK:
+ RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxok);
+ infomation_len = 4;
+ break;
+ case OID_GEN_RCV_ERROR:
+ RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxbad);
+ infomation_len = 4;
+ break;
+ case OID_GEN_XMIT_ERROR:
+ RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txbad);
+ infomation_len = 4;
+ break;
+ case OID_GEN_RCV_NO_BUFFER:
+ RNDIS_INQUIRY_PUT_LE32(0);
+ infomation_len = 4;
+ break;
+ default:
+ resp->Status = RNDIS_STATUS_FAILURE;
+ infomation_len = 0;
+ USB_LOG_WRN("Unhandled query for Object ID 0x%x\r\n", cmd->Oid);
+ break;
+ }
+
+ resp->MessageLength = sizeof(rndis_query_cmplt_t) + infomation_len;
+ resp->InformationBufferLength = infomation_len;
+
+ rndis_notify_rsp();
+ return 0;
+}
+
+static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
+{
+ rndis_set_msg_t *cmd = (rndis_set_msg_t *)data;
+ rndis_set_cmplt_t *resp;
+ rndis_config_parameter_t *param;
+
+ resp = ((rndis_set_cmplt_t *)rndis_encapsulated_resp_buffer);
+ resp->RequestId = cmd->RequestId;
+ resp->MessageType = REMOTE_NDIS_SET_CMPLT;
+ resp->MessageLength = sizeof(rndis_set_cmplt_t);
+ resp->Status = RNDIS_STATUS_SUCCESS;
+
+ switch (cmd->Oid) {
+ case OID_GEN_RNDIS_CONFIG_PARAMETER:
+ param = (rndis_config_parameter_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
+ USB_LOG_WRN("RNDIS cfg param: NameOfs=%d, NameLen=%d, ValueOfs=%d, ValueLen=%d\r\n",
+ param->ParameterNameOffset, param->ParameterNameLength,
+ param->ParameterValueOffset, param->ParameterValueLength);
+ break;
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ if (cmd->InformationBufferLength < sizeof(usbd_rndis_cfg.net_filter)) {
+ USB_LOG_WRN("PACKET_FILTER!\r\n");
+ resp->Status = RNDIS_STATUS_INVALID_DATA;
+ } else {
+ uint32_t *filter;
+ /* Parameter starts at offset buf_offset of the req_id field */
+ filter = (uint32_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
+
+ //usbd_rndis_cfg.net_filter = param->ParameterNameOffset;
+ usbd_rndis_cfg.net_filter = *(uint32_t *)filter;
+ if (usbd_rndis_cfg.net_filter) {
+ usbd_rndis_cfg.init_state = rndis_data_initialized;
+ } else {
+ usbd_rndis_cfg.init_state = rndis_initialized;
+ }
+ }
+ break;
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ break;
+ case OID_GEN_PROTOCOL_OPTIONS:
+ break;
+ case OID_802_3_MULTICAST_LIST:
+ break;
+ case OID_PNP_ADD_WAKE_UP_PATTERN:
+ case OID_PNP_REMOVE_WAKE_UP_PATTERN:
+ case OID_PNP_ENABLE_WAKE_UP:
+ default:
+ resp->Status = RNDIS_STATUS_FAILURE;
+ USB_LOG_WRN("Unhandled query for Object ID 0x%x\r\n", cmd->Oid);
+ break;
+ }
+
+ rndis_notify_rsp();
+
+ return 0;
+}
+
+static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
+{
+ rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
+ rndis_reset_cmplt_t *resp;
+
+ resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
+ resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
+ resp->MessageLength = sizeof(rndis_reset_cmplt_t);
+ resp->Status = RNDIS_STATUS_SUCCESS;
+ resp->AddressingReset = 1;
+
+ usbd_rndis_cfg.init_state = rndis_uninitialized;
+
+ rndis_notify_rsp();
+
+ return 0;
+}
+
+static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
+{
+ rndis_keepalive_msg_t *cmd = (rndis_keepalive_msg_t *)data;
+ rndis_keepalive_cmplt_t *resp;
+
+ resp = ((rndis_keepalive_cmplt_t *)rndis_encapsulated_resp_buffer);
+ resp->RequestId = cmd->RequestId;
+ resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
+ resp->MessageLength = sizeof(rndis_keepalive_cmplt_t);
+ resp->Status = RNDIS_STATUS_SUCCESS;
+
+ rndis_notify_rsp();
+
+ return 0;
+}
+
+static void rndis_notify_handler(uint8_t event, void *arg)
+{
+ switch (event) {
+ case USBD_EVENT_RESET:
+ usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
+ break;
+ case USBD_EVENT_CONFIGURED:
+ g_rndis_rx_data_length = 0;
+ g_rndis_tx_data_length = 0;
+ usbd_rndis_cfg.link_status = NDIS_MEDIA_STATE_CONNECTED;
+ usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
+ break;
+
+ default:
+ break;
+ }
+}
+
+void rndis_bulk_out(uint8_t ep, uint32_t nbytes)
+{
+ rndis_data_packet_t *hdr;
+
+ hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
+ g_rndis_rx_data_buffer = g_rndis_rx_buffer;
+ if ((hdr->MessageType != NDIS_PACKET_TYPE_DIRECTED) || (nbytes != hdr->MessageLength)) {
+ usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
+ return;
+ }
+
+ /* Point to the payload and update the message length */
+ g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t);
+ g_rndis_rx_data_length = hdr->DataLength;
+
+ usbd_rndis_data_recv((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
+}
+
+void rndis_bulk_in(uint8_t ep, uint32_t nbytes)
+{
+ if ((nbytes % RNDIS_MAX_PACKET_SIZE) == 0 && nbytes) {
+ /* send zlp */
+ usbd_ep_start_write(ep, NULL, 0);
+ } else {
+ g_rndis_tx_data_length = 0;
+ }
+}
+
+#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
+#include
+
+struct pbuf *usbd_rndis_eth_rx(void)
+{
+ struct pbuf *p;
+
+ if (g_rndis_rx_data_length == 0) {
+ return NULL;
+ }
+ p = pbuf_alloc(PBUF_RAW, g_rndis_rx_data_length, PBUF_POOL);
+ if (p == NULL) {
+ return NULL;
+ }
+ memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
+ p->len = g_rndis_rx_data_length;
+
+ g_rndis_rx_data_length = 0;
+ usbd_ep_start_read(rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
+
+ return p;
+}
+
+int usbd_rndis_eth_tx(struct pbuf *p)
+{
+ struct pbuf *q;
+ uint8_t *buffer;
+ rndis_data_packet_t *hdr;
+
+ if (usbd_rndis_cfg.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
+ return 0;
+ }
+
+ if (g_rndis_tx_data_length > 0) {
+ return -EBUSY;
+ }
+
+ if (p->tot_len > sizeof(g_rndis_tx_buffer)) {
+ p->tot_len = sizeof(g_rndis_tx_buffer);
+ }
+
+ buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
+ for (q = p; q != NULL; q = q->next) {
+ memcpy(buffer, q->payload, q->len);
+ buffer += q->len;
+ }
+
+ hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
+
+ memset(hdr, 0, sizeof(rndis_data_packet_t));
+ hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
+ hdr->MessageLength = sizeof(rndis_data_packet_t) + p->tot_len;
+ hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
+ hdr->DataLength = p->tot_len;
+
+ g_rndis_tx_data_length = sizeof(rndis_data_packet_t) + p->tot_len;
+
+ return usbd_ep_start_write(rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
+}
+#endif
+struct usbd_interface *usbd_rndis_alloc_intf(uint8_t out_ep, uint8_t in_ep, uint8_t int_ep, uint8_t mac[6])
+{
+ struct usbd_interface *intf = (struct usbd_interface *)usb_malloc(sizeof(struct usbd_interface));
+ if (intf == NULL) {
+ USB_LOG_ERR("no mem to alloc intf\r\n");
+ return NULL;
+ }
+
+ memcpy(usbd_rndis_cfg.mac, mac, 6);
+
+ rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr = out_ep;
+ rndis_ep_data[RNDIS_OUT_EP_IDX].ep_cb = rndis_bulk_out;
+ rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr = in_ep;
+ rndis_ep_data[RNDIS_IN_EP_IDX].ep_cb = rndis_bulk_in;
+ rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr = int_ep;
+ rndis_ep_data[RNDIS_INT_EP_IDX].ep_cb = NULL;
+
+ usbd_add_endpoint(&rndis_ep_data[RNDIS_OUT_EP_IDX]);
+ usbd_add_endpoint(&rndis_ep_data[RNDIS_IN_EP_IDX]);
+ usbd_add_endpoint(&rndis_ep_data[RNDIS_INT_EP_IDX]);
+
+ intf->class_interface_handler = rndis_class_interface_request_handler;
+ intf->class_endpoint_handler = NULL;
+ intf->vendor_handler = NULL;
+ intf->notify_handler = rndis_notify_handler;
+
+ return intf;
+}
diff --git a/third-party/cherryusb-0.6.0/class/wireless/usbd_rndis.h b/third-party/cherryusb-0.6.0/class/wireless/usbd_rndis.h
new file mode 100644
index 0000000000000000000000000000000000000000..05ed53ae4a578cfbf75c71014b0d9f6cf9184112
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/wireless/usbd_rndis.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBD_RNDIS_H
+#define USBD_RNDIS_H
+
+#include "usb_cdc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct usbd_interface *usbd_rndis_alloc_intf(uint8_t out_ep, uint8_t in_ep, uint8_t int_ep, uint8_t mac[6]);
+
+#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
+struct pbuf *usbd_rndis_eth_rx(void);
+int usbd_rndis_eth_tx(struct pbuf *p);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBD_RNDIS_H */
diff --git a/third-party/cherryusb-0.6.0/class/wireless/usbh_rndis.c b/third-party/cherryusb-0.6.0/class/wireless/usbh_rndis.c
new file mode 100644
index 0000000000000000000000000000000000000000..4c2674672ada721e6faf64f7cdd39590db2fb375
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/wireless/usbh_rndis.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbh_core.h"
+#include "usbh_rndis.h"
+#include "rndis_protocol.h"
+
+#define DEV_FORMAT "/dev/rndis"
+
+static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
+{
+ struct usb_setup_packet *setup = &rndis_class->hport->setup;
+ int ret = 0;
+ rndis_initialize_msg_t cmd;
+ rndis_initialize_cmplt_t resp;
+
+ cmd.MessageType = REMOTE_NDIS_INITIALIZE_MSG;
+ cmd.MessageLength = sizeof(rndis_initialize_msg_t);
+ cmd.RequestId = rndis_class->request_id++;
+ cmd.MajorVersion = 1;
+ cmd.MinorVersion = 0;
+ cmd.MaxTransferSize = 0x4000;
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
+ setup->wValue = 0;
+ setup->wIndex = 0;
+ setup->wLength = sizeof(rndis_initialize_msg_t);
+
+ ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)&cmd);
+ if (ret < 0) {
+ USB_LOG_ERR("rndis_initialize_msg_t send error, ret: %d\r\n", ret);
+ return ret;
+ }
+
+ //ret = usbh_ep_intr_transfer()
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
+ setup->wValue = 0;
+ setup->wIndex = 0;
+ setup->wLength = 4096;
+
+ ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)&resp);
+ if (ret < 0) {
+ USB_LOG_ERR("rndis_initialize_cmplt_t recv error, ret: %d\r\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint32_t query_len, uint8_t *info, uint32_t *info_len)
+{
+ struct usb_setup_packet *setup = &rndis_class->hport->setup;
+ int ret = 0;
+ rndis_query_msg_t cmd;
+ rndis_query_cmplt_t *resp;
+
+ cmd.MessageType = REMOTE_NDIS_QUERY_MSG;
+ cmd.MessageLength = query_len + sizeof(rndis_query_msg_t);
+ cmd.RequestId = rndis_class->request_id++;
+ cmd.Oid = oid;
+ cmd.InformationBufferLength = query_len;
+ cmd.InformationBufferOffset = 20;
+ cmd.DeviceVcHandle = 0;
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
+ setup->wValue = 0;
+ setup->wIndex = 0;
+ setup->wLength = sizeof(rndis_query_msg_t);
+
+ ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)&cmd);
+ if (ret < 0) {
+ USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
+ return ret;
+ }
+
+ //ret = usbh_ep_intr_transfer()
+
+ resp = usb_iomalloc(sizeof(rndis_query_cmplt_t) + 512);
+ if (resp == NULL) {
+ USB_LOG_ERR("Fail to alloc resp\r\n");
+ return -ENOMEM;
+ }
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
+ setup->wValue = 0;
+ setup->wIndex = 0;
+ setup->wLength = 4096;
+
+ ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)resp);
+ if (ret < 0) {
+ USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
+ goto error_out;
+ }
+
+ memcpy(info, ((uint8_t *)resp + sizeof(rndis_query_cmplt_t)), resp->InformationBufferLength);
+ *info_len = resp->InformationBufferLength;
+
+error_out:
+ if (resp) {
+ usb_iofree(resp);
+ }
+ return ret;
+}
+
+static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint8_t *info, uint32_t info_len)
+{
+ struct usb_setup_packet *setup = &rndis_class->hport->setup;
+ int ret = 0;
+ rndis_set_msg_t *cmd;
+ rndis_set_cmplt_t resp;
+
+ cmd = usb_iomalloc(sizeof(rndis_set_msg_t) + info_len);
+ if (cmd == NULL) {
+ USB_LOG_ERR("Fail to alloc cmd\r\n");
+ return -ENOMEM;
+ }
+ cmd->MessageType = REMOTE_NDIS_SET_MSG;
+ cmd->MessageLength = info_len + sizeof(rndis_set_msg_t);
+ cmd->RequestId = rndis_class->request_id++;
+ cmd->Oid = oid;
+ cmd->InformationBufferLength = info_len;
+ cmd->InformationBufferOffset = 20;
+ cmd->DeviceVcHandle = 0;
+
+ memcpy(((uint8_t *)cmd + sizeof(rndis_set_msg_t)), info, info_len);
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
+ setup->wValue = 0;
+ setup->wIndex = 0;
+ setup->wLength = sizeof(rndis_set_msg_t);
+
+ ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)cmd);
+ if (ret < 0) {
+ USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
+ goto error_out;
+ }
+
+ //ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500);
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
+ setup->wValue = 0;
+ setup->wIndex = 0;
+ setup->wLength = 4096;
+
+ ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)&resp);
+ if (ret < 0) {
+ USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
+ goto error_out;
+ }
+
+error_out:
+ if (cmd) {
+ usb_iofree(cmd);
+ }
+ return ret;
+}
+
+int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
+{
+ struct usb_setup_packet *setup = &rndis_class->hport->setup;
+ int ret = 0;
+ rndis_keepalive_msg_t cmd;
+ rndis_keepalive_cmplt_t resp;
+
+ cmd.MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
+ cmd.MessageLength = sizeof(rndis_keepalive_msg_t);
+ cmd.RequestId = rndis_class->request_id++;
+
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
+ setup->wValue = 0;
+ setup->wIndex = 0;
+ setup->wLength = sizeof(rndis_keepalive_msg_t);
+
+ ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)&cmd);
+ if (ret < 0) {
+ USB_LOG_ERR("keepalive send error, ret: %d\r\n", ret);
+ return ret;
+ }
+
+ //ret = usbh_ep_intr_transfer(rndis_class->hport->intin,buf,len,500);
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
+ setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
+ setup->wValue = 0;
+ setup->wIndex = 0;
+ setup->wLength = 4096;
+
+ ret = usbh_control_transfer(rndis_class->hport->ep0, setup, (uint8_t *)&resp);
+ if (ret < 0) {
+ USB_LOG_ERR("keepalive recv error, ret: %d\r\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
+{
+ struct usbh_endpoint_cfg ep_cfg = { 0 };
+ struct usb_endpoint_descriptor *ep_desc;
+ int ret;
+ uint32_t *oid_support_list;
+ unsigned int oid = 0;
+ unsigned int oid_num = 0;
+ uint32_t data_len;
+
+ struct usbh_rndis *rndis_class = usb_malloc(sizeof(struct usbh_rndis));
+ if (rndis_class == NULL) {
+ USB_LOG_ERR("Fail to alloc rndis_class\r\n");
+ return -ENOMEM;
+ }
+
+ memset(rndis_class, 0, sizeof(struct usbh_rndis));
+
+ rndis_class->hport = hport;
+ rndis_class->ctrl_intf = intf;
+ rndis_class->data_intf = intf + 1;
+
+ hport->config.intf[intf].priv = rndis_class;
+ hport->config.intf[intf + 1].priv = NULL;
+
+#ifdef CONFIG_USBHOST_RNDIS_NOTIFY
+ ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
+ ep_cfg.ep_addr = ep_desc->bEndpointAddress;
+ ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
+ ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;;
+ ep_cfg.ep_interval = ep_desc->bInterval;
+ ep_cfg.hport = hport;
+ usbh_pipe_alloc(&rndis_class->intin, &ep_cfg);
+
+#endif
+ for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
+ ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
+
+ ep_cfg.ep_addr = ep_desc->bEndpointAddress;
+ ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
+ ep_cfg.ep_mps = ep_desc->wMaxPacketSize;
+ ep_cfg.ep_interval = ep_desc->bInterval;
+ ep_cfg.hport = hport;
+ if (ep_desc->bEndpointAddress & 0x80) {
+ usbh_pipe_alloc(&rndis_class->bulkin, &ep_cfg);
+ } else {
+ usbh_pipe_alloc(&rndis_class->bulkout, &ep_cfg);
+ }
+ }
+
+ ret = usbh_rndis_init_msg_transfer(rndis_class);
+ if (ret < 0) {
+ return ret;
+ }
+ USB_LOG_INFO("rndis init success\r\n");
+
+ uint8_t *tmp_buffer = usb_iomalloc(512);
+ uint8_t data[32];
+
+ ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_SUPPORTED_LIST, 0, tmp_buffer, &data_len);
+ if (ret < 0) {
+ goto query_errorout;
+ }
+ oid_num = (data_len / 4);
+ USB_LOG_INFO("rndis query OID_GEN_SUPPORTED_LIST success,oid num :%d\r\n", oid_num);
+
+ oid_support_list = (uint32_t *)tmp_buffer;
+
+ for (uint8_t i = 0; i < oid_num; i++) {
+ oid = oid_support_list[i];
+ switch (oid) {
+ case OID_GEN_PHYSICAL_MEDIUM:
+ ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_PHYSICAL_MEDIUM, 4, data, &data_len);
+ if (ret < 0) {
+ goto query_errorout;
+ }
+ break;
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MAXIMUM_FRAME_SIZE, 4, data, &data_len);
+ if (ret < 0) {
+ goto query_errorout;
+ }
+ break;
+ case OID_GEN_LINK_SPEED:
+ ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_LINK_SPEED, 4, data, &data_len);
+ if (ret < 0) {
+ goto query_errorout;
+ }
+ break;
+ case OID_GEN_MEDIA_CONNECT_STATUS:
+ ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len);
+ if (ret < 0) {
+ goto query_errorout;
+ }
+ break;
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_MAXIMUM_LIST_SIZE, 4, data, &data_len);
+ if (ret < 0) {
+ goto query_errorout;
+ }
+ break;
+ case OID_802_3_CURRENT_ADDRESS:
+ ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_CURRENT_ADDRESS, 6, data, &data_len);
+ if (ret < 0) {
+ goto query_errorout;
+ }
+ break;
+ case OID_802_3_PERMANENT_ADDRESS:
+ ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_PERMANENT_ADDRESS, 6, data, &data_len);
+ if (ret < 0) {
+ goto query_errorout;
+ }
+ break;
+ default:
+ USB_LOG_WRN("Ignore rndis query iod:%08x\r\n", oid);
+ continue;
+ }
+ USB_LOG_INFO("rndis query iod:%08x success\r\n", oid);
+ }
+ usb_iofree(tmp_buffer);
+
+ uint32_t packet_filter = 0x0f;
+ usbh_rndis_set_msg_transfer(rndis_class, OID_GEN_CURRENT_PACKET_FILTER, (uint8_t *)&packet_filter, 4);
+ if (ret < 0) {
+ return ret;
+ }
+ USB_LOG_INFO("rndis set OID_GEN_CURRENT_PACKET_FILTER success\r\n");
+
+ uint8_t multicast_list[6] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x01 };
+ usbh_rndis_set_msg_transfer(rndis_class, OID_802_3_MULTICAST_LIST, multicast_list, 6);
+ if (ret < 0) {
+ return ret;
+ }
+ USB_LOG_INFO("rndis set OID_802_3_MULTICAST_LIST success\r\n");
+
+ strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
+
+ USB_LOG_INFO("Register RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
+ return ret;
+query_errorout:
+ USB_LOG_ERR("rndis query iod:%08x error\r\n", oid);
+ usb_iofree(tmp_buffer);
+ return ret;
+}
+
+static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
+{
+ int ret = 0;
+
+ struct usbh_rndis *rndis_class = (struct usbh_rndis *)hport->config.intf[intf].priv;
+
+ if (rndis_class) {
+ if (rndis_class->bulkin) {
+ usbh_pipe_free(rndis_class->bulkin);
+ }
+
+ if (rndis_class->bulkout) {
+ usbh_pipe_free(rndis_class->bulkout);
+ }
+
+ usb_free(rndis_class);
+
+ if (hport->config.intf[intf].devname[0] != '\0'){
+ USB_LOG_INFO("Unregister RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
+ }
+ memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN);
+
+ hport->config.intf[intf].priv = NULL;
+ hport->config.intf[intf + 1].priv = NULL;
+ }
+
+ return ret;
+}
+
+static const struct usbh_class_driver rndis_class_driver = {
+ .driver_name = "rndis",
+ .connect = usbh_rndis_connect,
+ .disconnect = usbh_rndis_disconnect
+};
+
+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,
+ .vid = 0x00,
+ .pid = 0x00,
+ .class_driver = &rndis_class_driver
+};
diff --git a/third-party/cherryusb-0.6.0/class/wireless/usbh_rndis.h b/third-party/cherryusb-0.6.0/class/wireless/usbh_rndis.h
new file mode 100644
index 0000000000000000000000000000000000000000..88562c64ea971bdfcf59fd2c3ca26ca94da174e0
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/class/wireless/usbh_rndis.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBH_RNDIS_H
+#define USBH_RNDIS_H
+
+#include "usb_cdc.h"
+
+struct usbh_rndis {
+ struct usbh_hubport *hport;
+
+ uint8_t ctrl_intf; /* Control interface number */
+ uint8_t data_intf; /* Data interface number */
+
+ usbh_pipe_t bulkin; /* Bulk IN endpoint */
+ usbh_pipe_t bulkout; /* Bulk OUT endpoint */
+ usbh_pipe_t intin; /* Notify endpoint */
+
+ uint32_t request_id;
+ uint8_t mac[6];
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int usbh_rndis_keepalive(struct usbh_rndis *rndis_class);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBH_RNDIS_H */
diff --git a/third-party/cherryusb-0.6.0/common/usb_dc.h b/third-party/cherryusb-0.6.0/common/usb_dc.h
new file mode 100644
index 0000000000000000000000000000000000000000..b11f8a68985c0ce0d216d891b9148e0089fe040f
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/common/usb_dc.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_DC_H
+#define USB_DC_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief USB Endpoint Configuration.
+ *
+ * Structure containing the USB endpoint configuration.
+ */
+struct usbd_endpoint_cfg {
+ uint8_t ep_addr; /* Endpoint addr with direction */
+ uint8_t ep_type; /* Endpoint type */
+ uint16_t ep_mps; /* Endpoint max packet size */
+};
+
+/**
+ * @brief init device controller registers.
+ * @return On success will return 0, and others indicate fail.
+ */
+int usb_dc_init(void);
+
+/**
+ * @brief deinit device controller registers.
+ * @return On success will return 0, and others indicate fail.
+ */
+int usb_dc_deinit(void);
+
+/**
+ * @brief Set USB device address
+ *
+ * @param[in] addr Device address
+ *
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbd_set_address(const uint8_t addr);
+
+/**
+ * @brief configure and enable endpoint.
+ *
+ * @param [in] ep_cfg Endpoint config.
+ *
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg);
+
+/**
+ * @brief Disable the selected endpoint
+ *
+ * @param[in] ep Endpoint address
+ *
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbd_ep_close(const uint8_t ep);
+
+/**
+ * @brief Set stall condition for the selected endpoint
+ *
+ * @param[in] ep Endpoint address
+ *
+ *
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbd_ep_set_stall(const uint8_t ep);
+
+/**
+ * @brief Clear stall condition for the selected endpoint
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ * listed in the device configuration table
+ *
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbd_ep_clear_stall(const uint8_t ep);
+
+/**
+ * @brief Check if the selected endpoint is stalled
+ *
+ * @param[in] ep Endpoint address
+ *
+ * @param[out] stalled Endpoint stall status
+ *
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
+
+/**
+ * @brief Setup in ep transfer setting and start transfer.
+ *
+ * This function is asynchronous.
+ * This function is similar to uart with tx dma.
+ *
+ * This function is called to write data to the specified endpoint. The
+ * supplied usbd_endpoint_callback function will be called when data is transmitted
+ * out.
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ * listed in the device configuration table
+ * @param[in] data Pointer to data to write
+ * @param[in] data_len Length of the data requested to write. This may
+ * be zero for a zero length status packet.
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len);
+
+/**
+ * @brief Setup out ep transfer setting and start transfer.
+ *
+ * This function is asynchronous.
+ * This function is similar to uart with rx dma.
+ *
+ * This function is called to read data to the specified endpoint. The
+ * supplied usbd_endpoint_callback function will be called when data is received
+ * in.
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ * listed in the device configuration table
+ * @param[in] data Pointer to data to read
+ * @param[in] data_len Max length of the data requested to read.
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len);
+
+/* usb dcd irq callback */
+
+/**
+ * @brief Usb reset irq callback.
+ */
+void usbd_event_reset_handler(void);
+/**
+ * @brief Usb setup packet recv irq callback.
+ * @param[in] psetup setup packet.
+ */
+void usbd_event_ep0_setup_complete_handler(uint8_t *psetup);
+/**
+ * @brief In ep transfer complete irq callback.
+ * @param[in] ep Endpoint address corresponding to the one
+ * listed in the device configuration table
+ * @param[in] nbytes How many nbytes have transferred.
+ */
+void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes);
+/**
+ * @brief Out ep transfer complete irq callback.
+ * @param[in] ep Endpoint address corresponding to the one
+ * listed in the device configuration table
+ * @param[in] nbytes How many nbytes have transferred.
+ */
+void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USB_DC_H */
diff --git a/third-party/cherryusb-0.6.0/common/usb_def.h b/third-party/cherryusb-0.6.0/common/usb_def.h
new file mode 100644
index 0000000000000000000000000000000000000000..fdb17fb6711139a3b7368ddbf6a3d851a2a00f5c
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/common/usb_def.h
@@ -0,0 +1,690 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_DEF_H
+#define USB_DEF_H
+
+/* Useful define */
+#define USB_1_1 0x0110
+#define USB_2_0 0x0200
+/* Set USB version to 2.1 so that the host will request the BOS descriptor */
+#define USB_2_1 0x0210
+
+/* Device speeds */
+#define USB_SPEED_UNKNOWN 0 /* Transfer rate not yet set */
+#define USB_SPEED_LOW 1 /* USB 1.1 */
+#define USB_SPEED_FULL 2 /* USB 1.1 */
+#define USB_SPEED_HIGH 3 /* USB 2.0 */
+#define USB_SPEED_WIRELESS 4 /* Wireless USB 2.5 */
+#define USB_SPEED_SUPER 5 /* USB 3.0 */
+#define USB_SPEED_SUPER_PLUS 6 /* USB 3.1 */
+
+/* Maximum number of devices per controller */
+#define USB_MAX_DEVICES (127)
+
+/* Default USB control EP, always 0 and 0x80 */
+#define USB_CONTROL_OUT_EP0 0
+#define USB_CONTROL_IN_EP0 0x80
+
+/**< maximum packet size (MPS) for EP 0 */
+#define USB_CTRL_EP_MPS 64
+
+/* USB PID Types */
+#define USB_PID_OUT (0x01) /* Tokens */
+#define USB_PID_IN (0x09)
+#define USB_PID_SOF (0x05)
+#define USB_PID_SETUP (0x0d)
+
+#define USB_PID_DATA0 (0x03) /* Data */
+#define USB_PID_DATA1 (0x0b)
+#define USB_PID_DATA2 (0x07)
+#define USB_PID_MDATA (0x0f)
+
+#define USB_PID_ACK (0x02) /* Handshake */
+#define USB_PID_NAK (0x0a)
+#define USB_PID_STALL (0x0e)
+#define USB_PID_NYET (0x06)
+
+#define USB_PID_PRE (0x0c) /* Special */
+#define USB_PID_ERR (0x0c)
+#define USB_PID_SPLIT (0x08)
+#define USB_PID_PING (0x04)
+#define USB_PID_RESERVED (0x00)
+
+#define USB_REQUEST_DIR_SHIFT 7U /* Bits 7: Request dir */
+#define USB_REQUEST_DIR_OUT (0U << USB_REQUEST_DIR_SHIFT) /* Bit 7=0: Host-to-device */
+#define USB_REQUEST_DIR_IN (1U << USB_REQUEST_DIR_SHIFT) /* Bit 7=1: Device-to-host */
+#define USB_REQUEST_DIR_MASK (1U << USB_REQUEST_DIR_SHIFT) /* Bit 7=1: Direction bit */
+
+#define USB_REQUEST_TYPE_SHIFT 5U /* Bits 5:6: Request type */
+#define USB_REQUEST_STANDARD (0U << USB_REQUEST_TYPE_SHIFT)
+#define USB_REQUEST_CLASS (1U << USB_REQUEST_TYPE_SHIFT)
+#define USB_REQUEST_VENDOR (2U << USB_REQUEST_TYPE_SHIFT)
+#define USB_REQUEST_RESERVED (3U << USB_REQUEST_TYPE_SHIFT)
+#define USB_REQUEST_TYPE_MASK (3U << USB_REQUEST_TYPE_SHIFT)
+
+#define USB_REQUEST_RECIPIENT_SHIFT 0U /* Bits 0:4: Recipient */
+#define USB_REQUEST_RECIPIENT_DEVICE (0U << USB_REQUEST_RECIPIENT_SHIFT)
+#define USB_REQUEST_RECIPIENT_INTERFACE (1U << USB_REQUEST_RECIPIENT_SHIFT)
+#define USB_REQUEST_RECIPIENT_ENDPOINT (2U << USB_REQUEST_RECIPIENT_SHIFT)
+#define USB_REQUEST_RECIPIENT_OTHER (3U << USB_REQUEST_RECIPIENT_SHIFT)
+#define USB_REQUEST_RECIPIENT_MASK (3U << USB_REQUEST_RECIPIENT_SHIFT)
+
+/* USB Standard Request Codes */
+#define USB_REQUEST_GET_STATUS 0x00
+#define USB_REQUEST_CLEAR_FEATURE 0x01
+#define USB_REQUEST_SET_FEATURE 0x03
+#define USB_REQUEST_SET_ADDRESS 0x05
+#define USB_REQUEST_GET_DESCRIPTOR 0x06
+#define USB_REQUEST_SET_DESCRIPTOR 0x07
+#define USB_REQUEST_GET_CONFIGURATION 0x08
+#define USB_REQUEST_SET_CONFIGURATION 0x09
+#define USB_REQUEST_GET_INTERFACE 0x0A
+#define USB_REQUEST_SET_INTERFACE 0x0B
+#define USB_REQUEST_SYNCH_FRAME 0x0C
+#define USB_REQUEST_SET_ENCRYPTION 0x0D
+#define USB_REQUEST_GET_ENCRYPTION 0x0E
+#define USB_REQUEST_RPIPE_ABORT 0x0E
+#define USB_REQUEST_SET_HANDSHAKE 0x0F
+#define USB_REQUEST_RPIPE_RESET 0x0F
+#define USB_REQUEST_GET_HANDSHAKE 0x10
+#define USB_REQUEST_SET_CONNECTION 0x11
+#define USB_REQUEST_SET_SECURITY_DATA 0x12
+#define USB_REQUEST_GET_SECURITY_DATA 0x13
+#define USB_REQUEST_SET_WUSB_DATA 0x14
+#define USB_REQUEST_LOOPBACK_DATA_WRITE 0x15
+#define USB_REQUEST_LOOPBACK_DATA_READ 0x16
+#define USB_REQUEST_SET_INTERFACE_DS 0x17
+
+/* USB Standard Feature selectors */
+#define USB_FEATURE_ENDPOINT_HALT 0
+#define USB_FEATURE_SELF_POWERED 0
+#define USB_FEATURE_REMOTE_WAKEUP 1
+#define USB_FEATURE_TEST_MODE 2
+#define USB_FEATURE_BATTERY 2
+#define USB_FEATURE_BHNPENABLE 3
+#define USB_FEATURE_WUSBDEVICE 3
+#define USB_FEATURE_AHNPSUPPORT 4
+#define USB_FEATURE_AALTHNPSUPPORT 5
+#define USB_FEATURE_DEBUGMODE 6
+
+/* USB GET_STATUS Bit Values */
+#define USB_GETSTATUS_ENDPOINT_HALT 0x01
+#define USB_GETSTATUS_SELF_POWERED 0x01
+#define USB_GETSTATUS_REMOTE_WAKEUP 0x02
+
+/* USB Descriptor Types */
+#define USB_DESCRIPTOR_TYPE_DEVICE 0x01U
+#define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02U
+#define USB_DESCRIPTOR_TYPE_STRING 0x03U
+#define USB_DESCRIPTOR_TYPE_INTERFACE 0x04U
+#define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05U
+#define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 0x06U
+#define USB_DESCRIPTOR_TYPE_OTHER_SPEED 0x07U
+#define USB_DESCRIPTOR_TYPE_INTERFACE_POWER 0x08U
+#define USB_DESCRIPTOR_TYPE_OTG 0x09U
+#define USB_DESCRIPTOR_TYPE_DEBUG 0x0AU
+#define USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0BU
+#define USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE 0x0FU
+#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 0x10U
+#define USB_DESCRIPTOR_TYPE_WIRELESS_ENDPOINTCOMP 0x11U
+
+/* Class Specific Descriptor */
+#define USB_CS_DESCRIPTOR_TYPE_DEVICE 0x21U
+#define USB_CS_DESCRIPTOR_TYPE_CONFIGURATION 0x22U
+#define USB_CS_DESCRIPTOR_TYPE_STRING 0x23U
+#define USB_CS_DESCRIPTOR_TYPE_INTERFACE 0x24U
+#define USB_CS_DESCRIPTOR_TYPE_ENDPOINT 0x25U
+
+#define USB_DESCRIPTOR_TYPE_SUPERSPEED_ENDPOINT_COMPANION 0x30U
+#define USB_DESCRIPTOR_TYPE_SUPERSPEED_ISO_ENDPOINT_COMPANION 0x31U
+
+/* USB Device Classes */
+#define USB_DEVICE_CLASS_RESERVED 0x00
+#define USB_DEVICE_CLASS_AUDIO 0x01
+#define USB_DEVICE_CLASS_CDC 0x02
+#define USB_DEVICE_CLASS_HID 0x03
+#define USB_DEVICE_CLASS_MONITOR 0x04
+#define USB_DEVICE_CLASS_PHYSICAL 0x05
+#define USB_DEVICE_CLASS_IMAGE 0x06
+#define USB_DEVICE_CLASS_PRINTER 0x07
+#define USB_DEVICE_CLASS_MASS_STORAGE 0x08
+#define USB_DEVICE_CLASS_HUB 0x09
+#define USB_DEVICE_CLASS_CDC_DATA 0x0a
+#define USB_DEVICE_CLASS_SMART_CARD 0x0b
+#define USB_DEVICE_CLASS_SECURITY 0x0d
+#define USB_DEVICE_CLASS_VIDEO 0x0e
+#define USB_DEVICE_CLASS_HEALTHCARE 0x0f
+#define USB_DEVICE_CLASS_DIAG_DEVICE 0xdc
+#define USB_DEVICE_CLASS_WIRELESS 0xe0
+#define USB_DEVICE_CLASS_MISC 0xef
+#define USB_DEVICE_CLASS_APP_SPECIFIC 0xfe
+#define USB_DEVICE_CLASS_VEND_SPECIFIC 0xff
+
+/* usb string index define */
+#define USB_STRING_LANGID_INDEX 0x00
+#define USB_STRING_MFC_INDEX 0x01
+#define USB_STRING_PRODUCT_INDEX 0x02
+#define USB_STRING_SERIAL_INDEX 0x03
+#define USB_STRING_CONFIG_INDEX 0x04
+#define USB_STRING_INTERFACE_INDEX 0x05
+#define USB_STRING_OS_INDEX 0x06
+#define USB_STRING_MAX USB_STRING_OS_INDEX
+/*
+ * Devices supporting Microsoft OS Descriptors store special string
+ * descriptor at fixed index (0xEE). It is read when a new device is
+ * attached to a computer for the first time.
+ */
+#define USB_OSDESC_STRING_DESC_INDEX 0xEE
+
+/* bmAttributes in Configuration Descriptor */
+#define USB_CONFIG_REMOTE_WAKEUP 0x20
+#define USB_CONFIG_POWERED_MASK 0x40
+#define USB_CONFIG_BUS_POWERED 0x80
+#define USB_CONFIG_SELF_POWERED 0xC0
+
+/* bMaxPower in Configuration Descriptor */
+#define USB_CONFIG_POWER_MA(mA) ((mA) / 2)
+
+/* bEndpointAddress in Endpoint Descriptor */
+#define USB_ENDPOINT_DIRECTION_MASK 0x80
+#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
+#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
+
+/**
+ * USB endpoint direction and number.
+ */
+#define USB_EP_DIR_MASK 0x80U
+#define USB_EP_DIR_IN 0x80U
+#define USB_EP_DIR_OUT 0x00U
+
+/** Get endpoint index (number) from endpoint address */
+#define USB_EP_GET_IDX(ep) ((ep) & ~USB_EP_DIR_MASK)
+/** Get direction from endpoint address */
+#define USB_EP_GET_DIR(ep) ((ep)&USB_EP_DIR_MASK)
+/** Get endpoint address from endpoint index and direction */
+#define USB_EP_GET_ADDR(idx, dir) ((idx) | ((dir)&USB_EP_DIR_MASK))
+/** True if the endpoint is an IN endpoint */
+#define USB_EP_DIR_IS_IN(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_IN)
+/** True if the endpoint is an OUT endpoint */
+#define USB_EP_DIR_IS_OUT(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_OUT)
+
+/* bmAttributes in Endpoint Descriptor */
+#define USB_ENDPOINT_TYPE_SHIFT 0
+#define USB_ENDPOINT_TYPE_CONTROL (0 << USB_ENDPOINT_TYPE_SHIFT)
+#define USB_ENDPOINT_TYPE_ISOCHRONOUS (1 << USB_ENDPOINT_TYPE_SHIFT)
+#define USB_ENDPOINT_TYPE_BULK (2 << USB_ENDPOINT_TYPE_SHIFT)
+#define USB_ENDPOINT_TYPE_INTERRUPT (3 << USB_ENDPOINT_TYPE_SHIFT)
+#define USB_ENDPOINT_TYPE_MASK (3 << USB_ENDPOINT_TYPE_SHIFT)
+
+#define USB_ENDPOINT_SYNC_SHIFT 2
+#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION (0 << USB_ENDPOINT_SYNC_SHIFT)
+#define USB_ENDPOINT_SYNC_ASYNCHRONOUS (1 << USB_ENDPOINT_SYNC_SHIFT)
+#define USB_ENDPOINT_SYNC_ADAPTIVE (2 << USB_ENDPOINT_SYNC_SHIFT)
+#define USB_ENDPOINT_SYNC_SYNCHRONOUS (3 << USB_ENDPOINT_SYNC_SHIFT)
+#define USB_ENDPOINT_SYNC_MASK (3 << USB_ENDPOINT_SYNC_SHIFT)
+
+#define USB_ENDPOINT_USAGE_SHIFT 4
+#define USB_ENDPOINT_USAGE_DATA (0 << USB_ENDPOINT_USAGE_SHIFT)
+#define USB_ENDPOINT_USAGE_FEEDBACK (1 << USB_ENDPOINT_USAGE_SHIFT)
+#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK (2 << USB_ENDPOINT_USAGE_SHIFT)
+#define USB_ENDPOINT_USAGE_MASK (3 << USB_ENDPOINT_USAGE_SHIFT)
+
+#define USB_ENDPOINT_MAX_ADJUSTABLE (1 << 7)
+
+/* wMaxPacketSize in Endpoint Descriptor */
+#define USB_MAXPACKETSIZE_SHIFT 0
+#define USB_MAXPACKETSIZE_MASK (0x7ff << USB_MAXPACKETSIZE_SHIFT)
+#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT 11
+#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_NONE (0 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
+#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_ONE (1 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
+#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_TWO (2 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
+#define USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK (3 << USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT)
+
+/* bDevCapabilityType in Device Capability Descriptor */
+#define USB_DEVICE_CAPABILITY_WIRELESS_USB 1
+#define USB_DEVICE_CAPABILITY_USB_2_0_EXTENSION 2
+#define USB_DEVICE_CAPABILITY_SUPERSPEED_USB 3
+#define USB_DEVICE_CAPABILITY_CONTAINER_ID 4
+#define USB_DEVICE_CAPABILITY_PLATFORM 5
+#define USB_DEVICE_CAPABILITY_POWER_DELIVERY_CAPABILITY 6
+#define USB_DEVICE_CAPABILITY_BATTERY_INFO_CAPABILITY 7
+#define USB_DEVICE_CAPABILITY_PD_CONSUMER_PORT_CAPABILITY 8
+#define USB_DEVICE_CAPABILITY_PD_PROVIDER_PORT_CAPABILITY 9
+#define USB_DEVICE_CAPABILITY_SUPERSPEED_PLUS 10
+#define USB_DEVICE_CAPABILITY_PRECISION_TIME_MEASUREMENT 11
+#define USB_DEVICE_CAPABILITY_WIRELESS_USB_EXT 12
+
+#define USB_BOS_CAPABILITY_EXTENSION 0x02
+#define USB_BOS_CAPABILITY_PLATFORM 0x05
+
+/* OTG SET FEATURE Constants */
+#define USB_OTG_FEATURE_B_HNP_ENABLE 3 /* Enable B device to perform HNP */
+#define USB_OTG_FEATURE_A_HNP_SUPPORT 4 /* A device supports HNP */
+#define USB_OTG_FEATURE_A_ALT_HNP_SUPPORT 5 /* Another port on the A device supports HNP */
+
+/* WinUSB Microsoft OS 2.0 descriptor request codes */
+#define WINUSB_REQUEST_GET_DESCRIPTOR_SET 0x07
+#define WINUSB_REQUEST_SET_ALT_ENUM 0x08
+
+/* WinUSB Microsoft OS 2.0 descriptor sizes */
+#define WINUSB_DESCRIPTOR_SET_HEADER_SIZE 10
+#define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8
+#define WINUSB_FEATURE_COMPATIBLE_ID_SIZE 20
+
+/* WinUSB Microsoft OS 2.0 Descriptor Types */
+#define WINUSB_SET_HEADER_DESCRIPTOR_TYPE 0x00
+#define WINUSB_SUBSET_HEADER_CONFIGURATION_TYPE 0x01
+#define WINUSB_SUBSET_HEADER_FUNCTION_TYPE 0x02
+#define WINUSB_FEATURE_COMPATIBLE_ID_TYPE 0x03
+#define WINUSB_FEATURE_REG_PROPERTY_TYPE 0x04
+#define WINUSB_FEATURE_MIN_RESUME_TIME_TYPE 0x05
+#define WINUSB_FEATURE_MODEL_ID_TYPE 0x06
+#define WINUSB_FEATURE_CCGP_DEVICE_TYPE 0x07
+
+#define WINUSB_PROP_DATA_TYPE_REG_SZ 0x01
+#define WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ 0x07
+
+/* WebUSB Descriptor Types */
+#define WEBUSB_DESCRIPTOR_SET_HEADER_TYPE 0x00
+#define WEBUSB_CONFIGURATION_SUBSET_HEADER_TYPE 0x01
+#define WEBUSB_FUNCTION_SUBSET_HEADER_TYPE 0x02
+#define WEBUSB_URL_TYPE 0x03
+
+/* WebUSB Request Codes */
+#define WEBUSB_REQUEST_GET_URL 0x02
+
+/* bScheme in URL descriptor */
+#define WEBUSB_URL_SCHEME_HTTP 0x00
+#define WEBUSB_URL_SCHEME_HTTPS 0x01
+
+/* WebUSB Descriptor sizes */
+#define WEBUSB_DESCRIPTOR_SET_HEADER_SIZE 5
+#define WEBUSB_CONFIGURATION_SUBSET_HEADER_SIZE 4
+#define WEBUSB_FUNCTION_SUBSET_HEADER_SIZE 3
+
+/* Setup packet definition used to read raw data from USB line */
+struct usb_setup_packet {
+ /** Request type. Bits 0:4 determine recipient, see
+ * \ref usb_request_recipient. Bits 5:6 determine type, see
+ * \ref usb_request_type. Bit 7 determines data transfer direction, see
+ * \ref usb_endpoint_direction.
+ */
+ uint8_t bmRequestType;
+
+ /** Request. If the type bits of bmRequestType are equal to
+ * \ref usb_request_type::LIBUSB_REQUEST_TYPE_STANDARD
+ * "USB_REQUEST_TYPE_STANDARD" then this field refers to
+ * \ref usb_standard_request. For other cases, use of this field is
+ * application-specific. */
+ uint8_t bRequest;
+
+ /** Value. Varies according to request */
+ uint16_t wValue;
+
+ /** Index. Varies according to request, typically used to pass an index
+ * or offset */
+ uint16_t wIndex;
+
+ /** Number of bytes to transfer */
+ uint16_t wLength;
+} __PACKED;
+
+#define USB_SIZEOF_SETUP_PACKET 8
+
+/** Standard Device Descriptor */
+struct usb_device_descriptor {
+ uint8_t bLength; /* Descriptor size in bytes = 18 */
+ uint8_t bDescriptorType; /* DEVICE descriptor type = 1 */
+ uint16_t bcdUSB; /* USB spec in BCD, e.g. 0x0200 */
+ uint8_t bDeviceClass; /* Class code, if 0 see interface */
+ uint8_t bDeviceSubClass; /* Sub-Class code, 0 if class = 0 */
+ uint8_t bDeviceProtocol; /* Protocol, if 0 see interface */
+ uint8_t bMaxPacketSize0; /* Endpoint 0 max. size */
+ uint16_t idVendor; /* Vendor ID per USB-IF */
+ uint16_t idProduct; /* Product ID per manufacturer */
+ uint16_t bcdDevice; /* Device release # in BCD */
+ uint8_t iManufacturer; /* Index to manufacturer string */
+ uint8_t iProduct; /* Index to product string */
+ uint8_t iSerialNumber; /* Index to serial number string */
+ uint8_t bNumConfigurations; /* Number of possible configurations */
+} __PACKED;
+
+#define USB_SIZEOF_DEVICE_DESC 18
+
+/** Standard Configuration Descriptor */
+struct usb_configuration_descriptor {
+ uint8_t bLength; /* Descriptor size in bytes = 9 */
+ uint8_t bDescriptorType; /* CONFIGURATION type = 2 or 7 */
+ uint16_t wTotalLength; /* Length of concatenated descriptors */
+ uint8_t bNumInterfaces; /* Number of interfaces, this config. */
+ uint8_t bConfigurationValue; /* Value to set this config. */
+ uint8_t iConfiguration; /* Index to configuration string */
+ uint8_t bmAttributes; /* Config. characteristics */
+ uint8_t bMaxPower; /* Max.power from bus, 2mA units */
+} __PACKED;
+
+#define USB_SIZEOF_CONFIG_DESC 9
+
+/** Standard Interface Descriptor */
+struct usb_interface_descriptor {
+ uint8_t bLength; /* Descriptor size in bytes = 9 */
+ uint8_t bDescriptorType; /* INTERFACE descriptor type = 4 */
+ uint8_t bInterfaceNumber; /* Interface no.*/
+ uint8_t bAlternateSetting; /* Value to select this IF */
+ uint8_t bNumEndpoints; /* Number of endpoints excluding 0 */
+ uint8_t bInterfaceClass; /* Class code, 0xFF = vendor */
+ uint8_t bInterfaceSubClass; /* Sub-Class code, 0 if class = 0 */
+ uint8_t bInterfaceProtocol; /* Protocol, 0xFF = vendor */
+ uint8_t iInterface; /* Index to interface string */
+} __PACKED;
+
+#define USB_SIZEOF_INTERFACE_DESC 9
+
+/** Standard Endpoint Descriptor */
+struct usb_endpoint_descriptor {
+ uint8_t bLength; /* Descriptor size in bytes = 7 */
+ uint8_t bDescriptorType; /* ENDPOINT descriptor type = 5 */
+ uint8_t bEndpointAddress; /* Endpoint # 0 - 15 | IN/OUT */
+ uint8_t bmAttributes; /* Transfer type */
+ uint16_t wMaxPacketSize; /* Bits 10:0 = max. packet size */
+ uint8_t bInterval; /* Polling interval in (micro) frames */
+} __PACKED;
+
+#define USB_SIZEOF_ENDPOINT_DESC 7
+
+/** Unicode (UTF16LE) String Descriptor */
+struct usb_string_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bString;
+} __PACKED;
+
+#define USB_SIZEOF_STRING_LANGID_DESC 4
+
+/* USB Interface Association Descriptor */
+struct usb_interface_association_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bFirstInterface;
+ uint8_t bInterfaceCount;
+ uint8_t bFunctionClass;
+ uint8_t bFunctionSubClass;
+ uint8_t bFunctionProtocol;
+ uint8_t iFunction;
+} __PACKED;
+
+#define USB_SIZEOF_IAD_DESC 8
+
+/** USB device_qualifier descriptor */
+struct usb_device_qualifier_descriptor {
+ uint8_t bLength; /* Descriptor size in bytes = 10 */
+ uint8_t bDescriptorType; /* DEVICE QUALIFIER type = 6 */
+ uint16_t bcdUSB; /* USB spec in BCD, e.g. 0x0200 */
+ uint8_t bDeviceClass; /* Class code, if 0 see interface */
+ uint8_t bDeviceSubClass; /* Sub-Class code, 0 if class = 0 */
+ uint8_t bDeviceProtocol; /* Protocol, if 0 see interface */
+ uint8_t bMaxPacketSize; /* Endpoint 0 max. size */
+ uint8_t bNumConfigurations; /* Number of possible configurations */
+ uint8_t bReserved; /* Reserved = 0 */
+} __PACKED;
+
+#define USB_SIZEOF_DEVICE_QUALIFIER_DESC 10
+
+/* Microsoft OS function descriptor.
+ * This can be used to request a specific driver (such as WINUSB) to be
+ * loaded on Windows. Unlike other descriptors, it is requested by a special
+ * request USB_REQ_GETMSFTOSDESCRIPTOR.
+ * More details:
+ * https://msdn.microsoft.com/en-us/windows/hardware/gg463179
+ * And excellent explanation:
+ * https://github.com/pbatard/libwdi/wiki/WCID-Devices
+ *
+ * The device will have exactly one "Extended Compat ID Feature Descriptor",
+ * which may contain multiple "Function Descriptors" associated with
+ * different interfaces.
+ */
+
+/* MS OS 1.0 string descriptor */
+struct usb_msosv1_string_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bString[14];
+ uint8_t bMS_VendorCode; /* Vendor Code, used for a control request */
+ uint8_t bPad; /* Padding byte for VendorCode look as UTF16 */
+} __PACKED;
+
+/* MS OS 1.0 Header descriptor */
+struct usb_msosv1_compat_id_header_descriptor {
+ uint32_t dwLength;
+ uint16_t bcdVersion;
+ uint16_t wIndex;
+ uint8_t bCount;
+ uint8_t reserved[7];
+} __PACKED;
+
+/* MS OS 1.0 Function descriptor */
+struct usb_msosv1_comp_id_function_descriptor {
+ uint8_t bFirstInterfaceNumber;
+ uint8_t reserved1;
+ uint8_t compatibleID[8];
+ uint8_t subCompatibleID[8];
+ uint8_t reserved2[6];
+} __PACKED;
+
+#define usb_msosv1_comp_id_create(x) \
+ struct usb_msosv1_comp_id { \
+ struct usb_msosv1_compat_id_header_descriptor compat_id_header; \
+ struct usb_msosv1_comp_id_function_descriptor compat_id_function[x]; \
+ };
+
+struct usb_msosv1_descriptor {
+ uint8_t *string;
+ uint8_t string_len;
+ uint8_t vendor_code;
+ uint8_t *compat_id;
+ uint16_t compat_id_len;
+ uint8_t *comp_id_property;
+ uint16_t comp_id_property_len;
+};
+
+/* MS OS 2.0 Header descriptor */
+struct usb_msosv2_header_descriptor {
+ uint32_t dwLength;
+ uint16_t bcdVersion;
+ uint16_t wIndex;
+ uint8_t bCount;
+} __PACKED;
+
+/*Microsoft OS 2.0 set header descriptor*/
+struct usb_msosv2_set_header_descriptor {
+ uint16_t wLength;
+ uint16_t wDescriptorType;
+ uint32_t dwWindowsVersion;
+ uint16_t wDescriptorSetTotalLength;
+} __PACKED;
+
+/* Microsoft OS 2.0 compatibleID descriptor*/
+struct usb_msosv2_comp_id_descriptor {
+ uint16_t wLength;
+ uint16_t wDescriptorType;
+ uint8_t compatibleID[8];
+ uint8_t subCompatibleID[8];
+} __PACKED;
+
+/* MS OS 2.0 property descriptor */
+struct usb_msosv2_property_descriptor {
+ uint16_t wLength;
+ uint16_t wDescriptorType;
+ uint32_t dwPropertyDataType;
+ uint16_t wPropertyNameLength;
+ const char *bPropertyName;
+ uint32_t dwPropertyDataLength;
+ const char *bPropertyData;
+};
+
+/* Microsoft OS 2.0 subset function descriptor */
+struct usb_msosv2_subset_function_descriptor {
+ uint16_t wLength;
+ uint16_t wDescriptorType;
+ uint8_t bFirstInterface;
+ uint8_t bReserved;
+ uint16_t wSubsetLength;
+} __PACKED;
+
+struct usb_msosv2_descriptor {
+ uint8_t *compat_id;
+ uint16_t compat_id_len;
+ uint8_t vendor_code;
+};
+
+/* BOS header Descriptor */
+struct usb_bos_header_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t wTotalLength;
+ uint8_t bNumDeviceCaps;
+} __PACKED;
+
+/* BOS Capability platform Descriptor */
+struct usb_bos_capability_platform_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+ uint8_t bReserved;
+ uint8_t PlatformCapabilityUUID[16];
+} __PACKED;
+
+/* BOS Capability MS OS Descriptors version 2 */
+struct usb_bos_capability_msosv2_descriptor {
+ uint32_t dwWindowsVersion;
+ uint16_t wMSOSDescriptorSetTotalLength;
+ uint8_t bVendorCode;
+ uint8_t bAltEnumCode;
+} __PACKED;
+
+/* BOS Capability webusb */
+struct usb_bos_capability_webusb_descriptor {
+ uint16_t bcdVersion;
+ uint8_t bVendorCode;
+ uint8_t iLandingPage;
+} __PACKED;
+
+/* BOS Capability extension Descriptor*/
+struct usb_bos_capability_extension_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+ uint32_t bmAttributes;
+} __PACKED;
+
+/* Microsoft OS 2.0 Platform Capability Descriptor
+* See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/
+* microsoft-defined-usb-descriptors
+* Adapted from the source:
+* https://github.com/sowbug/weblight/blob/master/firmware/webusb.c
+* (BSD-2) Thanks http://janaxelson.com/files/ms_os_20_descriptors.c
+*/
+struct usb_bos_capability_platform_msosv2_descriptor {
+ struct usb_bos_capability_platform_descriptor platform_msos;
+ struct usb_bos_capability_msosv2_descriptor data_msosv2;
+} __PACKED;
+
+/* WebUSB Platform Capability Descriptor:
+* https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
+*/
+struct usb_bos_capability_platform_webusb_descriptor {
+ struct usb_bos_capability_platform_descriptor platform_webusb;
+ struct usb_bos_capability_webusb_descriptor data_webusb;
+} __PACKED;
+
+struct usb_webusb_url_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bScheme;
+ char URL[];
+} __PACKED;
+
+struct usb_bos_descriptor {
+ uint8_t *string;
+ uint32_t string_len;
+};
+
+/* USB Device Capability Descriptor */
+struct usb_device_capability_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+} __PACKED;
+
+/** USB descriptor header */
+struct usb_desc_header {
+ uint8_t bLength; /**< descriptor length */
+ uint8_t bDescriptorType; /**< descriptor type */
+};
+// clang-format off
+#define USB_DEVICE_DESCRIPTOR_INIT(bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct, bcdDevice, bNumConfigurations) \
+ 0x12, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_DEVICE, /* bDescriptorType */ \
+ WBVAL(bcdUSB), /* bcdUSB */ \
+ bDeviceClass, /* bDeviceClass */ \
+ bDeviceSubClass, /* bDeviceSubClass */ \
+ bDeviceProtocol, /* bDeviceProtocol */ \
+ 0x40, /* bMaxPacketSize */ \
+ WBVAL(idVendor), /* idVendor */ \
+ WBVAL(idProduct), /* idProduct */ \
+ WBVAL(bcdDevice), /* bcdDevice */ \
+ USB_STRING_MFC_INDEX, /* iManufacturer */ \
+ USB_STRING_PRODUCT_INDEX, /* iProduct */ \
+ USB_STRING_SERIAL_INDEX, /* iSerial */ \
+ bNumConfigurations /* bNumConfigurations */
+
+#define USB_CONFIG_DESCRIPTOR_INIT(wTotalLength, bNumInterfaces, bConfigurationValue, bmAttributes, bMaxPower) \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_CONFIGURATION, /* bDescriptorType */ \
+ WBVAL(wTotalLength), /* wTotalLength */ \
+ bNumInterfaces, /* bNumInterfaces */ \
+ bConfigurationValue, /* bConfigurationValue */ \
+ 0x00, /* iConfiguration */ \
+ bmAttributes, /* bmAttributes */ \
+ USB_CONFIG_POWER_MA(bMaxPower) /* bMaxPower */
+
+#define USB_INTERFACE_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints, \
+ bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface) \
+ 0x09, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \
+ bInterfaceNumber, /* bInterfaceNumber */ \
+ bAlternateSetting, /* bAlternateSetting */ \
+ bNumEndpoints, /* bNumEndpoints */ \
+ bInterfaceClass, /* bInterfaceClass */ \
+ bInterfaceSubClass, /* bInterfaceSubClass */ \
+ bInterfaceProtocol, /* bInterfaceProtocol */ \
+ iInterface /* iInterface */
+
+#define USB_ENDPOINT_DESCRIPTOR_INIT(bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval) \
+ 0x07, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \
+ bEndpointAddress, /* bEndpointAddress */ \
+ bmAttributes, /* bmAttributes */ \
+ WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \
+ bInterval /* bInterval */
+
+#define USB_IAD_INIT(bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol) \
+ 0x08, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \
+ bFirstInterface, /* bFirstInterface */ \
+ bInterfaceCount, /* bInterfaceCount */ \
+ bFunctionClass, /* bFunctionClass */ \
+ bFunctionSubClass, /* bFunctionSubClass */ \
+ bFunctionProtocol, /* bFunctionProtocol */ \
+ 0x00 /* iFunction */
+
+#define USB_LANGID_INIT(id) \
+ 0x04, /* bLength */ \
+ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ \
+ WBVAL(id) /* wLangID0 */
+// clang-format on
+
+#endif /* USB_DEF_H */
diff --git a/third-party/cherryusb-0.6.0/common/usb_errno.h b/third-party/cherryusb-0.6.0/common/usb_errno.h
new file mode 100644
index 0000000000000000000000000000000000000000..aef08e518ba2411e1a72fe4ffb293effcdb717e7
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/common/usb_errno.h
@@ -0,0 +1,326 @@
+/*
+ * Apache NuttX
+ * Copyright 2020 The Apache Software Foundation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef __INCLUDE_ERRNO_H
+#define __INCLUDE_ERRNO_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Convenience/compatibility definition. If the errno is accessed from the
+ * internal OS code, then the OS code should use the set_errno() and
+ * get_errno(). Currently, those are just placeholders but would be needed
+ * in the KERNEL mode build in order to instantiate the process address
+ * environment as necessary to access the TLS-based errno variable.
+ */
+
+#define errno *__errno()
+#define set_errno(e) \
+ do \
+ { \
+ errno = (int)(e); \
+ } \
+ while (0)
+#define get_errno() errno
+
+/* Definitions of error numbers and the string that would be
+ * returned by strerror().
+ */
+
+#define EPERM 1
+#define EPERM_STR "Operation not permitted"
+#define ENOENT 2
+#define ENOENT_STR "No such file or directory"
+#define ESRCH 3
+#define ESRCH_STR "No such process"
+#define EINTR 4
+#define EINTR_STR "Interrupted system call"
+#define EIO 5
+#define EIO_STR "I/O error"
+#define ENXIO 6
+#define ENXIO_STR "No such device or address"
+#define E2BIG 7
+#define E2BIG_STR "Arg list too long"
+#define ENOEXEC 8
+#define ENOEXEC_STR "Exec format error"
+#define EBADF 9
+#define EBADF_STR "Bad file number"
+#define ECHILD 10
+#define ECHILD_STR "No child processes"
+#define EAGAIN 11
+#define EWOULDBLOCK EAGAIN
+#define EAGAIN_STR "Try again"
+#define ENOMEM 12
+#define ENOMEM_STR "Out of memory"
+#define EACCES 13
+#define EACCES_STR "Permission denied"
+#define EFAULT 14 /* Linux errno extension */
+#define EFAULT_STR "Bad address"
+#define ENOTBLK 15
+#define ENOTBLK_STR "Block device required"
+#define EBUSY 16
+#define EBUSY_STR "Device or resource busy"
+#define EEXIST 17
+#define EEXIST_STR "File exists"
+#define EXDEV 18
+#define EXDEV_STR "Cross-device link"
+#define ENODEV 19
+#define ENODEV_STR "No such device"
+#define ENOTDIR 20
+#define ENOTDIR_STR "Not a directory"
+#define EISDIR 21
+#define EISDIR_STR "Is a directory"
+#define EINVAL 22
+#define EINVAL_STR "Invalid argument"
+#define ENFILE 23
+#define ENFILE_STR "File table overflow"
+#define EMFILE 24
+#define EMFILE_STR "Too many open files"
+#define ENOTTY 25
+#define ENOTTY_STR "Not a typewriter"
+#define ETXTBSY 26
+#define ETXTBSY_STR "Text file busy"
+#define EFBIG 27
+#define EFBIG_STR "File too large"
+#define ENOSPC 28
+#define ENOSPC_STR "No space left on device"
+#define ESPIPE 29
+#define ESPIPE_STR "Illegal seek"
+#define EROFS 30
+#define EROFS_STR "Read-only file system"
+#define EMLINK 31
+#define EMLINK_STR "Too many links"
+#define EPIPE 32
+#define EPIPE_STR "Broken pipe"
+#define EDOM 33
+#define EDOM_STR "Math argument out of domain of func"
+#define ERANGE 34
+#define ERANGE_STR "Math result not representable"
+#define ENOMSG 35
+#define ENOMSG_STR "No message of desired type"
+#define EIDRM 36
+#define EIDRM_STR "Identifier removed"
+#define ECHRNG 37 /* Linux errno extension */
+#define ECHRNG_STR "Channel number out of range"
+#define EL2NSYNC 38 /* Linux errno extension */
+#define EL2NSYNC_STR "Level 2 not synchronized"
+#define EL3HLT 39 /* Linux errno extension */
+#define EL3HLT_STR "Level 3 halted"
+#define EL3RST 40 /* Linux errno extension */
+#define EL3RST_STR "Level 3 reset"
+#define ELNRNG 41 /* Linux errno extension */
+#define ELNRNG_STR "Link number out of range"
+#define EUNATCH 42 /* Linux errno extension */
+#define EUNATCH_STR "Protocol driver not attached"
+#define ENOCSI 43 /* Linux errno extension */
+#define ENOCSI_STR "No CSI structure available"
+#define EL2HLT 44 /* Linux errno extension */
+#define EL2HLT_STR "Level 2 halted"
+#define EDEADLK 45
+#define EDEADLK_STR "Resource deadlock would occur"
+#define ENOLCK 46
+#define ENOLCK_STR "No record locks available"
+
+#define EBADE 50 /* Linux errno extension */
+#define EBADE_STR "Invalid exchange"
+#define EBADR 51 /* Linux errno extension */
+#define EBADR_STR "Invalid request descriptor"
+#define EXFULL 52 /* Linux errno extension */
+#define EXFULL_STR "Exchange full"
+#define ENOANO 53 /* Linux errno extension */
+#define ENOANO_STR "No anode"
+#define EBADRQC 54 /* Linux errno extension */
+#define EBADRQC_STR "Invalid request code"
+#define EBADSLT 55 /* Linux errno extension */
+#define EBADSLT_STR "Invalid slot"
+#define EDEADLOCK 56 /* Linux errno extension */
+#define EDEADLOCK_STR "File locking deadlock error"
+#define EBFONT 57 /* Linux errno extension */
+#define EBFONT_STR "Bad font file format"
+
+#define ENOSTR 60
+#define ENOSTR_STR "Device not a stream"
+#define ENODATA 61
+#define ENODATA_STR "No data available"
+#define ETIME 62
+#define ETIME_STR "Timer expired"
+#define ENOSR 63
+#define ENOSR_STR "Out of streams resources"
+#define ENONET 64 /* Linux errno extension */
+#define ENONET_STR "Machine is not on the network"
+#define ENOPKG 65 /* Linux errno extension */
+#define ENOPKG_STR "Package not installed"
+#define EREMOTE 66 /* Linux errno extension */
+#define EREMOTE_STR "Object is remote"
+#define ENOLINK 67
+#define ENOLINK_STR "Link has been severed"
+#define EADV 68 /* Linux errno extension */
+#define EADV_STR "Advertise error"
+#define ESRMNT 69 /* Linux errno extension */
+#define ESRMNT_STR "Srmount error"
+#define ECOMM 70 /* Linux errno extension */
+#define ECOMM_STR "Communication error on send"
+#define EPROTO 71
+#define EPROTO_STR "Protocol error"
+
+#define EMULTIHOP 74
+#define EMULTIHOP_STR "Multihop attempted"
+#define ELBIN 75 /* Linux errno extension */
+#define ELBIN_STR "Inode is remote"
+#define EDOTDOT 76 /* Linux errno extension */
+#define EDOTDOT_STR "RFS specific error"
+#define EBADMSG 77
+#define EBADMSG_STR "Not a data message"
+
+#define EFTYPE 79
+#define EFTYPE_STR "Inappropriate file type or format"
+#define ENOTUNIQ 80 /* Linux errno extension */
+#define ENOTUNIQ_STR "Name not unique on network"
+#define EBADFD 81 /* Linux errno extension */
+#define EBADFD_STR "File descriptor in bad state"
+#define EREMCHG 82 /* Linux errno extension */
+#define EREMCHG_STR "Remote address changed"
+#define ELIBACC 83 /* Linux errno extension */
+#define ELIBACC_STR "Can not access a needed shared library"
+#define ELIBBAD 84 /* Linux errno extension */
+#define ELIBBAD_STR "Accessing a corrupted shared library"
+#define ELIBSCN 85 /* Linux errno extension */
+#define ELIBSCN_STR ".lib section in a.out corrupted"
+#define ELIBMAX 86 /* Linux errno extension */
+#define ELIBMAX_STR "Attempting to link in too many shared libraries"
+#define ELIBEXEC 87 /* Linux errno extension */
+#define ELIBEXEC_STR "Cannot exec a shared library directly"
+#define ENOSYS 88
+#define ENOSYS_STR "Function not implemented"
+#define ENMFILE 89 /* Cygwin */
+#define ENMFILE_STR "No more files"
+#define ENOTEMPTY 90
+#define ENOTEMPTY_STR "Directory not empty"
+#define ENAMETOOLONG 91
+#define ENAMETOOLONG_STR "File name too long"
+#define ELOOP 92
+#define ELOOP_STR "Too many symbolic links encountered"
+
+#define EOPNOTSUPP 95
+#define EOPNOTSUPP_STR "Operation not supported on transport endpoint"
+#define EPFNOSUPPORT 96
+#define EPFNOSUPPORT_STR "Protocol family not supported"
+
+#define ECONNRESET 104
+#define ECONNRESET_STR "Connection reset by peer"
+#define ENOBUFS 105
+#define ENOBUFS_STR "No buffer space available"
+#define EAFNOSUPPORT 106
+#define EAFNOSUPPORT_STR "Address family not supported by protocol"
+#define EPROTOTYPE 107
+#define EPROTOTYPE_STR "Protocol wrong type for socket"
+#define ENOTSOCK 108
+#define ENOTSOCK_STR "Socket operation on non-socket"
+#define ENOPROTOOPT 109
+#define ENOPROTOOPT_STR "Protocol not available"
+#define ESHUTDOWN 110 /* Linux errno extension */
+#define ESHUTDOWN_STR "Cannot send after transport endpoint shutdown"
+#define ECONNREFUSED 111
+#define ECONNREFUSED_STR "Connection refused"
+#define EADDRINUSE 112
+#define EADDRINUSE_STR "Address already in use"
+#define ECONNABORTED 113
+#define ECONNABORTED_STR "Software caused connection abort"
+#define ENETUNREACH 114
+#define ENETUNREACH_STR "Network is unreachable"
+#define ENETDOWN 115
+#define ENETDOWN_STR "Network is down"
+#define ETIMEDOUT 116
+#define ETIMEDOUT_STR "Connection timed out"
+#define EHOSTDOWN 117
+#define EHOSTDOWN_STR "Host is down"
+#define EHOSTUNREACH 118
+#define EHOSTUNREACH_STR "No route to host"
+#define EINPROGRESS 119
+#define EINPROGRESS_STR "Operation now in progress"
+#define EALREADY 120
+#define EALREADY_STR "Socket already connected"
+#define EDESTADDRREQ 121
+#define EDESTADDRREQ_STR "Destination address required"
+#define EMSGSIZE 122
+#define EMSGSIZE_STR "Message too long"
+#define EPROTONOSUPPORT 123
+#define EPROTONOSUPPORT_STR "Protocol not supported"
+#define ESOCKTNOSUPPORT 124 /* Linux errno extension */
+#define ESOCKTNOSUPPORT_STR "Socket type not supported"
+#define EADDRNOTAVAIL 125
+#define EADDRNOTAVAIL_STR "Cannot assign requested address"
+#define ENETRESET 126
+#define ENETRESET_STR "Network dropped connection because of reset"
+#define EISCONN 127
+#define EISCONN_STR "Transport endpoint is already connected"
+#define ENOTCONN 128
+#define ENOTCONN_STR "Transport endpoint is not connected"
+#define ETOOMANYREFS 129
+#define ETOOMANYREFS_STR "Too many references: cannot splice"
+#define EPROCLIM 130
+#define EPROCLIM_STR "Limit would be exceeded by attempted fork"
+#define EUSERS 131
+#define EUSERS_STR "Too many users"
+#define EDQUOT 132
+#define EDQUOT_STR "Quota exceeded"
+#define ESTALE 133
+#define ESTALE_STR "Stale NFS file handle"
+#define ENOTSUP 134
+#define ENOTSUP_STR "Not supported"
+#define ENOMEDIUM 135 /* Linux errno extension */
+#define ENOMEDIUM_STR "No medium found"
+#define ENOSHARE 136 /* Cygwin */
+#define ENOSHARE_STR "No such host or network path"
+#define ECASECLASH 137 /* Cygwin */
+#define ECASECLASH_STR "Filename exists with different case"
+#define EILSEQ 138
+#define EILSEQ_STR "Illegal byte sequence"
+#define EOVERFLOW 139
+#define EOVERFLOW_STR "Value too large for defined data type"
+#define ECANCELED 140
+#define ECANCELED_STR "Operation cancelled"
+#define ENOTRECOVERABLE 141
+#define ENOTRECOVERABLE_STR "State not recoverable"
+#define EOWNERDEAD 142
+#define EOWNERDEAD_STR "Previous owner died"
+#define ESTRPIPE 143 /* Linux errno extension */
+#define ESTRPIPE_STR "Streams pipe error"
+
+#define __ELASTERROR 2000 /* Users can add values starting here */
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/* Return a pointer to the thread specific errno. */
+
+int *__errno(void);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __INCLUDE_ERRNO_H */
diff --git a/third-party/cherryusb-0.6.0/common/usb_hc.h b/third-party/cherryusb-0.6.0/common/usb_hc.h
new file mode 100644
index 0000000000000000000000000000000000000000..9a2d4cd18c4dfc5d8092d40ac67f7fb294104c18
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/common/usb_hc.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_HC_H
+#define USB_HC_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*usbh_complete_callback_t)(void *arg, int nbytes);
+typedef void *usbh_pipe_t;
+
+/**
+ * @brief USB Endpoint Configuration.
+ *
+ * Structure containing the USB endpoint configuration.
+ */
+struct usbh_endpoint_cfg {
+ struct usbh_hubport *hport;
+ uint8_t ep_addr; /* Endpoint addr with direction */
+ uint8_t ep_type; /* Endpoint type */
+ uint16_t ep_mps; /* Endpoint max packet size */
+ uint8_t ep_interval; /* Endpoint interval */
+ uint8_t mult; /* Endpoint additional transcation */
+};
+
+/**
+ * @brief USB Iso Configuration.
+ *
+ * Structure containing the USB Iso configuration.
+ */
+struct usbh_iso_frame_packet {
+ uint8_t *transfer_buffer;
+ uint32_t transfer_buffer_length;
+ uint32_t actual_length;
+ int errorcode;
+};
+
+/**
+ * @brief USB Urb Configuration.
+ *
+ * Structure containing the USB Urb configuration.
+ */
+struct usbh_urb {
+ usbh_pipe_t pipe;
+ struct usb_setup_packet *setup;
+ uint8_t *transfer_buffer;
+ uint32_t transfer_buffer_length;
+ int transfer_flags;
+ uint32_t actual_length;
+ uint32_t timeout;
+ int errorcode;
+ uint32_t num_of_iso_packets;
+ usbh_complete_callback_t complete;
+ void *arg;
+ struct usbh_iso_frame_packet iso_packet[0];
+};
+
+/**
+ * @brief usb host controller hardware init.
+ *
+ * @return On success will return 0, and others indicate fail.
+ */
+int usb_hc_init(void);
+
+/**
+ * @brief control roothub.
+ *
+ * @param setup setup request buffer.
+ * @param buf buf for reading response or write data.
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf);
+
+/**
+ * @brief reconfig control endpoint pipe.
+ *
+ * @param pipe A memory allocated for pipe.
+ * @param dev_addr device address.
+ * @param ep_mps control endpoint max packet size.
+ * @param speed port speed
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbh_ep0_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed);
+
+/**
+ * @brief Allocate pipe for endpoint
+ *
+ * @param pipe A memory location provided by the caller in which to save the allocated pipe.
+ * @param ep_cfg Describes the endpoint info to be allocated.
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg);
+
+/**
+ * @brief Free a pipe in which saves endpoint info.
+ *
+ * @param pipe A memory location provided by the caller in which to free the allocated endpoint info.
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbh_pipe_free(usbh_pipe_t pipe);
+
+/**
+ * @brief Submit a usb transfer request to an endpoint.
+ *
+ * If timeout is not zero, this function will be in poll transfer mode,
+ * otherwise will be in async transfer mode.
+ *
+ * @param urb Usb request block.
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbh_submit_urb(struct usbh_urb *urb);
+
+/**
+ * @brief Cancel a transfer request.
+ *
+ * This function will call When calls usbh_submit_urb and return -ETIMEOUT or -ESHUTDOWN.
+ *
+ * @param urb Usb request block.
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbh_kill_urb(struct usbh_urb *urb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USB_HC_H */
diff --git a/third-party/cherryusb-0.6.0/common/usb_list.h b/third-party/cherryusb-0.6.0/common/usb_list.h
new file mode 100644
index 0000000000000000000000000000000000000000..3078a1f24e781e9a4a54953b0497e1004cb2d0a3
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/common/usb_list.h
@@ -0,0 +1,459 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_LIST_H
+#define USB_LIST_H
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * usb_container_of - return the member address of ptr, if the type of ptr is the
+ * struct type.
+ */
+#define usb_container_of(ptr, type, member) \
+ ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
+
+/**
+ * Single List structure
+ */
+struct usb_slist_node {
+ struct usb_slist_node *next; /**< point to next node. */
+};
+typedef struct usb_slist_node usb_slist_t; /**< Type for single list. */
+
+/**
+ * @brief initialize a single list
+ *
+ * @param l the single list to be initialized
+ */
+static inline void usb_slist_init(usb_slist_t *l)
+{
+ l->next = NULL;
+}
+
+static inline void usb_slist_add_head(usb_slist_t *l, usb_slist_t *n)
+{
+ n->next = l->next;
+ l->next = n;
+}
+
+static inline void usb_slist_add_tail(usb_slist_t *l, usb_slist_t *n)
+{
+ usb_slist_t *tmp = l;
+
+ while (tmp->next) {
+ tmp = tmp->next;
+ }
+
+ /* append the node to the tail */
+ tmp->next = n;
+ n->next = NULL;
+}
+
+static inline void usb_slist_insert(usb_slist_t *l, usb_slist_t *next, usb_slist_t *n)
+{
+ if (!next) {
+ usb_slist_add_tail(next, l);
+ return;
+ }
+
+ while (l->next) {
+ if (l->next == next) {
+ l->next = n;
+ n->next = next;
+ }
+
+ l = l->next;
+ }
+}
+
+static inline usb_slist_t *usb_slist_remove(usb_slist_t *l, usb_slist_t *n)
+{
+ usb_slist_t *tmp = l;
+ /* remove slist head */
+ while (tmp->next && tmp->next != n) {
+ tmp = tmp->next;
+ }
+
+ /* remove node */
+ if (tmp->next != (usb_slist_t *)0) {
+ tmp->next = tmp->next->next;
+ }
+
+ return l;
+}
+
+static inline unsigned int usb_slist_len(const usb_slist_t *l)
+{
+ unsigned int len = 0;
+ const usb_slist_t *list = l->next;
+
+ while (list != NULL) {
+ list = list->next;
+ len++;
+ }
+
+ return len;
+}
+
+static inline unsigned int usb_slist_contains(usb_slist_t *l, usb_slist_t *n)
+{
+ while (l->next) {
+ if (l->next == n) {
+ return 0;
+ }
+
+ l = l->next;
+ }
+
+ return 1;
+}
+
+static inline usb_slist_t *usb_slist_head(usb_slist_t *l)
+{
+ return l->next;
+}
+
+static inline usb_slist_t *usb_slist_tail(usb_slist_t *l)
+{
+ while (l->next) {
+ l = l->next;
+ }
+
+ return l;
+}
+
+static inline usb_slist_t *usb_slist_next(usb_slist_t *n)
+{
+ return n->next;
+}
+
+static inline int usb_slist_isempty(usb_slist_t *l)
+{
+ return l->next == NULL;
+}
+
+/**
+ * @brief initialize a slist object
+ */
+#define USB_SLIST_OBJECT_INIT(object) \
+ { \
+ NULL \
+ }
+
+/**
+ * @brief initialize a slist object
+ */
+#define USB_SLIST_DEFINE(slist) \
+ usb_slist_t slist = { NULL }
+
+/**
+ * @brief get the struct for this single list node
+ * @param node the entry point
+ * @param type the type of structure
+ * @param member the name of list in structure
+ */
+#define usb_slist_entry(node, type, member) \
+ usb_container_of(node, type, member)
+
+/**
+ * usb_slist_first_entry - get the first element from a slist
+ * @ptr: the slist head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the slist_struct within the struct.
+ *
+ * Note, that slist is expected to be not empty.
+ */
+#define usb_slist_first_entry(ptr, type, member) \
+ usb_slist_entry((ptr)->next, type, member)
+
+/**
+ * usb_slist_tail_entry - get the tail element from a slist
+ * @ptr: the slist head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the slist_struct within the struct.
+ *
+ * Note, that slist is expected to be not empty.
+ */
+#define usb_slist_tail_entry(ptr, type, member) \
+ usb_slist_entry(usb_slist_tail(ptr), type, member)
+
+/**
+ * usb_slist_first_entry_or_null - get the first element from a slist
+ * @ptr: the slist head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the slist_struct within the struct.
+ *
+ * Note, that slist is expected to be not empty.
+ */
+#define usb_slist_first_entry_or_null(ptr, type, member) \
+ (usb_slist_isempty(ptr) ? NULL : usb_slist_first_entry(ptr, type, member))
+
+/**
+ * usb_slist_for_each - iterate over a single list
+ * @pos: the usb_slist_t * to use as a loop cursor.
+ * @head: the head for your single list.
+ */
+#define usb_slist_for_each(pos, head) \
+ for (pos = (head)->next; pos != NULL; pos = pos->next)
+
+#define usb_slist_for_each_safe(pos, next, head) \
+ for (pos = (head)->next, next = pos->next; pos; \
+ pos = next, next = pos->next)
+
+/**
+ * usb_slist_for_each_entry - iterate over single list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your single list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define usb_slist_for_each_entry(pos, head, member) \
+ for (pos = usb_slist_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (NULL); \
+ pos = usb_slist_entry(pos->member.next, typeof(*pos), member))
+
+#define usb_slist_for_each_entry_safe(pos, n, head, member) \
+ for (pos = usb_slist_entry((head)->next, typeof(*pos), member), \
+ n = usb_slist_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (NULL); \
+ pos = n, n = usb_slist_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * Double List structure
+ */
+struct usb_dlist_node {
+ struct usb_dlist_node *next; /**< point to next node. */
+ struct usb_dlist_node *prev; /**< point to prev node. */
+};
+typedef struct usb_dlist_node usb_dlist_t; /**< Type for lists. */
+
+/**
+ * @brief initialize a list
+ *
+ * @param l list to be initialized
+ */
+static inline void usb_dlist_init(usb_dlist_t *l)
+{
+ l->next = l->prev = l;
+}
+
+/**
+ * @brief insert a node after a list
+ *
+ * @param l list to insert it
+ * @param n new node to be inserted
+ */
+static inline void usb_dlist_insert_after(usb_dlist_t *l, usb_dlist_t *n)
+{
+ l->next->prev = n;
+ n->next = l->next;
+
+ l->next = n;
+ n->prev = l;
+}
+
+/**
+ * @brief insert a node before a list
+ *
+ * @param n new node to be inserted
+ * @param l list to insert it
+ */
+static inline void usb_dlist_insert_before(usb_dlist_t *l, usb_dlist_t *n)
+{
+ l->prev->next = n;
+ n->prev = l->prev;
+
+ l->prev = n;
+ n->next = l;
+}
+
+/**
+ * @brief remove node from list.
+ * @param n the node to remove from the list.
+ */
+static inline void usb_dlist_remove(usb_dlist_t *n)
+{
+ n->next->prev = n->prev;
+ n->prev->next = n->next;
+
+ n->next = n->prev = n;
+}
+
+/**
+ * @brief move node from list.
+ * @param n the node to remove from the list.
+ */
+static inline void usb_dlist_move_head(usb_dlist_t *l, usb_dlist_t *n)
+{
+ usb_dlist_remove(n);
+ usb_dlist_insert_after(l, n);
+}
+
+/**
+ * @brief move node from list.
+ * @param n the node to remove from the list.
+ */
+static inline void usb_dlist_move_tail(usb_dlist_t *l, usb_dlist_t *n)
+{
+ usb_dlist_remove(n);
+ usb_dlist_insert_before(l, n);
+}
+
+/**
+ * @brief tests whether a list is empty
+ * @param l the list to test.
+ */
+static inline int usb_dlist_isempty(const usb_dlist_t *l)
+{
+ return l->next == l;
+}
+
+/**
+ * @brief get the list length
+ * @param l the list to get.
+ */
+static inline unsigned int usb_dlist_len(const usb_dlist_t *l)
+{
+ unsigned int len = 0;
+ const usb_dlist_t *p = l;
+
+ while (p->next != l) {
+ p = p->next;
+ len++;
+ }
+
+ return len;
+}
+
+/**
+ * @brief initialize a dlist object
+ */
+#define USB_DLIST_OBJECT_INIT(object) \
+ { \
+ &(object), &(object) \
+ }
+/**
+ * @brief initialize a dlist object
+ */
+#define USB_DLIST_DEFINE(list) \
+ usb_dlist_t list = { &(list), &(list) }
+
+/**
+ * @brief get the struct for this entry
+ * @param node the entry point
+ * @param type the type of structure
+ * @param member the name of list in structure
+ */
+#define usb_dlist_entry(node, type, member) \
+ usb_container_of(node, type, member)
+
+/**
+ * dlist_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define usb_dlist_first_entry(ptr, type, member) \
+ usb_dlist_entry((ptr)->next, type, member)
+/**
+ * dlist_first_entry_or_null - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define usb_dlist_first_entry_or_null(ptr, type, member) \
+ (usb_dlist_isempty(ptr) ? NULL : usb_dlist_first_entry(ptr, type, member))
+
+/**
+ * usb_dlist_for_each - iterate over a list
+ * @pos: the usb_dlist_t * to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define usb_dlist_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * usb_dlist_for_each_prev - iterate over a list
+ * @pos: the dlist_t * to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define usb_dlist_for_each_prev(pos, head) \
+ for (pos = (head)->prev; pos != (head); pos = pos->prev)
+
+/**
+ * usb_dlist_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the dlist_t * to use as a loop cursor.
+ * @n: another dlist_t * to use as temporary storage
+ * @head: the head for your list.
+ */
+#define usb_dlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+#define usb_dlist_for_each_prev_safe(pos, n, head) \
+ for (pos = (head)->prev, n = pos->prev; pos != (head); \
+ pos = n, n = pos->prev)
+/**
+ * usb_dlist_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define usb_dlist_for_each_entry(pos, head, member) \
+ for (pos = usb_dlist_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = usb_dlist_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * usb_usb_dlist_for_each_entry_reverse - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define usb_dlist_for_each_entry_reverse(pos, head, member) \
+ for (pos = usb_dlist_entry((head)->prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = usb_dlist_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * usb_usb_dlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define usb_dlist_for_each_entry_safe(pos, n, head, member) \
+ for (pos = usb_dlist_entry((head)->next, typeof(*pos), member), \
+ n = usb_dlist_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = usb_dlist_entry(n->member.next, typeof(*n), member))
+
+/**
+ * usb_usb_dlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define usb_dlist_for_each_entry_safe_reverse(pos, n, head, member) \
+ for (pos = usb_dlist_entry((head)->prev, typeof(*pos), field), \
+ n = usb_dlist_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = usb_dlist_entry(pos->member.prev, typeof(*pos), member))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USB_LIST_H */
diff --git a/third-party/cherryusb-0.6.0/common/usb_log.h b/third-party/cherryusb-0.6.0/common/usb_log.h
new file mode 100644
index 0000000000000000000000000000000000000000..45ad9e171a6588fca613add1bd799b9c1dd8d6a5
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/common/usb_log.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_LOG_H
+#define USB_LOG_H
+
+#include
+
+/* DEBUG level */
+#define USB_DBG_ERROR 0
+#define USB_DBG_WARNING 1
+#define USB_DBG_INFO 2
+#define USB_DBG_LOG 3
+
+#ifndef CONFIG_USB_DBG_LEVEL
+#define CONFIG_USB_DBG_LEVEL USB_DBG_INFO
+#endif
+
+#ifndef USB_DBG_TAG
+#define USB_DBG_TAG "USB"
+#endif
+/*
+ * The color for terminal (foreground)
+ * BLACK 30
+ * RED 31
+ * GREEN 32
+ * YELLOW 33
+ * BLUE 34
+ * PURPLE 35
+ * CYAN 36
+ * WHITE 37
+ */
+#ifndef CONFIG_USB_PRINTF
+#define CONFIG_USB_PRINTF printf
+#endif
+
+#ifdef CONFIG_USB_PRINTF_COLOR_ENABLE
+#define _USB_DBG_COLOR(n) CONFIG_USB_PRINTF("\033[" #n "m")
+#define _USB_DBG_LOG_HDR(lvl_name, color_n) \
+ CONFIG_USB_PRINTF("\033[" #color_n "m[" lvl_name "/" USB_DBG_TAG "] ")
+#define _USB_DBG_LOG_X_END \
+ CONFIG_USB_PRINTF("\033[0m")
+#else
+#define _USB_DBG_COLOR(n)
+#define _USB_DBG_LOG_HDR(lvl_name, color_n) \
+ CONFIG_USB_PRINTF("[" lvl_name "/" USB_DBG_TAG "] ")
+#define _USB_DBG_LOG_X_END
+#endif
+
+#define usb_dbg_log_line(lvl, color_n, fmt, ...) \
+ do { \
+ _USB_DBG_LOG_HDR(lvl, color_n); \
+ CONFIG_USB_PRINTF(fmt, ##__VA_ARGS__); \
+ _USB_DBG_LOG_X_END; \
+ } while (0)
+
+#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_LOG)
+#define USB_LOG_DBG(fmt, ...) usb_dbg_log_line("D", 0, fmt, ##__VA_ARGS__)
+#else
+#define USB_LOG_DBG(...)
+#endif
+
+#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_INFO)
+#define USB_LOG_INFO(fmt, ...) usb_dbg_log_line("I", 32, fmt, ##__VA_ARGS__)
+#else
+#define USB_LOG_INFO(...)
+#endif
+
+#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_WARNING)
+#define USB_LOG_WRN(fmt, ...) usb_dbg_log_line("W", 33, fmt, ##__VA_ARGS__)
+#else
+#define USB_LOG_WRN(...)
+#endif
+
+#if (CONFIG_USB_DBG_LEVEL >= USB_DBG_ERROR)
+#define USB_LOG_ERR(fmt, ...) usb_dbg_log_line("E", 31, fmt, ##__VA_ARGS__)
+#else
+#define USB_LOG_ERR(...)
+#endif
+
+#define USB_LOG_RAW CONFIG_USB_PRINTF
+
+void usb_assert(const char *filename, int linenum);
+#define USB_ASSERT(f) \
+ do { \
+ if (!(f)) \
+ usb_assert(__FILE__, __LINE__); \
+ } while (0)
+
+#endif /* USB_LOG_H */
diff --git a/third-party/cherryusb-0.6.0/common/usb_mem.h b/third-party/cherryusb-0.6.0/common/usb_mem.h
new file mode 100644
index 0000000000000000000000000000000000000000..3377ba62829b392c161b3a72ed93782368cd3f48
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/common/usb_mem.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_MEM_H
+#define USB_MEM_H
+
+#include "usb_config.h"
+
+#ifdef CONFIG_USBHOST_XHCI
+
+void *usb_hc_malloc(size_t size);
+void usb_hc_free();
+void *usb_hc_malloc_align(size_t align, size_t size);
+
+#define usb_malloc(size) usb_hc_malloc(size)
+#define usb_free(ptr) usb_hc_free(ptr)
+#define usb_align(align, size) usb_hc_malloc_align(align, size)
+
+#else
+
+#define usb_malloc(size) malloc(size)
+#define usb_free(ptr) free(ptr)
+
+#endif
+
+#ifndef CONFIG_USB_ALIGN_SIZE
+#define CONFIG_USB_ALIGN_SIZE 4
+#endif
+
+#ifndef USB_NOCACHE_RAM_SECTION
+#define USB_NOCACHE_RAM_SECTION
+#endif
+#define USB_MEM_ALIGNX __attribute__((aligned(CONFIG_USB_ALIGN_SIZE)))
+
+#if (CONFIG_USB_ALIGN_SIZE > 4)
+static inline void *usb_iomalloc(size_t size)
+{
+ void *ptr;
+ void *align_ptr;
+ int uintptr_size;
+ size_t align_size;
+ uint32_t align = CONFIG_USB_ALIGN_SIZE;
+
+ /* sizeof pointer */
+ uintptr_size = sizeof(void *);
+ uintptr_size -= 1;
+
+ /* align the alignment size to uintptr size byte */
+ align = ((align + uintptr_size) & ~uintptr_size);
+
+ /* get total aligned size */
+ align_size = ((size + uintptr_size) & ~uintptr_size) + align;
+ /* allocate memory block from heap */
+ ptr = usb_malloc(align_size);
+ if (ptr != NULL) {
+ /* the allocated memory block is aligned */
+ if (((unsigned long)ptr & (align - 1)) == 0) {
+ align_ptr = (void *)((unsigned long)ptr + align);
+ } else {
+ align_ptr = (void *)(((unsigned long)ptr + (align - 1)) & ~(align - 1));
+ }
+
+ /* set the pointer before alignment pointer to the real pointer */
+ *((unsigned long *)((unsigned long)align_ptr - sizeof(void *))) = (unsigned long)ptr;
+
+ ptr = align_ptr;
+ }
+
+ return ptr;
+}
+
+static inline void usb_iofree(void *ptr)
+{
+ void *real_ptr;
+
+ real_ptr = (void *)*(unsigned long *)((unsigned long)ptr - sizeof(void *));
+ usb_free(real_ptr);
+}
+#else
+#define usb_iomalloc(size) usb_malloc(size)
+#define usb_iofree(ptr) usb_free(ptr)
+#endif
+
+#endif /* USB_MEM_H */
diff --git a/third-party/cherryusb-0.6.0/common/usb_util.h b/third-party/cherryusb-0.6.0/common/usb_util.h
new file mode 100644
index 0000000000000000000000000000000000000000..790dfe544a4f8e49a5e206e52aa6952557cfa60b
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/common/usb_util.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_UTIL_H
+#define USB_UTIL_H
+
+#if defined(__CC_ARM)
+#ifndef __USED
+#define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+#define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+#define __PACKED __attribute__((packed))
+#endif
+#ifndef __PACKED_STRUCT
+#define __PACKED_STRUCT __packed struct
+#endif
+#ifndef __PACKED_UNION
+#define __PACKED_UNION __packed union
+#endif
+#ifndef __ALIGNED
+#define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#elif defined(__GNUC__)
+#ifndef __USED
+#define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+#define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+#define __PACKED __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_STRUCT
+#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_UNION
+#define __PACKED_UNION union __attribute__((packed, aligned(1)))
+#endif
+#ifndef __ALIGNED
+#define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#elif defined(__ICCARM__)
+#ifndef __USED
+#if __ICCARM_V8
+#define __USED __attribute__((used))
+#else
+#define __USED _Pragma("__root")
+#endif
+#endif
+
+#ifndef __WEAK
+#if __ICCARM_V8
+#define __WEAK __attribute__((weak))
+#else
+#define __WEAK _Pragma("__weak")
+#endif
+#endif
+
+#ifndef __PACKED
+#if __ICCARM_V8
+#define __PACKED __attribute__((packed, aligned(1)))
+#else
+/* Needs IAR language extensions */
+#define __PACKED __packed
+#endif
+#endif
+
+#ifndef __PACKED_STRUCT
+#if __ICCARM_V8
+#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+#else
+/* Needs IAR language extensions */
+#define __PACKED_STRUCT __packed struct
+#endif
+#endif
+
+#ifndef __PACKED_UNION
+#if __ICCARM_V8
+#define __PACKED_UNION union __attribute__((packed, aligned(1)))
+#else
+/* Needs IAR language extensions */
+#define __PACKED_UNION __packed union
+#endif
+#endif
+
+#ifndef __ALIGNED
+#if __ICCARM_V8
+#define __ALIGNED(x) __attribute__((aligned(x)))
+#elif (__VER__ >= 7080000)
+/* Needs IAR language extensions */
+#define __ALIGNED(x) __attribute__((aligned(x)))
+#else
+#warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored.
+#define __ALIGNED(x)
+#endif
+#endif
+
+#endif
+
+#ifndef __ALIGN_BEGIN
+#define __ALIGN_BEGIN
+#endif
+#ifndef __ALIGN_END
+#define __ALIGN_END __attribute__((aligned(4)))
+#endif
+
+#ifndef ARG_UNUSED
+#define ARG_UNUSED(x) (void)(x)
+#endif
+
+#ifndef LO_BYTE
+#define LO_BYTE(x) ((uint8_t)(x & 0x00FF))
+#endif
+
+#ifndef HI_BYTE
+#define HI_BYTE(x) ((uint8_t)((x & 0xFF00) >> 8))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef BCD
+#define BCD(x) ((((x) / 10) << 4) | ((x) % 10))
+#endif
+
+#ifdef BIT
+#undef BIT
+#define BIT(n) (1UL << (n))
+#else
+#define BIT(n) (1UL << (n))
+#endif
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) \
+ ((int)((sizeof(array) / sizeof((array)[0]))))
+#endif
+
+#ifndef BSWAP16
+#define BSWAP16(u16) (__builtin_bswap16(u16))
+#endif
+#ifndef BSWAP32
+#define BSWAP32(u32) (__builtin_bswap32(u32))
+#endif
+
+#define GET_BE16(field) \
+ (((uint16_t)(field)[0] << 8) | ((uint16_t)(field)[1]))
+
+#define GET_BE32(field) \
+ (((uint32_t)(field)[0] << 24) | ((uint32_t)(field)[1] << 16) | ((uint32_t)(field)[2] << 8) | ((uint32_t)(field)[3] << 0))
+
+#define SET_BE16(field, value) \
+ do { \
+ (field)[0] = (uint8_t)((value) >> 8); \
+ (field)[1] = (uint8_t)((value) >> 0); \
+ } while (0)
+
+#define SET_BE24(field, value) \
+ do { \
+ (field)[0] = (uint8_t)((value) >> 16); \
+ (field)[1] = (uint8_t)((value) >> 8); \
+ (field)[2] = (uint8_t)((value) >> 0); \
+ } while (0)
+
+#define SET_BE32(field, value) \
+ do { \
+ (field)[0] = (uint8_t)((value) >> 24); \
+ (field)[1] = (uint8_t)((value) >> 16); \
+ (field)[2] = (uint8_t)((value) >> 8); \
+ (field)[3] = (uint8_t)((value) >> 0); \
+ } while (0)
+
+#define WBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF)
+#define DBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF), ((x >> 16) & 0xFF), ((x >> 24) & 0xFF)
+
+#define PP_NARG(...) \
+ PP_NARG_(__VA_ARGS__, PP_RSEQ_N())
+#define PP_NARG_(...) \
+ PP_ARG_N(__VA_ARGS__)
+#define PP_ARG_N( \
+ _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
+ _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
+ _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \
+ _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \
+ _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
+ _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \
+ _61, _62, _63, N, ...) N
+#define PP_RSEQ_N() \
+ 63, 62, 61, 60, \
+ 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
+ 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
+ 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \
+ 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
+ 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
+ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
+#endif /* USB_UTIL_H */
diff --git a/third-party/cherryusb-0.6.0/core/usbd_core.c b/third-party/cherryusb-0.6.0/core/usbd_core.c
new file mode 100644
index 0000000000000000000000000000000000000000..612e79519229f2c58274273feae3cb9c1d3add9e
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/core/usbd_core.c
@@ -0,0 +1,982 @@
+/*
+ * Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbd_core.h"
+
+/* general descriptor field offsets */
+#define DESC_bLength 0 /** Length offset */
+#define DESC_bDescriptorType 1 /** Descriptor type offset */
+
+/* config descriptor field offsets */
+#define CONF_DESC_wTotalLength 2 /** Total length offset */
+#define CONF_DESC_bConfigurationValue 5 /** Configuration value offset */
+#define CONF_DESC_bmAttributes 7 /** configuration characteristics */
+
+/* interface descriptor field offsets */
+#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
+#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
+
+#define USB_EP_OUT_NUM 8
+#define USB_EP_IN_NUM 8
+
+USB_NOCACHE_RAM_SECTION struct usbd_core_cfg_priv {
+ /** Setup packet */
+ USB_MEM_ALIGNX struct usb_setup_packet setup;
+ /** Pointer to data buffer */
+ uint8_t *ep0_data_buf;
+ /** Remaining bytes in buffer */
+ uint32_t ep0_data_buf_residue;
+ /** Total length of control transfer */
+ uint32_t ep0_data_buf_len;
+ /** Zero length packet flag of control transfer */
+ bool zlp_flag;
+ /** Pointer to registered descriptors */
+ const uint8_t *descriptors;
+ /* Buffer used for storing standard, class and vendor request data */
+ USB_MEM_ALIGNX uint8_t req_data[CONFIG_USBDEV_REQUEST_BUFFER_LEN];
+
+ usbd_endpoint_callback in_ep_cb[USB_EP_IN_NUM];
+ usbd_endpoint_callback out_ep_cb[USB_EP_OUT_NUM];
+
+ /** Variable to check whether the usb has been configured */
+ bool configured;
+ /** Currently selected configuration */
+ uint8_t configuration;
+#ifdef CONFIG_USBDEV_TEST_MODE
+ bool test_mode;
+#endif
+ uint8_t intf_offset;
+} usbd_core_cfg;
+
+usb_slist_t usbd_intf_head = USB_SLIST_OBJECT_INIT(usbd_intf_head);
+
+static struct usb_msosv1_descriptor *msosv1_desc;
+static struct usb_msosv2_descriptor *msosv2_desc;
+static struct usb_bos_descriptor *bos_desc;
+
+static void usbd_class_event_notify_handler(uint8_t event, void *arg);
+
+static void usbd_print_setup(struct usb_setup_packet *setup)
+{
+ USB_LOG_INFO("Setup: "
+ "bmRequestType 0x%02x, bRequest 0x%02x, wValue 0x%04x, wIndex 0x%04x, wLength 0x%04x\r\n",
+ setup->bmRequestType,
+ setup->bRequest,
+ setup->wValue,
+ setup->wIndex,
+ setup->wLength);
+}
+
+static bool is_device_configured(void)
+{
+ return (usbd_core_cfg.configuration != 0);
+}
+
+/**
+ * @brief configure and enable endpoint
+ *
+ * This function sets endpoint configuration according to one specified in USB
+ * endpoint descriptor and then enables it for data transfers.
+ *
+ * @param [in] ep_desc Endpoint descriptor byte array
+ *
+ * @return true if successfully configured and enabled
+ */
+static bool usbd_set_endpoint(const struct usb_endpoint_descriptor *ep_desc)
+{
+ struct usbd_endpoint_cfg ep_cfg;
+
+ ep_cfg.ep_addr = ep_desc->bEndpointAddress;
+ ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
+ ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
+
+ USB_LOG_INFO("Open endpoint:0x%x type:%u mps:%u\r\n",
+ ep_cfg.ep_addr, ep_cfg.ep_type, ep_cfg.ep_mps);
+
+ return usbd_ep_open(&ep_cfg) == 0 ? true : false;
+}
+/**
+ * @brief Disable endpoint for transferring data
+ *
+ * This function cancels transfers that are associated with endpoint and
+ * disabled endpoint itself.
+ *
+ * @param [in] ep_desc Endpoint descriptor byte array
+ *
+ * @return true if successfully deconfigured and disabled
+ */
+static bool usbd_reset_endpoint(const struct usb_endpoint_descriptor *ep_desc)
+{
+ struct usbd_endpoint_cfg ep_cfg;
+
+ ep_cfg.ep_addr = ep_desc->bEndpointAddress;
+ ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
+ ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
+
+ USB_LOG_INFO("Close endpoint:0x%x type:%u\r\n",
+ ep_cfg.ep_addr, ep_cfg.ep_type);
+
+ return usbd_ep_close(ep_cfg.ep_addr) == 0 ? true : false;
+}
+
+/**
+ * @brief get specified USB descriptor
+ *
+ * This function parses the list of installed USB descriptors and attempts
+ * to find the specified USB descriptor.
+ *
+ * @param [in] type_index Type and index of the descriptor
+ * @param [out] data Descriptor data
+ * @param [out] len Descriptor length
+ *
+ * @return true if the descriptor was found, false otherwise
+ */
+static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *len)
+{
+ uint8_t type = 0U;
+ uint8_t index = 0U;
+ uint8_t *p = NULL;
+ uint32_t cur_index = 0U;
+ bool found = false;
+
+ type = HI_BYTE(type_index);
+ index = LO_BYTE(type_index);
+
+ if ((type == USB_DESCRIPTOR_TYPE_STRING) && (index == USB_OSDESC_STRING_DESC_INDEX)) {
+ USB_LOG_INFO("read MS OS 2.0 descriptor string\r\n");
+
+ if (!msosv1_desc) {
+ return false;
+ }
+
+ *data = (uint8_t *)msosv1_desc->string;
+ *len = msosv1_desc->string_len;
+
+ return true;
+ } else if (type == USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE) {
+ USB_LOG_INFO("read BOS descriptor string\r\n");
+
+ if (!bos_desc) {
+ return false;
+ }
+
+ *data = bos_desc->string;
+ *len = bos_desc->string_len;
+ return true;
+ }
+ /*
+ * Invalid types of descriptors,
+ * see USB Spec. Revision 2.0, 9.4.3 Get Descriptor
+ */
+ else if ((type == USB_DESCRIPTOR_TYPE_INTERFACE) || (type == USB_DESCRIPTOR_TYPE_ENDPOINT) ||
+#ifndef CONFIG_USB_HS
+ (type > USB_DESCRIPTOR_TYPE_ENDPOINT)) {
+#else
+ (type > USB_DESCRIPTOR_TYPE_OTHER_SPEED)) {
+#endif
+ return false;
+ }
+
+ p = (uint8_t *)usbd_core_cfg.descriptors;
+
+ cur_index = 0U;
+
+ while (p[DESC_bLength] != 0U) {
+ if (p[DESC_bDescriptorType] == type) {
+ if (cur_index == index) {
+ found = true;
+ break;
+ }
+
+ cur_index++;
+ }
+
+ /* skip to next descriptor */
+ p += p[DESC_bLength];
+ }
+
+ if (found) {
+ /* found descriptor, save descriptor premiere address */
+ *data = p;
+
+ if ((type == USB_DESCRIPTOR_TYPE_CONFIGURATION) || ((type == USB_DESCRIPTOR_TYPE_OTHER_SPEED))) {
+ /* configuration or other speed descriptor is an
+ * exception, length is at offset 2 and 3
+ */
+ *len = (p[CONF_DESC_wTotalLength]) |
+ (p[CONF_DESC_wTotalLength + 1] << 8);
+ } else {
+ /* normally length is at offset 0 */
+ *len = p[DESC_bLength];
+ }
+ } else {
+ /* nothing found */
+ USB_LOG_ERR("descriptor not found!\r\n", type, index);
+ }
+
+ return found;
+}
+
+/**
+ * @brief set USB configuration
+ *
+ * This function configures the device according to the specified configuration
+ * index and alternate setting by parsing the installed USB descriptor list.
+ * A configuration index of 0 unconfigures the device.
+ *
+ * @param [in] config_index Configuration index
+ * @param [in] alt_setting Alternate setting number
+ *
+ * @return true if successfully configured false if error or unconfigured
+ */
+static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting)
+{
+ uint8_t *p = (uint8_t *)usbd_core_cfg.descriptors;
+ uint8_t cur_alt_setting = 0xFF;
+ uint8_t cur_config = 0xFF;
+ bool found = false;
+
+ /* configure endpoints for this configuration/altsetting */
+ while (p[DESC_bLength] != 0U) {
+ switch (p[DESC_bDescriptorType]) {
+ case USB_DESCRIPTOR_TYPE_CONFIGURATION:
+ /* remember current configuration index */
+ cur_config = p[CONF_DESC_bConfigurationValue];
+
+ if (cur_config == config_index) {
+ found = true;
+ }
+
+ break;
+
+ case USB_DESCRIPTOR_TYPE_INTERFACE:
+ /* remember current alternate setting */
+ cur_alt_setting =
+ p[INTF_DESC_bAlternateSetting];
+ break;
+
+ case USB_DESCRIPTOR_TYPE_ENDPOINT:
+ if ((cur_config != config_index) ||
+ (cur_alt_setting != alt_setting)) {
+ break;
+ }
+
+ found = usbd_set_endpoint((struct usb_endpoint_descriptor *)p);
+ break;
+
+ default:
+ break;
+ }
+
+ /* skip to next descriptor */
+ p += p[DESC_bLength];
+ }
+
+ return found;
+}
+
+/**
+ * @brief set USB interface
+ *
+ * @param [in] iface Interface index
+ * @param [in] alt_setting Alternate setting number
+ *
+ * @return true if successfully configured false if error or unconfigured
+ */
+static bool usbd_set_interface(uint8_t iface, uint8_t alt_setting)
+{
+ const uint8_t *p = usbd_core_cfg.descriptors;
+ const uint8_t *if_desc = NULL;
+ struct usb_endpoint_descriptor *ep_desc;
+ uint8_t cur_alt_setting = 0xFF;
+ uint8_t cur_iface = 0xFF;
+ bool ret = false;
+
+ USB_LOG_DBG("iface %u alt_setting %u\r\n", iface, alt_setting);
+
+ while (p[DESC_bLength] != 0U) {
+ switch (p[DESC_bDescriptorType]) {
+ case USB_DESCRIPTOR_TYPE_INTERFACE:
+ /* remember current alternate setting */
+ cur_alt_setting = p[INTF_DESC_bAlternateSetting];
+ cur_iface = p[INTF_DESC_bInterfaceNumber];
+
+ if (cur_iface == iface &&
+ cur_alt_setting == alt_setting) {
+ if_desc = (void *)p;
+ }
+
+ USB_LOG_DBG("Current iface %u alt setting %u",
+ cur_iface, cur_alt_setting);
+ break;
+
+ case USB_DESCRIPTOR_TYPE_ENDPOINT:
+ if (cur_iface == iface) {
+ ep_desc = (struct usb_endpoint_descriptor *)p;
+
+ if (cur_alt_setting != alt_setting) {
+ ret = usbd_reset_endpoint(ep_desc);
+ } else {
+ ret = usbd_set_endpoint(ep_desc);
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ /* skip to next descriptor */
+ p += p[DESC_bLength];
+ }
+
+ usbd_class_event_notify_handler(USBD_EVENT_SET_INTERFACE, (void *)if_desc);
+
+ return ret;
+}
+
+/**
+ * @brief handle a standard device request
+ *
+ * @param [in] setup The setup packet
+ * @param [in,out] data Data buffer
+ * @param [in,out] len Pointer to data length
+ *
+ * @return true if the request was handled successfully
+ */
+static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ uint16_t value = setup->wValue;
+ bool ret = true;
+
+ switch (setup->bRequest) {
+ case USB_REQUEST_GET_STATUS:
+ /* bit 0: self-powered */
+ /* bit 1: remote wakeup */
+ (*data)[0] = 0x00;
+ (*data)[1] = 0x00;
+ *len = 2;
+ break;
+
+ case USB_REQUEST_CLEAR_FEATURE:
+ case USB_REQUEST_SET_FEATURE:
+ if (value == USB_FEATURE_REMOTE_WAKEUP) {
+ } else if (value == USB_FEATURE_TEST_MODE) {
+#ifdef CONFIG_USBDEV_TEST_MODE
+ usbd_core_cfg.test_mode = true;
+ usbd_execute_test_mode(setup);
+#endif
+ }
+ *len = 0;
+ break;
+
+ case USB_REQUEST_SET_ADDRESS:
+ usbd_set_address(value);
+ *len = 0;
+ break;
+
+ case USB_REQUEST_GET_DESCRIPTOR:
+ ret = usbd_get_descriptor(value, data, len);
+ break;
+
+ case USB_REQUEST_SET_DESCRIPTOR:
+ ret = false;
+ break;
+
+ case USB_REQUEST_GET_CONFIGURATION:
+ *data = (uint8_t *)&usbd_core_cfg.configuration;
+ *len = 1;
+ break;
+
+ case USB_REQUEST_SET_CONFIGURATION:
+ value &= 0xFF;
+
+ if (!usbd_set_configuration(value, 0)) {
+ ret = false;
+ } else {
+ usbd_core_cfg.configuration = value;
+ usbd_core_cfg.configured = true;
+ usbd_class_event_notify_handler(USBD_EVENT_CONFIGURED, NULL);
+ usbd_configure_done_callback();
+ }
+ *len = 0;
+ break;
+
+ case USB_REQUEST_GET_INTERFACE:
+ case USB_REQUEST_SET_INTERFACE:
+ ret = false;
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief handle a standard interface request
+ *
+ * @param [in] setup The setup packet
+ * @param [in,out] data Data buffer
+ * @param [in,out] len Pointer to data length
+ *
+ * @return true if the request was handled successfully
+ */
+static bool usbd_std_interface_req_handler(struct usb_setup_packet *setup,
+ uint8_t **data, uint32_t *len)
+{
+ uint8_t type = HI_BYTE(setup->wValue);
+ uint8_t intf_num = LO_BYTE(setup->wIndex);
+ bool ret = true;
+
+ /* Only when device is configured, then interface requests can be valid. */
+ if (!is_device_configured()) {
+ return false;
+ }
+
+ switch (setup->bRequest) {
+ case USB_REQUEST_GET_STATUS:
+ (*data)[0] = 0x00;
+ (*data)[1] = 0x00;
+ *len = 2;
+ break;
+
+ case USB_REQUEST_GET_DESCRIPTOR:
+ if (type == 0x22) { /* HID_DESCRIPTOR_TYPE_HID_REPORT */
+ USB_LOG_INFO("read hid report descriptor\r\n");
+ usb_slist_t *i;
+
+ usb_slist_for_each(i, &usbd_intf_head)
+ {
+ struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
+
+ if (intf->intf_num == intf_num) {
+ *data = (uint8_t *)intf->hid_report_descriptor;
+ *len = intf->hid_report_descriptor_len;
+ return true;
+ }
+ }
+ }
+ ret = false;
+ break;
+ case USB_REQUEST_CLEAR_FEATURE:
+ case USB_REQUEST_SET_FEATURE:
+ ret = false;
+ break;
+ case USB_REQUEST_GET_INTERFACE:
+ (*data)[0] = 0;
+ *len = 1;
+ break;
+
+ case USB_REQUEST_SET_INTERFACE:
+ usbd_set_interface(setup->wIndex, setup->wValue);
+ *len = 0;
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief handle a standard endpoint request
+ *
+ * @param [in] setup The setup packet
+ * @param [in,out] data Data buffer
+ * @param [in,out] len Pointer to data length
+ *
+ * @return true if the request was handled successfully
+ */
+static bool usbd_std_endpoint_req_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ uint8_t ep = (uint8_t)setup->wIndex;
+ bool ret = true;
+
+ /* Only when device is configured, then endpoint requests can be valid. */
+ if (!is_device_configured()) {
+ return false;
+ }
+
+ switch (setup->bRequest) {
+ case USB_REQUEST_GET_STATUS:
+ (*data)[0] = 0x00;
+ (*data)[1] = 0x00;
+ *len = 2;
+ break;
+ case USB_REQUEST_CLEAR_FEATURE:
+ if (setup->wValue == USB_FEATURE_ENDPOINT_HALT) {
+ USB_LOG_ERR("ep:%02x clear halt\r\n", ep);
+
+ usbd_ep_clear_stall(ep);
+ break;
+ } else {
+ ret = false;
+ }
+ *len = 0;
+ break;
+ case USB_REQUEST_SET_FEATURE:
+ if (setup->wValue == USB_FEATURE_ENDPOINT_HALT) {
+ USB_LOG_ERR("ep:%02x set halt\r\n", ep);
+
+ usbd_ep_set_stall(ep);
+ } else {
+ ret = false;
+ }
+ *len = 0;
+ break;
+
+ case USB_REQUEST_SYNCH_FRAME:
+ ret = false;
+ break;
+ default:
+ ret = false;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief handle standard requests (list in chapter 9)
+ *
+ * @param [in] setup The setup packet
+ * @param [in,out] data Data buffer
+ * @param [in,out] len Pointer to data length
+ *
+ * @return true if the request was handled successfully
+ */
+static int usbd_standard_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ int rc = 0;
+
+ switch (setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) {
+ case USB_REQUEST_RECIPIENT_DEVICE:
+ if (usbd_std_device_req_handler(setup, data, len) == false) {
+ rc = -1;
+ }
+
+ break;
+
+ case USB_REQUEST_RECIPIENT_INTERFACE:
+ if (usbd_std_interface_req_handler(setup, data, len) == false) {
+ rc = -1;
+ }
+
+ break;
+
+ case USB_REQUEST_RECIPIENT_ENDPOINT:
+ if (usbd_std_endpoint_req_handler(setup, data, len) == false) {
+ rc = -1;
+ }
+
+ break;
+
+ default:
+ rc = -1;
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * @brief handler for class requests
+ *
+ * If a custom request handler was installed, this handler is called first.
+ *
+ * @param [in] setup The setup packet
+ * @param [in,out] data Data buffer
+ * @param [in,out] len Pointer to data length
+ *
+ * @return true if the request was handled successfully
+ */
+static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ usb_slist_t *i;
+ if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_INTERFACE) {
+ usb_slist_for_each(i, &usbd_intf_head)
+ {
+ struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
+
+ if (intf->class_interface_handler && (intf->intf_num == (setup->wIndex & 0xFF))) {
+ return intf->class_interface_handler(setup, data, len);
+ }
+ }
+ } else if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_ENDPOINT) {
+ usb_slist_for_each(i, &usbd_intf_head)
+ {
+ struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
+
+ if (intf->class_endpoint_handler && (intf->intf_num == ((setup->wIndex >> 8) & 0xFF))) {
+ return intf->class_endpoint_handler(setup, data, len);
+ }
+ }
+ }
+ return -1;
+}
+
+/**
+ * @brief handler for vendor requests
+ *
+ * If a custom request handler was installed, this handler is called first.
+ *
+ * @param [in] setup The setup packet
+ * @param [in,out] data Data buffer
+ * @param [in,out] len Pointer to data length
+ *
+ * @return true if the request was handled successfully
+ */
+static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ if (msosv1_desc) {
+ if (setup->bRequest == msosv1_desc->vendor_code) {
+ switch (setup->wIndex) {
+ case 0x04:
+ USB_LOG_INFO("get Compat ID\r\n");
+ *data = (uint8_t *)msosv1_desc->compat_id;
+ *len = msosv1_desc->compat_id_len;
+
+ return 0;
+ case 0x05:
+ USB_LOG_INFO("get Compat id properties\r\n");
+ *data = (uint8_t *)msosv1_desc->comp_id_property;
+ *len = msosv1_desc->comp_id_property_len;
+
+ return 0;
+ default:
+ USB_LOG_ERR("unknown vendor code\r\n");
+ return -1;
+ }
+ }
+ } else if (msosv2_desc) {
+ if (setup->bRequest == msosv2_desc->vendor_code) {
+ switch (setup->wIndex) {
+ case WINUSB_REQUEST_GET_DESCRIPTOR_SET:
+ USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n");
+ *data = (uint8_t *)msosv2_desc->compat_id;
+ *len = msosv2_desc->compat_id_len;
+ return 0;
+ default:
+ USB_LOG_ERR("unknown vendor code\r\n");
+ return -1;
+ }
+ }
+ }
+
+ usb_slist_t *i;
+
+ usb_slist_for_each(i, &usbd_intf_head)
+ {
+ struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
+
+ if (intf->vendor_handler && !intf->vendor_handler(setup, data, len)) {
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * @brief handle setup request( standard/class/vendor/other)
+ *
+ * @param [in] setup The setup packet
+ * @param [in,out] data Data buffer
+ * @param [in,out] len Pointer to data length
+ *
+ * @return true if the request was handles successfully
+ */
+static bool usbd_setup_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
+{
+ switch (setup->bmRequestType & USB_REQUEST_TYPE_MASK) {
+ case USB_REQUEST_STANDARD:
+ if (usbd_standard_request_handler(setup, data, len) < 0) {
+ USB_LOG_ERR("standard request error\r\n");
+ usbd_print_setup(setup);
+ return false;
+ }
+ break;
+ case USB_REQUEST_CLASS:
+ if (usbd_class_request_handler(setup, data, len) < 0) {
+ USB_LOG_ERR("class request error\r\n");
+ usbd_print_setup(setup);
+ return false;
+ }
+ break;
+ case USB_REQUEST_VENDOR:
+ if (usbd_vendor_request_handler(setup, data, len) < 0) {
+ USB_LOG_ERR("vendor request error\r\n");
+ usbd_print_setup(setup);
+ return false;
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+static void usbd_class_event_notify_handler(uint8_t event, void *arg)
+{
+ usb_slist_t *i;
+ usb_slist_for_each(i, &usbd_intf_head)
+ {
+ struct usbd_interface *intf = usb_slist_entry(i, struct usbd_interface, list);
+
+ if (intf->notify_handler) {
+ intf->notify_handler(event, arg);
+ }
+ }
+}
+
+void usbd_event_connect_handler(void)
+{
+ usbd_class_event_notify_handler(USBD_EVENT_CONNECTED, NULL);
+}
+
+void usbd_event_disconnect_handler(void)
+{
+ usbd_class_event_notify_handler(USBD_EVENT_DISCONNECTED, NULL);
+}
+
+void usbd_event_resume_handler(void)
+{
+ usbd_class_event_notify_handler(USBD_EVENT_RESUME, NULL);
+}
+
+void usbd_event_suspend_handler(void)
+{
+ usbd_class_event_notify_handler(USBD_EVENT_SUSPEND, NULL);
+}
+
+void usbd_event_reset_handler(void)
+{
+ usbd_set_address(0);
+ usbd_core_cfg.configured = 0;
+ usbd_core_cfg.configuration = 0;
+#ifdef CONFIG_USBDEV_TEST_MODE
+ usbd_core_cfg.test_mode = false;
+#endif
+ struct usbd_endpoint_cfg ep0_cfg;
+
+ ep0_cfg.ep_mps = USB_CTRL_EP_MPS;
+ ep0_cfg.ep_type = USB_ENDPOINT_TYPE_CONTROL;
+ ep0_cfg.ep_addr = USB_CONTROL_IN_EP0;
+ usbd_ep_open(&ep0_cfg);
+
+ ep0_cfg.ep_addr = USB_CONTROL_OUT_EP0;
+ usbd_ep_open(&ep0_cfg);
+
+ usbd_class_event_notify_handler(USBD_EVENT_RESET, NULL);
+}
+
+void usbd_event_ep0_setup_complete_handler(uint8_t *psetup)
+{
+ struct usb_setup_packet *setup = &usbd_core_cfg.setup;
+
+ memcpy(setup, psetup, 8);
+#ifdef CONFIG_USBDEV_SETUP_LOG_PRINT
+ usbd_print_setup(setup);
+#endif
+ if (setup->wLength > CONFIG_USBDEV_REQUEST_BUFFER_LEN) {
+ if ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT) {
+ USB_LOG_ERR("Request buffer too small\r\n");
+ usbd_ep_set_stall(USB_CONTROL_IN_EP0);
+ return;
+ }
+ }
+
+ usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data;
+ usbd_core_cfg.ep0_data_buf_residue = setup->wLength;
+ usbd_core_cfg.ep0_data_buf_len = setup->wLength;
+ usbd_core_cfg.zlp_flag = false;
+
+ /* handle class request when all the data is received */
+ if (setup->wLength && ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) {
+ USB_LOG_DBG("Start reading %d bytes from ep0\r\n", setup->wLength);
+ usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, setup->wLength);
+ return;
+ }
+
+ /* Ask installed handler to process request */
+ if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) {
+ usbd_ep_set_stall(USB_CONTROL_IN_EP0);
+ return;
+ }
+#ifdef CONFIG_USBDEV_TEST_MODE
+ /* send status in test mode, so do not execute downward, just return */
+ if (usbd_core_cfg.test_mode) {
+ usbd_core_cfg.test_mode = false;
+ return;
+ }
+#endif
+ /* Send smallest of requested and offered length */
+ usbd_core_cfg.ep0_data_buf_residue = MIN(usbd_core_cfg.ep0_data_buf_len,
+ setup->wLength);
+
+ /* check if the data buf addr matches align size,if not, copy into align buf */
+#ifndef CONFIG_USBDEV_ALIGN_CHECK_DISABLE
+ if (((unsigned long)usbd_core_cfg.ep0_data_buf) & (CONFIG_USB_ALIGN_SIZE - 1)) {
+ if (usbd_core_cfg.ep0_data_buf_residue > CONFIG_USBDEV_REQUEST_BUFFER_LEN) {
+ USB_LOG_ERR("Request buffer too small\r\n");
+ return;
+ }
+ /* copy data buf from misalignx addr to alignx addr */
+ memcpy(usbd_core_cfg.req_data, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
+ usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data;
+ }
+#endif
+ /* Send data or status to host */
+ usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
+ /*
+ * Set ZLP flag when host asks for a bigger length and the data size is multiplier of USB_CTRL_EP_MPS,
+ * to indicate the transfer done after zlp sent.
+ */
+ if ((setup->wLength > usbd_core_cfg.ep0_data_buf_len) && (!(usbd_core_cfg.ep0_data_buf_len % USB_CTRL_EP_MPS))) {
+ usbd_core_cfg.zlp_flag = true;
+ USB_LOG_DBG("EP0 Set zlp\r\n");
+ }
+}
+
+void usbd_event_ep_in_complete_handler(uint8_t ep, uint32_t nbytes)
+{
+ if (ep == USB_CONTROL_IN_EP0) {
+ struct usb_setup_packet *setup = &usbd_core_cfg.setup;
+
+ usbd_core_cfg.ep0_data_buf += nbytes;
+ usbd_core_cfg.ep0_data_buf_residue -= nbytes;
+
+ USB_LOG_DBG("EP0 send %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue);
+
+ if (usbd_core_cfg.ep0_data_buf_residue != 0) {
+ /* Start sending the remain data */
+ usbd_ep_start_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
+ } else {
+ if (usbd_core_cfg.zlp_flag == true) {
+ usbd_core_cfg.zlp_flag = false;
+ /* Send zlp to host */
+ USB_LOG_DBG("EP0 Send zlp\r\n");
+ usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0);
+ } else {
+ /* Satisfying three conditions will jump here.
+ * 1. send status completely
+ * 2. send zlp completely
+ * 3. send last data completely.
+ */
+ if (setup->wLength && ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_IN)) {
+ /* if all data has sent completely, start reading out status */
+ usbd_ep_start_read(USB_CONTROL_OUT_EP0, NULL, 0);
+ }
+ }
+ }
+ } else {
+ if (usbd_core_cfg.in_ep_cb[ep & 0x7f]) {
+ usbd_core_cfg.in_ep_cb[ep & 0x7f](ep, nbytes);
+ }
+ }
+}
+
+void usbd_event_ep_out_complete_handler(uint8_t ep, uint32_t nbytes)
+{
+ if (ep == USB_CONTROL_OUT_EP0) {
+ struct usb_setup_packet *setup = &usbd_core_cfg.setup;
+
+ if (nbytes > 0) {
+ usbd_core_cfg.ep0_data_buf += nbytes;
+ usbd_core_cfg.ep0_data_buf_residue -= nbytes;
+
+ USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, usbd_core_cfg.ep0_data_buf_residue);
+
+ if (usbd_core_cfg.ep0_data_buf_residue == 0) {
+ /* Received all, send data to handler */
+ usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data;
+ if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) {
+ usbd_ep_set_stall(USB_CONTROL_IN_EP0);
+ return;
+ }
+
+ /*Send status to host*/
+ usbd_ep_start_write(USB_CONTROL_IN_EP0, NULL, 0);
+ } else {
+ /* Start reading the remain data */
+ usbd_ep_start_read(USB_CONTROL_OUT_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue);
+ }
+ } else {
+ /* Read out status completely, do nothing */
+ USB_LOG_DBG("EP0 recv out status\r\n");
+ }
+ } else {
+ if (usbd_core_cfg.out_ep_cb[ep & 0x7f]) {
+ usbd_core_cfg.out_ep_cb[ep & 0x7f](ep, nbytes);
+ }
+ }
+}
+
+void usbd_desc_register(const uint8_t *desc)
+{
+ usbd_core_cfg.descriptors = desc;
+ usbd_core_cfg.intf_offset = 0;
+}
+
+/* Register MS OS Descriptors version 1 */
+void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc)
+{
+ msosv1_desc = desc;
+}
+
+/* Register MS OS Descriptors version 2 */
+void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc)
+{
+ msosv2_desc = desc;
+}
+
+void usbd_bos_desc_register(struct usb_bos_descriptor *desc)
+{
+ bos_desc = desc;
+}
+
+void usbd_add_interface(struct usbd_interface *intf)
+{
+ intf->intf_num = usbd_core_cfg.intf_offset;
+ usb_slist_add_tail(&usbd_intf_head, &intf->list);
+ usbd_core_cfg.intf_offset++;
+}
+
+void usbd_add_endpoint(struct usbd_endpoint *ep)
+{
+ if (ep->ep_addr & 0x80) {
+ usbd_core_cfg.in_ep_cb[ep->ep_addr & 0x7f] = ep->ep_cb;
+ } else {
+ usbd_core_cfg.out_ep_cb[ep->ep_addr & 0x7f] = ep->ep_cb;
+ }
+}
+
+bool usb_device_is_configured(void)
+{
+ return usbd_core_cfg.configured;
+}
+
+int usbd_initialize(void)
+{
+ return usb_dc_init();
+}
+
+int usbd_deinitialize(void)
+{
+ usbd_core_cfg.intf_offset = 0;
+ usb_slist_init(&usbd_intf_head);
+ usb_dc_deinit();
+ return 0;
+}
diff --git a/third-party/cherryusb-0.6.0/core/usbd_core.h b/third-party/cherryusb-0.6.0/core/usbd_core.h
new file mode 100644
index 0000000000000000000000000000000000000000..2583fc916491136a29ac5602cbcd957e3646977b
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/core/usbd_core.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBD_CORE_H
+#define USBD_CORE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include
+
+#include "usb_config.h"
+#include "usb_util.h"
+#include "usb_errno.h"
+#include "usb_def.h"
+#include "usb_list.h"
+#include "usb_mem.h"
+#include "usb_log.h"
+#include "usb_dc.h"
+
+enum usbd_event_type {
+ /* USB DCD IRQ */
+ USBD_EVENT_ERROR, /** USB error reported by the controller */
+ USBD_EVENT_RESET, /** USB reset */
+ USBD_EVENT_SOF, /** Start of Frame received */
+ USBD_EVENT_CONNECTED, /** USB connected*/
+ USBD_EVENT_DISCONNECTED, /** USB disconnected */
+ USBD_EVENT_SUSPEND, /** USB connection suspended by the HOST */
+ USBD_EVENT_RESUME, /** USB connection resumed by the HOST */
+
+ /* USB DEVICE STATUS */
+ USBD_EVENT_CONFIGURED, /** USB configuration done */
+ USBD_EVENT_SET_INTERFACE, /** USB interface selected */
+ USBD_EVENT_UNKNOWN
+};
+
+typedef int (*usbd_request_handler)(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len);
+typedef void (*usbd_endpoint_callback)(uint8_t ep, uint32_t nbytes);
+typedef void (*usbd_notify_handler)(uint8_t event, void *arg);
+
+extern usb_slist_t usbd_intf_head;
+
+struct usbd_endpoint {
+ uint8_t ep_addr;
+ usbd_endpoint_callback ep_cb;
+};
+
+struct usbd_interface {
+ usb_slist_t list;
+ usbd_request_handler class_interface_handler;
+ usbd_request_handler class_endpoint_handler;
+ usbd_request_handler vendor_handler;
+ usbd_notify_handler notify_handler;
+ const uint8_t *hid_report_descriptor;
+ uint32_t hid_report_descriptor_len;
+ uint8_t intf_num;
+};
+
+void usbd_desc_register(const uint8_t *desc);
+void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc);
+void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc);
+void usbd_bos_desc_register(struct usb_bos_descriptor *desc);
+
+void usbd_add_interface(struct usbd_interface *intf);
+void usbd_add_endpoint(struct usbd_endpoint *ep);
+
+bool usb_device_is_configured(void);
+void usbd_configure_done_callback(void);
+int usbd_initialize(void);
+int usbd_deinitialize(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBD_CORE_H */
diff --git a/third-party/cherryusb-0.6.0/core/usbh_core.c b/third-party/cherryusb-0.6.0/core/usbh_core.c
new file mode 100644
index 0000000000000000000000000000000000000000..afb0e8850d32f3e028088513924686579a83744c
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/core/usbh_core.c
@@ -0,0 +1,805 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usbh_core.h"
+#include "usbh_hub.h"
+
+struct usbh_class_info *usbh_class_info_table_begin = NULL;
+struct usbh_class_info *usbh_class_info_table_end = NULL;
+
+USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_REQUEST_BUFFER_LEN];
+
+/* general descriptor field offsets */
+#define DESC_bLength 0 /** Length offset */
+#define DESC_bDescriptorType 1 /** Descriptor type offset */
+
+#define USB_DEV_ADDR_MAX 0x7f
+#define USB_DEV_ADDR_MARK_OFFSET 5
+#define USB_DEV_ADDR_MARK_MASK 0x1f
+
+struct usbh_devaddr_map {
+ /**
+ * alloctab[0]:addr from 0~31
+ * alloctab[1]:addr from 32~63
+ * alloctab[2]:addr from 64~95
+ * alloctab[3]:addr from 96~127
+ *
+ */
+ uint8_t next; /* Next device address */
+ uint32_t alloctab[4]; /* Bit allocation table */
+};
+
+struct usbh_bus {
+ struct usbh_devaddr_map devgen;
+} g_usbh_bus;
+
+static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
+{
+ uint8_t startaddr = devgen->next;
+ uint8_t devaddr;
+ int index;
+ int bitno;
+
+ for (;;) {
+ devaddr = devgen->next;
+ if (devgen->next >= 0x7f) {
+ devgen->next = 2;
+ } else {
+ devgen->next++;
+ }
+
+ index = devaddr >> 5;
+ bitno = devaddr & 0x1f;
+ if ((devgen->alloctab[index] & (1 << bitno)) == 0) {
+ devgen->alloctab[index] |= (1 << bitno);
+ return (int)devaddr;
+ }
+
+ if (startaddr == devaddr) {
+ return -ENOMEM;
+ }
+ }
+}
+
+static int usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
+{
+ int index;
+ int bitno;
+
+ if ((devaddr > 0) && (devaddr < USB_DEV_ADDR_MAX)) {
+ index = devaddr >> USB_DEV_ADDR_MARK_OFFSET;
+ bitno = devaddr & USB_DEV_ADDR_MARK_MASK;
+
+ /* Free the address */
+ if ((devgen->alloctab[index] |= (1 << bitno)) != 0) {
+ devgen->alloctab[index] &= ~(1 << bitno);
+ } else {
+ return -1;
+ }
+
+ if (devaddr < devgen->next) {
+ devgen->next = devaddr;
+ }
+ }
+
+ return 0;
+}
+
+static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uint8_t subclass, uint8_t protocol,
+ uint16_t vid, uint16_t pid)
+{
+ 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_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) ==
+ (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) {
+ if (index->vid == vid && index->pid == pid &&
+ index->class == class && index->subclass == subclass && index->protocol == protocol) {
+ return index->class_driver;
+ }
+ } else if ((index->match_flags & (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) ==
+ (USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL)) {
+ if (index->class == class && index->subclass == subclass && index->protocol == protocol) {
+ return index->class_driver;
+ }
+ } else if ((index->match_flags & (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS)) ==
+ (USB_CLASS_MATCH_VENDOR | USB_CLASS_MATCH_PRODUCT | USB_CLASS_MATCH_INTF_CLASS)) {
+ if (index->vid == vid && index->pid == pid && index->class == class) {
+ return index->class_driver;
+ }
+ } else if (index->match_flags & (USB_CLASS_MATCH_INTF_CLASS)) {
+ if (index->class == class) {
+ return index->class_driver;
+ }
+ }
+ }
+ return NULL;
+}
+
+static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device_descriptor *desc, uint16_t length)
+{
+ if (desc->bLength != USB_SIZEOF_DEVICE_DESC) {
+ USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
+ return -EINVAL;
+ } else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_DEVICE) {
+ USB_LOG_ERR("unexpected device descriptor 0x%02x\r\n", desc->bDescriptorType);
+ return -EINVAL;
+ } else {
+ if (length <= 8) {
+ return 0;
+ }
+#if 0
+ USB_LOG_DBG("Device Descriptor:\r\n");
+ USB_LOG_DBG("bLength: 0x%02x \r\n", desc->bLength);
+ USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
+ USB_LOG_DBG("bcdUSB: 0x%04x \r\n", desc->bcdUSB);
+ USB_LOG_DBG("bDeviceClass: 0x%02x \r\n", desc->bDeviceClass);
+ USB_LOG_DBG("bDeviceSubClass: 0x%02x \r\n", desc->bDeviceSubClass);
+ USB_LOG_DBG("bDeviceProtocol: 0x%02x \r\n", desc->bDeviceProtocol);
+ USB_LOG_DBG("bMaxPacketSize0: 0x%02x \r\n", desc->bMaxPacketSize0);
+ USB_LOG_DBG("idVendor: 0x%04x \r\n", desc->idVendor);
+ USB_LOG_DBG("idProduct: 0x%04x \r\n", desc->idProduct);
+ USB_LOG_DBG("bcdDevice: 0x%04x \r\n", desc->bcdDevice);
+ USB_LOG_DBG("iManufacturer: 0x%02x \r\n", desc->iManufacturer);
+ USB_LOG_DBG("iProduct: 0x%02x \r\n", desc->iProduct);
+ USB_LOG_DBG("iSerialNumber: 0x%02x \r\n", desc->iSerialNumber);
+ USB_LOG_DBG("bNumConfigurations: 0x%02x\r\n", desc->bNumConfigurations);
+#endif
+ hport->device_desc.bLength = desc->bLength;
+ hport->device_desc.bDescriptorType = desc->bDescriptorType;
+ hport->device_desc.bcdUSB = desc->bcdUSB;
+ hport->device_desc.bDeviceClass = desc->bDeviceClass;
+ hport->device_desc.bDeviceSubClass = desc->bDeviceSubClass;
+ hport->device_desc.bDeviceProtocol = desc->bDeviceProtocol;
+ hport->device_desc.bMaxPacketSize0 = desc->bMaxPacketSize0;
+ hport->device_desc.idVendor = desc->idVendor;
+ hport->device_desc.idProduct = desc->idProduct;
+ hport->device_desc.bcdDevice = desc->bcdDevice;
+ hport->device_desc.iManufacturer = desc->iManufacturer;
+ hport->device_desc.iProduct = desc->iProduct;
+ hport->device_desc.iSerialNumber = desc->iSerialNumber;
+ hport->device_desc.bNumConfigurations = desc->bNumConfigurations;
+ }
+ return 0;
+}
+
+static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_configuration_descriptor *desc, uint16_t length)
+{
+ struct usb_interface_descriptor *intf_desc;
+ struct usb_endpoint_descriptor *ep_desc;
+ uint8_t cur_alt_setting = 0xff;
+ uint8_t cur_iface = 0xff;
+ uint8_t cur_ep = 0xff;
+ uint8_t cur_ep_num = 0xff;
+ uint32_t desc_len = 0;
+ uint8_t *p;
+
+ if (desc->bLength != USB_SIZEOF_CONFIG_DESC) {
+ USB_LOG_ERR("invalid config bLength 0x%02x\r\n", desc->bLength);
+ return -EINVAL;
+ } else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_CONFIGURATION) {
+ USB_LOG_ERR("unexpected config descriptor 0x%02x\r\n", desc->bDescriptorType);
+ return -EINVAL;
+ } else {
+ if (length <= USB_SIZEOF_CONFIG_DESC) {
+ return 0;
+ }
+#if 0
+ USB_LOG_DBG("Config Descriptor:\r\n");
+ USB_LOG_DBG("bLength: 0x%02x \r\n", desc->bLength);
+ USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
+ USB_LOG_DBG("wTotalLength: 0x%04x \r\n", desc->wTotalLength);
+ USB_LOG_DBG("bNumInterfaces: 0x%02x \r\n", desc->bNumInterfaces);
+ USB_LOG_DBG("bConfigurationValue: 0x%02x \r\n", desc->bConfigurationValue);
+ USB_LOG_DBG("iConfiguration: 0x%02x \r\n", desc->iConfiguration);
+ USB_LOG_DBG("bmAttributes: 0x%02x \r\n", desc->bmAttributes);
+ USB_LOG_DBG("bMaxPower: 0x%02x \r\n", desc->bMaxPower);
+#endif
+ hport->config.config_desc.bLength = desc->bLength;
+ hport->config.config_desc.bDescriptorType = desc->bDescriptorType;
+ hport->config.config_desc.wTotalLength = desc->wTotalLength;
+ hport->config.config_desc.bNumInterfaces = desc->bNumInterfaces;
+ hport->config.config_desc.bConfigurationValue = desc->bConfigurationValue;
+ hport->config.config_desc.iConfiguration = desc->iConfiguration;
+ hport->config.config_desc.iConfiguration = desc->iConfiguration;
+ hport->config.config_desc.bmAttributes = desc->bmAttributes;
+ hport->config.config_desc.bMaxPower = desc->bMaxPower;
+
+ p = (uint8_t *)desc;
+ p += USB_SIZEOF_CONFIG_DESC;
+ desc_len = USB_SIZEOF_CONFIG_DESC;
+
+ memset(hport->config.intf, 0, sizeof(struct usbh_interface) * CONFIG_USBHOST_MAX_INTERFACES);
+
+ while (p[DESC_bLength] && (desc_len <= length)) {
+ switch (p[DESC_bDescriptorType]) {
+ case USB_DESCRIPTOR_TYPE_INTERFACE:
+ intf_desc = (struct usb_interface_descriptor *)p;
+ cur_iface = intf_desc->bInterfaceNumber;
+ cur_alt_setting = intf_desc->bAlternateSetting;
+ cur_ep_num = intf_desc->bNumEndpoints;
+ cur_ep = 0;
+ if (cur_iface > (CONFIG_USBHOST_MAX_INTERFACES - 1)) {
+ USB_LOG_ERR("Interface num overflow\r\n");
+ return -ENOMEM;
+ }
+ if (cur_alt_setting > (CONFIG_USBHOST_MAX_INTF_ALTSETTINGS - 1)) {
+ USB_LOG_ERR("Interface altsetting num overflow\r\n");
+ return -ENOMEM;
+ }
+ if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
+ USB_LOG_ERR("Endpoint num overflow\r\n");
+ return -ENOMEM;
+ }
+#if 0
+ USB_LOG_DBG("Interface Descriptor:\r\n");
+ USB_LOG_DBG("bLength: 0x%02x \r\n", intf_desc->bLength);
+ USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", intf_desc->bDescriptorType);
+ USB_LOG_DBG("bInterfaceNumber: 0x%02x \r\n", intf_desc->bInterfaceNumber);
+ USB_LOG_DBG("bAlternateSetting: 0x%02x \r\n", intf_desc->bAlternateSetting);
+ USB_LOG_DBG("bNumEndpoints: 0x%02x \r\n", intf_desc->bNumEndpoints);
+ USB_LOG_DBG("bInterfaceClass: 0x%02x \r\n", intf_desc->bInterfaceClass);
+ USB_LOG_DBG("bInterfaceSubClass: 0x%02x \r\n", intf_desc->bInterfaceSubClass);
+ USB_LOG_DBG("bInterfaceProtocol: 0x%02x \r\n", intf_desc->bInterfaceProtocol);
+ USB_LOG_DBG("iInterface: 0x%02x \r\n", intf_desc->iInterface);
+#endif
+ memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].intf_desc, intf_desc, 9);
+ hport->config.intf[cur_iface].altsetting_num = cur_alt_setting + 1;
+ break;
+ case USB_DESCRIPTOR_TYPE_ENDPOINT:
+ ep_desc = (struct usb_endpoint_descriptor *)p;
+ memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].ep[cur_ep].ep_desc, ep_desc, 7);
+ cur_ep++;
+ break;
+
+ default:
+ break;
+ }
+ /* skip to next descriptor */
+ p += p[DESC_bLength];
+ desc_len += p[DESC_bLength];
+ }
+ }
+ return 0;
+}
+
+#ifdef CONFIG_USBHOST_GET_STRING_DESC
+void usbh_print_string(char *lead, uint8_t *str)
+{
+ uint8_t string[64 + 1] = { 0 };
+
+ int len, i = 2, j = 0;
+
+ len = str[0];
+ while (i < len) {
+ string[j] = str[i];
+ i += 2;
+ j++;
+ }
+ USB_LOG_RAW("%s%s\r\n", lead, string);
+}
+#endif
+
+static void usbh_print_hubport_info(struct usbh_hubport *hport)
+{
+ USB_LOG_RAW("Device Descriptor:\r\n");
+ USB_LOG_RAW("bLength: 0x%02x \r\n", hport->device_desc.bLength);
+ USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->device_desc.bDescriptorType);
+ USB_LOG_RAW("bcdUSB: 0x%04x \r\n", hport->device_desc.bcdUSB);
+ USB_LOG_RAW("bDeviceClass: 0x%02x \r\n", hport->device_desc.bDeviceClass);
+ USB_LOG_RAW("bDeviceSubClass: 0x%02x \r\n", hport->device_desc.bDeviceSubClass);
+ USB_LOG_RAW("bDeviceProtocol: 0x%02x \r\n", hport->device_desc.bDeviceProtocol);
+ USB_LOG_RAW("bMaxPacketSize0: 0x%02x \r\n", hport->device_desc.bMaxPacketSize0);
+ USB_LOG_RAW("idVendor: 0x%04x \r\n", hport->device_desc.idVendor);
+ USB_LOG_RAW("idProduct: 0x%04x \r\n", hport->device_desc.idProduct);
+ USB_LOG_RAW("bcdDevice: 0x%04x \r\n", hport->device_desc.bcdDevice);
+ USB_LOG_RAW("iManufacturer: 0x%02x \r\n", hport->device_desc.iManufacturer);
+ USB_LOG_RAW("iProduct: 0x%02x \r\n", hport->device_desc.iProduct);
+ USB_LOG_RAW("iSerialNumber: 0x%02x \r\n", hport->device_desc.iSerialNumber);
+ USB_LOG_RAW("bNumConfigurations: 0x%02x\r\n", hport->device_desc.bNumConfigurations);
+
+ USB_LOG_RAW("Config Descriptor:\r\n");
+ USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.config_desc.bLength);
+ USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.config_desc.bDescriptorType);
+ USB_LOG_RAW("wTotalLength: 0x%04x \r\n", hport->config.config_desc.wTotalLength);
+ USB_LOG_RAW("bNumInterfaces: 0x%02x \r\n", hport->config.config_desc.bNumInterfaces);
+ USB_LOG_RAW("bConfigurationValue: 0x%02x \r\n", hport->config.config_desc.bConfigurationValue);
+ USB_LOG_RAW("iConfiguration: 0x%02x \r\n", hport->config.config_desc.iConfiguration);
+ USB_LOG_RAW("bmAttributes: 0x%02x \r\n", hport->config.config_desc.bmAttributes);
+ USB_LOG_RAW("bMaxPower: 0x%02x \r\n", hport->config.config_desc.bMaxPower);
+
+ for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
+ for (uint8_t j = 0; j < hport->config.intf[i].altsetting_num; j++) {
+ USB_LOG_RAW("Interface Descriptor:\r\n");
+ USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bLength);
+ USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bDescriptorType);
+ USB_LOG_RAW("bInterfaceNumber: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceNumber);
+ USB_LOG_RAW("bAlternateSetting: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bAlternateSetting);
+ USB_LOG_RAW("bNumEndpoints: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints);
+ USB_LOG_RAW("bInterfaceClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceClass);
+ USB_LOG_RAW("bInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceSubClass);
+ USB_LOG_RAW("bInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceProtocol);
+ USB_LOG_RAW("iInterface: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.iInterface);
+
+ for (uint8_t k = 0; k < hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints; k++) {
+ USB_LOG_RAW("Endpoint Descriptor:\r\n");
+ USB_LOG_RAW("bLength: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bLength);
+ USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bDescriptorType);
+ USB_LOG_RAW("bEndpointAddress: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bEndpointAddress);
+ USB_LOG_RAW("bmAttributes: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bmAttributes);
+ USB_LOG_RAW("wMaxPacketSize: 0x%04x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.wMaxPacketSize);
+ USB_LOG_RAW("bInterval: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bInterval);
+ }
+ }
+ }
+}
+
+static int usbh_get_default_mps(int speed)
+{
+ switch (speed) {
+ case USB_SPEED_LOW: /* For low speed, we use 8 bytes */
+ return 8;
+ case USB_SPEED_FULL: /* For full or high speed, we use 64 bytes */
+ case USB_SPEED_HIGH:
+ return 64;
+ case USB_SPEED_SUPER: /* For super speed , we must use 512 bytes */
+ case USB_SPEED_SUPER_PLUS:
+ return 512;
+ default:
+ return 64;
+ }
+}
+
+int usbh_hport_activate_ep0(struct usbh_hubport *hport)
+{
+ struct usbh_endpoint_cfg ep0_cfg = { 0 };
+
+ ep0_cfg.ep_addr = 0x00;
+ ep0_cfg.ep_interval = 0x00;
+ ep0_cfg.ep_mps = usbh_get_default_mps(hport->speed);
+ ep0_cfg.ep_type = USB_ENDPOINT_TYPE_CONTROL;
+ ep0_cfg.hport = hport;
+
+ usbh_pipe_alloc(&hport->ep0, &ep0_cfg);
+ return 0;
+}
+
+int usbh_hport_deactivate_ep0(struct usbh_hubport *hport)
+{
+#ifndef CONFIG_USBHOST_XHCI
+ if (hport->dev_addr > 0) {
+ usbh_free_devaddr(&g_usbh_bus.devgen, hport->dev_addr);
+ }
+#endif
+ if (hport->ep0) {
+ usbh_pipe_free(hport->ep0);
+ }
+
+ hport->ep0 = NULL;
+ hport->dev_addr = 0;
+ return 0;
+}
+
+int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc)
+{
+ struct usbh_endpoint_cfg ep_cfg = { 0 };
+
+ ep_cfg.ep_addr = ep_desc->bEndpointAddress;
+ ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK;
+ ep_cfg.ep_mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
+ ep_cfg.ep_interval = ep_desc->bInterval;
+ ep_cfg.mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
+ ep_cfg.hport = hport;
+
+ USB_LOG_INFO("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
+ ep_cfg.ep_addr,
+ ep_desc->bmAttributes,
+ ep_cfg.ep_mps,
+ ep_cfg.ep_interval,
+ ep_cfg.mult);
+
+ return usbh_pipe_alloc(pipe, &ep_cfg);
+}
+
+int usbh_enumerate(struct usbh_hubport *hport)
+{
+ struct usb_interface_descriptor *intf_desc;
+ struct usb_setup_packet *setup;
+ int dev_addr;
+ uint16_t ep_mps;
+ int ret;
+
+#define USB_REQUEST_BUFFER_SIZE 256
+ setup = &hport->setup;
+
+ /* Configure EP0 with the default maximum packet size */
+ usbh_hport_activate_ep0(hport);
+
+ /* Read the first 8 bytes of the device descriptor */
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
+ setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0);
+ setup->wIndex = 0;
+ setup->wLength = 8;
+
+ ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret);
+ goto errout;
+ }
+
+ parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer, 8);
+
+ /* Extract the correct max packetsize from the device descriptor */
+ ep_mps = ((struct usb_device_descriptor *)ep0_request_buffer)->bMaxPacketSize0;
+
+ /* Reconfigure EP0 with the correct maximum packet size */
+ usbh_ep0_pipe_reconfigure(hport->ep0, 0, ep_mps, hport->speed);
+
+#ifdef CONFIG_USBHOST_XHCI
+ extern int usbh_get_xhci_devaddr(usbh_pipe_t * pipe);
+
+ /* for XHCI, dev address is allocated by xHc instead of SW */
+ dev_addr = usbh_get_xhci_devaddr(hport->ep0);
+ if (dev_addr < 0) {
+ USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret);
+ goto errout;
+ }
+#else
+ /* Assign a function address to the device connected to this port */
+ dev_addr = usbh_allocate_devaddr(&g_usbh_bus.devgen);
+ if (dev_addr < 0) {
+ USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret);
+ goto errout;
+ }
+#endif
+
+ /* Set the USB device address */
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
+ setup->bRequest = USB_REQUEST_SET_ADDRESS;
+ setup->wValue = dev_addr;
+ setup->wIndex = 0;
+ setup->wLength = 0;
+
+ ret = usbh_control_transfer(hport->ep0, setup, NULL);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret);
+ goto errout;
+ }
+
+ /* Wait device set address completely */
+ usb_osal_msleep(2);
+
+ /* Assign the function address to the port */
+ hport->dev_addr = dev_addr;
+
+ /* And reconfigure EP0 with the correct address */
+ usbh_ep0_pipe_reconfigure(hport->ep0, dev_addr, ep_mps, hport->speed);
+
+ /* Read the full device descriptor */
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
+ setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0);
+ setup->wIndex = 0;
+ setup->wLength = USB_SIZEOF_DEVICE_DESC;
+
+ ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret);
+ goto errout;
+ }
+
+ parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer, USB_SIZEOF_DEVICE_DESC);
+ USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n",
+ ((struct usb_device_descriptor *)ep0_request_buffer)->idVendor,
+ ((struct usb_device_descriptor *)ep0_request_buffer)->idProduct,
+ ((struct usb_device_descriptor *)ep0_request_buffer)->bcdDevice);
+
+ /* Read the first 9 bytes of the config descriptor */
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
+ setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | 0);
+ setup->wIndex = 0;
+ setup->wLength = USB_SIZEOF_CONFIG_DESC;
+
+ ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret);
+ goto errout;
+ }
+
+ parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer, USB_SIZEOF_CONFIG_DESC);
+
+ /* Read the full size of the configuration data */
+ uint16_t wTotalLength = ((struct usb_configuration_descriptor *)ep0_request_buffer)->wTotalLength;
+
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
+ setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | 0);
+ setup->wIndex = 0;
+ setup->wLength = wTotalLength;
+
+ ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret);
+ goto errout;
+ }
+
+ ret = parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer, wTotalLength);
+ if (ret < 0) {
+ USB_LOG_ERR("Parse config fail\r\n");
+ goto errout;
+ }
+ USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer)->bNumInterfaces);
+ hport->raw_config_desc = usb_malloc(wTotalLength);
+ if (hport->raw_config_desc == NULL) {
+ ret = -ENOMEM;
+ USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
+ goto errout;
+ }
+ memcpy(hport->raw_config_desc, ep0_request_buffer, wTotalLength);
+#ifdef CONFIG_USBHOST_GET_STRING_DESC
+ /* Get Manufacturer string */
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
+ setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | USB_STRING_MFC_INDEX);
+ setup->wIndex = 0x0409;
+ setup->wLength = 255;
+
+ ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to get Manufacturer string,errorcode:%d\r\n", ret);
+ goto errout;
+ }
+
+ usbh_print_string("Manufacturer: ", ep0_request_buffer);
+
+ /* Get Product string */
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
+ setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | USB_STRING_PRODUCT_INDEX);
+ setup->wIndex = 0x0409;
+ setup->wLength = 255;
+
+ ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to get get Product string,errorcode:%d\r\n", ret);
+ goto errout;
+ }
+
+ usbh_print_string("Product: ", ep0_request_buffer);
+
+ /* Get SerialNumber string */
+ setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
+ setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | USB_STRING_SERIAL_INDEX);
+ setup->wIndex = 0x0409;
+ setup->wLength = 255;
+
+ ret = usbh_control_transfer(hport->ep0, setup, ep0_request_buffer);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to get get SerialNumber string,errorcode:%d\r\n", ret);
+ goto errout;
+ }
+
+ usbh_print_string("SerialNumber: ", ep0_request_buffer);
+#endif
+ /* Select device configuration 1 */
+ setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
+ setup->bRequest = USB_REQUEST_SET_CONFIGURATION;
+ setup->wValue = 1;
+ setup->wIndex = 0;
+ setup->wLength = 0;
+
+ ret = usbh_control_transfer(hport->ep0, setup, NULL);
+ if (ret < 0) {
+ USB_LOG_ERR("Failed to set configuration,errorcode:%d\r\n", ret);
+ goto errout;
+ }
+
+ USB_LOG_INFO("Enumeration success, start loading class driver\r\n");
+ /*search supported class driver*/
+ for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
+ intf_desc = &hport->config.intf[i].altsetting[0].intf_desc;
+
+ struct usbh_class_driver *class_driver = (struct usbh_class_driver *)usbh_find_class_driver(intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol, hport->device_desc.idVendor, hport->device_desc.idProduct);
+
+ if (class_driver == NULL) {
+ USB_LOG_ERR("do not support Class:0x%02x,Subclass:0x%02x,Protocl:0x%02x\r\n",
+ intf_desc->bInterfaceClass,
+ intf_desc->bInterfaceSubClass,
+ intf_desc->bInterfaceProtocol);
+
+ continue;
+ }
+ hport->config.intf[i].class_driver = class_driver;
+ USB_LOG_INFO("Loading %s class driver\r\n", class_driver->driver_name);
+ ret = CLASS_CONNECT(hport, i);
+ if (ret < 0) {
+ ret = CLASS_DISCONNECT(hport, i);
+ goto errout;
+ }
+ }
+
+ usbh_device_mount_done_callback(hport);
+errout:
+ if (ret < 0) {
+ usbh_hport_deactivate_ep0(hport);
+ }
+ if (hport->raw_config_desc) {
+ usb_free(hport->raw_config_desc);
+ hport->raw_config_desc = NULL;
+ }
+ return ret;
+}
+
+struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr)
+{
+ struct usbh_hubport *hport;
+ usb_slist_t *hub_list;
+ usb_slist_for_each(hub_list, &hub_class_head)
+ {
+ struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
+ for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ hport = &hub->child[port];
+ if (hport->connected) {
+ if (hport->dev_addr == dev_addr) {
+ return &hub->child[port];
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+void *usbh_find_class_instance(const char *devname)
+{
+ struct usbh_hubport *hport;
+ usb_slist_t *hub_list;
+
+ usb_slist_for_each(hub_list, &hub_class_head)
+ {
+ struct usbh_hub *hub = usb_slist_entry(hub_list, struct usbh_hub, list);
+ for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ hport = &hub->child[port];
+ if (hport->connected) {
+ for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
+ if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
+ return hport->config.intf[itf].priv;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+int usbh_initialize(void)
+{
+ memset(&g_usbh_bus, 0, sizeof(struct usbh_bus));
+
+#ifdef __ARMCC_VERSION /* ARM C Compiler */
+ extern const int usbh_class_info$$Base;
+ extern const int usbh_class_info$$Limit;
+ usbh_class_info_table_begin = (struct usbh_class_info *)&usbh_class_info$$Base;
+ usbh_class_info_table_end = (struct usbh_class_info *)&usbh_class_info$$Limit;
+#elif defined(__GNUC__)
+ extern uint32_t __usbh_class_info_start__;
+ extern uint32_t __usbh_class_info_end__;
+ usbh_class_info_table_begin = (struct usbh_class_info *)&__usbh_class_info_start__;
+ usbh_class_info_table_end = (struct usbh_class_info *)&__usbh_class_info_end__;
+#endif
+
+ /* devaddr 1 is for roothub */
+ g_usbh_bus.devgen.next = 2;
+
+ usbh_hub_initialize();
+ return 0;
+}
+
+int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer)
+{
+ struct usbh_urb *urb;
+ int ret;
+
+ urb = usb_malloc(sizeof(struct usbh_urb));
+ memset(urb, 0, sizeof(struct usbh_urb));
+
+ usbh_control_urb_fill(urb, pipe, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
+
+ ret = usbh_submit_urb(urb);
+ if (ret == 0) {
+ ret = urb->actual_length;
+ }
+ usb_free(urb);
+ return ret;
+}
+
+int lsusb(int argc, char **argv)
+{
+ usb_slist_t *i;
+ struct usbh_hubport *hport;
+
+ if (argc < 2) {
+ USB_LOG_RAW("Usage: lsusb [options]...\r\n");
+ USB_LOG_RAW("List USB devices\r\n");
+ USB_LOG_RAW(" -v, --verbose\r\n");
+ USB_LOG_RAW(" Increase verbosity (show descriptors)\r\n");
+ // USB_LOG_RAW(" -s [[bus]:[devnum]]\r\n");
+ // USB_LOG_RAW(" Show only devices with specified device and/or bus numbers (in decimal)\r\n");
+ // USB_LOG_RAW(" -d vendor:[product]\r\n");
+ // USB_LOG_RAW(" Show only devices with the specified vendor and product ID numbers (in hexadecimal)\r\n");
+ USB_LOG_RAW(" -t, --tree\r\n");
+ USB_LOG_RAW(" Dump the physical USB device hierachy as a tree\r\n");
+ USB_LOG_RAW(" -V, --version\r\n");
+ USB_LOG_RAW(" Show version of program\r\n");
+ USB_LOG_RAW(" -h, --help\r\n");
+ USB_LOG_RAW(" Show usage and help\r\n");
+ return 0;
+ }
+ if (argc > 3) {
+ return 0;
+ }
+
+ if (strcmp(argv[1], "-t") == 0) {
+ usb_slist_for_each(i, &hub_class_head)
+ {
+ struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list);
+
+ if (hub->is_roothub) {
+ USB_LOG_RAW("/: Hub %02u, ports=%u, is roothub\r\n", hub->index, hub->hub_desc.bNbrPorts);
+ } else {
+ USB_LOG_RAW("/: Hub %02u, ports=%u, mounted on Hub %02u:Port %u\r\n",
+ hub->index,
+ hub->hub_desc.bNbrPorts,
+ hub->parent->parent->index,
+ hub->parent->port);
+ }
+
+ for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ hport = &hub->child[port];
+ if (hport->connected) {
+ for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
+ if (hport->config.intf[i].class_driver->driver_name) {
+ USB_LOG_RAW(" |__Port %u,Port addr:0x%02x,If %u,ClassDriver=%s\r\n",
+ hport->port,
+ hport->dev_addr,
+ i,
+ hport->config.intf[i].class_driver->driver_name);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (strcmp(argv[1], "-v") == 0) {
+ usb_slist_for_each(i, &hub_class_head)
+ {
+ struct usbh_hub *hub = usb_slist_entry(i, struct usbh_hub, list);
+ for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ hport = &hub->child[port];
+ if (hport->connected) {
+ USB_LOG_RAW("Hub %02u,Port %u,Port addr:0x%02x,VID:PID 0x%04x:0x%04x\r\n",
+ hub->index,
+ hport->port,
+ hport->dev_addr,
+ hport->device_desc.idVendor,
+ hport->device_desc.idProduct);
+ usbh_print_hubport_info(hport);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+__WEAK void usbh_device_mount_done_callback(struct usbh_hubport *hport)
+{
+}
+
+__WEAK void usbh_device_unmount_done_callback(struct usbh_hubport *hport)
+{
+}
diff --git a/third-party/cherryusb-0.6.0/core/usbh_core.h b/third-party/cherryusb-0.6.0/core/usbh_core.h
new file mode 100644
index 0000000000000000000000000000000000000000..ff2c0fc3f16423d7c68b82578c94b3b1def147de
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/core/usbh_core.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USBH_CORE_H
+#define USBH_CORE_H
+
+#include
+#include
+#include
+#include
+
+#include "usb_config.h"
+#include "usb_util.h"
+#include "usb_errno.h"
+#include "usb_def.h"
+#include "usb_list.h"
+#include "usb_mem.h"
+#include "usb_log.h"
+#include "usb_hc.h"
+#include "usb_osal.h"
+#include "usb_hub.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define USB_CLASS_MATCH_VENDOR 0x0001
+#define USB_CLASS_MATCH_PRODUCT 0x0002
+#define USB_CLASS_MATCH_INTF_CLASS 0x0004
+#define USB_CLASS_MATCH_INTF_SUBCLASS 0x0008
+#define USB_CLASS_MATCH_INTF_PROTOCOL 0x0010
+
+#define CLASS_CONNECT(hport, i) ((hport)->config.intf[i].class_driver->connect(hport, i))
+#define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i))
+
+#ifdef __ARMCC_VERSION /* ARM C Compiler */
+#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
+#elif defined(__GNUC__)
+#define CLASS_INFO_DEFINE __attribute__((section(".usbh_class_info"))) __USED __ALIGNED(1)
+#endif
+
+static inline void usbh_control_urb_fill(struct usbh_urb *urb,
+ usbh_pipe_t pipe,
+ struct usb_setup_packet *setup,
+ uint8_t *transfer_buffer,
+ uint32_t transfer_buffer_length,
+ uint32_t timeout,
+ usbh_complete_callback_t complete,
+ void *arg)
+{
+ urb->pipe = pipe;
+ urb->setup = setup;
+ urb->transfer_buffer = transfer_buffer;
+ urb->transfer_buffer_length = transfer_buffer_length;
+ urb->timeout = timeout;
+ urb->complete = complete;
+ urb->arg = arg;
+}
+
+static inline void usbh_bulk_urb_fill(struct usbh_urb *urb,
+ usbh_pipe_t pipe,
+ uint8_t *transfer_buffer,
+ uint32_t transfer_buffer_length,
+ uint32_t timeout,
+ usbh_complete_callback_t complete,
+ void *arg)
+{
+ urb->pipe = pipe;
+ urb->setup = NULL;
+ urb->transfer_buffer = transfer_buffer;
+ urb->transfer_buffer_length = transfer_buffer_length;
+ urb->timeout = timeout;
+ urb->complete = complete;
+ urb->arg = arg;
+}
+
+static inline void usbh_int_urb_fill(struct usbh_urb *urb,
+ usbh_pipe_t pipe,
+ uint8_t *transfer_buffer,
+ uint32_t transfer_buffer_length,
+ uint32_t timeout,
+ usbh_complete_callback_t complete,
+ void *arg)
+{
+ urb->pipe = pipe;
+ urb->setup = NULL;
+ urb->transfer_buffer = transfer_buffer;
+ urb->transfer_buffer_length = transfer_buffer_length;
+ urb->timeout = timeout;
+ urb->complete = complete;
+ urb->arg = arg;
+}
+
+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. */
+ uint16_t vid; /* Vendor ID (for vendor/product specific devices) */
+ uint16_t pid; /* Product ID (for vendor/product specific devices) */
+ const struct usbh_class_driver *class_driver;
+};
+
+struct usbh_hubport;
+struct usbh_class_driver {
+ const char *driver_name;
+ int (*connect)(struct usbh_hubport *hport, uint8_t intf);
+ int (*disconnect)(struct usbh_hubport *hport, uint8_t intf);
+};
+
+struct usbh_endpoint {
+ struct usb_endpoint_descriptor ep_desc;
+};
+
+struct usbh_interface_altsetting {
+ struct usb_interface_descriptor intf_desc;
+ struct usbh_endpoint ep[CONFIG_USBHOST_MAX_ENDPOINTS];
+};
+
+struct usbh_interface {
+ struct usbh_interface_altsetting altsetting[CONFIG_USBHOST_MAX_INTF_ALTSETTINGS];
+ uint8_t altsetting_num;
+ char devname[CONFIG_USBHOST_DEV_NAMELEN];
+ struct usbh_class_driver *class_driver;
+ void *priv;
+};
+
+struct usbh_configuration {
+ struct usb_configuration_descriptor config_desc;
+ struct usbh_interface intf[CONFIG_USBHOST_MAX_INTERFACES];
+};
+
+struct usbh_hubport {
+ bool connected; /* True: device connected; false: disconnected */
+ uint8_t port; /* Hub port index */
+ uint8_t dev_addr; /* device address */
+ uint8_t speed; /* device speed */
+ usbh_pipe_t ep0; /* control ep pipe info */
+ struct usb_device_descriptor device_desc;
+ struct usbh_configuration config;
+ const char *iManufacturer;
+ const char *iProduct;
+ const char *iSerialNumber;
+ uint8_t* raw_config_desc;
+ USB_MEM_ALIGNX struct usb_setup_packet setup;
+ struct usbh_hub *parent;
+};
+
+struct usbh_hub {
+ usb_slist_t list;
+ bool connected;
+ bool is_roothub;
+ uint8_t index;
+ uint8_t hub_addr;
+ usbh_pipe_t intin;
+ USB_MEM_ALIGNX uint8_t int_buffer[1];
+ struct usbh_urb intin_urb;
+ struct usb_hub_descriptor hub_desc;
+ struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
+ struct usbh_hubport *parent;
+ usb_slist_t hub_event_list;
+};
+
+int usbh_hport_activate_epx(usbh_pipe_t *pipe, struct usbh_hubport *hport, struct usb_endpoint_descriptor *ep_desc);
+
+/**
+ * @brief Submit an bulk transfer to an endpoint.
+ * This is a blocking method; this method will not return until the transfer has completed.
+ * Default timeout is 500ms.
+ *
+ * @param pipe The control endpoint to send/receive the control request.
+ * @param setup Setup packet to be sent.
+ * @param buffer buffer used for sending the request and for returning any responses.
+ * @return On success will return 0, and others indicate fail.
+ */
+int usbh_control_transfer(usbh_pipe_t pipe, struct usb_setup_packet *setup, uint8_t *buffer);
+
+int usbh_initialize(void);
+struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr);
+void *usbh_find_class_instance(const char *devname);
+
+void usbh_device_mount_done_callback(struct usbh_hubport *hport);
+void usbh_device_unmount_done_callback(struct usbh_hubport *hport);
+
+int lsusb(int argc, char **argv);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USBH_CORE_H */
diff --git a/third-party/cherryusb-0.6.0/makefile b/third-party/cherryusb-0.6.0/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..a494e7aaf29e2558d14cc05456e8bb1b9d752a3e
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/makefile
@@ -0,0 +1,66 @@
+
+CHERRY_USB_DIR := $(THIRD_PARTY_CUR_DIR)/cherryusb-0.6.0
+
+INC_DIR += $(CHERRY_USB_DIR)/core \
+ $(CHERRY_USB_DIR)/common \
+ $(CHERRY_USB_DIR)/osal
+
+SRC_DIR += $(CHERRY_USB_DIR)/core \
+ $(CHERRY_USB_DIR)/common \
+ $(CHERRY_USB_DIR)/osal
+
+ifdef CONFIG_CHERRY_USB_PORT_XHCI
+ INC_DIR += $(CHERRY_USB_DIR)/port/xhci
+ SRC_DIR += $(CHERRY_USB_DIR)/port/xhci
+endif #CONFIG_CHERRY_USB_PORT_XHCI
+
+ifdef CONFIG_CHERRYUSB_HOST
+ EXCL_SRC += $(CHERRY_USB_DIR)/core/usbd_core.c
+
+ ifdef CONFIG_CHERRY_USB_HOST_HUB
+ EXCL_SRC += $(CHERRY_USB_DIR)/class/hub/usbd_hub.c
+
+ INC_DIR += $(CHERRY_USB_DIR)/class/hub
+ SRC_DIR += $(CHERRY_USB_DIR)/class/hub
+ endif #CONFIG_CHERRY_USB_HOST_HUB
+
+ ifdef CONFIG_CHERRY_USB_HOST_MSC
+ EXCL_SRC += $(CHERRY_USB_DIR)/class/msc/usbd_msc.c
+
+ INC_DIR += $(CHERRY_USB_DIR)/class/msc
+ SRC_DIR += $(CHERRY_USB_DIR)/class/msc
+ endif #CONFIG_CHERRY_USB_HOST_MSC
+
+ ifdef CONFIG_CHERRY_USB_HOST_HID
+ EXCL_SRC += $(CHERRY_USB_DIR)/class/hid/usbd_hid.c
+
+ INC_DIR += $(CHERRY_USB_DIR)/class/hid
+ SRC_DIR += $(CHERRY_USB_DIR)/class/hid
+ endif #CONFIG_CHERRY_USB_HOST_HID
+
+ ifdef CONFIG_CHERRY_USB_HOST_VEDIO
+ EXCL_SRC += $(CHERRY_USB_DIR)/class/vedio/usbd_vedio.c
+
+ INC_DIR += $(CHERRY_USB_DIR)/class/vedio
+ SRC_DIR += $(CHERRY_USB_DIR)/class/vedio
+ endif #CONFIG_CHERRY_USB_HOST_VEDIO
+
+ ifdef CONFIG_CHERRY_USB_HOST_RNDIS_WIRELESS
+ EXCL_SRC += $(CHERRY_USB_DIR)/class/wireless/usbd_rndis.c
+
+ INC_DIR += $(CHERRY_USB_DIR)/class/wireless
+ SRC_DIR += $(CHERRY_USB_DIR)/class/wireless
+ endif #CONFIG_CHERRY_USB_HOST_RNDIS_WIRELESS
+
+ ifdef CONFIG_CHERRY_USB_HOST_CDC
+ EXCL_SRC += $(CHERRY_USB_DIR)/class/cdc/usbd_cdc.c
+
+ INC_DIR += $(CHERRY_USB_DIR)/class/cdc
+ SRC_DIR += $(CHERRY_USB_DIR)/class/cdc
+ endif #CONFIG_CHERRY_USB_HOST_CDC
+
+endif #CONFIG_CHERRYUSB_HOST
+
+ifdef CONFIG_CHERRYUSB_DEVICE
+ EXCL_SRC += $(CHERRY_USB_DIR)/core/usbh_core.c
+endif #CONFIG_CHERRYUSB_DEVICE
diff --git a/third-party/cherryusb-0.6.0/osal/usb_osal.h b/third-party/cherryusb-0.6.0/osal/usb_osal.h
new file mode 100644
index 0000000000000000000000000000000000000000..45adf3133425d52f3462a5740b5a183f7c7552e0
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/osal/usb_osal.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef USB_OSAL_H
+#define USB_OSAL_H
+
+#include
+#include
+
+typedef void *usb_osal_thread_t;
+typedef void *usb_osal_sem_t;
+typedef void *usb_osal_mutex_t;
+typedef void (*usb_thread_entry_t)(void *argument);
+
+usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args);
+
+usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count);
+void usb_osal_sem_delete(usb_osal_sem_t sem);
+int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout);
+int usb_osal_sem_give(usb_osal_sem_t sem);
+
+usb_osal_mutex_t usb_osal_mutex_create(void);
+void usb_osal_mutex_delete(usb_osal_mutex_t mutex);
+int usb_osal_mutex_take(usb_osal_mutex_t mutex);
+int usb_osal_mutex_give(usb_osal_mutex_t mutex);
+
+size_t usb_osal_enter_critical_section(void);
+void usb_osal_leave_critical_section(size_t flag);
+
+void usb_osal_msleep(uint32_t delay);
+
+#endif /* USB_OSAL_H */
+
diff --git a/third-party/cherryusb-0.6.0/osal/usb_osal_freertos.c b/third-party/cherryusb-0.6.0/osal/usb_osal_freertos.c
new file mode 100644
index 0000000000000000000000000000000000000000..009a61b32b9977f8eca99a549f5c758f47caf198
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/osal/usb_osal_freertos.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2022, sakumisu
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "usb_osal.h"
+#include "usb_errno.h"
+#include
+#include "semphr.h"
+#include "timers.h"
+#include "event_groups.h"
+
+usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args)
+{
+ TaskHandle_t htask = NULL;
+ stack_size /= sizeof(StackType_t);
+ xTaskCreate(entry, name, stack_size, args, prio, &htask);
+ return (usb_osal_thread_t)htask;
+}
+
+usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count)
+{
+ return (usb_osal_sem_t)xSemaphoreCreateCounting(1, initial_count);
+}
+
+void usb_osal_sem_delete(usb_osal_sem_t sem)
+{
+ vSemaphoreDelete((SemaphoreHandle_t)sem);
+}
+
+int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout)
+{
+ return (xSemaphoreTake((SemaphoreHandle_t)sem, pdMS_TO_TICKS(timeout)) == pdPASS) ? 0 : -ETIMEDOUT;
+}
+
+int usb_osal_sem_give(usb_osal_sem_t sem)
+{
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ int ret;
+
+ ret = xSemaphoreGiveFromISR((SemaphoreHandle_t)sem, &xHigherPriorityTaskWoken);
+ if (ret == pdPASS) {
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+ }
+
+ return (ret == pdPASS) ? 0 : -EINVAL;
+}
+
+usb_osal_mutex_t usb_osal_mutex_create(void)
+{
+ return (usb_osal_mutex_t)xSemaphoreCreateMutex();
+}
+
+void usb_osal_mutex_delete(usb_osal_mutex_t mutex)
+{
+ vSemaphoreDelete((SemaphoreHandle_t)mutex);
+}
+
+int usb_osal_mutex_take(usb_osal_mutex_t mutex)
+{
+ return (xSemaphoreTake((SemaphoreHandle_t)mutex, portMAX_DELAY) == pdPASS) ? 0 : -ETIMEDOUT;
+}
+
+int usb_osal_mutex_give(usb_osal_mutex_t mutex)
+{
+ return (xSemaphoreGive((SemaphoreHandle_t)mutex) == pdPASS) ? 0 : -EINVAL;
+}
+
+size_t usb_osal_enter_critical_section(void)
+{
+ taskDISABLE_INTERRUPTS();
+ return 1;
+}
+
+void usb_osal_leave_critical_section(size_t flag)
+{
+ taskENABLE_INTERRUPTS();
+}
+
+void usb_osal_msleep(uint32_t delay)
+{
+ vTaskDelay(pdMS_TO_TICKS(delay));
+}
diff --git a/third-party/cherryusb-0.6.0/port/xhci/usb_config.h b/third-party/cherryusb-0.6.0/port/xhci/usb_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..0869d15e7488e1b569cc1b238a16420a45bb8d79
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/port/xhci/usb_config.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: usb_config.h
+ * Date: 2022-09-19 17:28:44
+ * LastEditTime: 2022-09-19 17:28:45
+ * Description: This files is for usb hc xhci configuration
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ * 1.0 zhugengyu 2022/9/19 init commit
+ */
+
+#ifndef CHERRYUSB_CONFIG_H
+#define CHERRYUSB_CONFIG_H
+
+
+/* ================ USB common Configuration ================ */
+
+#ifndef CONFIG_USB_DBG_LEVEL
+#define CONFIG_USB_DBG_LEVEL USB_DBG_ERROR
+#endif
+
+#ifndef CONFIG_USB_PRINTF
+#define CONFIG_USB_PRINTF printf
+#endif
+
+/* Enable print with color */
+#define CONFIG_USB_PRINTF_COLOR_ENABLE
+
+/* data align size when use dma */
+#ifndef CONFIG_USB_ALIGN_SIZE
+#define CONFIG_USB_ALIGN_SIZE 4
+#endif
+
+/* attribute data into no cache ram */
+#define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable")))
+
+/* ================= USB Device Stack Configuration ================ */
+
+/* Ep0 max transfer buffer, specially for receiving data from ep0 out */
+#define CONFIG_USBDEV_REQUEST_BUFFER_LEN 256
+
+
+#ifndef CONFIG_USBDEV_MSC_BLOCK_SIZE
+#define CONFIG_USBDEV_MSC_BLOCK_SIZE 512
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_MANUFACTURER_STRING
+#define CONFIG_USBDEV_MSC_MANUFACTURER_STRING ""
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_PRODUCT_STRING
+#define CONFIG_USBDEV_MSC_PRODUCT_STRING ""
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_VERSION_STRING
+#define CONFIG_USBDEV_MSC_VERSION_STRING "0.01"
+#endif
+
+// #define CONFIG_USBHOST_GET_STRING_DESC
+#define CONFIG_USBHOST_GET_DEVICE_DESC
+
+// #define CONFIG_USBDEV_MSC_THREAD
+#define CONFIG_INPUT_MOUSE_WHEEL
+
+#ifdef CONFIG_USBDEV_MSC_THREAD
+#ifndef CONFIG_USBDEV_MSC_STACKSIZE
+#define CONFIG_USBDEV_MSC_STACKSIZE 2048
+#endif
+
+#ifndef CONFIG_USBDEV_MSC_PRIO
+#define CONFIG_USBDEV_MSC_PRIO 4
+#endif
+#endif
+
+#ifndef CONFIG_USBDEV_AUDIO_VERSION
+#define CONFIG_USBDEV_AUDIO_VERSION 0x0100
+#endif
+
+#ifndef CONFIG_USBDEV_AUDIO_MAX_CHANNEL
+#define CONFIG_USBDEV_AUDIO_MAX_CHANNEL 8
+#endif
+
+/* ================ USB HOST Stack Configuration ================== */
+
+#define CONFIG_USBHOST_MAX_RHPORTS 1
+#define CONFIG_USBHOST_MAX_EXTHUBS 2
+#define CONFIG_USBHOST_MAX_EHPORTS 4
+#define CONFIG_USBHOST_MAX_INTERFACES 6
+#define CONFIG_USBHOST_MAX_INTF_ALTSETTINGS 1
+#define CONFIG_USBHOST_MAX_ENDPOINTS 4
+
+#define CONFIG_USBHOST_DEV_NAMELEN 16
+
+#ifndef CONFIG_USBHOST_PSC_PRIO
+#define CONFIG_USBHOST_PSC_PRIO 4
+#endif
+#ifndef CONFIG_USBHOST_PSC_STACKSIZE
+#define CONFIG_USBHOST_PSC_STACKSIZE 2048
+#endif
+
+/* Ep0 max transfer buffer */
+#define CONFIG_USBHOST_REQUEST_BUFFER_LEN 512
+
+#ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT
+#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500
+#endif
+
+#ifndef CONFIG_USBHOST_MSC_TIMEOUT
+#define CONFIG_USBHOST_MSC_TIMEOUT 5000
+#endif
+
+/* ================ USB Device Port Configuration ================*/
+
+#define CONFIG_XHCI_PAGE_SIZE 4096U
+#define CONFIG_XHCI_PAGE_SHIFT 12U
+
+/* ================ USB Host Port Configuration ==================*/
+
+#define CONFIG_USBHOST_PIPE_NUM 10
+
+/* ================ XHCI Configuration ================ */
+#define CONFIG_USBHOST_XHCI
+
+#endif
diff --git a/third-party/cherryusb-0.6.0/port/xhci/usb_hc_xhci.c b/third-party/cherryusb-0.6.0/port/xhci/usb_hc_xhci.c
new file mode 100644
index 0000000000000000000000000000000000000000..0d9100d6649cededdcc141d3b99b811c24022e48
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/port/xhci/usb_hc_xhci.c
@@ -0,0 +1,1511 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: usb_hc_xhci.c
+ * Date: 2022-09-19 17:24:36
+ * LastEditTime: 2022-09-19 17:24:36
+ * Description: This files is for xhci function implementation
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ * 1.0 zhugengyu 2022/9/19 init commit
+ * 1.1 zhugengyu 2022/10/9 add dumpers and fix command abort
+ */
+
+/***************************** Include Files *********************************/
+#include "usbh_core.h"
+#include "usbh_hub.h"
+#include "xhci_reg.h"
+#include "usb_hc_xhci.h"
+
+/************************** Constant Definitions *****************************/
+
+/************************** Variable Definitions *****************************/
+/* input is xhci speed */
+static const char *speed_name[16] = {
+ [ 0 ] = " - ",
+ [ 1 ] = "Full",
+ [ 2 ] = "Low",
+ [ 3 ] = "High",
+ [ 4 ] = "Super",
+};
+
+static const int speed_from_xhci[16] = {
+ [ 0 ] = -1,
+ [ 1 ] = USB_SPEED_FULL,
+ [ 2 ] = USB_SPEED_LOW,
+ [ 3 ] = USB_SPEED_HIGH,
+ [ 4 ] = USB_SPEED_SUPER,
+ [ 5 ... 15 ] = -1,
+};
+
+static const int speed_to_xhci[] = {
+ [ USB_SPEED_FULL ] = 1,
+ [ USB_SPEED_LOW ] = 2,
+ [ USB_SPEED_HIGH ] = 3,
+ [ USB_SPEED_SUPER ] = 4,
+};
+
+static volatile struct xhci_pipe *cur_cmd_pipe = NULL; /* pass current command pipe to interrupt */
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+void usb_hc_dcache_invalidate(void *addr, unsigned long len);
+struct xhci_pipe *xhci_event_process(struct xhci_s *xhci);
+
+/*****************************************************************************/
+static void xhci_dump_slot_ctx(const struct xhci_slotctx *const sc)
+{
+ USB_LOG_DBG("ctx[0]=0x%x\n", sc->ctx[0]);
+ USB_LOG_DBG(" route=0x%x\n",
+ XHCI_SLOTCTX_0_ROUTE_GET(sc->ctx[0]));
+ USB_LOG_DBG("ctx[1]=0x%x\n", sc->ctx[1]);
+ USB_LOG_DBG("ctx[2]=0x%x\n", sc->ctx[2]);
+ USB_LOG_DBG(" tt-port=0x%x, tt-hub-slot=0x%x\n",
+ XHCI_SLOTCTX_2_HUB_PORT_GET(sc->ctx[2]),
+ XHCI_SLOTCTX_2_HUB_SLOT_GET(sc->ctx[2]));
+ USB_LOG_DBG("ctx[3]=0x%x\n", sc->ctx[3]);
+}
+
+static void xhci_dump_ep_ctx(const struct xhci_epctx *const ec)
+{
+ USB_LOG_DBG("ctx[0]=0x%x\n", ec->ctx[0]);
+ USB_LOG_DBG("ctx[1]=0x%x\n", ec->ctx[1]);
+ USB_LOG_DBG(" ep_type=%d, mps=%d\n",
+ XHCI_EPCTX_1_EPTYPE_GET(ec->ctx[1]),
+ XHCI_EPCTX_1_MPS_GET(ec->ctx[1]));
+ USB_LOG_DBG("deq_low=0x%x\n", ec->deq_low);
+ USB_LOG_DBG("deq_high=0x%x\n", ec->deq_high);
+ USB_LOG_DBG("length=0x%x\n", ec->length);
+}
+
+static void xhci_dump_input_ctx(struct xhci_s *xhci, const struct xhci_inctx *const inctx)
+{
+ USB_LOG_DBG("===input ctx====\n");
+ USB_LOG_DBG("add=0x%x\n", inctx->add);
+ USB_LOG_DBG("del=0x%x\n", inctx->del);
+ if (inctx->add & (0x1)) {
+ USB_LOG_DBG("===slot ctx====\n");
+ const struct xhci_slotctx *const sc = (void*)&inctx[1 << xhci->context64];
+ xhci_dump_slot_ctx(sc);
+ }
+
+ for (int epid = 1; epid <= 31; epid++){
+ if (inctx->add & (0x1 << (epid)))
+ {
+ USB_LOG_DBG("===ep-%d ctx====\n", epid);
+ const struct xhci_epctx *const ec = (void*)&inctx[(epid+1) << xhci->context64];
+ xhci_dump_ep_ctx(ec);
+ }
+ }
+ USB_LOG_DBG("\n");
+}
+
+static void xhci_dump_pipe(const struct xhci_pipe *const ppipe)
+{
+ USB_LOG_DBG("pipe@%p\n", ppipe);
+ if (NULL == ppipe)
+ return;
+
+ USB_LOG_DBG("epaddr=%d\n", ppipe->epaddr);
+ USB_LOG_DBG("speed=%d\n", ppipe->speed);
+ USB_LOG_DBG("interval=%d\n", ppipe->interval);
+ USB_LOG_DBG("maxpacket=%d\n", ppipe->maxpacket);
+ USB_LOG_DBG("eptype=%d\n", ppipe->eptype);
+ USB_LOG_DBG("slotid=%d\n", ppipe->slotid);
+ USB_LOG_DBG("epid=%d\n", ppipe->epid);
+ USB_LOG_DBG("timeout=%d\n", ppipe->timeout);
+ USB_LOG_DBG("waiter=%d\n", ppipe->waiter);
+ USB_LOG_DBG("waitsem=%p\n", ppipe->waitsem);
+ USB_LOG_DBG("hport=%p\n", ppipe->hport);
+ USB_LOG_DBG("urb=%p\n", ppipe->urb);
+}
+
+/* Wait until bit = value or timeout */
+static int xhci_wait_bit(unsigned long reg_off, uint32_t mask, uint32_t value, uint32_t timeout)
+{
+ uint32_t delay = 0U; /* calc wait end time */
+
+ while ((readl(reg_off) & mask) != value) {
+ if (++delay > timeout) { /* check if timeout */
+ USB_LOG_ERR("wait timeout !!!\n");
+ return -1;
+ }
+ usb_osal_msleep(1U);
+ }
+ return 0;
+}
+
+/* Check if device attached to port */
+static void xhci_print_port_state(const char *prefix, uint32_t port, uint32_t portsc)
+{
+ uint32_t pls = XHCI_REG_OP_PORTS_PORTSC_PLS_GET(portsc);
+ uint32_t speed = XHCI_REG_OP_PORTS_PORTSC_PORT_SPEED_GET(portsc);
+
+ USB_LOG_DBG("%s port #%d: 0x%08x,%s%s pls %d, speed %d [%s]\n",
+ prefix, port + 1, portsc,
+ (portsc & XHCI_REG_OP_PORTS_PORTSC_PP) ? " powered," : "",
+ (portsc & XHCI_REG_OP_PORTS_PORTSC_PED) ? " enabled," : "",
+ pls, speed, speed_name[speed]);
+}
+
+static inline uint32_t xhci_readl_port(struct xhci_s *xhci, uint32_t port, uint32_t offset)
+{
+ /* Operational Base + (400h + (10h * (n–1))) */
+ return readl(xhci->pr + port * XHCI_REG_OP_PORTS_SIZE + offset);
+}
+
+static inline void xhci_writel_port(struct xhci_s *xhci, uint32_t port, uint32_t offset, uint32_t val)
+{
+ /* Operational Base + (400h + (10h * (n–1))) */
+ return writel(xhci->pr + port * XHCI_REG_OP_PORTS_SIZE + offset, val);
+}
+
+static void xhci_setup_mmio(struct xhci_s *xhci, unsigned long base_addr)
+{
+ xhci->base = base_addr;
+ xhci->caps = xhci->base;
+
+ /* add to register base to find the beginning of the Operational Register Space */
+ xhci->op = xhci->base + readb(xhci->caps + XHCI_REG_CAP_CAPLENGTH);
+ xhci->db = xhci->base + XHCI_REG_CAP_DBOFF_GET(readl(xhci->caps + XHCI_REG_CAP_DBOFF));
+ xhci->ir = xhci->base + XHCI_REG_CAP_RTSOFF_GET(readl(xhci->caps + XHCI_REG_CAP_RTSOFF)) +
+ XHCI_REG_RT_IR0;
+ xhci->pr = xhci->op + XHCI_REG_OP_PORTS_BASE;
+
+ /* cache static information of CAP_HCSPARAMS */
+ xhci->hcs[0] = readl(xhci->caps + XHCI_REG_CAP_HCS1);
+ xhci->hcs[1] = readl(xhci->caps + XHCI_REG_CAP_HCS2);
+ xhci->hcs[2] = readl(xhci->caps + XHCI_REG_CAP_HCS3);
+ xhci->hcc = readl(xhci->caps + XHCI_REG_CAP_HCC);
+
+ /* avoid access XHCI_REG_CAP_HCIVERSION = 0x2, unaligned memory */
+ xhci->version = ((readl(xhci->caps + XHCI_REG_CAP_CAPLENGTH) >> 16) & 0xffff);
+
+ xhci->ports = XHCI_REG_CAP_HCS1_MAX_PORTS_GET(xhci->hcs[0]); /* bit[31:24] max ports */
+ xhci->slots = XHCI_REG_CAP_HCS1_MAX_SLOTS_GET(xhci->hcs[0]); /* bit[7:0] max device slots */
+
+ /* For example, using the offset of Base is 1000h and the xECP value of 0068h, we can calculated
+ the following effective address of the first extended capability:
+ 1000h + (0068h << 2) -> 1000h + 01A0h -> 11A0h */
+ xhci->xcap = XHCI_REG_CAP_HCC_XECP_GET(xhci->hcc) << 2; /* bit[31:16] xHCI extended cap pointer */
+ xhci->context64 = (XHCI_REG_CAP_HCC_CSZ & xhci->hcc) ? true : false;
+
+ USB_LOG_INFO(" hc version: 0x%x\n", xhci->version);
+ USB_LOG_INFO(" mmio base: 0x%x\n", xhci->base);
+ USB_LOG_INFO(" oper base: 0x%x\n", xhci->op);
+ USB_LOG_INFO(" doorbell base: 0x%x\n", xhci->db);
+ USB_LOG_INFO(" runtime base: 0x%x\n", xhci->ir);
+ USB_LOG_INFO(" port base: 0x%x\n", xhci->pr);
+ USB_LOG_INFO(" xcap base: 0x%x\n", xhci->xcap);
+
+ USB_LOG_INFO(" slot num: 0x%x\n", xhci->slots);
+ USB_LOG_INFO(" port num: 0x%x\n", xhci->ports);
+ USB_LOG_INFO(" context: %d bit\n", xhci->context64 ? 64 : 32);
+}
+
+
+/* Reset device on port */
+static int xhci_hub_reset(struct xhci_s *xhci, uint32_t port)
+{
+ uint32_t portsc = xhci_readl_port(xhci, port, XHCI_REG_OP_PORTS_PORTSC);
+ if (!(portsc & XHCI_REG_OP_PORTS_PORTSC_CCS)) /* double check if connected */
+ /* Device no longer connected?! */
+ return -1;
+
+ switch (XHCI_REG_OP_PORTS_PORTSC_PLS_GET(portsc)) {
+ case PLS_U0:
+ /* A USB3 port - controller automatically performs reset */
+ break;
+ case PLS_POLLING:
+ /* A USB2 port - perform device reset */
+ xhci_print_port_state(__func__, port, portsc);
+ xhci_writel_port(xhci, port, XHCI_REG_OP_PORTS_PORTSC,
+ portsc | XHCI_REG_OP_PORTS_PORTSC_PR); /* reset port */
+ break;
+ default:
+ return -1;
+ }
+
+ // Wait for device to complete reset and be enabled
+ uint32_t end = 1000U, start = 0U;
+ for (;;) {
+ portsc = xhci_readl_port(xhci, port, XHCI_REG_OP_PORTS_PORTSC);
+ if (!(portsc & XHCI_REG_OP_PORTS_PORTSC_CCS))
+ /* Device disconnected during reset */
+ return -1;
+
+ if (portsc & XHCI_REG_OP_PORTS_PORTSC_PED) /* check if port enabled */
+ /* Reset complete */
+ break;
+
+ if (++start > end) {
+ USB_LOG_ERR("wait timeout, portsc=0x%x!!!\n", portsc);
+ return -1;
+ }
+
+ usb_osal_msleep(1);
+ }
+
+ int rc = speed_from_xhci[XHCI_REG_OP_PORTS_PORTSC_PORT_SPEED_GET(portsc)];
+ xhci_print_port_state("XHCI", port, portsc);
+ return rc;
+}
+
+/* Add a TRB to the given ring */
+static void xhci_trb_fill(struct xhci_ring *ring, void *data, uint32_t xferlen, uint32_t flags)
+{
+ struct xhci_trb *dst = &ring->ring[ring->nidx];
+ if (flags & TRB_TR_IDT) {
+ memcpy(&dst->ptr_low, data, xferlen);
+ } else {
+ dst->ptr_low = (uint32_t)(unsigned long)data;
+#ifdef XHCI_AARCH64
+ dst->ptr_high = (uint32_t)((uint64_t)data >> 32U);
+#else
+ dst->ptr_high = 0U;
+#endif
+ }
+ dst->status = xferlen;
+ /* cycle bit */
+ dst->control = flags | (ring->cs ? TRB_C : 0);
+}
+
+/* Queue a TRB onto a ring, wrapping ring as needed */
+static void xhci_trb_queue(struct xhci_ring *ring, void *data, uint32_t xferlen, uint32_t flags)
+{
+ if (ring->nidx >= ARRAY_SIZE(ring->ring) - 1) { /* if it is the last trb in the list */
+ /* indicate the end of ring, bit[1], toggle cycle = 1, xHc shall toggle cycle bit interpretation */
+ xhci_trb_fill(ring, ring->ring, 0, (TR_LINK << 10) | TRB_LK_TC);
+ ring->nidx = 0; /* adjust dequeue index to 0 */
+ ring->cs ^= 1; /* toggle cycle interpretation of sw */
+ }
+
+ xhci_trb_fill(ring, data, xferlen, flags);
+ ring->nidx++; /* ahead dequeue index */
+}
+
+/* Signal the hardware to process events on a TRB ring */
+static void xhci_doorbell(struct xhci_s *xhci, uint32_t slotid, uint32_t value)
+{
+ writel(xhci->db + slotid * XHCI_REG_DB_SIZE, value); /* bit[7:0] db target, is ep_id */
+}
+
+/* Wait for a ring to empty (all TRBs processed by hardware) */
+static int xhci_event_wait(struct xhci_s *xhci,
+ struct xhci_pipe *pipe,
+ struct xhci_ring *ring)
+{
+ int ret = CC_SUCCESS;
+
+ if (pipe->timeout > 0){
+ ret = usb_osal_sem_take(pipe->waitsem, pipe->timeout);
+ if (ret < 0) {
+ ret = CC_TIMEOUT;
+ } else {
+ ret = TRB_CC_GET(ring->evt.status); /* bit[31:24] completion code */
+ }
+ }
+
+ return ret;
+}
+
+static int xhci_cmd_abort(struct xhci_s *xhci, struct xhci_pipe *pipe)
+{
+ uint64_t crcr;
+
+ crcr = readq(xhci->op + XHCI_REG_OP_CRCR);
+ USB_LOG_WRN("aborting command, crcr = 0x%llx\r\n", crcr);
+ crcr |= XHCI_REG_OP_CRCR_CA;
+ writeq(xhci->op + XHCI_REG_OP_CRCR, crcr); /* abort command */
+
+ usb_osal_msleep(500); /* allow time for command to abort */
+
+ crcr = readl(xhci->op + XHCI_REG_OP_CRCR);
+ if (XHCI_REG_OP_CRCR_CRR & crcr) {
+ /* Device has failed to abort a command and is almost
+ * certainly beyond repair. Reset device, abandoning
+ * all state, and mark device as failed to avoid
+ * delays on any future command attempts.
+ */
+ USB_LOG_ERR("failed to abort command \r\n");
+ return -1;
+ }
+
+ pipe->timeout = 5000;
+ pipe->waiter = true;
+ cur_cmd_pipe = pipe;
+
+ int rc = xhci_event_wait(xhci, pipe, xhci->cmds);
+
+ /* Reset the command ring control register */
+ memset(xhci->cmds->ring, 0U, XHCI_RING_ITEMS * sizeof(struct xhci_trb));
+ writeq(xhci->op + XHCI_REG_OP_CRCR, (uint64_t)(unsigned long)xhci->cmds | xhci->cmds->cs);
+
+ return rc;
+}
+
+/* Submit a command to the xhci controller ring */
+static int xhci_cmd_submit(struct xhci_s *xhci, struct xhci_inctx *inctx,
+ struct xhci_pipe *pipe, uint32_t flags)
+{
+ if (inctx) {
+ struct xhci_slotctx *slot = (void*)&inctx[1 << xhci->context64];
+ uint32_t port = XHCI_SLOTCTX_1_ROOT_PORT_GET(slot->ctx[1]) - 1;
+ uint32_t portsc = xhci_readl_port(xhci, port, XHCI_REG_OP_PORTS_PORTSC);
+ if (!(portsc & XHCI_REG_OP_PORTS_PORTSC_CCS)) {
+ /* Device no longer connected?! */
+ xhci_print_port_state(__func__, port, portsc);
+ return CC_DISCONNECTED;
+ }
+ }
+
+ usb_osal_mutex_take(xhci->cmds->lock); /* handle command one by one */
+
+ pipe->timeout = 5000;
+ pipe->waiter = true;
+ cur_cmd_pipe = pipe;
+
+ xhci_trb_queue(xhci->cmds, inctx, 0, flags);
+
+ /* pass command trb to hardware */
+ DSB();
+
+ xhci_doorbell(xhci, 0, 0); /* 0 = db host controller, 0 = db targe hc command */
+ int rc = xhci_event_wait(xhci, pipe, xhci->cmds);
+
+ if (CC_SUCCESS != rc) {
+ rc = xhci_cmd_abort(xhci, pipe);
+ }
+
+ usb_osal_mutex_give(xhci->cmds->lock);
+
+ return rc;
+}
+
+static int xhci_cmd_nop(struct xhci_s *xhci, struct xhci_pipe *pipe)
+{
+ USB_LOG_DBG("%s\n", __func__);
+ return xhci_cmd_submit(xhci, NULL, pipe, TRB_TYPE_SET(CR_NOOP));
+}
+
+static int xhci_cmd_enable_slot(struct xhci_s *xhci, struct xhci_pipe *pipe)
+{
+ int cc = xhci_cmd_submit(xhci, NULL, pipe, TRB_TYPE_SET(CR_ENABLE_SLOT));
+ if (cc != CC_SUCCESS)
+ return cc;
+
+ struct xhci_trb *evt = &(xhci->cmds->evt);
+ return TRB_CR_SLOTID_GET(evt->control); /* bit [31:24] slot id */
+}
+
+static int xhci_cmd_disable_slot(struct xhci_s *xhci, struct xhci_pipe *pipe)
+{
+ USB_LOG_DBG("%s: slotid %d\n", __func__, pipe->slotid);
+ return xhci_cmd_submit(xhci, NULL, pipe, TRB_TYPE_SET(CR_DISABLE_SLOT) | TRB_CR_SLOTID_SET(pipe->slotid));
+}
+
+static int xhci_cmd_address_device(struct xhci_s *xhci, struct xhci_pipe *pipe, struct xhci_inctx *inctx)
+{
+ USB_LOG_DBG("%s: slotid %d\n", __func__, pipe->slotid);
+ return xhci_cmd_submit(xhci, inctx, pipe, TRB_TYPE_SET(CR_ADDRESS_DEVICE) | TRB_CR_SLOTID_SET(pipe->slotid));
+}
+
+static int xhci_cmd_configure_endpoint(struct xhci_s *xhci, struct xhci_pipe *pipe,
+ struct xhci_inctx *inctx, bool defconfig)
+{
+ USB_LOG_DBG("%s: slotid %d\n", __func__, pipe->slotid);
+ return xhci_cmd_submit(xhci, inctx, pipe, TRB_TYPE_SET(CR_CONFIGURE_ENDPOINT) |
+ TRB_CR_SLOTID_SET(pipe->slotid) |
+ (defconfig ? TRB_CR_DC : 0));
+}
+
+static int xhci_cmd_evaluate_context(struct xhci_s *xhci, struct xhci_pipe *pipe, struct xhci_inctx *inctx)
+{
+ USB_LOG_DBG("%s: slotid %d\n", __func__, pipe->slotid);
+ /* bit[15:10] TRB type, bit[31:24] Slot id */
+ return xhci_cmd_submit(xhci, inctx, pipe, TRB_TYPE_SET(CR_EVALUATE_CONTEXT) | TRB_CR_SLOTID_SET(pipe->slotid));
+}
+static int xhci_cmd_reset_endpoint(struct xhci_s *xhci, struct xhci_pipe *pipe)
+{
+ USB_LOG_DBG("%s: slotid %d, epid %d\n", __func__, pipe->slotid, pipe->epid);
+ /* bit[15:10] TRB type, bit[31:24] Slot id */
+ return xhci_cmd_submit(xhci, NULL, pipe, TRB_TYPE_SET(CR_RESET_ENDPOINT) | TRB_CR_SLOTID_SET(pipe->slotid) |
+ TRB_CR_EPID_SET(pipe->epid));
+}
+
+static int xhci_controller_configure(struct xhci_s *xhci)
+{
+ uint32_t reg;
+
+ /* trbs */
+ xhci->devs = usb_align(XHCI_ALIGMENT, sizeof(*xhci->devs) * (xhci->slots + 1)); /* device slot */
+ xhci->eseg = usb_align(XHCI_ALIGMENT, sizeof(*xhci->eseg)); /* event segment */
+ xhci->cmds = usb_align(XHCI_RING_SIZE, sizeof(*xhci->cmds)); /* command ring */
+ xhci->evts = usb_align(XHCI_RING_SIZE, sizeof(*xhci->evts)); /* event ring */
+
+ if (!xhci->devs || !xhci->cmds || !xhci->evts || !xhci->eseg) {
+ USB_LOG_ERR("allocate memory failed !!!\n");
+ goto fail;
+ }
+
+ memset(xhci->devs, 0U, sizeof(*xhci->devs) * (xhci->slots + 1));
+ memset(xhci->cmds, 0U, sizeof(*xhci->cmds));
+ memset(xhci->evts, 0U, sizeof(*xhci->evts));
+ memset(xhci->eseg, 0U, sizeof(*xhci->eseg));
+
+ xhci->cmds->lock = usb_osal_mutex_create();
+ USB_ASSERT(xhci->cmds->lock);
+
+ reg = readl(xhci->op + XHCI_REG_OP_USBCMD);
+ if (reg & XHCI_REG_OP_USBCMD_RUN_STOP) { /* if xHc running, stop it first */
+ reg &= ~XHCI_REG_OP_USBCMD_RUN_STOP;
+ writel(xhci->op + XHCI_REG_OP_USBCMD, reg); /* stop xHc */
+
+ if (xhci_wait_bit(xhci->op + XHCI_REG_OP_USBSTS,
+ XHCI_REG_OP_USBSTS_HCH, XHCI_REG_OP_USBSTS_HCH, 32) != 0) /* wait xHc halt */
+ goto fail;
+ }
+
+ USB_LOG_DBG("%s: resetting\n", __func__);
+
+ writel(xhci->op + XHCI_REG_OP_USBCMD, XHCI_REG_OP_USBCMD_HCRST); /* reset xHc */
+ if (xhci_wait_bit(xhci->op + XHCI_REG_OP_USBCMD, XHCI_REG_OP_USBCMD_HCRST, 0, 1000) != 0) /* wait reset process done */
+ goto fail;
+
+ if (xhci_wait_bit(xhci->op + XHCI_REG_OP_USBSTS, XHCI_REG_OP_USBSTS_CNR, 0, 1000) != 0) /* wait until xHc ready */
+ goto fail;
+
+ writel(xhci->op + XHCI_REG_OP_CONFIG, xhci->slots); /* bit[7:0], set max num of device slot enabled */
+ writeq(xhci->op + XHCI_REG_OP_DCBAAP, (uint64_t)(unsigned long)xhci->devs); /* bit[63:6] device context base address array pointer */
+ writeq(xhci->op + XHCI_REG_OP_CRCR, (uint64_t)(unsigned long)xhci->cmds | 1); /* command ring pointer, cycle state = 1 */
+ xhci->cmds->cs = 1; /* cycle state = 1 */
+
+ xhci->eseg->ptr_low = (uint32_t)((unsigned long)xhci->evts); /* event ring pointer */
+#ifdef XHCI_AARCH64
+ xhci->eseg->ptr_high = (uint32_t)((unsigned long)xhci->evts >> 32U);
+#else
+ xhci->eseg->ptr_high = 0U;
+#endif
+
+ xhci->eseg->size = XHCI_RING_ITEMS; /* items of event ring TRB */
+ writel(xhci->ir + XHCI_REG_RT_IR_ERSTSZ, 1); /* bit[15:0] event ring segment table size */
+ writeq(xhci->ir + XHCI_REG_RT_IR_ERDP, (uint64_t)(unsigned long)xhci->evts); /* bit[63:4] event ring dequeue pointer */
+ writeq(xhci->ir + XHCI_REG_RT_IR_ERSTBA, (uint64_t)(unsigned long)xhci->eseg); /* bit[63:6] event ring segment table base addr */
+ xhci->evts->cs = 1; /* cycle state = 1 */
+
+ reg = xhci->hcs[1];
+ uint32_t spb = XHCI_REG_CAP_HCS2_MAX_SCRATCHPAD_BUFS_GET(reg); /* bit [25:21] | bit [31:27] max scratchpad buffers */
+ if (spb) {
+ /* reserve scratchpad buffers for xHc */
+ USB_LOG_DBG("%s: setup %d scratch pad buffers\n", __func__, spb);
+ uint64_t *spba = usb_align(XHCI_ALIGMENT, sizeof(*spba) * spb); /* base addr of scratchpad buffers */
+ void *pad = usb_align(CONFIG_XHCI_PAGE_SIZE, CONFIG_XHCI_PAGE_SIZE * spb); /* the whole scratchpad buffers */
+ if (!spba || !pad) {
+ USB_LOG_ERR("allocate memory failed !!!\n");
+ usb_free(spba);
+ usb_free(pad);
+ goto fail;
+ }
+ for (uint32_t i = 0; i < spb; i++)
+ spba[i] = (uint64_t)(unsigned long)(pad + (i * CONFIG_XHCI_PAGE_SIZE)); /* assign base addr for each pad */
+ xhci->devs[0].ptr_low = (uint32_t)((unsigned long)spba); /* bit[63:6] scratchpad buffers base addr */
+#ifdef XHCI_AARCH64
+ xhci->devs[0].ptr_high = (uint32_t)((uint64_t)spba >> 32U);
+#else
+ xhci->devs[0].ptr_high = 0U;
+#endif
+ }
+
+ /* enable port interrupt */
+ writel(xhci->ir + XHCI_REG_RT_IR_IMOD, 500U);
+ reg = readl(xhci->ir + XHCI_REG_RT_IR_IMAN);
+ reg |= XHCI_REG_RT_IR_IMAN_IE;
+ writel(xhci->ir + + XHCI_REG_RT_IR_IMAN, reg);
+
+ reg = readl(xhci->op + XHCI_REG_OP_USBCMD);
+ reg |= XHCI_REG_OP_USBCMD_INTE; /* enable interrupt */
+ writel(xhci->op + XHCI_REG_OP_USBCMD, reg);
+
+ USB_LOG_DBG("Start xHc ....\n");
+
+ reg = readl(xhci->op + XHCI_REG_OP_USBCMD);
+ reg |= XHCI_REG_OP_USBCMD_RUN_STOP; /* start xHc */
+ writel(xhci->op + XHCI_REG_OP_USBCMD, reg);
+
+ return 0U; /* Success */
+fail:
+ USB_LOG_ERR("Configure Roothub failed !!!\n");
+ usb_free(xhci->eseg);
+ usb_free(xhci->evts);
+ usb_free(xhci->cmds);
+ usb_free(xhci->devs);
+ return -1; /* Failed */
+}
+
+static void xhci_check_xcap(struct xhci_s *xhci)
+{
+ if (xhci->xcap) { /* read Extended Capabilities */
+ uint32_t off;
+ unsigned long addr = xhci->base + xhci->xcap; /* start read ext-cap */
+
+ do {
+ unsigned long xcap = addr;
+ uint32_t ports, name, cap = readl(xcap + XHCI_REG_EXT_CAP_USBSPCF_OFFSET);
+ switch (XHCI_REG_EXT_CAP_CAP_ID_GET(cap)) {
+ case XHCI_EXT_CAP_ID_SUPPORT_PROTOCOL: /* 0x2, supported protocol */
+ name = readl(xcap + XHCI_REG_EXT_CAP_USBSPCFDEF_OFFSET);
+ ports = readl(xcap + XHCI_REG_EXT_CAP_USBSPCFDEF2_OFFSET);
+ uint8_t major = XHCI_USBSPCF_MAJOR_REVERSION_GET(cap);
+ uint8_t minor = XHCI_USBSPCF_MINOR_REVERSION_GET(cap);
+ uint8_t count = XHCI_USBSPCFDEF2_COMPATIBLE_PORT_CNT_GET(ports);
+ uint8_t start = XHCI_USBSPCFDEF2_COMPATIBLE_PORT_OFF_GET(ports);
+ USB_LOG_INFO("XHCI protocol %c%c%c%c %x.%02x"
+ ", %d ports (offset %d), def %x\n"
+ , (name >> 0) & 0xff
+ , (name >> 8) & 0xff
+ , (name >> 16) & 0xff
+ , (name >> 24) & 0xff /* Print string 'USB' */
+ , major, minor
+ , count, start
+ , ports >> 16);
+ if (name == XHCI_USBSPCFDEF_NAME_STRING_USB /* ASCII "USB " */) {
+ if (major == 2) {
+ xhci->usb2.start = start; /* USB 2.0 port range */
+ xhci->usb2.count = count;
+ }
+ if (major == 3) {
+ xhci->usb3.start = start; /* USB 3.0 port range */
+ xhci->usb3.count = count;
+ }
+ }
+ break;
+ default:
+ USB_LOG_INFO("XHCI extcap 0x%x @ %p\n",
+ XHCI_REG_EXT_CAP_CAP_ID_GET(cap), addr);
+ break;
+ }
+ off = XHCI_REG_EXT_NEXT_CAP_PTR_GET(cap);
+ addr += off << 2; /* addr of next ext-cap */
+ } while (off > 0);
+ }
+
+}
+
+static int xhci_controller_setup(struct xhci_s *xhci, unsigned long baseaddr)
+{
+ USB_LOG_INFO("%s@0x%x\n", __func__, baseaddr);
+
+ /* get register offset */
+ xhci_setup_mmio(xhci, baseaddr);
+ if (xhci->version < 0x96 || xhci->version > 0x120) {
+ USB_LOG_ERR("xHCI-0x%x not support\n", xhci->version);
+ return -1;
+ }
+
+ xhci_check_xcap(xhci);
+
+ uint32_t pagesize = readl(xhci->op + XHCI_REG_OP_PAGESIZE); /* get page-size */
+ USB_LOG_INFO("XHCI page size %d \n", (pagesize << CONFIG_XHCI_PAGE_SHIFT));
+ if (CONFIG_XHCI_PAGE_SIZE != (pagesize << CONFIG_XHCI_PAGE_SHIFT)) {
+ USB_LOG_ERR("XHCI driver does not support page size code %d\n"
+ , pagesize << CONFIG_XHCI_PAGE_SHIFT);
+ return -1;
+ }
+
+ USB_LOG_INFO("config XHCI ....\n");
+ if (xhci_controller_configure(xhci)) {
+ USB_LOG_ERR("init XHCI failed !!!\n");
+ return -1;
+ } else {
+ USB_LOG_INFO("init XHCI success !!!\n");
+ }
+
+ return 0;
+}
+
+struct xhci_pipe *xhci_event_process(struct xhci_s *xhci)
+{
+ struct xhci_pipe *work_pipe = NULL;
+ struct xhci_ring *evts = xhci->evts;
+
+ /* check and ack event */
+ for (;;) {
+ uint32_t nidx = evts->nidx; /* index of dequeue trb */
+ uint32_t cs = evts->cs; /* cycle state toggle by xHc */
+ struct xhci_trb *etrb = evts->ring + nidx; /* current trb */
+ uint32_t control = etrb->control; /* trb control field */
+
+ if ((control & TRB_C) != (cs ? 1 : 0)) /* if cycle state not toggle, no events need to handle */
+ break;
+
+ /* process event on etrb */
+ uint32_t evt_type = TRB_TYPE_GET(control);
+ uint32_t evt_cc = TRB_CC_GET(etrb->status); /* bit[31:24] completion code */
+
+ if (ER_PORT_STATUS_CHANGE == evt_type) {
+ /* bit[31:24] port id, the port num of root hub port that generated this event */
+ uint32_t port = TRB_PORT_ID_GET(etrb->ptr_low) - 1;
+ uint32_t portsc = xhci_readl_port(xhci, port, XHCI_REG_OP_PORTS_PORTSC); /* Read status */
+
+ xhci_print_port_state(__func__, port, portsc);
+ if (portsc & XHCI_REG_OP_PORTS_PORTSC_CSC) {
+ usbh_roothub_thread_wakeup(port + 1); /* wakeup when connection status changed */
+ }
+ } else if ((ER_COMMAND_COMPLETE == evt_type) || (ER_TRANSFER_COMPLETE == evt_type)) {
+ struct xhci_trb *rtrb = (void*)(unsigned long)etrb->ptr_low;
+ struct xhci_ring *ring = XHCI_RING(rtrb); /* to align addr is ring base */
+ struct xhci_trb *evt = &ring->evt; /* first event trb */
+ uint32_t eidx = rtrb - ring->ring + 1; /* calculate current evt trb index */
+
+ memcpy(evt, etrb, sizeof(*etrb)); /* copy current trb to cmd/transfer ring */
+ ring->eidx = eidx;
+
+ if (ER_COMMAND_COMPLETE == evt_type) {
+ work_pipe = (struct xhci_pipe *)cur_cmd_pipe;
+ } else if (ER_TRANSFER_COMPLETE == evt_type) {
+ /* xhci_pipe begin with reqs ring, therefore we get pipe instance from reqs ring */
+ work_pipe = (struct xhci_pipe *)(void *)ring;
+ }
+
+ if (work_pipe) {
+ if (work_pipe->waiter) {
+ work_pipe->waiter = false;
+ usb_osal_sem_give(work_pipe->waitsem);
+ }
+
+ if (work_pipe->urb) {
+ struct usbh_urb *cur_urb = work_pipe->urb;
+ cur_urb->errorcode = evt_cc;
+ /* bit [23:0] TRB Transfer length, residual number of bytes not transferred
+ for OUT, is the value of (len of trb) - (data bytes transmitted), '0' means successful
+ for IN, is the value of (len of trb) - (data bytes received),
+ if cc is Short Packet, value is the diff between expected trans size and actual recv bytes
+ if cc is other error, value is the diff between expected trans size and actual recv bytes */
+ cur_urb->actual_length += cur_urb->transfer_buffer_length -
+ TRB_TR_TRANS_LEN_SET(evt->status); /* bit [23:0] */
+ }
+ }
+ } else {
+ USB_LOG_ERR("%s: unknown event, type %d, cc %d\n",
+ __func__, evt_type, evt_cc);
+ }
+
+ /* move ring index, notify xhci */
+ nidx++; /* head to next trb */
+ if (nidx == XHCI_RING_ITEMS) {
+ nidx = 0; /* roll-back if reach end of list */
+ cs = cs ? 0 : 1;
+ evts->cs = cs; /* sw toggle cycle state */
+ }
+ evts->nidx = nidx;
+ uint64_t erdp = (uint64_t)(unsigned long)(evts->ring + nidx);
+ writeq(xhci->ir + XHCI_REG_RT_IR_ERDP, erdp | XHCI_REG_RT_IR_ERDP_EHB); /* bit[63:4] update current event ring dequeue pointer */
+ }
+
+ return work_pipe;
+}
+
+static struct xhci_inctx *xhci_alloc_inctx_config_ep(struct xhci_s *xhci, struct usbh_hubport *hport, int maxepid)
+{
+ USB_ASSERT(xhci && hport);
+
+ int size = (sizeof(struct xhci_inctx) * XHCI_INCTX_ENTRY_NUM) << xhci->context64;
+ struct xhci_inctx *in = usb_align(XHCI_INCTX_ALIGMENT << xhci->context64, size);
+ int devport = hport->port;
+
+ if (!in) {
+ USB_LOG_ERR("allocate memory failed !!!\n");
+ return NULL;
+ }
+ memset(in, 0, size);
+
+ struct xhci_slotctx *slot = (void*)&in[1 << xhci->context64]; /* slot context */
+ slot->ctx[0] |= XHCI_SLOTCTX_0_MAX_EPID_SET(maxepid); /* bit[31:27] index of the last valid ep context */
+ slot->ctx[0] |= XHCI_SLOTCTX_0_SPEED_SET(speed_to_xhci[hport->speed]); /* bit[23:20] speed of this device */
+
+ /* Set high-speed hub flags. */
+ struct usbh_hub *hubdev = hport->parent;
+ USB_ASSERT(hubdev);
+ if (!hubdev->is_roothub) { /* if device is not under roothub */
+ /* Is this the first high-speed hub with a non-high-speed device following in chain */
+ struct usbh_hubport *hub_port = hubdev->parent;
+ if (hport->speed == USB_SPEED_LOW || hport->speed == USB_SPEED_FULL) {
+ if (hub_port->speed == USB_SPEED_HIGH) {
+ slot->ctx[2] |= XHCI_SLOTCTX_2_HUB_SLOT_SET(hub_port->dev_addr); /* bit[7:0] parent hub slot id */
+ slot->ctx[2] |= XHCI_SLOTCTX_2_HUB_PORT_SET(hport->port); /* bit[15:8] parent port num */
+ slot->ctx[0] |= XHCI_SLOTCTX_0_MULTI_TT;
+ } else {
+ struct xhci_slotctx *hslot = (void*)(unsigned long)xhci->devs[hub_port->dev_addr].ptr_low;
+ slot->ctx[2] = hslot->ctx[2]; /* 08h, copy hub slot context */
+ }
+ }
+
+ uint32_t route = 0U;
+ do {
+ route <<= 4;
+ route |= (hport->port) & 0xf; /* record port for each tire */
+
+ hport = hubdev->parent;
+ hubdev = hport->parent;
+ } while ((!hubdev) || (!hubdev->is_roothub));
+
+ slot->ctx[0] |= XHCI_SLOTCTX_0_ROUTE_SET(route); /* bit[19:0] route string, max 5 tires */
+ }
+
+ /* refer to spec. Ports are numbered from 1 to MaxPorts. */
+ slot->ctx[1] |= XHCI_SLOTCTX_1_ROOT_PORT_SET(hport->port); /* bit[23:16] root hub port number */
+
+ return in;
+}
+
+/* allocate input context to update max packet size of endpoint-0 */
+static struct xhci_inctx *xhci_alloc_inctx_set_ep_mps(struct xhci_s *xhci, uint32_t slotid, uint16_t ep_mps)
+{
+ USB_ASSERT(xhci);
+
+ int size = (sizeof(struct xhci_inctx) * XHCI_INCTX_ENTRY_NUM) << xhci->context64;
+ struct xhci_inctx *in = usb_align(XHCI_INCTX_ALIGMENT << xhci->context64, size);
+ if (!in) {
+ USB_LOG_ERR("allocate memory failed !!!\n");
+ return NULL;
+ }
+ memset(in, 0, size);
+
+ /* copy 32 entries after inctx controller field from devctx to inctx */
+#ifdef XHCI_AARCH64
+ struct xhci_slotctx *devctx = (struct xhci_slotctx *)(((uint64_t)xhci->devs[slotid].ptr_high << 32U) |
+ ((uint64_t)xhci->devs[slotid].ptr_low));
+#else
+ struct xhci_slotctx *devctx = (struct xhci_slotctx *)(unsigned long)xhci->devs[slotid].ptr_low;
+#endif
+ struct xhci_slotctx *input_devctx = (void*)&in[1 << xhci->context64];
+
+ memcpy(input_devctx, devctx, XHCI_SLOTCTX_ENTRY_NUM * sizeof(struct xhci_slotctx));
+
+ /*
+ input ctrl context
+ slot
+ ep-0 context, offset = 2 * xhci->context64, e.g, for 64 bit (0x40), offset = 0x80
+ */
+ struct xhci_epctx *ep = (void*)&in[2 << xhci->context64]; /* ep context */
+ ep->ctx[1] |= XHCI_EPCTX_1_MPS_SET(ep_mps); /* bit[31:16] update maxpacket size */
+
+ return in;
+}
+
+static struct xhci_inctx *xhci_alloc_inctx_enable_hub_func(struct xhci_s *xhci, uint32_t slotid, struct xhci_hubinfo *hub_info)
+{
+ USB_ASSERT(xhci);
+
+ int size = (sizeof(struct xhci_inctx) * XHCI_INCTX_ENTRY_NUM) << xhci->context64;
+ struct xhci_inctx *in = usb_align(XHCI_INCTX_ALIGMENT << xhci->context64, size);
+ if (!in) {
+ USB_LOG_ERR("allocate memory failed !!!\n");
+ return NULL;
+ }
+ memset(in, 0, size);
+
+ /* copy 32 entries after inctx controller field from devctx to inctx */
+#ifdef XHCI_AARCH64
+ struct xhci_slotctx *devctx = (struct xhci_slotctx *)(((uint64_t)xhci->devs[slotid].ptr_high << 32U) |
+ ((uint64_t)xhci->devs[slotid].ptr_low));
+#else
+ struct xhci_slotctx *devctx = (struct xhci_slotctx *)(unsigned long)xhci->devs[slotid].ptr_low;
+#endif
+ struct xhci_slotctx *input_devctx = (void*)&in[1 << xhci->context64];
+
+ memcpy(input_devctx, devctx, XHCI_SLOTCTX_ENTRY_NUM * sizeof(struct xhci_slotctx));
+
+ input_devctx->ctx[0] |= XHCI_SLOTCTX_0_MAX_EPID_SET(XHCI_SLOTCTX_ENTRY_NUM);
+ input_devctx->ctx[0] |= XHCI_SLOTCTX_0_HUB;
+ input_devctx->ctx[0] |= XHCI_SLOTCTX_0_SPEED_SET(hub_info->speed);
+ input_devctx->ctx[1] |= XHCI_SLOTCTX_1_PORTS_NUM_SET(hub_info->num_of_ports);
+
+ if (hub_info->speed == USB_SPEED_HIGH) {
+ input_devctx->ctx[0] |= hub_info->has_multiple_tts ? XHCI_SLOTCTX_0_MULTI_TT : 0U;
+ input_devctx->ctx[2] |= XHCI_SLOTCTX_2_TTT_THINK_SET(hub_info->tt_think_time);
+ }
+
+ return in;
+}
+
+/* Submit a USB "setup" message request to the pipe's ring */
+static void xhci_xfer_setup(struct xhci_s *xhci, struct xhci_pipe *pipe,
+ bool dir_in, void *cmd, void *data, int datalen)
+{
+ /* SETUP TRB ctrl, bit[15:10] trb type
+ bit[6] Immediate Data (IDT), parameters take effect
+ bit[17:16] Transfer type, 2 = OUT Data, 3 = IN Data */
+ uint32_t trans_type = (datalen > 0) ? (dir_in ? TRB_TR_IN_DATA : TRB_TR_OUT_DATA): TRB_TR_NO_DATA;
+ xhci_trb_queue(&pipe->reqs, cmd, USB_SIZEOF_SETUP_PACKET,
+ TRB_TYPE_SET(TR_SETUP) | TRB_TR_IDT | TRB_TR_TYPE_SET(trans_type));
+
+ /* DATA TRB ctrl, bit[15:10] trb type
+ bit[16] Direction, 0 = OUT, 1 = IN */
+ if (datalen) {
+ xhci_trb_queue(&pipe->reqs, data, datalen,
+ TRB_TYPE_SET(TR_DATA) | (dir_in ? TRB_TR_DIR : 0));
+ }
+
+ /* STATUS TRB ctrl, bit[5] Interrupt On Completion (IOC).
+ bit[16] Direction, 0 = OUT, 1 = IN */
+ xhci_trb_queue(&pipe->reqs, NULL, 0,
+ TRB_TYPE_SET(TR_STATUS) | TRB_TR_IOC | ((dir_in ? 0 : TRB_TR_DIR)));
+
+ /* pass command trb to hardware */
+ DSB();
+
+ /* notfiy xHc that device slot - epid */
+ xhci_doorbell(xhci, pipe->slotid, pipe->epid);
+}
+
+/* Submit a USB transfer request to the pipe's ring */
+static void xhci_xfer_normal(struct xhci_s *xhci, struct xhci_pipe *pipe,
+ void *data, int datalen)
+{
+ /* Normal trb, used in bulk and interrupt transfer */
+ xhci_trb_queue(&pipe->reqs, data, datalen, TRB_TYPE_SET(TR_NORMAL) | TRB_TR_IOC);
+
+ /* pass command trb to hardware */
+ DSB();
+
+ xhci_doorbell(xhci, pipe->slotid, pipe->epid);
+}
+
+/* -------------------------------------------------------------- */
+/* port functions */
+static struct xhci_s xhci_host;
+
+__WEAK void usb_hc_low_level_init(void)
+{
+}
+
+__WEAK void *usb_hc_malloc(size_t size)
+{
+ return NULL;
+}
+
+__WEAK void *usb_hc_malloc_align(size_t align, size_t size)
+{
+ return NULL;
+}
+
+__WEAK void usb_hc_free()
+{
+}
+
+/* one may get xhci register base address by PCIe bus emuration */
+__WEAK unsigned long usb_hc_get_register_base(void)
+{
+ return 0U;
+}
+
+int usb_hc_init(void)
+{
+ usb_hc_low_level_init();
+
+ memset(&xhci_host, 0, sizeof(xhci_host));
+ if (xhci_controller_setup(&xhci_host, usb_hc_get_register_base()))
+ return -1;
+
+ return 0;
+}
+
+int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
+{
+ uint8_t nports;
+ uint8_t port;
+ uint32_t portsc;
+ uint32_t status;
+ int ret = 0;
+ struct xhci_s *xhci = &xhci_host;
+
+ nports = CONFIG_USBHOST_MAX_RHPORTS;
+
+ port = setup->wIndex;
+ if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) {
+ switch (setup->bRequest) {
+ case HUB_REQUEST_CLEAR_FEATURE:
+ switch (setup->wValue) {
+ case HUB_FEATURE_HUB_C_LOCALPOWER:
+ break;
+ case HUB_FEATURE_HUB_C_OVERCURRENT:
+ break;
+ default:
+ return -EPIPE;
+ }
+ break;
+ case HUB_REQUEST_SET_FEATURE:
+ switch (setup->wValue) {
+ case HUB_FEATURE_HUB_C_LOCALPOWER:
+ break;
+ case HUB_FEATURE_HUB_C_OVERCURRENT:
+ break;
+ default:
+ return -EPIPE;
+ }
+ break;
+ case HUB_REQUEST_GET_DESCRIPTOR:
+ USB_LOG_ERR("HUB_REQUEST_GET_DESCRIPTOR not implmented \n");
+ break;
+ case HUB_REQUEST_GET_STATUS:
+ memset(buf, 0, 4);
+ break;
+ default:
+ break;
+ }
+ } else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER) {
+ switch (setup->bRequest) {
+ case HUB_REQUEST_CLEAR_FEATURE:
+ if (!port || port > nports) {
+ return -EPIPE;
+ }
+
+ portsc = xhci_readl_port(xhci, port - 1, XHCI_REG_OP_PORTS_PORTSC);
+
+ switch (setup->wValue) {
+ case HUB_PORT_FEATURE_ENABLE:
+ break;
+ case HUB_PORT_FEATURE_SUSPEND:
+ case HUB_PORT_FEATURE_C_SUSPEND:
+ break;
+ case HUB_PORT_FEATURE_POWER:
+ break;
+ case HUB_PORT_FEATURE_C_CONNECTION:
+ portsc |= XHCI_REG_OP_PORTS_PORTSC_CSC;
+ break;
+ case HUB_PORT_FEATURE_C_ENABLE:
+ portsc |= XHCI_REG_OP_PORTS_PORTSC_PEC;
+ break;
+ case HUB_PORT_FEATURE_C_OVER_CURREN:
+ break;
+ case HUB_PORT_FEATURE_C_RESET:
+ break;
+ default:
+ return -EPIPE;
+ }
+
+ uint32_t pclear = portsc & XHCI_REG_OP_PORTS_PORTSC_RW_MASK;
+ xhci_writel_port(xhci, port - 1, XHCI_REG_OP_PORTS_PORTSC, pclear); /* clear port status */
+
+ break;
+ case HUB_REQUEST_SET_FEATURE:
+ if (!port || port > nports) {
+ return -EPIPE;
+ }
+
+ switch (setup->wValue) {
+ case HUB_PORT_FEATURE_SUSPEND:
+ break;
+ case HUB_PORT_FEATURE_POWER:
+ break;
+ case HUB_PORT_FEATURE_RESET:
+ ret = xhci_hub_reset(xhci, port - 1);
+ break;
+
+ default:
+ return -EPIPE;
+ }
+ break;
+ case HUB_REQUEST_GET_STATUS:
+ if (!port || port > nports) {
+ return -EPIPE;
+ }
+
+ portsc = xhci_readl_port(xhci, port - 1, XHCI_REG_OP_PORTS_PORTSC);
+
+ status = 0;
+ if (portsc & XHCI_REG_OP_PORTS_PORTSC_CSC) {
+ /* Port connection status changed */
+ status |= (1 << HUB_PORT_FEATURE_C_CONNECTION);
+ }
+
+ if (portsc & XHCI_REG_OP_PORTS_PORTSC_PEC) {
+ /* Port enabled status changed */
+ status |= (1 << HUB_PORT_FEATURE_C_ENABLE);
+ }
+
+ if (portsc & XHCI_REG_OP_PORTS_PORTSC_OCC) {
+ /* Port status changed due to over-current */
+ status |= (1 << HUB_PORT_FEATURE_C_OVER_CURREN);
+ }
+
+ if (portsc & XHCI_REG_OP_PORTS_PORTSC_CCS) {
+ /* Port connected */
+ status |= (1 << HUB_PORT_FEATURE_CONNECTION);
+ }
+
+ if (portsc & XHCI_REG_OP_PORTS_PORTSC_PED) {
+ /* Port enabled */
+ status |= (1 << HUB_PORT_FEATURE_ENABLE);
+
+ const int speed = speed_from_xhci[XHCI_REG_OP_PORTS_PORTSC_PORT_SPEED_GET(portsc)];
+ if (speed == USB_SPEED_LOW) {
+ status |= (1 << HUB_PORT_FEATURE_LOWSPEED);
+ } else if ((speed == USB_SPEED_HIGH) || (speed == USB_SPEED_SUPER) ||
+ (speed == USB_SPEED_FULL)) {
+ status |= (1 << HUB_PORT_FEATURE_HIGHSPEED);
+ }
+ }
+
+ if (portsc & XHCI_REG_OP_PORTS_PORTSC_OCA) {
+ /* Over-current condition */
+ status |= (1 << HUB_PORT_FEATURE_OVERCURRENT);
+ }
+
+ if (portsc & XHCI_REG_OP_PORTS_PORTSC_PR) {
+ /* Reset is in progress */
+ status |= (1 << HUB_PORT_FEATURE_RESET);
+ }
+
+ if (portsc & XHCI_REG_OP_PORTS_PORTSC_PP) {
+ /* Port is not power off */
+ status |= (1 << HUB_PORT_FEATURE_POWER);
+ }
+ memcpy(buf, &status, 4);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int usbh_get_xhci_devaddr(usbh_pipe_t *pipe)
+{
+ struct xhci_pipe *ppipe = (struct xhci_pipe *)pipe;
+ return ppipe->slotid;
+}
+
+int usbh_ep0_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed)
+{
+ int ret = 0;
+ struct xhci_s *xhci = &xhci_host;
+ struct xhci_pipe *ppipe = (struct xhci_pipe *)pipe;
+ int oldmaxpacket = ppipe->maxpacket; /* original max packetsz */
+
+ if (ep_mps != oldmaxpacket) {
+ /* maxpacket has changed on control endpoint - update controller. */
+ USB_LOG_DBG("update ep0 mps from %d to %d\r\n", oldmaxpacket, ep_mps);
+ struct xhci_inctx *in = xhci_alloc_inctx_set_ep_mps(xhci, ppipe->slotid, ep_mps); /* allocate input context */
+ if (!in)
+ return -1;
+
+ in->add = (1 << 1); /* update ep0 context */
+ in->del = (1 << 1);
+
+ usb_hc_dcache_invalidate(in, sizeof(struct xhci_inctx) * XHCI_INCTX_ENTRY_NUM);
+ xhci_dump_input_ctx(xhci, in);
+
+ int cc = xhci_cmd_evaluate_context(xhci, ppipe, in);
+ if (cc != CC_SUCCESS) {
+ USB_LOG_ERR("%s: reconf ctl endpoint: failed (cc %d) (mps %d => %d)\n",
+ __func__, cc, oldmaxpacket, ep_mps);
+ ret = -1;
+ } else {
+ ppipe->maxpacket = ep_mps; /* mps update success */
+ }
+
+ usb_free(in);
+ }
+
+ return ret;
+}
+
+static int usbh_get_period(int speed, int interval)
+{
+ if (speed != USB_SPEED_HIGH){
+ /* fls - find last (most-significant) bit set */
+ return (interval <= 4) ? 0 : fls(interval);
+ }
+
+ return (interval <= 4) ? 0 : interval - 4;
+}
+
+int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
+{
+ int ret = 0;
+ struct xhci_s *xhci = &xhci_host;
+ struct xhci_pipe *ppipe = usb_align(XHCI_RING_SIZE, sizeof(struct xhci_pipe));
+ struct usbh_hubport *hport = ep_cfg->hport;
+
+ uint32_t epid = 0U;
+ uint8_t eptype = 0U;
+
+ if (ppipe == NULL) {
+ return -ENOMEM;
+ }
+
+ memset(ppipe, 0, sizeof(struct xhci_pipe));
+
+ ppipe->epaddr = ep_cfg->ep_addr;
+ if (ep_cfg->ep_addr == 0) {
+ epid = 1; /* ep0, ep_id = 1 */
+ } else {
+ /* refer to spec. Figure 4-4: Endpoint Context Addressing
+ ep0 = 1, ep1-out = 2, ep1-in = 3, ... ep15-out = 30, ep15-in = 31 */
+ epid = (ep_cfg->ep_addr & 0x0f) * 2;
+ epid += (ep_cfg->ep_addr & USB_EP_DIR_IN) ? 1 : 0;
+ }
+ ppipe->epid = epid;
+ eptype = ep_cfg->ep_type;
+ ppipe->eptype = eptype;
+ ppipe->maxpacket = ep_cfg->ep_mps;
+ ppipe->interval = ep_cfg->ep_interval;
+ ppipe->speed = ep_cfg->hport->speed;
+ ppipe->hport = ep_cfg->hport;
+ ppipe->waitsem = usb_osal_sem_create(0);
+ ppipe->waiter = false;
+ ppipe->urb = NULL;
+
+ USB_LOG_DBG("%s epid = %d, epaddr = 0x%x eptype = %d, mps = %d, speed = %d, urb = %p\n",
+ __func__, ppipe->epid, ppipe->epaddr, ppipe->eptype, ppipe->maxpacket,
+ ppipe->speed, ppipe->urb);
+
+ ppipe->reqs.cs = 1; /* cycle state = 1 */
+
+ /* Allocate input context and initialize endpoint info. */
+ struct xhci_inctx *in = xhci_alloc_inctx_config_ep(xhci, hport, epid);
+ if (!in){
+ ret = -1;
+ goto fail;
+ }
+
+ if (ppipe->epid == 1) {
+ /* address device */
+ in->add = 0x01 /* Slot Context */ | (1 << epid); /* EP Context */
+ } else {
+ /* config endpoint */
+ in->add = (1 << epid);
+ in->del = (1 << epid);
+ }
+
+ struct xhci_epctx *ep = (void *)&in[(epid + 1) << xhci->context64];
+ if (eptype == USB_ENDPOINT_TYPE_INTERRUPT)
+ ep->ctx[0] = XHCI_EPCTX_0_INTERVAL_SET(usbh_get_period(ppipe->speed, ppipe->interval) + 3); /* bit[23:16] for interrupt ep, set interval to control interrupt period */
+
+ /*
+ Value Endpoint Type Direction
+ 0 Not Valid N/A
+ 1 Isoch Out
+ 2 Bulk Out
+ 3 Interrupt Out
+ 4 Control Bidirectional
+ 5 Isoch In
+ 6 Bulk In
+ 7 Interrupt In
+ */
+ ep->ctx[1] |= eptype << 3; /* bit[5:3] endpoint type */
+ if (ppipe->epaddr & USB_EP_DIR_IN || eptype == USB_ENDPOINT_TYPE_CONTROL)
+ ep->ctx[1] |= 1 << 5; /* ep_type 4 ~ 7 */
+
+ ep->ctx[1] |= XHCI_EPCTX_1_MPS_SET(ppipe->maxpacket); /* bit[31:16] max packet size */
+ if (eptype == USB_ENDPOINT_TYPE_INTERRUPT)
+ ep->ctx[1] |= XHCI_EPCTX_1_CERR_SET(3);
+
+ ep->deq_low = (uint32_t)((unsigned long)&ppipe->reqs.ring[0]); /* bit[63:4] tr dequeue pointer */
+ ep->deq_low |= 1; /* bit[0] dequeue cycle state */
+#ifdef XHCI_AARCH64
+ ep->deq_high = (uint32_t)((uint64_t)&ppipe->reqs.ring[0] >> 32U);
+#else
+ ep->deq_high = 0U;
+#endif
+
+ if (eptype == USB_ENDPOINT_TYPE_BULK){
+ ep->length = XHCI_EPCTX_AVE_TRB_LEN_SET(256U); /* bit[15:0] average trb length */
+
+ } else if (eptype == USB_ENDPOINT_TYPE_INTERRUPT){
+ ep->length = XHCI_EPCTX_AVE_TRB_LEN_SET(16U) | /* bit[15:0] average trb length */
+ XHCI_EPCTX_MAX_ESIT_SET(ppipe->maxpacket); /* bit[31:16] max ESIT payload */
+ }
+
+ if (ppipe->epid == 1) { /* when allocate ep-0, allocate device first */
+ struct usbh_hub *hubdev = hport->parent;
+ if (!hubdev->is_roothub){
+ /* make sure parent hub has been configured */
+ struct usbh_hubport *hubport = hubdev->parent;
+ struct xhci_pipe *hubep0 = (struct xhci_pipe *)hubport->ep0;
+ struct xhci_slotctx *hdslot = (void*)(unsigned long)xhci->devs[hubep0->slotid].ptr_low;
+ if (XHCI_SLOTCTX_3_SLOT_STATE_GET(hdslot->ctx[3]) != XHCI_SLOT_CONFIG) { /* bit [31:27] slot state, 3 means configured */
+ USB_LOG_ERR("%s parent hub-%d not yet configured\n", __func__, hubep0->slotid);
+ ret = -1;
+ goto fail;
+ }
+ }
+
+ /* enable slot. */
+ size_t size = (sizeof(struct xhci_slotctx) * XHCI_SLOTCTX_ENTRY_NUM) << xhci->context64;
+ struct xhci_slotctx *dev = usb_align(XHCI_SLOTCTX_ALIGMENT << xhci->context64, size);
+ if (!dev) {
+ USB_LOG_ERR("allocate memory failed !!!\n");
+ ret = -1;
+ goto fail;
+ }
+
+ /* send nop command to test if command ring ok */
+ for (int i = 0 ; i < 3; ++i) {
+ int cc = xhci_cmd_nop(xhci, ppipe);
+ if (cc != CC_SUCCESS) {
+ USB_LOG_ERR("%s: nop: failed\n", __func__);
+ usb_free(dev);
+ ret = -1;
+ goto fail;
+ }
+ }
+
+ int slotid = xhci_cmd_enable_slot(xhci, ppipe); /* get slot-id */
+ if (slotid < 0) {
+ USB_LOG_ERR("%s: enable slot: failed\n", __func__);
+ usb_free(dev);
+ ret = -1;
+ goto fail;
+ }
+
+ ppipe->slotid = slotid;
+ USB_LOG_DBG("%s: enable slot: got slotid %d\n", __func__, ppipe->slotid);
+ memset(dev, 0, size);
+ xhci->devs[slotid].ptr_low = (uint32_t)(unsigned long)dev; /* DCBAA */
+#ifdef XHCI_AARCH64
+ xhci->devs[slotid].ptr_high = (uint32_t)((uint64_t)dev >> 32U);
+#else
+ xhci->devs[slotid].ptr_high = 0;
+#endif
+
+ usb_hc_dcache_invalidate(in, sizeof(struct xhci_inctx) * XHCI_INCTX_ENTRY_NUM);
+
+ /* Send set_address command. */
+ int cc = xhci_cmd_address_device(xhci, ppipe, in);
+ if (cc != CC_SUCCESS) {
+ USB_LOG_ERR("%s: address device: failed (cc %d)\n", __func__, cc);
+ cc = xhci_cmd_disable_slot(xhci, ppipe);
+ if (cc != CC_SUCCESS) {
+ USB_LOG_ERR("%s: disable failed (cc %d)\n", __func__, cc);
+ ret = -1;
+ goto fail;
+ }
+
+ xhci->devs[slotid].ptr_low = 0; /* free DCBAA */
+ xhci->devs[slotid].ptr_high = 0;
+ usb_free(dev);
+
+ ret = -1;
+ goto fail;
+ }
+ } else { /* when allocate other ep, config ep */
+ struct xhci_pipe *defpipe = (struct xhci_pipe *)hport->ep0;
+ ppipe->slotid = defpipe->slotid;
+
+ /* handle hub device */
+ struct usb_device_descriptor *device_desc = &hport->device_desc;
+ if (device_desc->bDeviceClass == USB_DEVICE_CLASS_HUB) {
+ /* enable hub function */
+ struct usb_interface_descriptor *intf = &hport->config.intf[0U].altsetting[0U].intf_desc;
+ struct usbh_hub *this_hub = hport->config.intf[0U].priv;
+ USB_ASSERT(this_hub);
+ struct usb_hub_descriptor *hub_desc = &this_hub->hub_desc;
+ struct xhci_hubinfo hub_info = {0};
+
+#define HUB_TT_THINK_TIME(reg) (((reg) >> 5) & 3)
+
+ hub_info.num_of_ports = hub_desc->bNbrPorts;
+ hub_info.has_multiple_tts = (intf->bInterfaceProtocol == 2);
+ hub_info.tt_think_time = ((hub_desc->wHubCharacteristics) & HUB_CHAR_TTTT_MASK) >> HUB_CHAR_TTTT_SHIFT;
+ hub_info.speed = hport->speed;
+
+ USB_LOG_INFO("enable hub function, num_of_ports=%d, multi_tt=%d, tt_think=%d, speed=%d\r\n",
+ hub_info.num_of_ports,
+ hub_info.has_multiple_tts,
+ hub_info.tt_think_time,
+ hub_info.speed);
+ struct xhci_inctx *inctx_hub = xhci_alloc_inctx_enable_hub_func(xhci, ppipe->slotid, &hub_info);
+
+ inctx_hub->add = 0x01;
+ inctx_hub->del = 0x01;
+
+ usb_hc_dcache_invalidate(in, sizeof(struct xhci_inctx) * XHCI_INCTX_ENTRY_NUM);
+ if (CC_SUCCESS != xhci_cmd_evaluate_context(xhci, ppipe, inctx_hub)) {
+ USB_LOG_ERR("cannot enable hub function\r\n");
+ }
+
+ usb_free(inctx_hub);
+ }
+
+ /* reset if endpoint is not running */
+#ifdef XHCI_AARCH64
+ struct xhci_slotctx *devctx = (struct xhci_slotctx *)(((uint64_t)xhci->devs[ppipe->slotid].ptr_high << 32U) |
+ ((uint64_t)xhci->devs[ppipe->slotid].ptr_low));
+#else
+ struct xhci_slotctx *devctx = (struct xhci_slotctx *)(unsigned long)xhci->devs[ppipe->slotid].ptr_low;
+#endif
+ struct xhci_epctx *epctx = (void*)&devctx[epid << xhci->context64]; /* ep0 context */
+ uint32_t epstate = XHCI_EPCTX_0_EP_STATE_GET(epctx->ctx[0]);
+ int cc;
+
+
+ /* Reset endpoint in case it is not running */
+ if (epstate > 1){
+ cc = xhci_cmd_reset_endpoint(xhci, ppipe);
+ if (cc != CC_SUCCESS) {
+ USB_LOG_ERR("%s: reset endpoint: failed (cc %d)\n", __func__, cc);
+ ret = -1;
+ goto fail;
+ }
+ }
+
+ usb_hc_dcache_invalidate(in, sizeof(struct xhci_inctx) * XHCI_INCTX_ENTRY_NUM);
+ xhci_dump_input_ctx(xhci, in);
+
+ /* Send configure command. */
+ cc = xhci_cmd_configure_endpoint(xhci, ppipe, in, false);
+ if (cc != CC_SUCCESS) {
+ epctx = (void*)&devctx[epid << xhci->context64]; /* ep0 context */
+ epstate = XHCI_EPCTX_0_EP_STATE_GET(epctx->ctx[0]);
+ USB_LOG_ERR("%s: configure endpoint: failed (cc %d, epstate %d)\n", __func__, cc, epstate);
+ ret = -1;
+ goto fail;
+ }
+ }
+
+ *pipe = (usbh_pipe_t)ppipe;
+
+fail:
+ usb_free(in);
+ return ret;
+}
+
+int usbh_pipe_free(usbh_pipe_t pipe)
+{
+ int ret = 0;
+ struct xhci_s *xhci = &xhci_host;
+ struct xhci_pipe *ppipe = (struct xhci_pipe *)pipe;
+
+ if (!ppipe) {
+ return -EINVAL;
+ }
+
+ struct usbh_urb *urb = ppipe->urb;
+
+ if (urb) {
+ usbh_kill_urb(urb);
+ }
+
+ return -1;
+}
+
+int usbh_submit_urb(struct usbh_urb *urb)
+{
+ int ret = 0;
+ if (!urb || !urb->pipe) {
+ return -EINVAL;
+ }
+
+ struct xhci_s *xhci = &xhci_host;
+ struct xhci_pipe *ppipe = urb->pipe;
+ struct usb_setup_packet *setup = urb->setup;
+ size_t flags;
+
+ flags = usb_osal_enter_critical_section();
+
+ urb->errorcode = -EBUSY;
+ urb->actual_length = 0U;
+
+ ppipe->waiter = false;
+ ppipe->urb = urb;
+ ppipe->timeout = urb->timeout;
+
+ if (ppipe->timeout > 0) {
+ ppipe->waiter = true;
+ }
+
+ usb_osal_leave_critical_section(flags);
+ switch (ppipe->eptype){
+ case USB_ENDPOINT_TYPE_CONTROL:
+ USB_ASSERT(setup);
+ if (setup->bRequest == USB_REQUEST_SET_ADDRESS){
+ /* Set address command sent during xhci_alloc_pipe. */
+ goto skip_req;
+ }
+
+ USB_LOG_DBG("%s request-%d\n", __func__, setup->bRequest);
+ /* send setup in/out for command */
+ xhci_xfer_setup(xhci, ppipe, setup->bmRequestType & USB_EP_DIR_IN, (void*)setup,
+ urb->transfer_buffer, urb->transfer_buffer_length);
+ break;
+ case USB_ENDPOINT_TYPE_INTERRUPT:
+ case USB_ENDPOINT_TYPE_BULK:
+ xhci_xfer_normal(xhci, ppipe, urb->transfer_buffer, urb->transfer_buffer_length);
+ break;
+ default:
+ USB_ASSERT(0U);
+ break;
+ }
+
+ /* wait all ring handled by xHc */
+ int cc = xhci_event_wait(xhci, ppipe, &ppipe->reqs);
+ if ((cc != CC_SUCCESS) &&
+ !((cc == CC_TIMEOUT) && (ppipe->eptype == USB_ENDPOINT_TYPE_INTERRUPT))) {
+ /* ignore transfer timeout for interrupt type */
+ USB_LOG_ERR("%s: xfer failed (cc %d)\n", __func__, cc);
+ ret = -1;
+ urb->errorcode = cc;
+ goto errout_timeout;
+ }
+
+skip_req:
+errout_timeout:
+ /* Timeout will run here */
+ usbh_kill_urb(urb);
+ return ret;
+}
+
+int usbh_kill_urb(struct usbh_urb *urb)
+{
+ return 0;
+}
+
+void USBH_IRQHandler(void)
+{
+ uint32_t reg, status;
+ struct xhci_s *xhci = &xhci_host;
+ struct xhci_pipe *work_pipe = NULL;
+
+ USB_LOG_DBG("%s\n", __func__);
+
+ status = readl(xhci->op + XHCI_REG_OP_USBSTS);
+ status |= XHCI_REG_OP_USBSTS_EINT; /* clear interrupt status */
+ writel(xhci->op + XHCI_REG_OP_USBSTS, status);
+
+ reg = readl(xhci->ir + XHCI_REG_RT_IR_IMAN);
+ reg |= XHCI_REG_RT_IR_IMAN_IP; /* ack interrupt */
+ writel(xhci->ir + XHCI_REG_RT_IR_IMAN, reg);
+
+ work_pipe = xhci_event_process(xhci);
+
+ /* handle callbacks in interrupt */
+ if ((work_pipe) && (work_pipe->urb)) {
+ struct usbh_urb *cur_urb = work_pipe->urb;
+ if (cur_urb->complete) {
+ if (cur_urb->errorcode < 0) {
+ cur_urb->complete(cur_urb->arg, cur_urb->errorcode);
+ } else {
+ cur_urb->complete(cur_urb->arg, cur_urb->actual_length);
+ }
+ }
+ }
+
+ USB_LOG_DBG("%s exit\n", __func__);
+ return;
+}
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/port/xhci/usb_hc_xhci.h b/third-party/cherryusb-0.6.0/port/xhci/usb_hc_xhci.h
new file mode 100644
index 0000000000000000000000000000000000000000..d01c00f251eda4e0c9ad436b769f207cdefffc78
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/port/xhci/usb_hc_xhci.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: usb_hc_xhci.h
+ * Date: 2022-07-19 09:26:25
+ * LastEditTime: 2022-07-19 09:26:25
+ * Description: This files is for xhci data structure definition
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ * 1.0 zhugengyu 2022/9/19 init commit
+ */
+#ifndef USB_HC_XHCI_H
+#define USB_HC_XHCI_H
+
+/***************************** Include Files *********************************/
+#include "usbh_core.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/************************** Constant Definitions *****************************/
+
+/************************** Type Definitions *****************************/
+/* slot context */
+struct xhci_slotctx {
+ uint32_t ctx[4];
+#define XHCI_SLOTCTX_0_ROUTE_SET(route) XHCI32_SET_BITS(route, 19, 0)
+#define XHCI_SLOTCTX_0_ROUTE_GET(route) XHCI32_GET_BITS(route, 19, 0)
+#define XHCI_SLOTCTX_0_MAX_EPID_SET(maxid) XHCI32_SET_BITS(maxid, 31, 27)
+#define XHCI_SLOTCTX_0_SPEED_SET(speed) XHCI32_SET_BITS(speed, 23, 20)
+#define XHCI_SLOTCTX_0_MULTI_TT (1 << 25U)
+#define XHCI_SLOTCTX_0_HUB (1 << 26U)
+
+#define XHCI_SLOTCTX_1_ROOT_PORT_GET(val) XHCI32_GET_BITS(val, 23, 16)
+#define XHCI_SLOTCTX_1_ROOT_PORT_SET(port) XHCI32_SET_BITS(port, 23, 16)
+#define XHCI_SLOTCTX_1_PORTS_NUM_SET(ports) XHCI32_SET_BITS(ports, 31, 24)
+#define XHCI_SLOTCTX_1_PORTS_NUM_GET(val) XHCI32_GET_BITS(val, 31, 24)
+
+#define XHCI_SLOTCTX_2_HUB_SLOT_SET(slot) XHCI32_SET_BITS(slot, 7, 0)
+#define XHCI_SLOTCTX_2_HUB_SLOT_GET(slot) XHCI32_GET_BITS(slot, 7, 0)
+#define XHCI_SLOTCTX_2_HUB_PORT_SET(port) XHCI32_SET_BITS(port, 15, 8)
+#define XHCI_SLOTCTX_2_HUB_PORT_GET(port) XHCI32_GET_BITS(port, 15, 8)
+#define XHCI_SLOTCTX_2_TTT_THINK_SET(ttt) XHCI32_SET_BITS(ttt, 17, 16)
+
+#define XHCI_SLOTCTX_3_SLOT_STATE_GET(ctx) XHCI32_GET_BITS(ctx, 31, 27)
+ uint32_t reserved_01[4];
+#define XHCI_SLOTCTX_ENTRY_NUM 32U
+#define XHCI_SLOTCTX_ALIGMENT 1024U
+} __PACKED;
+
+enum xhci_slot_state {
+ XHCI_SLOT_DEFAULT = 1,
+ XHCI_SLOT_ADDRESS = 2,
+ XHCI_SLOT_CONFIG = 3
+};
+
+/* endpoint context */
+struct xhci_epctx {
+ uint32_t ctx[2];
+#define XHCI_EPCTX_0_EP_STATE_GET(ctx) XHCI32_GET_BITS(ctx, 2, 0)
+#define XHCI_EPCTX_0_INTERVAL_SET(interval) XHCI32_SET_BITS(interval, 23, 16)
+#define XHCI_EPCTX_1_MPS_SET(mps) XHCI32_SET_BITS(mps, 31, 16)
+#define XHCI_EPCTX_1_MPS_GET(ctx) XHCI32_GET_BITS(ctx, 31, 16)
+#define XHCI_EPCTX_1_EPTYPE_GET(ctx) XHCI32_GET_BITS(ctx, 5, 3)
+#define XHCI_EPCTX_1_CERR_SET(cerr) XHCI32_SET_BITS(cerr, 2, 1)
+ uint32_t deq_low;
+ uint32_t deq_high;
+ uint32_t length;
+#define XHCI_EPCTX_AVE_TRB_LEN_SET(len) XHCI32_SET_BITS(len, 15, 0)
+#define XHCI_EPCTX_MAX_ESIT_SET(esit) XHCI32_SET_BITS(esit, 31, 16)
+ uint32_t reserved_01[3];
+} __PACKED;
+
+/* device context array element */
+struct xhci_devlist {
+ uint32_t ptr_low;
+ uint32_t ptr_high;
+} __PACKED;
+
+/* input context */
+struct xhci_inctx {
+ uint32_t del;
+ uint32_t add;
+ uint32_t reserved_01[6];
+/* refer to spec. The Input Context is an array of up to 33 context data structure entries */
+#define XHCI_INCTX_ENTRY_NUM 33U
+#define XHCI_INCTX_ALIGMENT 2048
+} __PACKED;
+
+/* transfer block (ring element) */
+struct xhci_trb {
+ uint32_t ptr_low;
+ uint32_t ptr_high;
+ uint32_t status;
+ uint32_t control;
+} __PACKED;
+
+/* event ring segment */
+struct xhci_er_seg {
+ uint32_t ptr_low;
+ uint32_t ptr_high;
+ uint32_t size;
+ uint32_t reserved_01;
+} __PACKED;
+
+struct xhci_portmap {
+ uint8_t start;
+ uint8_t count;
+};
+
+struct xhci_ring {
+ struct xhci_trb ring[XHCI_RING_ITEMS];
+ struct xhci_trb evt;
+ uint32_t eidx;
+ uint32_t nidx;
+ uint32_t cs;
+ usb_osal_mutex_t lock;
+};
+
+struct xhci_pipe {
+ struct xhci_ring reqs; /* DO NOT MOVE reqs from structure beg */
+ uint8_t epaddr;
+ uint8_t speed;
+ uint8_t interval;
+ uint8_t eptype;
+ uint16_t maxpacket;
+ uint32_t slotid;
+ uint32_t epid;
+
+ /* command or transfer waiter */
+ int timeout; /* = 0 no need to wait */
+ bool waiter;
+ usb_osal_sem_t waitsem;
+
+ /* handle urb */
+ struct usbh_hubport *hport;
+ struct usbh_urb *urb; /* NULL if no active URB */
+};
+
+struct xhci_s {
+ /* devinfo */
+ uint32_t ports;
+ uint32_t slots;
+ bool context64;
+ struct xhci_portmap usb2;
+ struct xhci_portmap usb3;
+
+ /* xhci registers base addr */
+ unsigned long base; /* register base */
+ unsigned long caps; /* capability register base */
+ unsigned long op; /* operational register base */
+ unsigned long pr; /* port register base */
+ unsigned long ir; /* interrupt runtime register base */
+ unsigned long db; /* doorbell register base */
+ unsigned long xcap; /* extended capability */
+ uint32_t hcs[3]; /* capability cache */
+ uint32_t hcc;
+ uint16_t version; /* xhci version */
+
+ /* xhci data structures */
+ struct xhci_devlist *devs;
+ struct xhci_ring *cmds;
+ struct xhci_ring *evts;
+ struct xhci_er_seg *eseg;
+};
+
+struct xhci_hubinfo {
+ uint32_t num_of_ports;
+ bool has_multiple_tts;
+ uint8_t tt_think_time;
+ int speed;
+};
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/third-party/cherryusb-0.6.0/port/xhci/xhci_reg.h b/third-party/cherryusb-0.6.0/port/xhci/xhci_reg.h
new file mode 100644
index 0000000000000000000000000000000000000000..613dcb33deeb4d33269481bcb6f083947f5fcc8e
--- /dev/null
+++ b/third-party/cherryusb-0.6.0/port/xhci/xhci_reg.h
@@ -0,0 +1,529 @@
+/*
+ * Copyright : (C) 2022 Phytium Information Technology, Inc.
+ * All Rights Reserved.
+ *
+ * This program is OPEN SOURCE software: you can redistribute it and/or modify it
+ * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
+ * either version 1.0 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Phytium Public License for more details.
+ *
+ *
+ * FilePath: xhci_reg.h
+ * Date: 2022-07-19 09:26:25
+ * LastEditTime: 2022-07-19 09:26:25
+ * Description: This files is for xhci register definition
+ *
+ * Modify History:
+ * Ver Who Date Changes
+ * ----- ------ -------- --------------------------------------
+ * 1.0 zhugengyu 2022/9/19 init commit
+ */
+#ifndef XHCI_REG_H
+#define XHCI_REG_H
+
+/***************************** Include Files *********************************/
+#include "usbh_core.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/************************** Constant Definitions *****************************/
+#if defined(__aarch64__)
+#define BITS_PER_LONG 64U
+#define XHCI_AARCH64
+#else
+#define BITS_PER_LONG 32U
+#define XHCI_AARCH32
+#endif
+
+#define XHCI_GENMASK(h, l) \
+ (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
+
+#define XHCI_GENMASK_ULL(h, l) \
+ (((~0ULL) - (1ULL << (l)) + 1) & \
+ (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
+
+#define XHCI32_GET_BITS(x, a, b) (uint32_t)((((uint32_t)(x)) & XHCI_GENMASK(a, b)) >> b)
+#define XHCI32_SET_BITS(x, a, b) (uint32_t)((((uint32_t)(x)) << b) & XHCI_GENMASK(a, b))
+#define XHCI64_GET_BITS(x, a, b) (uint64_t)((((uint64_t)(x)) & XHCI_GENMASK_ULL(a, b)) >> b)
+#define XHCI64_SET_BITS(x, a, b) (uint64_t)((((uint64_t)(x)) << b) & XHCI_GENMASK_ULL(a, b))
+
+/** @name Register Map
+ *
+ * Register offsets from the base address of an XHCI device.
+ * @{
+ */
+#define XHCI_REG_CAP_CAPLENGTH 0x00 /* specify the limits, restrictions and capabilities */
+#define XHCI_REG_CAP_HCIVERSION 0x02 /* Interface Version Number */
+#define XHCI_REG_CAP_HCS1 0x04 /* Host Controller Structural Parameters 1 */
+#define XHCI_REG_CAP_HCS2 0x08 /* Host Controller Structural Parameters 2 */
+#define XHCI_REG_CAP_HCS3 0x0C /* Host Controller Structural Parameters 3 */
+#define XHCI_REG_CAP_HCC 0x10 /* Capability Parameters 1 */
+#define XHCI_REG_CAP_DBOFF 0x14 /* Doorbell Offset Register */
+#define XHCI_REG_CAP_RTSOFF 0x18 /* Runtime Register Space Offset Register */
+
+/***************** Host Controller Operational Registers ***********************/
+#define XHCI_REG_OP_USBCMD 0x00 /* USB Command Register */
+#define XHCI_REG_OP_USBSTS 0x04 /* USB Status Register */
+#define XHCI_REG_OP_PAGESIZE 0x08 /* Page Size Register */
+#define XHCI_REG_OP_DNCTRL 0x14 /* Device Notification Control Register */
+#define XHCI_REG_OP_CRCR 0x18 /* Command Ring Control Register */
+#define XHCI_REG_OP_DCBAAP 0x30 /* Device Context Base Address Array Pointer Register */
+#define XHCI_REG_OP_CONFIG 0x38 /* Configure Register */
+
+/* Port Status and Ctrl Register : OP Base + (400h + (10h * (n–1))) 'n' is port num */
+#define XHCI_REG_OP_PORTS_BASE 0x400 /* Port Status and Control Register Base */
+#define XHCI_REG_OP_PORTS_SIZE 0x10 /* Size of one Port SC Register */
+#define XHCI_REG_OP_PORTS_OFF(port, off) ((port) * XHCI_REG_OP_PORTS_SIZE + offset)
+
+#define XHCI_REG_OP_PORTS_PORTSC 0x00 /* Port Status and Control Register */
+#define XHCI_REG_OP_PORTS_PORTPMSC 0x04 /* USB3 Port Power Management Status and Control Register */
+#define XHCI_REG_OP_PORTS_PORTLI 0x08 /* Port Link Info Register */
+
+/***************** Host Controller Runtime Registers ***********************/
+#define XHCI_REG_RT_MFINDEX 0x00 /* Microframe Index */
+#define XHCI_REG_RT_IR0 0x20 /* Interrupter Register Set 0 */
+#define XHCI_REG_RT_IR1023 0x8000 /* Interrupter Register Set 1023 */
+
+/* Interrupter Register Set : RT Base + 020h + (32 * Interrupter) */
+#define XHCI_REG_RT_IR_IMAN 0x00 /* Interrupter Management Register */
+#define XHCI_REG_RT_IR_IMOD 0x04 /* Interrupter Moderation Register */
+#define XHCI_REG_RT_IR_ERSTSZ 0x08 /* Event Ring Segment Table Size Register */
+#define XHCI_REG_RT_IR_ERSTBA 0x10 /* Event Ring Segment Table Base Address Register */
+#define XHCI_REG_RT_IR_ERDP 0x18 /* Event Ring Dequeue Pointer Register */
+#define XHCI_REG_RT_IR_SIZE 0x20 /* Size of one IR Register */
+
+/***************** Doorbell Register ***********************/
+#define XHCI_REG_DB_SIZE 4 /* Doorbell registers are 32 bits in length */
+
+/***************** eXtensible Host Controller Capability Registers ***********************/
+
+/** @name XHCI_REG_CAP_HCS1 Register
+ */
+#define XHCI_REG_CAP_HCS1_MAX_SLOTS_GET(x) XHCI32_GET_BITS(x, 7, 0) /* Number of Device Slots (MaxSlots) */
+#define XHCI_REG_CAP_HCS1_MAX_INTRS_GET(x) XHCI32_GET_BITS(x, 18, 8) /* Number of Interrupters (MaxIntrs) */
+#define XHCI_REG_CAP_HCS1_MAX_PORTS_GET(x) XHCI32_GET_BITS(x, 31, 24) /* Number of Ports (MaxPorts) */
+
+/** @name XHCI_REG_CAP_HCS2 Register
+ */
+#define XHCI_REG_CAP_HCS2_IST_GET(x) XHCI32_GET_BITS(x, 3, 0) /* Isochronous Scheduling Threshold (IST) */
+#define XHCI_REG_CAP_HCS2_ERST_MAX_GET(x) XHCI32_GET_BITS(x, 7, 4) /* Event Ring Segment Table Max (ERST Max) */
+#define XHCI_REG_CAP_HCS2_SPR (1 << 26) /* Scratchpad Restore (SPR) */
+#define XHCI_REG_CAP_HCS2_MAX_SCRATCHPAD_BUFS_GET(x) XHCI32_GET_BITS(x, 25, 21) | XHCI32_GET_BITS(x, 31, 27) /* Max Scratchpad Buffers (Max Scratchpad Bufs) */
+
+/** @name XHCI_REG_CAP_HCS3 Register
+ */
+#define XHCI_REG_CAP_HCS3_U1_DEV_EXIT_LATENCY_GET(x) XHCI32_GET_BITS(x, 7, 0) /* U1 Device Exit Latency */
+#define XHCI_REG_CAP_HCS3_U2_DEV_EXIT_LATENCY_GET(x) XHCI32_GET_BITS(x, 31, 16) /* U2 Device Exit Latency */
+
+/** @name XHCI_REG_CAP_HCC Register
+ */
+#define XHCI_REG_CAP_HCC_AC64 (1 << 0) /* 64-bit Addressing Capabilitya 1: 64-bit */
+#define XHCI_REG_CAP_HCC_BNC (1 << 1) /* BW Negotiation Capability (BNC) 1: support */
+#define XHCI_REG_CAP_HCC_CSZ (1 << 2) /* Context Size (CSZ) 1: 64 byte context data */
+#define XHCI_REG_CAP_HCC_PPC (1 << 3) /* Port Power Control (PPC) 1: support */
+#define XHCI_REG_CAP_HCC_PIND (1 << 4) /* Port Indicators (PIND) 1: support */
+#define XHCI_REG_CAP_HCC_LHRC (1 << 5) /* Light HC Reset Capability (LHRC) 1: support */
+#define XHCI_REG_CAP_HCC_LTC (1 << 6) /* Latency Tolerance Messaging Capability (LTC) */
+#define XHCI_REG_CAP_HCC_NSS (1 << 7) /* No Secondary SID Support (NSS) */
+#define XHCI_REG_CAP_HCC_MAX_PSA_SIZE_GET(x) XHCI32_GET_BITS(x, 15, 12) /* Maximum Primary Stream Array Size (MaxPSASize) */
+#define XHCI_REG_CAP_HCC_XECP_GET(x) XHCI32_GET_BITS(x, 31, 16) /* xHCI Extended Capabilities Pointer (xECP) */
+
+/** @name XHCI_REG_CAP_DBOFF Register
+ */
+#define XHCI_REG_CAP_DBOFF_GET(x) ((x) & XHCI_GENMASK(31, 2)) /* 32-byte offset of the Doorbell Array base address from the Base */
+
+/** @name XHCI_REG_CAP_RTSOFF Register
+ */
+#define XHCI_REG_CAP_RTSOFF_GET(x) ((x) & XHCI_GENMASK(31, 5)) /* 32-byte offset of the xHCI Runtime Registers */
+
+
+/***************** Host Controller Operational Registers ***********************/
+
+/** @name XHCI_REG_OP_USBCMD Register
+ */
+#define XHCI_REG_OP_USBCMD_RUN_STOP (1 << 0) /* Run/Stop (R/S) 1: RUN, 0: STOP - RW */
+#define XHCI_REG_OP_USBCMD_HCRST (1 << 1) /* Host Controller Reset (HCRST) 1: RESET - RW */
+#define XHCI_REG_OP_USBCMD_INTE (1 << 2) /* Interrupter Enable (INTE) 1: enabled - RW */
+#define XHCI_REG_OP_USBCMD_HSEE (1 << 3) /* Host System Error Enable (HSEE) - RW */
+#define XHCI_REG_OP_USBCMD_LHCRST (1 << 7) /* Light Host Controller Reset (LHCRST) - RW */
+#define XHCI_REG_OP_USBCMD_CSS (1 << 8) /* Controller Save State (CSS) - RW */
+#define XHCI_REG_OP_USBCMD_CRS (1 << 9) /* Controller Restore State (CRS) - RW */
+#define XHCI_REG_OP_USBCMD_EWE (1 << 10) /* Enable Wrap Event (EWE) - RW */
+#define XHCI_REG_OP_USBCMD_EU3S (1 << 11) /* Enable U3 MFINDEX Stop (EU3S) - RW */
+
+/** @name XHCI_REG_OP_USBSTS Register
+ */
+#define XHCI_REG_OP_USBSTS_HCH (1 << 0) /* 1: Stopped executing */
+#define XHCI_REG_OP_USBSTS_HSE (1 << 2) /* 1: Serious error detected */
+#define XHCI_REG_OP_USBSTS_EINT (1 << 3) /* 1: Interrupt Pending (IP) */
+#define XHCI_REG_OP_USBSTS_PCD (1 << 4) /* 1: Port Change Detect */
+#define XHCI_REG_OP_USBSTS_SSS (1 << 8) /* remain 1 while the xHC saves its internal state */
+#define XHCI_REG_OP_USBSTS_RSS (1 << 9) /* remain 1 while the xHC restores its internal state */
+#define XHCI_REG_OP_USBSTS_SRE (1 << 10) /* if error occurs during a Save or Restore operation this bit shall be set to ‘1’. */
+#define XHCI_REG_OP_USBSTS_CNR (1 << 11) /* 1: Controller Not Ready */
+#define XHCI_REG_OP_USBSTS_HCE (1 << 12) /* 1: Internal xHC error condition */
+#define XHCI_REG_OP_USBSTS_PRSRV_MASK ((1 << 1) | 0xffffe000) /* Rsvd bits */
+
+
+/** @name XHCI_REG_OP_PAGESIZE Register
+ */
+/* This xHC supports a page size of 2^(n+12) if bit n is Set */
+#define XHCI_REG_OP_PAGESIZE_4K (1 << 0) /* if bit 0 is Set, the xHC supports 4k byte page sizes */
+
+/** @name XHCI_REG_OP_CRCR Register
+ */
+#define XHCI_REG_OP_CRCR_RCS (1 << 0) /* Ring Cycle State, value of the xHC Consumer Cycle State (CCS) flag */
+#define XHCI_REG_OP_CRCR_CS (1 << 1) /* Command Stop, 1 */
+#define XHCI_REG_OP_CRCR_CA (1 << 2) /* Command Abort, 1 */
+#define XHCI_REG_OP_CRCR_CRR (1 << 3) /* Command Ring Running */
+#define XHCI_REG_OP_CRCR_CR_PTR_MASK XHCI_GENMASK_ULL(63, 6) /* Command Ring Pointer, Dequeue Ptr of Command Ring */
+
+/** @name XHCI_REG_OP_DCBAAP Register
+ */
+#define XHCI_REG_OP_DCBAAP_MASK XHCI_GENMASK_ULL(63, 6) /* bit[31:6] Ptr of DCBAA */
+
+/** @name XHCI_REG_OP_CONFIG Register
+ */
+#define XHCI_REG_OP_CONFIG_MAX_SLOTS_EN_MASK XHCI_GENMASK(7, 0) /* Max Device Slots Enabled (MaxSlotsEn) – RW */
+#define XHCI_REG_OP_CONFIG_MAX_SLOTS_EN_SET(x) XHCI32_SET_BITS(x, 7, 0) /* bit[7:0] Max Device Slots Enabled */
+#define XHCI_REG_OP_CONFIG_MAX_SLOTS_EN_GET(x) XHCI32_GET_BITS(x, 7, 0)
+
+/** @name XHCI_REG_OP_PORTS_PORTSC Register
+ */
+#define XHCI_REG_OP_PORTS_PORTSC_CCS (1 << 0) /* Current Connect Status (CCS) – ROS */
+#define XHCI_REG_OP_PORTS_PORTSC_PED (1 << 1) /* Port Enabled/Disabled (PED) – RW1CS */
+#define XHCI_REG_OP_PORTS_PORTSC_OCA (1 << 3) /* Over-current Active (OCA) – RO */
+#define XHCI_REG_OP_PORTS_PORTSC_PR (1 << 4) /* Port Reset (PR) – RW1S */
+#define XHCI_REG_OP_PORTS_PORTSC_PLS_GET(x) XHCI32_GET_BITS(x, 8, 5) /* Port Link State (PLS) – RWS */
+#define XHCI_REG_OP_PORTS_PORTSC_PLS_SET(x) XHCI32_SET_BITS(x, 8, 5)
+#define XHCI_REG_OP_PORTS_PORTSC_PLS_MASK XHCI_GENMASK(8, 5)
+#define XHCI_REG_OP_PORTS_PORTSC_PLS(x) (x << 5)
+#define XHCI_REG_OP_PORTS_PORTSC_PLS_SET(x) XHCI32_SET_BITS(x, 8, 5)
+
+enum PLSStatus{
+ PLS_U0 = 0,
+ PLS_U1 = 1,
+ PLS_U2 = 2,
+ PLS_U3 = 3,
+ PLS_DISABLED = 4,
+ PLS_RX_DETECT = 5,
+ PLS_INACTIVE = 6,
+ PLS_POLLING = 7,
+ PLS_RECOVERY = 8,
+ PLS_HOT_RESET = 9,
+ PLS_COMPILANCE_MODE = 10,
+ PLS_TEST_MODE = 11,
+ PLS_RESUME = 15,
+}; /* Port status type */
+
+#define XHCI_REG_OP_PORTS_PORTSC_PP (1 << 9) /* Port Power (PP) – RWS */
+#define XHCI_REG_OP_PORTS_PORTSC_PORT_SPEED_GET(x) XHCI32_GET_BITS(x, 13, 10) /* Port Speed (Port Speed) – ROS */
+
+/* Protocol Speed ID (PSI) */
+#define XHCI_PORT_SPEED_UNKOWN 0U
+#define XHCI_PORT_SPEED_FULL 1U
+#define XHCI_PORT_SPEED_LOW 2U
+#define XHCI_PORT_SPEED_HIGH 3U
+#define XHCI_PORT_SPEED_SUPER 4U
+
+#define XHCI_REG_OP_PORTS_PORTSC_PIC_SET(x) XHCI32_SET_BITS(x, 15, 14)
+#define XHCI_REG_OP_PORTS_PORTSC_PIC_MASK XHCI_GENMASK(15, 14)
+
+#define XHCI_REG_OP_PORTS_PORTSC_LWS (1 << 16) /* Port Link State Write Strobe (LWS) */
+#define XHCI_REG_OP_PORTS_PORTSC_CSC (1 << 17) /* Connect Status Change (CSC) */
+#define XHCI_REG_OP_PORTS_PORTSC_PEC (1 << 18) /* Port Enabled/Disabled Change (PEC) 1: clear PED */
+#define XHCI_REG_OP_PORTS_PORTSC_WRC (1 << 19) /* Warm Port Reset Change 1: Warm Reset complete */
+#define XHCI_REG_OP_PORTS_PORTSC_OCC (1 << 20) /* Over-current Change 1: Over-current Active */
+#define XHCI_REG_OP_PORTS_PORTSC_PRC (1 << 21) /* Port Reset Change 1: Transition of Port Reset */
+#define XHCI_REG_OP_PORTS_PORTSC_PLC (1 << 22) /* Port Link State Change 1: PLS transition */
+#define XHCI_REG_OP_PORTS_PORTSC_CEC (1 << 23) /* Port Config Error Change 1: Port Config Error detected */
+#define XHCI_REG_OP_PORTS_PORTSC_CAS (1 << 24) /* Cold Attach Status 1: Far-end Receiver Terminations were detected */
+#define XHCI_REG_OP_PORTS_PORTSC_WCE (1 << 25) /* Wake on Connect Enable 1: enable port to be sensitive to device connects */
+#define XHCI_REG_OP_PORTS_PORTSC_WDE (1 << 26) /* Wake on Disconnect Enable 1: enable port to be sensitive to device disconnects */
+#define XHCI_REG_OP_PORTS_PORTSC_WOE (1 << 27) /* Wake on Over-current Enable 1: enable port to be sensitive to over-current conditions */
+#define XHCI_REG_OP_PORTS_PORTSC_DR (1 << 30) /* Device Removable, 0: Device is removable. 1: Device is non-removable */
+#define XHCI_REG_OP_PORTS_PORTSC_WPR (1 << 31) /* Warm Port Reset 1: follow Warm Reset sequence */
+#define XHCI_REG_OP_PORTS_PORTSC_RW_MASK (XHCI_REG_OP_PORTS_PORTSC_PR | XHCI_REG_OP_PORTS_PORTSC_PLS_MASK | XHCI_REG_OP_PORTS_PORTSC_PP \
+ | XHCI_REG_OP_PORTS_PORTSC_PIC_MASK | XHCI_REG_OP_PORTS_PORTSC_LWS | XHCI_REG_OP_PORTS_PORTSC_WCE \
+ | XHCI_REG_OP_PORTS_PORTSC_WDE | XHCI_REG_OP_PORTS_PORTSC_WOE)
+
+
+/***************** Host Controller Runtime Registers ***********************/
+
+/** @name XHCI_REG_RT_IR_IMAN Register
+ */
+#define XHCI_REG_RT_IR_IMAN_IP (1 << 0) /* Interrupt Pending, 1: an interrupt is pending for this Interrupter */
+#define XHCI_REG_RT_IR_IMAN_IE (1 << 1) /* Interrupt Enable, 1: capable of generating an interrupt. */
+
+/** @name XHCI_REG_RT_IR_IMOD Register
+ */
+#define XHCI_REG_RT_IR_IMOD_IMODI_MASK XHCI_GENMASK(15, 0) /* bit[15:0] Interrupt Moderation Interval default 4000 ==> 1ms */
+#define XHCI_REG_RT_IR_IMOD_IMODC_MASK XHCI_GENMASK(31, 16) /* bit[31:16] Interrupt Moderation Counter(Down counter) */
+
+/** @name XHCI_REG_RT_IR_ERSTSZ Register
+ */
+#define XHCI_REG_RT_IR_ERSTSZ_MASK XHCI_GENMASK(15, 0) /* bit[15:0] the number of valid Event Ring Segment Table entries */
+
+/** @name XHCI_REG_RT_IR_ERSTBA Register
+ */
+#define XHCI_REG_RT_IR_ERSTBA_MASK XHCI_GENMASK_ULL(63, 6) /* Event Ring Segment Table Base Address */
+
+/** @name XHCI_REG_RT_IR_ERDP Register
+ */
+#define XHCI_REG_RT_IR_ERDP_DESI_MASK XHCI_GENMASK_ULL(2, 0) /* bit[2:0] Dequeue ERST Segment Index */
+#define XHCI_REG_RT_IR_ERDP_EHB (1 << 3) /* Event Handler Busy */
+#define XHCI_REG_RT_IR_ERDP_MASK XHCI_GENMASK_ULL(63, 4) /* Event Ring Dequeue Pointer */
+
+/***************** Doorbell Register ***********************/
+#define XHCI_REG_DB_TARGET_HC_COMMAND 0 /* Host Controller Doorbell (0) Command Doorbell */
+#define XHCI_REG_DB_TARGET_EP0 1 /* Device Context Doorbells Control EP 0 Enqueue Pointer Update */
+#define XHCI_REG_DB_TARGET_EP1_OUT 2 /* EP 1 OUT Enqueue Pointer Update */
+#define XHCI_REG_DB_TARGET_EP1_IN 3 /* EP 1 IN Enqueue Pointer Update */
+#define XHCI_REG_DB_TARGET_EP15_OUT 30 /* EP 15 OUT Enqueue Pointer Update */
+#define XHCI_REG_DB_TARGET_EP15_IN 31 /* EP 15 IN Enqueue Pointer Update */
+
+/***************** xHCI Extended Capabilities Registers ***********************/
+#define XHCI_REG_EXT_CAP_USBSPCF_OFFSET 0x0
+#define XHCI_REG_EXT_CAP_CAP_ID_GET(x) XHCI32_GET_BITS(x, 7, 0)
+#define XHCI_REG_EXT_NEXT_CAP_PTR_GET(x) XHCI32_GET_BITS(x, 15, 8)
+/* refer to 'Table 138: xHCI Extended Capability Codes' for more details */
+enum
+{
+ XHCI_EXT_CAP_ID_USB_LEGACY_SUPPORT = 1,
+ XHCI_EXT_CAP_ID_SUPPORT_PROTOCOL = 2,
+ XHCI_EXT_CAP_ID_EXTEND_POWER_MANAGEMENT = 3,
+ XHCI_EXT_CAP_ID_IO_VIRTUALIZATION = 4,
+ XHCI_EXT_CAP_ID_MESSAGE_INTERRUPT = 5,
+ XHCI_EXT_CAP_ID_LOCAL_MEMORY = 6,
+ XHCI_EXT_CAP_ID_USB_DEBUG_CAPABILITY = 10,
+ XHCI_EXT_CAP_ID_EXT_MESSAGE_INTERRUPT = 17,
+
+ XHCI_EXT_CAP_ID_VENDOR_DEFINED_MIN = 192,
+ XHCI_EXT_CAP_ID_VENDOR_DEFINED_MAX = 255
+};
+
+/* xHCI Supported Protocol Capability */
+#define XHCI_REG_EXT_CAP_USBSPCFDEF_OFFSET 0x4
+
+#define XHCI_USBSPCF_MINOR_REVERSION_GET(x) XHCI32_GET_BITS(x, 23, 16)
+#define XHCI_USBSPCF_MAJOR_REVERSION_GET(x) XHCI32_GET_BITS(x, 31, 24)
+
+#define XHCI_USBSPCFDEF_NAME_STRING_GET(x) XHCI32_GET_BITS(x, 31, 0) /* four ASCII characters may be defined */
+#define XHCI_USBSPCFDEF_NAME_STRING_USB 0x20425355 /* ASCII = "USB" */
+
+#define XHCI_REG_EXT_CAP_USBSPCFDEF2_OFFSET 0x8
+#define XHCI_USBSPCFDEF2_COMPATIBLE_PORT_OFF_GET(x) XHCI32_GET_BITS(x, 7, 0)
+#define XHCI_USBSPCFDEF2_COMPATIBLE_PORT_CNT_GET(x) XHCI32_GET_BITS(x, 15, 8)
+#define XHCI_USBSPCFDEF2_PROTOCOL_DEFINED_GET(x) XHCI32_GET_BITS(x, 27, 16)
+
+/* trb bit definitions */
+
+/* configuration */
+#define XHCI_RING_ITEMS 16U
+#define XHCI_ALIGMENT 64U
+#define XHCI_RING_SIZE (XHCI_RING_ITEMS*sizeof(struct xhci_trb))
+
+#define TRB_C (1<<0)
+#define TRB_TYPE_SHIFT 10
+#define TRB_TYPE_MASK 0x3f
+#define TRB_TYPE_GET(val) XHCI32_GET_BITS(val, 15, 10)
+#define TRB_TYPE_SET(t) XHCI32_SET_BITS(t, 15, 10)
+
+#define TRB_EV_ED (1<<2)
+
+#define TRB_TR_ENT (1<<1)
+#define TRB_TR_ISP (1<<2)
+#define TRB_TR_NS (1<<3)
+#define TRB_TR_CH (1<<4)
+#define TRB_TR_IOC (1<<5)
+#define TRB_TR_IDT (1<<6)
+#define TRB_TR_TBC_SHIFT 7
+#define TRB_TR_TBC_MASK 0x3
+#define TRB_TR_BEI (1<<9)
+#define TRB_TR_TLBPC_SHIFT 16
+#define TRB_TR_TLBPC_MASK 0xf
+#define TRB_TR_FRAMEID_SHIFT 20
+#define TRB_TR_FRAMEID_MASK 0x7ff
+#define TRB_TR_SIA (1<<31)
+#define TRB_TR_TRANS_LEN_SET(len) XHCI32_SET_BITS(len, 23, 0)
+#define TRB_TR_TRANS_LEN_MASK XHCI_GENMASK(23, 0)
+
+#define TRB_TR_DIR (1<<16)
+#define TRB_TR_TYPE_SET(t) XHCI32_SET_BITS(t, 17, 16)
+#define TRB_TR_NO_DATA 0U
+#define TRB_TR_OUT_DATA 2U
+#define TRB_TR_IN_DATA 3U
+
+#define TRB_CC_GET(val) XHCI32_GET_BITS(val, 31, 24)
+#define TRB_PORT_ID_GET(val) XHCI32_GET_BITS(val, 31, 24)
+
+
+#define TRB_CR_SLOTID_SHIFT 24
+#define TRB_CR_SLOTID_MASK 0xff
+#define TRB_CR_SLOTID_SET(id) XHCI32_SET_BITS(id, 31, 24)
+#define TRB_CR_SLOTID_GET(val) XHCI32_GET_BITS(val, 31, 24)
+
+#define TRB_CR_EPID_SHIFT 16
+#define TRB_CR_EPID_MASK 0x1f
+#define TRB_CR_EPID_SET(id) XHCI32_SET_BITS(id, 20, 16)
+#define TRB_CR_EPID_GET(field) XHCI32_GET_BITS(field, 20, 16)
+
+#define TRB_CR_BSR (1<<9)
+#define TRB_CR_DC (1<<9)
+
+#define TRB_LK_TC (1<<1)
+
+#define TRB_INTR_SHIFT 22
+#define TRB_INTR_MASK 0x3ff
+#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK)
+
+/************************** Type Definitions *********************************/
+enum TRBType {
+ TRB_RESERVED = 0,
+ TR_NORMAL,
+ TR_SETUP,
+ TR_DATA,
+ TR_STATUS,
+ TR_ISOCH,
+ TR_LINK,
+ TR_EVDATA,
+ TR_NOOP,
+ CR_ENABLE_SLOT,
+ CR_DISABLE_SLOT,
+ CR_ADDRESS_DEVICE,
+ CR_CONFIGURE_ENDPOINT,
+ CR_EVALUATE_CONTEXT,
+ CR_RESET_ENDPOINT,
+ CR_STOP_ENDPOINT,
+ CR_SET_TR_DEQUEUE,
+ CR_RESET_DEVICE,
+ CR_FORCE_EVENT,
+ CR_NEGOTIATE_BW,
+ CR_SET_LATENCY_TOLERANCE,
+ CR_GET_PORT_BANDWIDTH,
+ CR_FORCE_HEADER,
+ CR_NOOP,
+ ER_TRANSFER_COMPLETE = 32,
+ ER_COMMAND_COMPLETE,
+ ER_PORT_STATUS_CHANGE,
+ ER_BANDWIDTH_REQUEST,
+ ER_DOORBELL,
+ ER_HOST_CONTROLLER,
+ ER_DEVICE_NOTIFICATION,
+ ER_MFINDEX_WRAP,
+};
+
+enum TRBCCode {
+ CC_DISCONNECTED = -2,
+ CC_TIMEOUT = -1,
+ CC_INVALID = 0,
+ CC_SUCCESS,
+ CC_DATA_BUFFER_ERROR,
+ CC_BABBLE_DETECTED,
+ CC_USB_TRANSACTION_ERROR,
+ CC_TRB_ERROR,
+ CC_STALL_ERROR,
+ CC_RESOURCE_ERROR,
+ CC_BANDWIDTH_ERROR,
+ CC_NO_SLOTS_ERROR,
+ CC_INVALID_STREAM_TYPE_ERROR,
+ CC_SLOT_NOT_ENABLED_ERROR,
+ CC_EP_NOT_ENABLED_ERROR,
+ CC_SHORT_PACKET,
+ CC_RING_UNDERRUN,
+ CC_RING_OVERRUN,
+ CC_VF_ER_FULL,
+ CC_PARAMETER_ERROR,
+ CC_BANDWIDTH_OVERRUN,
+ CC_CONTEXT_STATE_ERROR,
+ CC_NO_PING_RESPONSE_ERROR,
+ CC_EVENT_RING_FULL_ERROR,
+ CC_INCOMPATIBLE_DEVICE_ERROR,
+ CC_MISSED_SERVICE_ERROR,
+ CC_COMMAND_RING_STOPPED,
+ CC_COMMAND_ABORTED,
+ CC_STOPPED,
+ CC_STOPPED_LENGTH_INVALID,
+ CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29,
+ CC_ISOCH_BUFFER_OVERRUN = 31,
+ CC_EVENT_LOST_ERROR,
+ CC_UNDEFINED_ERROR,
+ CC_INVALID_STREAM_ID_ERROR,
+ CC_SECONDARY_BANDWIDTH_ERROR,
+ CC_SPLIT_TRANSACTION_ERROR
+};
+
+/***************** Macros (Inline Functions) Definitions *********************/
+/*
+ * xhci_ring structs are allocated with XHCI_RING_SIZE alignment,
+ * then we can get it from a trb pointer (provided by evt ring).
+ */
+#define XHCI_RING(_trb) \
+ ((struct xhci_ring*)((unsigned long)(_trb) & ~(XHCI_RING_SIZE-1)))
+
+#define BARRIER() __asm__ __volatile__("": : :"memory")
+
+#ifdef XHCI_AARCH64
+#define DSB() __asm__ __volatile__("dsb sy": : : "memory")
+#else
+#define DSB() __asm__ __volatile__("dsb": : : "memory")
+#endif
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+static inline void writeq(unsigned long addr, uint64_t val) {
+ BARRIER();
+ *(volatile uint64_t *)addr = val;
+}
+
+static inline void writel(unsigned long addr, uint32_t val) {
+ BARRIER();
+ *(volatile uint32_t *)addr = val;
+}
+
+static inline void writew(unsigned long addr, uint16_t val) {
+ BARRIER();
+ *(volatile uint16_t *)addr = val;
+}
+
+static inline void writeb(unsigned long addr, uint8_t val) {
+ BARRIER();
+ *(volatile uint8_t *)addr = val;
+}
+
+static inline uint64_t readq(unsigned long addr) {
+ uint64_t val = *(volatile const uint64_t *)addr;
+ BARRIER();
+ return val;
+}
+
+static inline uint32_t readl(unsigned long addr) {
+ uint32_t val = *(volatile const uint32_t *)addr;
+ BARRIER();
+ return val;
+}
+
+static inline uint16_t readw(unsigned long addr) {
+ uint16_t val = *(volatile const uint16_t *)addr;
+ BARRIER();
+ return val;
+}
+
+static inline uint8_t readb(unsigned long addr) {
+ uint8_t val = *(volatile const uint8_t *)addr;
+ BARRIER();
+ return val;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/third-party/third-party.mk b/third-party/third-party.mk
index 2010664a7229ebe9f63c71b2bd429ec96826e709..dfc34e2190e28617c0829b469b4af7d61af2dea5 100644
--- a/third-party/third-party.mk
+++ b/third-party/third-party.mk
@@ -229,4 +229,10 @@ $(shell export PATH=$(THIRD_PARTY_CUR_DIR)/sdmmc-1.0:$PATH)
SRC_DIR += $(THIRD_PARTY_CUR_DIR)/sdmmc-1.0/port \
$(THIRD_PARTY_CUR_DIR)/sdmmc-1.0/port/fsdio
endif #CONFIG_SDMMC_PORT_FSDIO
-endif #CONFIG_USE_SDMMC_CMD
\ No newline at end of file
+endif #CONFIG_USE_SDMMC_CMD
+
+ifdef CONFIG_USE_CHERRY_USB
+
+include $(THIRD_PARTY_CUR_DIR)/cherryusb-0.6.0/makefile
+
+endif #CONFIG_USE_CHERRY_USB