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初始化任务,创建定时发送任务,创建接收任务,并创建单次模式软件定时器 + +![create](./figs/create.png) + +- 定时器时间到,触发单次模式软件定时器的回调函数,删除发送和接收任务,去初始化can,删除软件定时器 + +![delete](./figs/delete.png) + +## 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](./figs/usb_disk_connection.png) + +![usb_disk_init](./figs/usb_disk_init.png) + +- 输入`usb disk`后,启动一个任务不断读写U盘 + +#### 2.4.2 获取键盘输入 + +- 目前 USB (xhci port) 协议栈中 hub 的支持还不够完善,低速设备需要直连板上的 USB 插槽进行测试 + +``` +usb init +usb input +``` + +- 输入`usb input`后,可以通过中断处理键盘输入 + +![usb_keyboard](./figs/usb_keyboard_connect.jpg) + +![usb_keyboard_input](./figs/usb_keyboard_input.png) + +#### 2.4.3 获取鼠标输入 + +- 目前 USB (xhci port) 协议栈中 hub 的支持还不够完善,低速设备需要直连板上的 USB 插槽进行测试 + +``` +usb init +usb input +``` + +- 输入`usb input`后,可以通过中断处理鼠标输入 + +![usb_mouse](./figs/usb_mouse_connect.jpg) + +![usb_mouse_input](./figs/usb_mouse_input.png) + +## 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. + +![CherryUSB](./docs/assets/usb_outline.png) + +## 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 主从协议栈。 + +![CherryUSB](./docs/assets/usb_outline.png) + +## 为什么选择 + +- 代码精简,并且内存占用极小,详细参考下面表格,而且还可进一步的裁剪 +- 全面的 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