update: 📝 更新cherry USB的初始化
file: 📦 添加cherry USB文件
This commit is contained in:
parent
28d878ed53
commit
7bbdfc0bf4
174
.clang-format
Normal file
174
.clang-format
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
---
|
||||||
|
# 语言: None, Cpp, Java, JavaScript, ObjC, Proto, TableGen, TextProto
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: LLVM
|
||||||
|
# 访问说明符(public、private等)的偏移
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
# 开括号(开圆括号、开尖括号、开方括号)后的对齐: Align, DontAlign, AlwaysBreak(总是在开括号后换行)
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
# 连续赋值时,对齐所有等号
|
||||||
|
AlignConsecutiveAssignments: true
|
||||||
|
# 连续声明时,对齐所有声明的变量名
|
||||||
|
AlignConsecutiveDeclarations: true
|
||||||
|
# 左对齐逃脱换行(使用反斜杠换行)的反斜杠
|
||||||
|
AlignEscapedNewlinesLeft: true
|
||||||
|
# 水平对齐二元和三元表达式的操作数
|
||||||
|
AlignOperands: true
|
||||||
|
# 对齐连续的尾随的注释
|
||||||
|
AlignTrailingComments: true
|
||||||
|
# 允许函数声明的所有参数在放在下一行
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
# 允许短的块放在同一行
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
# 允许短的case标签放在同一行
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
# 允许短的函数放在同一行: None, InlineOnly(定义在类中), Empty(空函数), Inline(定义在类中,空函数), All
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
# 允许短的if语句保持在同一行
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
# 允许短的循环保持在同一行
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
# 总是在定义返回类型后换行(deprecated)
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
# 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数),
|
||||||
|
# AllDefinitions(所有的定义,不包括声明), TopLevelDefinitions(所有的顶级函数的定义)
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
# 总是在多行string字面量前换行
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
# 总是在template声明后换行
|
||||||
|
AlwaysBreakTemplateDeclarations: false
|
||||||
|
# false表示函数实参要么都在同一行,要么都各自一行
|
||||||
|
BinPackArguments: true
|
||||||
|
# false表示所有形参要么都在同一行,要么都各自一行
|
||||||
|
BinPackParameters: true
|
||||||
|
# 大括号换行,只有当BreakBeforeBraces设置为Custom时才有效
|
||||||
|
BraceWrapping:
|
||||||
|
# class定义后面
|
||||||
|
AfterClass: true
|
||||||
|
# 控制语句后面
|
||||||
|
AfterControlStatement: false
|
||||||
|
# enum定义后面
|
||||||
|
AfterEnum: true
|
||||||
|
# 函数定义后面
|
||||||
|
AfterFunction: true
|
||||||
|
# 命名空间定义后面
|
||||||
|
AfterNamespace: true
|
||||||
|
# ObjC定义后面
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
# struct定义后面
|
||||||
|
AfterStruct: true
|
||||||
|
# union定义后面
|
||||||
|
AfterUnion: false
|
||||||
|
# catch之前
|
||||||
|
BeforeCatch: true
|
||||||
|
# else之前
|
||||||
|
BeforeElse: false
|
||||||
|
# 缩进大括号
|
||||||
|
IndentBraces: false
|
||||||
|
# 在二元运算符前换行: None(在操作符后换行), NonAssignment(在非赋值的操作符前换行), All(在操作符前换行)
|
||||||
|
BreakBeforeBinaryOperators: NonAssignment
|
||||||
|
# 在大括号前换行: Attach(始终将大括号附加到周围的上下文), Linux(除函数、命名空间和类定义,与Attach类似),
|
||||||
|
# Mozilla(除枚举、函数、记录定义,与Attach类似), Stroustrup(除函数定义、catch、else,与Attach类似),
|
||||||
|
# Allman(总是在大括号前换行), GNU(总是在大括号前换行,并对于控制语句的大括号增加额外的缩进), WebKit(在函数前换行), Custom
|
||||||
|
# 注:这里认为语句块也属于函数
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
# 在三元运算符前换行
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
# 在构造函数的初始化列表的逗号前换行
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
# 每行字符的限制,0表示没有限制
|
||||||
|
ColumnLimit: 80
|
||||||
|
# 描述具有特殊意义的注释的正则表达式,它不应该被分割为多行或以其它方式改变
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
# 构造函数的初始化列表要么都在同一行,要么都各自一行
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
# 构造函数的初始化列表的缩进宽度
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
# 延续的行的缩进宽度
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
# 去除C++11的列表初始化的大括号{后和}前的空格
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
|
# 继承最常用的指针和引用的对齐方式
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
# 关闭格式化
|
||||||
|
DisableFormat: false
|
||||||
|
# 自动检测函数的调用和定义是否被格式为每行一个参数(Experimental)
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
# 需要被解读为foreach循环而不是函数调用的宏
|
||||||
|
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||||
|
# 对#include进行排序,匹配了某正则表达式的#include拥有对应的优先级,匹配不到的则默认优先级为INT_MAX(优先级越小排序越靠前),
|
||||||
|
# 可以定义负数优先级从而保证某些#include永远在最前面
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '^(<|"(gtest|isl|json)/)'
|
||||||
|
Priority: 3
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 1
|
||||||
|
# 缩进case标签
|
||||||
|
IndentCaseLabels: true
|
||||||
|
# 缩进宽度
|
||||||
|
IndentWidth: 4
|
||||||
|
# 函数返回类型换行时,缩进函数声明或函数定义的函数名
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
# 保留在块开始处的空行
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
|
# 开始一个块的宏的正则表达式
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
# 结束一个块的宏的正则表达式
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
# 连续空行的最大数量
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
# 命名空间的缩进: None, Inner(缩进嵌套的命名空间中的内容), All
|
||||||
|
NamespaceIndentation: Inner
|
||||||
|
# 使用ObjC块时缩进宽度
|
||||||
|
ObjCBlockIndentWidth: 4
|
||||||
|
# 在ObjC的@property后添加一个空格
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
# 在ObjC的protocol列表前添加一个空格
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
# 在call(后对函数调用换行的penalty
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
# 在一个注释中引入换行的penalty
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
# 第一次在<<前换行的penalty
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
# 在一个字符串字面量中引入换行的penalty
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
# 对于每个在行字符数限制之外的字符的penalty
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
# 将函数的返回类型放到它自己的行的penalty
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
# 指针和引用的对齐: Left, Right, Middle
|
||||||
|
PointerAlignment: Left
|
||||||
|
# 允许重新排版注释
|
||||||
|
ReflowComments: false
|
||||||
|
# 允许排序#include
|
||||||
|
SortIncludes: false
|
||||||
|
# 在C风格类型转换后添加空格
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
# 在赋值运算符之前添加空格
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
# 开圆括号之前添加一个空格: Never, ControlStatements, Always
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
# 在空的圆括号中添加空格
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
# 在尾随的评论前添加的空格数(只适用于//)
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
# 在尖括号的<后和>前添加空格
|
||||||
|
SpacesInAngles: false
|
||||||
|
# 在容器(ObjC和JavaScript的数组和字典等)字面量中添加空格
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
# 在C风格类型转换的括号中添加空格
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
# 在圆括号的(后和)前添加空格
|
||||||
|
SpacesInParentheses: false
|
||||||
|
# 在方括号的[后和]前添加空格,lamda表达式和未指明大小的数组的声明不受影响
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
# 标准: Cpp03, Cpp11, Auto
|
||||||
|
Standard: Cpp11
|
||||||
|
# tab宽度
|
||||||
|
TabWidth: 4
|
||||||
|
# 使用tab字符: Never, ForIndentation, ForContinuationAndIndentation, Always
|
||||||
|
UseTab: Never
|
||||||
|
...
|
||||||
@ -1,14 +1,34 @@
|
|||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRC_DIRS
|
SRC_DIRS
|
||||||
"."
|
"."
|
||||||
"utilities/letter_shell/src"
|
"utilities/letter_shell/src"
|
||||||
"utilities/letter_shell/port/esp-idf"
|
"utilities/letter_shell/port/esp-idf"
|
||||||
|
"utilities/usb_cherry/addition/"
|
||||||
|
"utilities/usb_cherry/esp_setup"
|
||||||
|
"utilities/usb_cherry/CherryUSB/class/cdc/"
|
||||||
|
"utilities/usb_cherry/CherryUSB/class/msc/"
|
||||||
|
"utilities/usb_cherry/CherryUSB/core/"
|
||||||
|
"utilities/usb_cherry/CherryUSB/port/dwc2"
|
||||||
|
|
||||||
|
EXCLUDE_SRCS
|
||||||
|
"utilities/usb_cherry/CherryUSB/class/cdc/usbh_cdc_acm.c"
|
||||||
|
"utilities/usb_cherry/CherryUSB/class/msc/usbh_msc.c"
|
||||||
|
"utilities/usb_cherry/CherryUSB/core/usbh_core.c"
|
||||||
|
"utilities/usb_cherry/CherryUSB/port/dwc2/usb_hc_dwc2.c"
|
||||||
|
|
||||||
INCLUDE_DIRS
|
INCLUDE_DIRS
|
||||||
"."
|
"."
|
||||||
"utilities/letter_shell/src"
|
"utilities/letter_shell/src"
|
||||||
"utilities/letter_shell/port/esp-idf"
|
"utilities/letter_shell/port/esp-idf"
|
||||||
|
"utilities/usb_cherry/esp_setup"
|
||||||
|
"utilities/usb_cherry/CherryUSB/class/cdc"
|
||||||
|
"utilities/usb_cherry/CherryUSB/class/msc"
|
||||||
|
# "utilities/usb_cherry/CherryUSB/class/audio"
|
||||||
|
"utilities/usb_cherry/CherryUSB/common"
|
||||||
|
"utilities/usb_cherry/CherryUSB/core"
|
||||||
|
"utilities/usb_cherry/CherryUSB/port/dwc2"
|
||||||
|
|
||||||
LDFRAGMENTS
|
LDFRAGMENTS
|
||||||
"utilities/letter_shell/port/esp-idf/shell.lf"
|
"utilities/letter_shell/port/esp-idf/shell.lf"
|
||||||
)
|
)
|
||||||
|
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||||
51
main/main.c
51
main/main.c
@ -4,18 +4,18 @@
|
|||||||
* SPDX-License-Identifier: CC0-1.0
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "esp_chip_info.h"
|
||||||
#include <inttypes.h>
|
#include "esp_err.h"
|
||||||
#include "sdkconfig.h"
|
#include "esp_flash.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_spi_flash.h"
|
||||||
|
#include "esp_system.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_chip_info.h"
|
|
||||||
#include "esp_flash.h"
|
|
||||||
#include "esp_system.h"
|
|
||||||
#include "esp_spi_flash.h"
|
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "esp_err.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_log.h"
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "shell_port.h"
|
#include "shell_port.h"
|
||||||
|
|
||||||
@ -23,13 +23,16 @@ static void _init_esp()
|
|||||||
{
|
{
|
||||||
// Initialize NVS
|
// Initialize NVS
|
||||||
esp_err_t ret = nvs_flash_init();
|
esp_err_t ret = nvs_flash_init();
|
||||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES
|
||||||
|
|| ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
ret = nvs_flash_init();
|
ret = nvs_flash_init();
|
||||||
}
|
}
|
||||||
ESP_ERROR_CHECK(ret);
|
ESP_ERROR_CHECK(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void cdc_acm_msc_init();
|
||||||
|
extern int cdc_printf(const char* fmt, ...);
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
@ -39,35 +42,43 @@ void app_main(void)
|
|||||||
vTaskDelay(10);
|
vTaskDelay(10);
|
||||||
|
|
||||||
printf("Hello world!\n");
|
printf("Hello world!\n");
|
||||||
|
cdc_acm_msc_init();
|
||||||
|
|
||||||
/* Print chip information */
|
/* Print chip information */
|
||||||
esp_chip_info_t chip_info;
|
esp_chip_info_t chip_info;
|
||||||
uint32_t flash_size;
|
uint32_t flash_size;
|
||||||
esp_chip_info(&chip_info);
|
esp_chip_info(&chip_info);
|
||||||
printf("This is %s chip with %d CPU core(s), %s%s%s%s, ",
|
printf("This is %s chip with %d CPU core(s), %s%s%s%s, ", CONFIG_IDF_TARGET,
|
||||||
CONFIG_IDF_TARGET,
|
|
||||||
chip_info.cores,
|
chip_info.cores,
|
||||||
(chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi/" : "",
|
(chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi/" : "",
|
||||||
(chip_info.features & CHIP_FEATURE_BT) ? "BT" : "",
|
(chip_info.features & CHIP_FEATURE_BT) ? "BT" : "",
|
||||||
(chip_info.features & CHIP_FEATURE_BLE) ? "BLE" : "",
|
(chip_info.features & CHIP_FEATURE_BLE) ? "BLE" : "",
|
||||||
(chip_info.features & CHIP_FEATURE_IEEE802154) ? ", 802.15.4 (Zigbee/Thread)" : "");
|
(chip_info.features & CHIP_FEATURE_IEEE802154)
|
||||||
|
? ", 802.15.4 (Zigbee/Thread)"
|
||||||
|
: "");
|
||||||
|
|
||||||
unsigned major_rev = chip_info.revision / 100;
|
unsigned major_rev = chip_info.revision / 100;
|
||||||
unsigned minor_rev = chip_info.revision % 100;
|
unsigned minor_rev = chip_info.revision % 100;
|
||||||
printf("silicon revision v%d.%d, ", major_rev, minor_rev);
|
printf("silicon revision v%d.%d, ", major_rev, minor_rev);
|
||||||
if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
|
if (esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
|
||||||
printf("Get flash size failed");
|
printf("Get flash size failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),
|
printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),
|
||||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
|
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded"
|
||||||
|
: "external");
|
||||||
|
|
||||||
printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());
|
printf("Minimum free heap size: %" PRIu32 " bytes\n",
|
||||||
|
esp_get_minimum_free_heap_size());
|
||||||
|
|
||||||
for (int i = 10; i >= 0; i--) {
|
// for (int i = 10; i >= 0; i--) {
|
||||||
printf("Restarting in %d seconds...\n", i);
|
// printf("Restarting in %d seconds...\n", i);
|
||||||
|
// vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
// }
|
||||||
|
int i = 0;
|
||||||
|
while (1) {
|
||||||
|
cdc_printf("hello %d", i++);
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
printf("Restarting now.\n");
|
printf("Restarting now.\n");
|
||||||
|
|||||||
171
main/utilities/usb_cherry/CherryUSB/.clang-format
Normal file
171
main/utilities/usb_cherry/CherryUSB/.clang-format
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
# clang-format configuration file. Intended for clang-format >= 11.0
|
||||||
|
#
|
||||||
|
# For more information, see:
|
||||||
|
#
|
||||||
|
# https://clang.llvm.org/docs/ClangFormat.html
|
||||||
|
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||||
|
#
|
||||||
|
---
|
||||||
|
# 语言: None, Cpp, Java, JavaScript, ObjC, Proto, TableGen, TextProto
|
||||||
|
Language: Cpp
|
||||||
|
# BasedOnStyle: LLVM
|
||||||
|
# 访问说明符(public、private等)的偏移
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
# 开括号(开圆括号、开尖括号、开方括号)后的对齐: Align, DontAlign, AlwaysBreak(总是在开括号后换行)
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
# 连续赋值时,对齐所有等号
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
# 对齐位域
|
||||||
|
AlignConsecutiveBitFields: true
|
||||||
|
# 连续声明时,对齐所有声明的变量名
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
# 连续宏时,进行对齐
|
||||||
|
AlignConsecutiveMacros: true
|
||||||
|
# 左对齐逃脱换行(使用反斜杠换行)的反斜杠
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
# 水平对齐二元和三元表达式的操作数
|
||||||
|
AlignOperands: true
|
||||||
|
# 对齐连续的尾随的注释
|
||||||
|
AlignTrailingComments: true
|
||||||
|
# 允许函数声明的所有参数在放在下一行
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
# 允许短的块放在同一行
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
# 允许短的case标签放在同一行
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
# 允许短的函数放在同一行: None, InlineOnly(定义在类中), Empty(空函数), Inline(定义在类中,空函数), All
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
# 允许短的if语句保持在同一行
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
# 允许短的循环保持在同一行
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
# 总是在定义返回类型后换行(deprecated)
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
# 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数),
|
||||||
|
# AllDefinitions(所有的定义,不包括声明), TopLevelDefinitions(所有的顶级函数的定义)
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
# 总是在多行string字面量前换行
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
# 总是在template声明后换行
|
||||||
|
AlwaysBreakTemplateDeclarations: false
|
||||||
|
# false表示函数实参要么都在同一行,要么都各自一行
|
||||||
|
BinPackArguments: true
|
||||||
|
# false表示所有形参要么都在同一行,要么都各自一行
|
||||||
|
BinPackParameters: true
|
||||||
|
# 大括号换行,只有当BreakBeforeBraces设置为Custom时才有效
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false # Unknown to clang-format-5.0
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true # Unknown to clang-format-4.0
|
||||||
|
SplitEmptyRecord: true # Unknown to clang-format-4.0
|
||||||
|
SplitEmptyNamespace: true # Unknown to clang-format-4.0
|
||||||
|
# 在二元运算符前换行: None(在操作符后换行), NonAssignment(在非赋值的操作符前换行), All(在操作符前换行)
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
|
||||||
|
# 在三元运算符前换行
|
||||||
|
BreakBeforeTernaryOperators: false
|
||||||
|
# 在构造函数的初始化列表的逗号前换行
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: false
|
||||||
|
# 每行字符的限制,0表示没有限制
|
||||||
|
ColumnLimit: 0
|
||||||
|
# 描述具有特殊意义的注释的正则表达式,它不应该被分割为多行或以其它方式改变
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false # Unknown to clang-format-4.0
|
||||||
|
# 构造函数的初始化列表要么都在同一行,要么都各自一行
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
# 构造函数的初始化列表的缩进宽度
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
# 延续的行的缩进宽度
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
# 去除C++11的列表初始化的大括号{后和}前的空格
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
|
# 继承最常用的指针和引用的对齐方式
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
# 关闭格式化
|
||||||
|
DisableFormat: false
|
||||||
|
ForEachMacros:
|
||||||
|
- 'SHELL_EXPORT_CMD'
|
||||||
|
|
||||||
|
# 自动检测函数的调用和定义是否被格式为每行一个参数(Experimental)
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
# 缩进case标签
|
||||||
|
IndentCaseLabels: true
|
||||||
|
# 缩进宽度
|
||||||
|
IndentWidth: 4
|
||||||
|
# 函数返回类型换行时,缩进函数声明或函数定义的函数名
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
# 保留在块开始处的空行
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
# 开始一个块的宏的正则表达式
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
# 结束一个块的宏的正则表达式
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
# 连续空行的最大数量
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
# 命名空间的缩进: None, Inner(缩进嵌套的命名空间中的内容), All
|
||||||
|
NamespaceIndentation: None
|
||||||
|
# 使用ObjC块时缩进宽度
|
||||||
|
ObjCBlockIndentWidth: 4
|
||||||
|
# 在ObjC的@property后添加一个空格
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
# 在ObjC的protocol列表前添加一个空格
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
# 在call(后对函数调用换行的penalty
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 30
|
||||||
|
# 在一个注释中引入换行的penalty
|
||||||
|
PenaltyBreakComment: 10
|
||||||
|
# 第一次在<<前换行的penalty
|
||||||
|
PenaltyBreakFirstLessLess: 0
|
||||||
|
# 在一个字符串字面量中引入换行的penalty
|
||||||
|
PenaltyBreakString: 10
|
||||||
|
# 对于每个在行字符数限制之外的字符的penalty
|
||||||
|
PenaltyExcessCharacter: 100
|
||||||
|
# 将函数的返回类型放到它自己的行的penalty
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
# 指针和引用的对齐: Left, Right, Middle
|
||||||
|
PointerAlignment: Right
|
||||||
|
# 允许重新排版注释
|
||||||
|
ReflowComments: false
|
||||||
|
# 允许排序#include
|
||||||
|
SortIncludes: false
|
||||||
|
# 在C风格类型转换后添加空格
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
# 在赋值运算符之前添加空格
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
# 开圆括号之前添加一个空格: Never, ControlStatements, Always
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
# 在空的圆括号中添加空格
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
# 在尾随的评论前添加的空格数(只适用于//)
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
# 在尖括号的<后和>前添加空格
|
||||||
|
SpacesInAngles: false
|
||||||
|
# 在容器(ObjC和JavaScript的数组和字典等)字面量中添加空格
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
# 在C风格类型转换的括号中添加空格
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
# 在圆括号的(后和)前添加空格
|
||||||
|
SpacesInParentheses: false
|
||||||
|
# 在方括号的[后和]前添加空格,lamda表达式和未指明大小的数组的声明不受影响
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
# 标准: Cpp03, Cpp11, Auto
|
||||||
|
Standard: Cpp03
|
||||||
|
# tab宽度
|
||||||
|
TabWidth: 4
|
||||||
|
# 使用tab字符: Never, ForIndentation, ForContinuationAndIndentation, Always
|
||||||
|
UseTab: Never
|
||||||
|
...
|
||||||
|
|
||||||
47
main/utilities/usb_cherry/CherryUSB/.gitattributes
vendored
Normal file
47
main/utilities/usb_cherry/CherryUSB/.gitattributes
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
*.c linguist-language=C
|
||||||
|
*.C linguist-language=C
|
||||||
|
*.h linguist-language=C
|
||||||
|
*.H linguist-language=C
|
||||||
|
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
*.S text
|
||||||
|
*.asm text
|
||||||
|
*.c text
|
||||||
|
*.cc text
|
||||||
|
*.cpp text
|
||||||
|
*.cxx text
|
||||||
|
*.h text
|
||||||
|
*.htm text
|
||||||
|
*.html text
|
||||||
|
*.in text
|
||||||
|
*.ld text
|
||||||
|
*.m4 text
|
||||||
|
*.mak text
|
||||||
|
*.mk text
|
||||||
|
*.py text
|
||||||
|
*.rb text
|
||||||
|
*.s text
|
||||||
|
*.sct text
|
||||||
|
*.sh text
|
||||||
|
*.txt text
|
||||||
|
*.xml text
|
||||||
|
SConscript text
|
||||||
|
Makefile text
|
||||||
|
AUTHORS text
|
||||||
|
COPYING text
|
||||||
|
|
||||||
|
*.LZO -text
|
||||||
|
*.Opt -text
|
||||||
|
*.Uv2 -text
|
||||||
|
*.ewp -text
|
||||||
|
*.eww -text
|
||||||
|
*.vcproj -text
|
||||||
|
*.bat -text
|
||||||
|
*.dos -text
|
||||||
|
*.icf -text
|
||||||
|
*.inf -text
|
||||||
|
*.ini -text
|
||||||
|
*.sct -text
|
||||||
|
*.xsd -text
|
||||||
|
Jamfile -text
|
||||||
16
main/utilities/usb_cherry/CherryUSB/.gitignore
vendored
Normal file
16
main/utilities/usb_cherry/CherryUSB/.gitignore
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
.vscode
|
||||||
|
**/Drivers/**
|
||||||
|
**/MDK-ARM/DebugConfig/**
|
||||||
|
**/MDK-ARM/RTE/**
|
||||||
|
**/MDK-ARM/stm32f103c8t6/**
|
||||||
|
**/MDK-ARM/stm32f429igt6/**
|
||||||
|
**/MDK-ARM/stm32h743vbt6/**
|
||||||
|
**/obj/**
|
||||||
|
**/RET/**
|
||||||
|
**/Listings/**
|
||||||
|
**/Objects/**
|
||||||
|
*.map
|
||||||
|
*.lst
|
||||||
|
*.uvguix.*
|
||||||
|
*.scvd
|
||||||
|
*.usb.tmp
|
||||||
201
main/utilities/usb_cherry/CherryUSB/LICENSE
Normal file
201
main/utilities/usb_cherry/CherryUSB/LICENSE
Normal file
@ -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.
|
||||||
136
main/utilities/usb_cherry/CherryUSB/README.md
Normal file
136
main/utilities/usb_cherry/CherryUSB/README.md
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
# CherryUSB
|
||||||
|
|
||||||
|
[中文版](./README_zh.md)
|
||||||
|
|
||||||
|
CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB ip.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Why choose
|
||||||
|
|
||||||
|
- Ip-oriented programming means the same usb ip's driver has no need to be written repeatedly, only the parts(such as `usb_xx_low_level_init`:including usb clock, usb gpio and usb irq configuration)that are not the same have to be implemented,
|
||||||
|
- Tree-based coding makes it easier for users to understand usb concept, enumeration process and class driver loading process
|
||||||
|
- Templating the class drivers makes it easier to use composite device and add custom drivers
|
||||||
|
- Simplifying the complex transfer of usb makes it easier for users to use usb as easily as uart and dma
|
||||||
|
- Fewer directory structures, fewer apis, fewer codesize, extreme usb 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 Test and Measurement CLASS (TMC)
|
||||||
|
- 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) | RAM (Byte) |
|
||||||
|
|:-----------:|:--------------:|:------------:|
|
||||||
|
|usbd_core.c | 3045 | 373 |
|
||||||
|
|usbd_cdc.c | 302 | 20 |
|
||||||
|
|usbd_msc.c | 2452 | 132 |
|
||||||
|
|usbd_hid.c | 784 | 201 |
|
||||||
|
|usbd_audio.c | 438 | 14 |
|
||||||
|
|usbd_video.c | 402 | 4 |
|
||||||
|
|
||||||
|
## 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 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) | RAM (Byte) |
|
||||||
|
|:-------------:|:--------------:|:------------:|
|
||||||
|
|usbh_core.c | 7992 | 472 |
|
||||||
|
|usbh_cdc_acm.c | 1208 | 4 |
|
||||||
|
|usbh_msc.c | 2239 | 4 |
|
||||||
|
|usbh_hid.c | 930 | 4 |
|
||||||
|
|usbh_hub.c | 3878 | 14 |
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
| Manufacturer | CHIP or Series | USB IP| Repo Url |
|
||||||
|
|:-------------:|:----------:|:----------:|:----------:|
|
||||||
|
|Bouffalolab | BL702 | bouffalolab|[bl_mcu_sdk](https://github.com/bouffalolab/bl_mcu_sdk/tree/master/examples/usb)|
|
||||||
|
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/es32)|
|
||||||
|
|AllwinnerTech | F1C100S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|
|
||||||
|
|ST | STM32F103C8T6 | fsdev |[stm32f103_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f103c8t6)|
|
||||||
|
|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)|
|
||||||
|
|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)|
|
||||||
|
|WCH | CH32V307 | ch32_usbfs |[ch32v307_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/ch32/usb_device/CH32V307VCT6)|
|
||||||
|
|WCH | CH57x | ch58x |[ch57x_repo](https://github.com/CherryUSB/cherryusb_ch57x)|
|
||||||
|
|Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/nuvoton/usb_device/nuc442)|
|
||||||
|
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|
|
||||||
|
|Geehy | APM32E10x APM32F0xx| fsdev |[apm32_repo](https://github.com/CherryUSB/cherryusb_apm32)|
|
||||||
|
|Mindmotion | MM32L3xx | mm32 |[mm32_repo](https://github.com/CherryUSB/cherryusb_mm32)|
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
QQ group: 642693751
|
||||||
135
main/utilities/usb_cherry/CherryUSB/README_zh.md
Normal file
135
main/utilities/usb_cherry/CherryUSB/README_zh.md
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
# CherryUSB
|
||||||
|
|
||||||
|
[English](./README.md)
|
||||||
|
|
||||||
|
CherryUSB 是一个小而美的、可移植性高的、用于嵌入式系统(带 USB ip)的 USB 主从协议栈。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 为什么选择
|
||||||
|
|
||||||
|
- 面向 ip 编程,使得相同的 usb ip 驱动无需重复编写,仅需实现不相同的部分(例如实现 `usb_xx_low_level_init`:包含 usb 时钟、usb gpio、usb 中断)
|
||||||
|
- 代码树状化编写,轻松理解 usb 概念、枚举过程、class 驱动加载
|
||||||
|
- Class 驱动模板化,轻松实现复合设备和自定义添加驱动
|
||||||
|
- 将 usb 的复杂传输简单化,使得用户能够像 uart、dma 一样轻松使用 usb
|
||||||
|
- 少量的目录结构,少量的 api,少量的 codesize,极致的 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)
|
||||||
|
- 支持 Test and Measurement CLASS (TMC)
|
||||||
|
- 支持 Remote NDIS (RNDIS)
|
||||||
|
- 支持 WINUSB1.0、WINUSB2.0(带 BOS )
|
||||||
|
- 支持 Vendor 类 class
|
||||||
|
|
||||||
|
CherryUSB Device 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||||
|
|
||||||
|
| file | FLASH (Byte) | RAM (Byte) |
|
||||||
|
|:-----------:|:--------------:|:------------:|
|
||||||
|
|usbd_core.c | 3045 | 373 |
|
||||||
|
|usbd_cdc.c | 302 | 20 |
|
||||||
|
|usbd_msc.c | 2452 | 132 |
|
||||||
|
|usbd_hid.c | 784 | 201 |
|
||||||
|
|usbd_audio.c | 438 | 14 |
|
||||||
|
|usbd_video.c | 402 | 4 |
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
- 支持 Remote NDIS (RNDIS)
|
||||||
|
- 支持 Vendor 类 class
|
||||||
|
|
||||||
|
同时,CherryUSB Host 协议栈还提供了 lsusb 的功能,借助 shell 插件可以查看所有挂载设备的信息,包括外部 hub 上的设备的信息。
|
||||||
|
|
||||||
|
CherryUSB Host 协议栈资源占用说明(GCC 10.2 with -O2):
|
||||||
|
|
||||||
|
| file | FLASH (Byte) | RAM (Byte) |
|
||||||
|
|:-------------:|:--------------:|:------------:|
|
||||||
|
|usbh_core.c | 7992 | 472 |
|
||||||
|
|usbh_cdc_acm.c | 1208 | 4 |
|
||||||
|
|usbh_msc.c | 2239 | 4 |
|
||||||
|
|usbh_hid.c | 930 | 4 |
|
||||||
|
|usbh_hub.c | 3878 | 14 |
|
||||||
|
|
||||||
|
## 文档教程
|
||||||
|
|
||||||
|
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** 框架编写,当前用于自动化生成描述符数组,后续会增加其他功能。
|
||||||
|
|
||||||
|
## 示例仓库
|
||||||
|
|
||||||
|
| 厂商 | 芯片或者系列 | USB IP| 仓库链接 |
|
||||||
|
|:-------------:|:----------:|:----------:|:----------:|
|
||||||
|
|Bouffalolab | BL702 | bouffalolab|[bl_mcu_sdk](https://github.com/bouffalolab/bl_mcu_sdk/tree/master/examples/usb)|
|
||||||
|
|Essemi | ES32F36xx | musb |[es32f369_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/es32)|
|
||||||
|
|AllwinnerTech | F1C100S | musb |[cherryusb_rtt_f1c100s](https://github.com/CherryUSB/cherryusb_rtt_f1c100s)|
|
||||||
|
|ST | STM32F103C8T6 | fsdev |[stm32f103_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/stm32/usb_device/stm32f103c8t6)|
|
||||||
|
|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)|
|
||||||
|
|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)|
|
||||||
|
|WCH | CH32V307 | ch32_usbfs |[ch32v307_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/ch32/usb_device/CH32V307VCT6)|
|
||||||
|
|WCH | CH57x | ch58x |[ch57x_repo](https://github.com/CherryUSB/cherryusb_ch57x)|
|
||||||
|
|Nuvoton | Nuc442 | nuvoton |[nuc442_repo](https://github.com/sakumisu/CherryUSB/tree/master/demo/nuvoton/usb_device/nuc442)|
|
||||||
|
|Nordicsemi | Nrf52840 | nrf5x |[nrf5x_repo](https://github.com/CherryUSB/cherryusb_nrf5x)|
|
||||||
|
|Geehy | APM32E10x APM32F0xx| fsdev |[apm32_repo](https://github.com/CherryUSB/cherryusb_apm32)|
|
||||||
|
|Mindmotion | MM32L3xx | mm32 |[mm32_repo](https://github.com/CherryUSB/cherryusb_mm32)|
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
QQ 群:642693751
|
||||||
108
main/utilities/usb_cherry/CherryUSB/SConscript
Normal file
108
main/utilities/usb_cherry/CherryUSB/SConscript
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
from building import *
|
||||||
|
|
||||||
|
cwd = GetCurrentDir()
|
||||||
|
path = [cwd + '/common']
|
||||||
|
path += [cwd + '/core']
|
||||||
|
src = []
|
||||||
|
|
||||||
|
CPPDEFINES = []
|
||||||
|
|
||||||
|
# USB DEVICE
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE']):
|
||||||
|
src += Glob('core/usbd_core.c')
|
||||||
|
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']):
|
||||||
|
CPPDEFINES+=['CONFIG_USB_HS']
|
||||||
|
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC']):
|
||||||
|
path += [cwd + '/class/cdc']
|
||||||
|
src += Glob('class/cdc/usbd_cdc.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID']):
|
||||||
|
path += [cwd + '/class/hid']
|
||||||
|
src += Glob('class/hid/usbd_hid.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC']):
|
||||||
|
path += [cwd + '/class/msc']
|
||||||
|
src += Glob('class/msc/usbd_msc.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO']):
|
||||||
|
path += [cwd + '/class/audio']
|
||||||
|
src += Glob('class/audio/usbd_audio.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_VIDEO']):
|
||||||
|
path += [cwd + '/class/video']
|
||||||
|
src += Glob('class/video/usbd_video.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_RNDIS']):
|
||||||
|
path += [cwd + '/class/wireless']
|
||||||
|
src += Glob('class/wireless/usbd_rndis.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_USING_DFU']):
|
||||||
|
path += [cwd + '/class/dfu']
|
||||||
|
src += Glob('class/dfu/usbd_dfu.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_USING_HUB']):
|
||||||
|
path += [cwd + '/class/hub']
|
||||||
|
src += Glob('class/hub/usbd_hub.c')
|
||||||
|
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_CDC_TEMPLATE']):
|
||||||
|
src += Glob('demo/cdc_acm_template.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID_MOUSE_TEMPLATE']):
|
||||||
|
src += Glob('demo/hid_mouse_template.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_HID_KEYBOARD_TEMPLATE']):
|
||||||
|
src += Glob('demo/hid_keyboard_template.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_MSC_TEMPLATE']):
|
||||||
|
src += Glob('demo/msc_ram_template.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V1_TEMPLATE']):
|
||||||
|
src += Glob('demo/audio_v1_mic_speaker_multichan_template.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_AUDIO_V2_TEMPLATE']):
|
||||||
|
src += Glob('demo/audio_v2_mic_speaker_multichan_template.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_VIDEO_TEMPLATE']):
|
||||||
|
src += Glob('demo/video_static_mjpeg_template.c')
|
||||||
|
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_FSDEV']):
|
||||||
|
src += Glob('port/fsdev/usb_dc_fsdev.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2']):
|
||||||
|
src += Glob('port/dwc2/usb_dc_dwc2.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_PORT_FS']):
|
||||||
|
CPPDEFINES += ['CONFIG_USB_DWC2_PORT=FS_PORT']
|
||||||
|
elif GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_PORT_HS']):
|
||||||
|
CPPDEFINES += ['CONFIG_USB_DWC2_PORT=HS_PORT']
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB']):
|
||||||
|
src += Glob('port/musb/usb_dc_musb.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_SUNXI']):
|
||||||
|
CPPDEFINES += ['CONFIG_USB_MUSB_SUNXI']
|
||||||
|
|
||||||
|
# USB HOST
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST']):
|
||||||
|
path += [cwd + '/osal']
|
||||||
|
path += [cwd + '/class/hub']
|
||||||
|
src += Glob('core/usbh_core.c')
|
||||||
|
src += Glob('osal/usb_osal_rtthread.c')
|
||||||
|
src += Glob('osal/usb_workq.c')
|
||||||
|
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_CDC']):
|
||||||
|
path += [cwd + '/class/cdc']
|
||||||
|
src += Glob('class/cdc/usbh_cdc_acm.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_HID']):
|
||||||
|
path += [cwd + '/class/hid']
|
||||||
|
src += Glob('class/hid/usbh_hid.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_MSC']):
|
||||||
|
path += [cwd + '/class/msc']
|
||||||
|
src += Glob('class/msc/usbh_msc.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_RNDIS']):
|
||||||
|
src += Glob('class/wireless/usbh_rndis.c')
|
||||||
|
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_HUB']):
|
||||||
|
src += Glob('class/hub/usbh_hub.c')
|
||||||
|
CPPDEFINES += ['CONFIG_USBHOST_HUB']
|
||||||
|
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_DWC2']):
|
||||||
|
src += Glob('port/dwc2/usb_hc_dwc2.c')
|
||||||
|
CPPDEFINES += ['CONFIG_USBHOST_HIGH_WORKQ']
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB']):
|
||||||
|
src += Glob('port/musb/usb_hc_musb.c')
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_SUNXI']):
|
||||||
|
CPPDEFINES += ['CONFIG_USB_MUSB_SUNXI']
|
||||||
|
|
||||||
|
if GetDepend(['PKG_CHERRYUSB_HOST_TEMPLATE']):
|
||||||
|
src += Glob('demo/usb_host.c')
|
||||||
|
|
||||||
|
group = DefineGroup('CherryUSB', src, depend = ['PKG_USING_CHERRYUSB'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
|
||||||
|
|
||||||
|
Return('group')
|
||||||
|
|
||||||
1096
main/utilities/usb_cherry/CherryUSB/class/audio/usb_audio.h
Normal file
1096
main/utilities/usb_cherry/CherryUSB/class/audio/usb_audio.h
Normal file
File diff suppressed because it is too large
Load Diff
477
main/utilities/usb_cherry/CherryUSB/class/audio/usbd_audio.c
Normal file
477
main/utilities/usb_cherry/CherryUSB/class/audio/usbd_audio.c
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_audio.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#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];
|
||||||
|
uint32_t sampling_freq[CONFIG_USBDEV_AUDIO_MAX_CHANNEL];
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
struct audio_entity_info {
|
||||||
|
usb_slist_t list;
|
||||||
|
uint8_t bDescriptorSubtype;
|
||||||
|
uint8_t bEntityId;
|
||||||
|
void *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
static usb_slist_t usbd_audio_entity_info_head = USB_SLIST_OBJECT_INIT(usbd_audio_entity_info_head);
|
||||||
|
|
||||||
|
const uint8_t default_sampling_freq_table[] = {
|
||||||
|
AUDIO_SAMPLE_FREQ_NUM(5),
|
||||||
|
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),
|
||||||
|
};
|
||||||
|
|
||||||
|
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||||
|
static int audio_custom_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_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_control = NULL;
|
||||||
|
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_control = (struct usbd_audio_attribute_control *)current_entity_info->priv;
|
||||||
|
|
||||||
|
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_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_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_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_control->volume[ch].vol_current, 2);
|
||||||
|
*len = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUDIO_REQUEST_GET_MIN:
|
||||||
|
memcpy(*data, ¤t_control->volume[ch].vol_min, 2);
|
||||||
|
*len = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUDIO_REQUEST_GET_MAX:
|
||||||
|
memcpy(*data, ¤t_control->volume[ch].vol_max, 2);
|
||||||
|
*len = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUDIO_REQUEST_GET_RES:
|
||||||
|
memcpy(*data, ¤t_control->volume[ch].vol_res, 2);
|
||||||
|
*len = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUDIO_REQUEST_SET_RES:
|
||||||
|
memcpy(¤t_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_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_control->volume_bCUR & 0XFF;
|
||||||
|
(*data)[1] = (current_control->volume_bCUR >> 8) & 0xff;
|
||||||
|
*len = 2;
|
||||||
|
} else {
|
||||||
|
volume = (((uint16_t)(*data)[1] << 8) | ((uint16_t)(*data)[0]));
|
||||||
|
current_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_control->volume.wNumSubRanges;
|
||||||
|
*((uint16_t *)(*data + 2)) = current_control->volume.subrange[ch].wMin;
|
||||||
|
*((uint16_t *)(*data + 4)) = current_control->volume.subrange[ch].wMax;
|
||||||
|
*((uint16_t *)(*data + 6)) = current_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) {
|
||||||
|
uint32_t current_sampling_freq = current_control->sampling_freq[ch];
|
||||||
|
memcpy(*data, ¤t_sampling_freq, sizeof(uint32_t));
|
||||||
|
*len = 4;
|
||||||
|
} else {
|
||||||
|
uint32_t sampling_freq;
|
||||||
|
memcpy(&sampling_freq, *data, setup->wLength);
|
||||||
|
current_control->sampling_freq[ch] = sampling_freq;
|
||||||
|
USB_LOG_DBG("Set ClockId:%d ch[%d] %d Hz\r\n", entity_id, ch, (int)sampling_freq);
|
||||||
|
usbd_audio_set_sampling_freq(entity_id, ch, sampling_freq);
|
||||||
|
}
|
||||||
|
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_SOF:
|
||||||
|
usbd_audio_sof_callback();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_audio_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
|
||||||
|
{
|
||||||
|
static usbd_class_t *last_class = NULL;
|
||||||
|
|
||||||
|
if (last_class != devclass) {
|
||||||
|
last_class = devclass;
|
||||||
|
usbd_class_register(devclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
intf->class_handler = audio_class_request_handler;
|
||||||
|
#if CONFIG_USBDEV_AUDIO_VERSION < 0x0200
|
||||||
|
intf->custom_handler = audio_custom_request_handler;
|
||||||
|
#else
|
||||||
|
intf->custom_handler = NULL;
|
||||||
|
#endif
|
||||||
|
intf->vendor_handler = NULL;
|
||||||
|
intf->notify_handler = audio_notify_handler;
|
||||||
|
usbd_class_add_interface(devclass, 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->sampling_freq[ch] = 16000;
|
||||||
|
control->volume_bCUR = 50;
|
||||||
|
control->mute_bCUR = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
entity_info->priv = control;
|
||||||
|
} else if (bDescriptorSubtype == AUDIO_CONTROL_CLOCK_SOURCE) {
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
__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;
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbd_audio_set_pitch(uint8_t ep, bool enable)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbd_audio_sof_callback(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
48
main/utilities/usb_cherry/CherryUSB/class/audio/usbd_audio.h
Normal file
48
main/utilities/usb_cherry/CherryUSB/class/audio/usbd_audio.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_audio.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBD_AUDIO_H_
|
||||||
|
#define _USBD_AUDIO_H_
|
||||||
|
|
||||||
|
#include "usb_audio.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void usbd_audio_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
|
||||||
|
|
||||||
|
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);
|
||||||
|
void usbd_audio_sof_callback(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _USB_AUDIO_H_ */
|
||||||
444
main/utilities/usb_cherry/CherryUSB/class/cdc/usb_cdc.h
Normal file
444
main/utilities/usb_cherry/CherryUSB/class/cdc/usb_cdc.h
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief USB Communications Device Class (CDC) public header
|
||||||
|
*
|
||||||
|
* Header follows the Class Definitions for
|
||||||
|
* Communications Devices Specification (CDC120-20101103-track.pdf),
|
||||||
|
* PSTN Devices Specification (PSTN120.pdf) and
|
||||||
|
* Ethernet Control Model Devices Specification (ECM120.pdf).
|
||||||
|
* Header is limited to ACM and ECM Subclasses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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 */ \
|
||||||
|
0x40, 0x00, /* wMaxPacketSize */ \
|
||||||
|
0x00, /* 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 */ \
|
||||||
|
0x00, 0x02, /* wMaxPacketSize */ \
|
||||||
|
0x00, /* 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_ */
|
||||||
158
main/utilities/usb_cherry/CherryUSB/class/cdc/usbd_cdc.c
Normal file
158
main/utilities/usb_cherry/CherryUSB/class/cdc/usbd_cdc.c
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_cdc.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#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" };
|
||||||
|
|
||||||
|
/* Device data structure */
|
||||||
|
struct cdc_acm_cfg_priv {
|
||||||
|
/* CDC ACM line coding properties. LE order */
|
||||||
|
struct cdc_line_coding line_coding;
|
||||||
|
/* CDC ACM line state bitmap, DTE side */
|
||||||
|
uint8_t line_state;
|
||||||
|
/* CDC ACM serial state bitmap, DCE side */
|
||||||
|
uint8_t serial_state;
|
||||||
|
/* CDC ACM notification sent status */
|
||||||
|
uint8_t notification_sent;
|
||||||
|
} usbd_cdc_acm_cfg;
|
||||||
|
|
||||||
|
static void usbd_cdc_acm_reset(void)
|
||||||
|
{
|
||||||
|
usbd_cdc_acm_cfg.line_coding.dwDTERate = 2000000;
|
||||||
|
usbd_cdc_acm_cfg.line_coding.bDataBits = 8;
|
||||||
|
usbd_cdc_acm_cfg.line_coding.bParityType = 0;
|
||||||
|
usbd_cdc_acm_cfg.line_coding.bCharFormat = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handler called for Class requests not handled by the USB stack.
|
||||||
|
*
|
||||||
|
* @param setup Information about the request to execute.
|
||||||
|
* @param len Size of the buffer.
|
||||||
|
* @param data Buffer containing the request result.
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
static int cdc_acm_class_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);
|
||||||
|
|
||||||
|
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(&usbd_cdc_acm_cfg.line_coding, *data, sizeof(usbd_cdc_acm_cfg.line_coding));
|
||||||
|
USB_LOG_DBG("CDC_SET_LINE_CODING <%d %d %s %s>\r\n",
|
||||||
|
usbd_cdc_acm_cfg.line_coding.dwDTERate,
|
||||||
|
usbd_cdc_acm_cfg.line_coding.bDataBits,
|
||||||
|
parity_name[usbd_cdc_acm_cfg.line_coding.bParityType],
|
||||||
|
stop_name[usbd_cdc_acm_cfg.line_coding.bCharFormat]);
|
||||||
|
usbd_cdc_acm_set_line_coding(usbd_cdc_acm_cfg.line_coding.dwDTERate, usbd_cdc_acm_cfg.line_coding.bDataBits,
|
||||||
|
usbd_cdc_acm_cfg.line_coding.bParityType, usbd_cdc_acm_cfg.line_coding.bCharFormat);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CDC_REQUEST_SET_CONTROL_LINE_STATE:
|
||||||
|
usbd_cdc_acm_cfg.line_state = (uint8_t)setup->wValue;
|
||||||
|
bool dtr = (setup->wValue & 0x01);
|
||||||
|
bool rts = (setup->wValue & 0x02);
|
||||||
|
USB_LOG_DBG("DTR 0x%x,RTS 0x%x\r\n",
|
||||||
|
dtr, rts);
|
||||||
|
usbd_cdc_acm_set_dtr(dtr);
|
||||||
|
usbd_cdc_acm_set_rts(rts);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CDC_REQUEST_GET_LINE_CODING:
|
||||||
|
*data = (uint8_t *)(&usbd_cdc_acm_cfg.line_coding);
|
||||||
|
*len = sizeof(usbd_cdc_acm_cfg.line_coding);
|
||||||
|
USB_LOG_DBG("CDC_GET_LINE_CODING %d %d %d %d\r\n",
|
||||||
|
usbd_cdc_acm_cfg.line_coding.dwDTERate,
|
||||||
|
usbd_cdc_acm_cfg.line_coding.bCharFormat,
|
||||||
|
usbd_cdc_acm_cfg.line_coding.bParityType,
|
||||||
|
usbd_cdc_acm_cfg.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:
|
||||||
|
usbd_cdc_acm_reset();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_cdc_add_acm_interface(usbd_class_t *devclass, usbd_interface_t *intf)
|
||||||
|
{
|
||||||
|
static usbd_class_t *last_class = NULL;
|
||||||
|
|
||||||
|
if (last_class != devclass) {
|
||||||
|
last_class = devclass;
|
||||||
|
usbd_class_register(devclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
intf->class_handler = cdc_acm_class_request_handler;
|
||||||
|
intf->custom_handler = NULL;
|
||||||
|
intf->vendor_handler = NULL;
|
||||||
|
intf->notify_handler = cdc_notify_handler;
|
||||||
|
usbd_class_add_interface(devclass, intf);
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbd_cdc_acm_set_line_coding(uint32_t baudrate, uint8_t databits, uint8_t parity, uint8_t stopbits)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
__WEAK void usbd_cdc_acm_set_dtr(bool dtr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
__WEAK void usbd_cdc_acm_set_rts(bool rts)
|
||||||
|
{
|
||||||
|
}
|
||||||
42
main/utilities/usb_cherry/CherryUSB/class/cdc/usbd_cdc.h
Normal file
42
main/utilities/usb_cherry/CherryUSB/class/cdc/usbd_cdc.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_cdc.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBD_CDC_H
|
||||||
|
#define _USBD_CDC_H
|
||||||
|
|
||||||
|
#include "usb_cdc.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void usbd_cdc_add_acm_interface(usbd_class_t *devclass, usbd_interface_t *intf);
|
||||||
|
|
||||||
|
void usbd_cdc_acm_set_line_coding(uint32_t baudrate, uint8_t databits, uint8_t parity, uint8_t stopbits);
|
||||||
|
void usbd_cdc_acm_set_dtr(bool dtr);
|
||||||
|
void usbd_cdc_acm_set_rts(bool rts);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USBD_CDC_H_ */
|
||||||
267
main/utilities/usb_cherry/CherryUSB/class/cdc/usbh_cdc_acm.c
Normal file
267
main/utilities/usb_cherry/CherryUSB/class/cdc/usbh_cdc_acm.c
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_cdc_acm.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_cdc_acm.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/ttyACM%d"
|
||||||
|
|
||||||
|
static uint32_t g_devinuse = 0;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: usbh_cdc_acm_devno_alloc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate a unique /dev/ttyACM[n] minor number in the range 0-31.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int usbh_cdc_acm_devno_alloc(struct usbh_cdc_acm *cdc_acm_class)
|
||||||
|
{
|
||||||
|
size_t flags;
|
||||||
|
int devno;
|
||||||
|
|
||||||
|
flags = usb_osal_enter_critical_section();
|
||||||
|
for (devno = 0; devno < 32; devno++) {
|
||||||
|
uint32_t bitno = 1 << devno;
|
||||||
|
if ((g_devinuse & bitno) == 0) {
|
||||||
|
g_devinuse |= bitno;
|
||||||
|
cdc_acm_class->minor = devno;
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
return -EMFILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: usbh_cdc_acm_devno_free
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free a /dev/ttyACM[n] minor number so that it can be used.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
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) {
|
||||||
|
size_t flags = usb_osal_enter_critical_section();
|
||||||
|
g_devinuse &= ~(1 << devno);
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
ret = usbh_control_transfer(cdc_acm_class->hport->ep0, setup, (uint8_t *)line_coding);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
memcpy(cdc_acm_class->linecoding, line_coding, sizeof(struct cdc_line_coding));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 *)line_coding);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
memcpy(cdc_acm_class->linecoding, line_coding, sizeof(struct cdc_line_coding));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
ret = usbh_control_transfer(cdc_acm_class->hport->ep0, setup, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cdc_acm_class->dtr = dtr;
|
||||||
|
cdc_acm_class->rts = rts;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_cdc_acm_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_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 = usb_iomalloc(sizeof(struct cdc_line_coding));
|
||||||
|
if (cdc_acm_class->linecoding == NULL) {
|
||||||
|
USB_LOG_ERR("Fail to alloc linecoding\r\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
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].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_ep_alloc(&cdc_acm_class->intin, &ep_cfg);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
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_ep_alloc(&cdc_acm_class->bulkin, &ep_cfg);
|
||||||
|
} else {
|
||||||
|
usbh_ep_alloc(&cdc_acm_class->bulkout, &ep_cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
extern int cdc_acm_test();
|
||||||
|
cdc_acm_test();
|
||||||
|
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) {
|
||||||
|
ret = usb_ep_cancel(cdc_acm_class->bulkin);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(cdc_acm_class->bulkin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdc_acm_class->bulkout) {
|
||||||
|
ret = usb_ep_cancel(cdc_acm_class->bulkout);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(cdc_acm_class->bulkout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cdc_acm_class->linecoding)
|
||||||
|
usb_iofree(cdc_acm_class->linecoding);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
56
main/utilities/usb_cherry/CherryUSB/class/cdc/usbh_cdc_acm.h
Normal file
56
main/utilities/usb_cherry/CherryUSB/class/cdc/usbh_cdc_acm.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_cdc_acm.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#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_epinfo_t bulkin; /* Bulk IN endpoint */
|
||||||
|
usbh_epinfo_t bulkout; /* Bulk OUT endpoint */
|
||||||
|
#ifdef CONFIG_USBHOST_CDC_ACM_NOTIFY
|
||||||
|
usbh_epinfo_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
|
||||||
103
main/utilities/usb_cherry/CherryUSB/class/dfu/usb_dfu.h
Normal file
103
main/utilities/usb_cherry/CherryUSB/class/dfu/usb_dfu.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief USB DFU Class public header
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
/** 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.*/
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _USB_DFU_H_ */
|
||||||
87
main/utilities/usb_cherry/CherryUSB/class/dfu/usbd_dfu.c
Normal file
87
main/utilities/usb_cherry/CherryUSB/class/dfu/usbd_dfu.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_dfu.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_dfu.h"
|
||||||
|
|
||||||
|
/* Device data structure */
|
||||||
|
struct dfu_cfg_priv {
|
||||||
|
struct dfu_info info;
|
||||||
|
} usbd_dfu_cfg;
|
||||||
|
|
||||||
|
static int dfu_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
|
{
|
||||||
|
USB_LOG_WRN("DFU Class request: "
|
||||||
|
"bRequest 0x%02x\r\n",
|
||||||
|
setup->bRequest);
|
||||||
|
|
||||||
|
switch (setup->bRequest) {
|
||||||
|
case DFU_REQUEST_DETACH:
|
||||||
|
break;
|
||||||
|
case DFU_REQUEST_DNLOAD:
|
||||||
|
break;
|
||||||
|
case DFU_REQUEST_UPLOAD:
|
||||||
|
break;
|
||||||
|
case DFU_REQUEST_GETSTATUS:
|
||||||
|
break;
|
||||||
|
case DFU_REQUEST_CLRSTATUS:
|
||||||
|
break;
|
||||||
|
case DFU_REQUEST_GETSTATE:
|
||||||
|
break;
|
||||||
|
case 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:
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_dfu_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
|
||||||
|
{
|
||||||
|
static usbd_class_t *last_class = NULL;
|
||||||
|
|
||||||
|
if (last_class != devclass) {
|
||||||
|
last_class = devclass;
|
||||||
|
usbd_class_register(devclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
intf->class_handler = dfu_class_request_handler;
|
||||||
|
intf->custom_handler = NULL;
|
||||||
|
intf->vendor_handler = NULL;
|
||||||
|
intf->notify_handler = dfu_notify_handler;
|
||||||
|
|
||||||
|
usbd_class_add_interface(devclass, intf);
|
||||||
|
}
|
||||||
38
main/utilities/usb_cherry/CherryUSB/class/dfu/usbd_dfu.h
Normal file
38
main/utilities/usb_cherry/CherryUSB/class/dfu/usbd_dfu.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_dfu.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBD_DFU_H_
|
||||||
|
#define _USBD_DFU_H_
|
||||||
|
|
||||||
|
#include "usb_dfu.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void usbd_dfu_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _USBD_DFU_H_ */
|
||||||
708
main/utilities/usb_cherry/CherryUSB/class/hid/usb_hid.h
Normal file
708
main/utilities/usb_cherry/CherryUSB/class/hid/usb_hid.h
Normal file
@ -0,0 +1,708 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Human Interface Device (HID) Class public header
|
||||||
|
*
|
||||||
|
* Header follows Device Class Definition for Human Interface Devices (HID)
|
||||||
|
* Version 1.11 document (HID1_11-1.pdf).
|
||||||
|
*/
|
||||||
|
#ifndef __HID_H_
|
||||||
|
#define __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)
|
||||||
|
|
||||||
|
/* 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 USBHID_MODIFIER_* 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 USBHID_MOUSEIN_* 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 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HID keyboard button codes.
|
||||||
|
*/
|
||||||
|
enum hid_kbd_code {
|
||||||
|
HID_KEY_A = 4,
|
||||||
|
HID_KEY_B = 5,
|
||||||
|
HID_KEY_C = 6,
|
||||||
|
HID_KEY_D = 7,
|
||||||
|
HID_KEY_E = 8,
|
||||||
|
HID_KEY_F = 9,
|
||||||
|
HID_KEY_G = 10,
|
||||||
|
HID_KEY_H = 11,
|
||||||
|
HID_KEY_I = 12,
|
||||||
|
HID_KEY_J = 13,
|
||||||
|
HID_KEY_K = 14,
|
||||||
|
HID_KEY_L = 15,
|
||||||
|
HID_KEY_M = 16,
|
||||||
|
HID_KEY_N = 17,
|
||||||
|
HID_KEY_O = 18,
|
||||||
|
HID_KEY_P = 19,
|
||||||
|
HID_KEY_Q = 20,
|
||||||
|
HID_KEY_R = 21,
|
||||||
|
HID_KEY_S = 22,
|
||||||
|
HID_KEY_T = 23,
|
||||||
|
HID_KEY_U = 24,
|
||||||
|
HID_KEY_V = 25,
|
||||||
|
HID_KEY_W = 26,
|
||||||
|
HID_KEY_X = 27,
|
||||||
|
HID_KEY_Y = 28,
|
||||||
|
HID_KEY_Z = 29,
|
||||||
|
HID_KEY_1 = 30,
|
||||||
|
HID_KEY_2 = 31,
|
||||||
|
HID_KEY_3 = 32,
|
||||||
|
HID_KEY_4 = 33,
|
||||||
|
HID_KEY_5 = 34,
|
||||||
|
HID_KEY_6 = 35,
|
||||||
|
HID_KEY_7 = 36,
|
||||||
|
HID_KEY_8 = 37,
|
||||||
|
HID_KEY_9 = 38,
|
||||||
|
HID_KEY_0 = 39,
|
||||||
|
HID_KEY_ENTER = 40,
|
||||||
|
HID_KEY_ESC = 41,
|
||||||
|
HID_KEY_BACKSPACE = 42,
|
||||||
|
HID_KEY_TAB = 43,
|
||||||
|
HID_KEY_SPACE = 44,
|
||||||
|
HID_KEY_MINUS = 45,
|
||||||
|
HID_KEY_EQUAL = 46,
|
||||||
|
HID_KEY_LEFTBRACE = 47,
|
||||||
|
HID_KEY_RIGHTBRACE = 48,
|
||||||
|
HID_KEY_BACKSLASH = 49,
|
||||||
|
HID_KEY_HASH = 50, /* Non-US # and ~ */
|
||||||
|
HID_KEY_SEMICOLON = 51,
|
||||||
|
HID_KEY_APOSTROPHE = 52,
|
||||||
|
HID_KEY_GRAVE = 53,
|
||||||
|
HID_KEY_COMMA = 54,
|
||||||
|
HID_KEY_DOT = 55,
|
||||||
|
HID_KEY_SLASH = 56,
|
||||||
|
HID_KEY_CAPSLOCK = 57,
|
||||||
|
HID_KEY_F1 = 58,
|
||||||
|
HID_KEY_F2 = 59,
|
||||||
|
HID_KEY_F3 = 60,
|
||||||
|
HID_KEY_F4 = 61,
|
||||||
|
HID_KEY_F5 = 62,
|
||||||
|
HID_KEY_F6 = 63,
|
||||||
|
HID_KEY_F7 = 64,
|
||||||
|
HID_KEY_F8 = 65,
|
||||||
|
HID_KEY_F9 = 66,
|
||||||
|
HID_KEY_F10 = 67,
|
||||||
|
HID_KEY_F11 = 68,
|
||||||
|
HID_KEY_F12 = 69,
|
||||||
|
HID_KEY_SYSRQ = 70, /* PRINTSCREEN */
|
||||||
|
HID_KEY_SCROLLLOCK = 71,
|
||||||
|
HID_KEY_PAUSE = 72,
|
||||||
|
HID_KEY_INSERT = 73,
|
||||||
|
HID_KEY_HOME = 74,
|
||||||
|
HID_KEY_PAGEUP = 75,
|
||||||
|
HID_KEY_DELETE = 76,
|
||||||
|
HID_KEY_END = 77,
|
||||||
|
HID_KEY_PAGEDOWN = 78,
|
||||||
|
HID_KEY_RIGHT = 79,
|
||||||
|
HID_KEY_LEFT = 80,
|
||||||
|
HID_KEY_DOWN = 81,
|
||||||
|
HID_KEY_UP = 82,
|
||||||
|
HID_KEY_NUMLOCK = 83,
|
||||||
|
HID_KEY_KPSLASH = 84, /* NUMPAD DIVIDE */
|
||||||
|
HID_KEY_KPASTERISK = 85, /* NUMPAD MULTIPLY */
|
||||||
|
HID_KEY_KPMINUS = 86,
|
||||||
|
HID_KEY_KPPLUS = 87,
|
||||||
|
HID_KEY_KPENTER = 88,
|
||||||
|
HID_KEY_KP_1 = 89,
|
||||||
|
HID_KEY_KP_2 = 90,
|
||||||
|
HID_KEY_KP_3 = 91,
|
||||||
|
HID_KEY_KP_4 = 92,
|
||||||
|
HID_KEY_KP_5 = 93,
|
||||||
|
HID_KEY_KP_6 = 94,
|
||||||
|
HID_KEY_KP_7 = 95,
|
||||||
|
HID_KEY_KP_8 = 96,
|
||||||
|
HID_KEY_KP_9 = 97,
|
||||||
|
HID_KEY_KP_0 = 98,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HID keyboard modifiers.
|
||||||
|
*/
|
||||||
|
enum hid_kbd_modifier {
|
||||||
|
HID_KBD_MODIFIER_NONE = 0x00,
|
||||||
|
HID_KBD_MODIFIER_LEFT_CTRL = 0x01,
|
||||||
|
HID_KBD_MODIFIER_LEFT_SHIFT = 0x02,
|
||||||
|
HID_KBD_MODIFIER_LEFT_ALT = 0x04,
|
||||||
|
HID_KBD_MODIFIER_LEFT_UI = 0x08,
|
||||||
|
HID_KBD_MODIFIER_RIGHT_CTRL = 0x10,
|
||||||
|
HID_KBD_MODIFIER_RIGHT_SHIFT = 0x20,
|
||||||
|
HID_KBD_MODIFIER_RIGHT_ALT = 0x40,
|
||||||
|
HID_KBD_MODIFIER_RIGHT_UI = 0x80,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HID keyboard LEDs.
|
||||||
|
*/
|
||||||
|
enum hid_kbd_led {
|
||||||
|
HID_KBD_LED_NUM_LOCK = 0x01,
|
||||||
|
HID_KBD_LED_CAPS_LOCK = 0x02,
|
||||||
|
HID_KBD_LED_SCROLL_LOCK = 0x04,
|
||||||
|
HID_KBD_LED_COMPOSE = 0x08,
|
||||||
|
HID_KBD_LED_KANA = 0x10,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __HID_H_ */
|
||||||
285
main/utilities/usb_cherry/CherryUSB/class/hid/usbd_hid.c
Normal file
285
main/utilities/usb_cherry/CherryUSB/class/hid/usbd_hid.c
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_hid.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_hid.h"
|
||||||
|
|
||||||
|
#define HID_STATE_IDLE 0
|
||||||
|
#define HID_STATE_BUSY 1
|
||||||
|
|
||||||
|
struct usbd_hid_cfg_priv {
|
||||||
|
const uint8_t *hid_descriptor;
|
||||||
|
const uint8_t *hid_report_descriptor;
|
||||||
|
uint32_t hid_report_descriptor_len;
|
||||||
|
uint8_t current_intf_num;
|
||||||
|
uint8_t hid_state;
|
||||||
|
uint8_t report;
|
||||||
|
uint8_t idle_state;
|
||||||
|
uint8_t protocol;
|
||||||
|
|
||||||
|
uint8_t (*get_report_callback)(uint8_t report_id, uint8_t report_type);
|
||||||
|
void (*set_report_callback)(uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len);
|
||||||
|
uint8_t (*get_idle_callback)(uint8_t report_id);
|
||||||
|
void (*set_idle_callback)(uint8_t report_id, uint8_t duration);
|
||||||
|
void (*set_protocol_callback)(uint8_t protocol);
|
||||||
|
uint8_t (*get_protocol_callback)(void);
|
||||||
|
|
||||||
|
usb_slist_t list;
|
||||||
|
} usbd_hid_cfg[4];
|
||||||
|
|
||||||
|
static usb_slist_t usbd_hid_class_head = USB_SLIST_OBJECT_INIT(usbd_hid_class_head);
|
||||||
|
|
||||||
|
static void usbd_hid_reset(void)
|
||||||
|
{
|
||||||
|
usb_slist_t *i;
|
||||||
|
usb_slist_for_each(i, &usbd_hid_class_head)
|
||||||
|
{
|
||||||
|
struct usbd_hid_cfg_priv *hid_intf = usb_slist_entry(i, struct usbd_hid_cfg_priv, list);
|
||||||
|
hid_intf->hid_state = HID_STATE_IDLE;
|
||||||
|
hid_intf->report = 0;
|
||||||
|
hid_intf->idle_state = 0;
|
||||||
|
hid_intf->protocol = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
struct usbd_hid_cfg_priv *current_hid_intf = NULL;
|
||||||
|
usb_slist_t *i;
|
||||||
|
usb_slist_for_each(i, &usbd_hid_class_head)
|
||||||
|
{
|
||||||
|
struct usbd_hid_cfg_priv *hid_intf = usb_slist_entry(i, struct usbd_hid_cfg_priv, list);
|
||||||
|
|
||||||
|
if (hid_intf->current_intf_num == intf_num) {
|
||||||
|
current_hid_intf = hid_intf;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_hid_intf == NULL) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (value) {
|
||||||
|
case HID_DESCRIPTOR_TYPE_HID:
|
||||||
|
USB_LOG_INFO("get HID Descriptor\r\n");
|
||||||
|
*data = (uint8_t *)current_hid_intf->hid_descriptor;
|
||||||
|
*len = current_hid_intf->hid_descriptor[0];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HID_DESCRIPTOR_TYPE_HID_REPORT:
|
||||||
|
USB_LOG_INFO("get Report Descriptor\r\n");
|
||||||
|
*data = (uint8_t *)current_hid_intf->hid_report_descriptor;
|
||||||
|
*len = current_hid_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_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);
|
||||||
|
|
||||||
|
struct usbd_hid_cfg_priv *current_hid_intf = NULL;
|
||||||
|
usb_slist_t *i;
|
||||||
|
usb_slist_for_each(i, &usbd_hid_class_head)
|
||||||
|
{
|
||||||
|
struct usbd_hid_cfg_priv *hid_intf = usb_slist_entry(i, struct usbd_hid_cfg_priv, list);
|
||||||
|
uint8_t intf_num = (uint8_t)setup->wIndex;
|
||||||
|
if (hid_intf->current_intf_num == intf_num) {
|
||||||
|
current_hid_intf = hid_intf;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_hid_intf == NULL) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (setup->bRequest) {
|
||||||
|
case HID_REQUEST_GET_REPORT:
|
||||||
|
if (current_hid_intf->get_report_callback)
|
||||||
|
current_hid_intf->report = current_hid_intf->get_report_callback(LO_BYTE(setup->wValue), HI_BYTE(setup->wValue)); /*report id ,report type*/
|
||||||
|
|
||||||
|
*data = (uint8_t *)¤t_hid_intf->report;
|
||||||
|
*len = 1;
|
||||||
|
break;
|
||||||
|
case HID_REQUEST_GET_IDLE:
|
||||||
|
if (current_hid_intf->get_idle_callback)
|
||||||
|
current_hid_intf->idle_state = current_hid_intf->get_idle_callback(LO_BYTE(setup->wValue));
|
||||||
|
|
||||||
|
*data = (uint8_t *)¤t_hid_intf->idle_state;
|
||||||
|
*len = 1;
|
||||||
|
break;
|
||||||
|
case HID_REQUEST_GET_PROTOCOL:
|
||||||
|
if (current_hid_intf->get_protocol_callback)
|
||||||
|
current_hid_intf->protocol = current_hid_intf->get_protocol_callback();
|
||||||
|
|
||||||
|
*data = (uint8_t *)¤t_hid_intf->protocol;
|
||||||
|
*len = 1;
|
||||||
|
break;
|
||||||
|
case HID_REQUEST_SET_REPORT:
|
||||||
|
if (current_hid_intf->set_report_callback)
|
||||||
|
current_hid_intf->set_report_callback(LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len); /*report id ,report type,report,report len*/
|
||||||
|
|
||||||
|
current_hid_intf->report = **data;
|
||||||
|
break;
|
||||||
|
case HID_REQUEST_SET_IDLE:
|
||||||
|
if (current_hid_intf->set_idle_callback)
|
||||||
|
current_hid_intf->set_idle_callback(LO_BYTE(setup->wValue), HI_BYTE(setup->wIndex)); /*report id ,duration*/
|
||||||
|
|
||||||
|
current_hid_intf->idle_state = HI_BYTE(setup->wIndex);
|
||||||
|
break;
|
||||||
|
case HID_REQUEST_SET_PROTOCOL:
|
||||||
|
if (current_hid_intf->set_protocol_callback)
|
||||||
|
current_hid_intf->set_protocol_callback(LO_BYTE(setup->wValue)); /*protocol*/
|
||||||
|
|
||||||
|
current_hid_intf->protocol = LO_BYTE(setup->wValue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
USB_LOG_WRN("Unhandled HID Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hid_notify_handler(uint8_t event, void *arg)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case USBD_EVENT_RESET:
|
||||||
|
usbd_hid_reset();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_hid_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
|
||||||
|
{
|
||||||
|
static usbd_class_t *last_class = NULL;
|
||||||
|
static uint8_t hid_num = 0;
|
||||||
|
if (last_class != devclass) {
|
||||||
|
last_class = devclass;
|
||||||
|
usbd_class_register(devclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
intf->class_handler = hid_class_request_handler;
|
||||||
|
intf->custom_handler = hid_custom_request_handler;
|
||||||
|
intf->vendor_handler = NULL;
|
||||||
|
intf->notify_handler = hid_notify_handler;
|
||||||
|
usbd_class_add_interface(devclass, intf);
|
||||||
|
|
||||||
|
usbd_hid_cfg[hid_num].current_intf_num = intf->intf_num;
|
||||||
|
usb_slist_add_tail(&usbd_hid_class_head, &usbd_hid_cfg[hid_num].list);
|
||||||
|
hid_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_hid_descriptor_register(uint8_t intf_num, const uint8_t *desc)
|
||||||
|
{
|
||||||
|
// usbd_hid_cfg.hid_descriptor = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len)
|
||||||
|
{
|
||||||
|
usb_slist_t *i;
|
||||||
|
usb_slist_for_each(i, &usbd_hid_class_head)
|
||||||
|
{
|
||||||
|
struct usbd_hid_cfg_priv *hid_intf = usb_slist_entry(i, struct usbd_hid_cfg_priv, list);
|
||||||
|
|
||||||
|
if (hid_intf->current_intf_num == intf_num) {
|
||||||
|
hid_intf->hid_report_descriptor = desc;
|
||||||
|
hid_intf->hid_report_descriptor_len = desc_len;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_hid_set_request_callback(uint8_t intf_num,
|
||||||
|
uint8_t (*get_report_callback)(uint8_t report_id, uint8_t report_type),
|
||||||
|
void (*set_report_callback)(uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len),
|
||||||
|
uint8_t (*get_idle_callback)(uint8_t report_id),
|
||||||
|
void (*set_idle_callback)(uint8_t report_id, uint8_t duration),
|
||||||
|
void (*set_protocol_callback)(uint8_t protocol),
|
||||||
|
uint8_t (*get_protocol_callback)(void))
|
||||||
|
{
|
||||||
|
usb_slist_t *i;
|
||||||
|
usb_slist_for_each(i, &usbd_hid_class_head)
|
||||||
|
{
|
||||||
|
struct usbd_hid_cfg_priv *hid_intf = usb_slist_entry(i, struct usbd_hid_cfg_priv, list);
|
||||||
|
|
||||||
|
if (hid_intf->current_intf_num == intf_num) {
|
||||||
|
if (get_report_callback)
|
||||||
|
hid_intf->get_report_callback = get_report_callback;
|
||||||
|
if (set_report_callback)
|
||||||
|
hid_intf->set_report_callback = set_report_callback;
|
||||||
|
if (get_idle_callback)
|
||||||
|
hid_intf->get_idle_callback = get_idle_callback;
|
||||||
|
if (set_idle_callback)
|
||||||
|
hid_intf->set_idle_callback = set_idle_callback;
|
||||||
|
if (set_protocol_callback)
|
||||||
|
hid_intf->set_protocol_callback = set_protocol_callback;
|
||||||
|
if (get_protocol_callback)
|
||||||
|
hid_intf->get_protocol_callback = get_protocol_callback;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_hid_reset_state(void)
|
||||||
|
{
|
||||||
|
// usbd_hid_cfg.hid_state = HID_STATE_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_hid_send_report(uint8_t ep, uint8_t *data, uint8_t len)
|
||||||
|
{
|
||||||
|
// if(usbd_hid_cfg.hid_state == HID_STATE_IDLE)
|
||||||
|
// {
|
||||||
|
// usbd_hid_cfg.hid_state = HID_STATE_BUSY;
|
||||||
|
// usbd_ep_write(ep, data, len, NULL);
|
||||||
|
// }
|
||||||
|
}
|
||||||
50
main/utilities/usb_cherry/CherryUSB/class/hid/usbd_hid.h
Normal file
50
main/utilities/usb_cherry/CherryUSB/class/hid/usbd_hid.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_hid.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBD_HID_H_
|
||||||
|
#define _USBD_HID_H_
|
||||||
|
|
||||||
|
#include "usb_hid.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
void usbd_hid_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
|
||||||
|
void usbd_hid_reset_state(void);
|
||||||
|
void usbd_hid_send_report(uint8_t ep, uint8_t *data, uint8_t len);
|
||||||
|
|
||||||
|
void usbd_hid_set_request_callback(uint8_t intf_num,
|
||||||
|
uint8_t (*get_report_callback)(uint8_t report_id, uint8_t report_type),
|
||||||
|
void (*set_report_callback)(uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len),
|
||||||
|
uint8_t (*get_idle_callback)(uint8_t report_id),
|
||||||
|
void (*set_idle_callback)(uint8_t report_id, uint8_t duration),
|
||||||
|
void (*set_protocol_callback)(uint8_t protocol),
|
||||||
|
uint8_t (*get_protocol_callback)(void));
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _USBD_HID_H_ */
|
||||||
230
main/utilities/usb_cherry/CherryUSB/class/hid/usbh_hid.c
Normal file
230
main/utilities/usb_cherry/CherryUSB/class/hid/usbh_hid.c
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_hid.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_hid.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/input%d"
|
||||||
|
|
||||||
|
static uint32_t g_devinuse = 0;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: usbh_hid_devno_alloc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate a unique /dev/input[n] minor number in the range 0-31.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int usbh_hid_devno_alloc(struct usbh_hid *hid_class)
|
||||||
|
{
|
||||||
|
size_t flags;
|
||||||
|
int devno;
|
||||||
|
|
||||||
|
flags = usb_osal_enter_critical_section();
|
||||||
|
for (devno = 0; devno < 32; devno++) {
|
||||||
|
uint32_t bitno = 1 << devno;
|
||||||
|
if ((g_devinuse & bitno) == 0) {
|
||||||
|
g_devinuse |= bitno;
|
||||||
|
hid_class->minor = devno;
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
return -EMFILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: usbh_hid_devno_free
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free a /dev/input[n] minor number so that it can be used.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void usbh_hid_devno_free(struct usbh_hid *hid_class)
|
||||||
|
{
|
||||||
|
int devno = hid_class->minor;
|
||||||
|
|
||||||
|
if (devno >= 0 && devno < 32) {
|
||||||
|
size_t flags = usb_osal_enter_critical_section();
|
||||||
|
g_devinuse &= ~(1 << devno);
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_hid_get_report_descriptor(struct usbh_hid *hid_class, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = hid_class->hport->setup;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return usbh_control_transfer(hid_class->hport->ep0, setup, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = report_id;
|
||||||
|
setup->wIndex = (duration << 8) | 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return usbh_control_transfer(hid_class->hport->ep0, setup, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_hid_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_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;
|
||||||
|
|
||||||
|
ret = usbh_hid_set_idle(hid_class, 0, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *report_buffer = usb_iomalloc(128);
|
||||||
|
ret = usbh_hid_get_report_descriptor(hid_class, report_buffer);
|
||||||
|
if (ret < 0) {
|
||||||
|
usb_iofree(report_buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
usb_iofree(report_buffer);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < hport->config.intf[intf].intf_desc.bNumEndpoints; i++) {
|
||||||
|
ep_desc = &hport->config.intf[intf].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_ep_alloc(&hid_class->intin, &ep_cfg);
|
||||||
|
} else {
|
||||||
|
usbh_ep_alloc(&hid_class->intout, &ep_cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
extern int hid_test();
|
||||||
|
hid_test();
|
||||||
|
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) {
|
||||||
|
ret = usb_ep_cancel(hid_class->intin);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(hid_class->intin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hid_class->intout) {
|
||||||
|
ret = usb_ep_cancel(hid_class->intout);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(hid_class->intout);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN);
|
||||||
|
hport->config.intf[intf].priv = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
48
main/utilities/usb_cherry/CherryUSB/class/hid/usbh_hid.h
Normal file
48
main/utilities/usb_cherry/CherryUSB/class/hid/usbh_hid.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_hid.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBH_HID_H
|
||||||
|
#define _USBH_HID_H
|
||||||
|
|
||||||
|
#include "usb_hid.h"
|
||||||
|
|
||||||
|
struct usbh_hid {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
|
||||||
|
uint8_t intf; /* interface number */
|
||||||
|
uint8_t minor;
|
||||||
|
usbh_epinfo_t intin; /* INTR IN endpoint */
|
||||||
|
usbh_epinfo_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
|
||||||
120
main/utilities/usb_cherry/CherryUSB/class/hub/usb_hub.h
Normal file
120
main/utilities/usb_cherry/CherryUSB/class/hub/usb_hub.h
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief USB HUB Device Class public header
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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_ */
|
||||||
106
main/utilities/usb_cherry/CherryUSB/class/hub/usbd_hub.c
Normal file
106
main/utilities/usb_cherry/CherryUSB/class/hub/usbd_hub.c
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_hub.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_hub.h"
|
||||||
|
|
||||||
|
static struct usb_hub_descriptor hub_desc = {
|
||||||
|
.bLength = 0x09,
|
||||||
|
.bDescriptorType = HUB_DESCRIPTOR_TYPE_HUB,
|
||||||
|
.bNbrPorts = 4,
|
||||||
|
.wHubCharacteristics = HUB_CHAR_PORTIND | HUB_CHAR_TTTT_32_BITS,
|
||||||
|
.bPwrOn2PwrGood = 0x32,
|
||||||
|
.bHubContrCurrent = 0x64,
|
||||||
|
.DeviceRemovable = 0x00,
|
||||||
|
.PortPwrCtrlMask = 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
static int hub_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
|
{
|
||||||
|
USBD_LOG_DBG("HUB Class Custom request: "
|
||||||
|
"bRequest 0x%02x\r\n",
|
||||||
|
setup->bRequest);
|
||||||
|
|
||||||
|
if (((setup->bmRequestType & USB_REQUEST_TYPE_MASK) == USB_REQUEST_CLASS) &&
|
||||||
|
((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_DEVICE) &&
|
||||||
|
(setup->bRequest == HUB_REQUEST_GET_DESCRIPTOR)) {
|
||||||
|
uint8_t value = (uint8_t)(setup->wValue >> 8);
|
||||||
|
uint8_t intf_num = (uint8_t)setup->wIndex;
|
||||||
|
|
||||||
|
switch (value) {
|
||||||
|
case HUB_DESCRIPTOR_TYPE_HUB:
|
||||||
|
*data = (uint8_t *)&hub_desc;
|
||||||
|
*len = hub_desc.bLength;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (((setup->bmRequestType & USB_REQUEST_TYPE_MASK) == USB_REQUEST_CLASS) &&
|
||||||
|
((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_OTHER)) {
|
||||||
|
uint8_t hub_port_feature = (uint8_t)(setup->wValue);
|
||||||
|
uint8_t hub_port = (uint8_t)setup->wIndex;
|
||||||
|
|
||||||
|
switch (setup->bRequest) {
|
||||||
|
case HUB_REQUEST_GET_STATUS:
|
||||||
|
break;
|
||||||
|
case HUB_REQUEST_CLEAR_FEATURE:
|
||||||
|
break;
|
||||||
|
case HUB_REQUEST_SET_FEATURE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
USBD_LOG_WRN("Unhandled HUB Class Custom bRequest 0x%02x\r\n", setup->bRequest);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hub_notify_handler(uint8_t event, void *arg)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case USBD_EVENT_RESET:
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_hub_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
|
||||||
|
{
|
||||||
|
static usbd_class_t *last_class = NULL;
|
||||||
|
|
||||||
|
if (last_class != devclass) {
|
||||||
|
last_class = devclass;
|
||||||
|
usbd_class_register(devclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
intf->class_handler = NULL;
|
||||||
|
intf->custom_handler = hub_custom_request_handler;
|
||||||
|
intf->vendor_handler = NULL;
|
||||||
|
intf->notify_handler = hub_notify_handler;
|
||||||
|
usbd_class_add_interface(devclass, intf);
|
||||||
|
}
|
||||||
38
main/utilities/usb_cherry/CherryUSB/class/hub/usbd_hub.h
Normal file
38
main/utilities/usb_cherry/CherryUSB/class/hub/usbd_hub.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_hub.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBD_HUB_H_
|
||||||
|
#define _USBD_HUB_H_
|
||||||
|
|
||||||
|
#include "usb_hub.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void usbd_hub_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _USBD_HUB_H_ */
|
||||||
519
main/utilities/usb_cherry/CherryUSB/class/hub/usbh_hub.c
Normal file
519
main/utilities/usb_cherry/CherryUSB/class/hub/usbh_hub.c
Normal file
@ -0,0 +1,519 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_hub.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_hub.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/hub%d"
|
||||||
|
|
||||||
|
static uint32_t g_devinuse = 0;
|
||||||
|
|
||||||
|
usb_slist_t hub_class_head = USB_SLIST_OBJECT_INIT(hub_class_head);
|
||||||
|
|
||||||
|
USB_MEM_ALIGN32 uint8_t int_buffer[6][USBH_HUB_INTIN_BUFSIZE];
|
||||||
|
extern void usbh_external_hport_connect(struct usbh_hubport *hport);
|
||||||
|
extern void usbh_external_hport_disconnect(struct usbh_hubport *hport);
|
||||||
|
extern void usbh_hport_activate(struct usbh_hubport *hport);
|
||||||
|
extern void usbh_hport_deactivate(struct usbh_hubport *hport);
|
||||||
|
|
||||||
|
static void usbh_external_hub_callback(void *arg, int nbytes);
|
||||||
|
|
||||||
|
static inline void usbh_hub_register(struct usbh_hub *hub_class)
|
||||||
|
{
|
||||||
|
usb_slist_add_tail(&hub_class_head, &hub_class->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void usbh_hub_unregister(struct usbh_hub *hub_class)
|
||||||
|
{
|
||||||
|
usb_slist_remove(&hub_class_head, &hub_class->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: usbh_hub_devno_alloc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate a unique /dev/hub[n] minor number in the range 2-31.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int usbh_hub_devno_alloc(struct usbh_hub *hub_class)
|
||||||
|
{
|
||||||
|
size_t flags;
|
||||||
|
int devno;
|
||||||
|
|
||||||
|
flags = usb_osal_enter_critical_section();
|
||||||
|
for (devno = 2; devno < 32; devno++) {
|
||||||
|
uint32_t bitno = 1 << devno;
|
||||||
|
if ((g_devinuse & bitno) == 0) {
|
||||||
|
g_devinuse |= bitno;
|
||||||
|
hub_class->index = devno;
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
return -EMFILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: usbh_hub_devno_free
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free a /dev/hub[n] minor number so that it can be used.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void usbh_hub_devno_free(struct usbh_hub *hub_class)
|
||||||
|
{
|
||||||
|
int devno = hub_class->index;
|
||||||
|
|
||||||
|
if (devno >= 2 && devno < 32) {
|
||||||
|
size_t flags = usb_osal_enter_critical_section();
|
||||||
|
g_devinuse &= ~(1 << devno);
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_hub_get_hub_descriptor(struct usbh_hub *hub_class, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup;
|
||||||
|
|
||||||
|
setup = hub_class->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;
|
||||||
|
|
||||||
|
return usbh_control_transfer(hub_class->parent->ep0, setup, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_hub_get_status(struct usbh_hub *hub_class, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup;
|
||||||
|
|
||||||
|
setup = hub_class->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;
|
||||||
|
|
||||||
|
return usbh_control_transfer(hub_class->parent->ep0, setup, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_hub_get_portstatus(struct usbh_hub *hub_class, uint8_t port, struct hub_port_status *port_status)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup;
|
||||||
|
|
||||||
|
setup = hub_class->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;
|
||||||
|
|
||||||
|
return usbh_control_transfer(hub_class->parent->ep0, setup, (uint8_t *)port_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_hub_set_feature(struct usbh_hub *hub_class, uint8_t port, uint8_t feature)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup;
|
||||||
|
|
||||||
|
setup = hub_class->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_class->parent->ep0, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_hub_clear_feature(struct usbh_hub *hub_class, uint8_t port, uint8_t feature)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup;
|
||||||
|
|
||||||
|
setup = hub_class->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_class->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_INFO("Device Descriptor:\r\n");
|
||||||
|
USB_LOG_INFO("bLength: 0x%02x \r\n", desc->bLength);
|
||||||
|
USB_LOG_INFO("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
|
||||||
|
USB_LOG_INFO("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
|
||||||
|
USB_LOG_INFO("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
|
||||||
|
USB_LOG_INFO("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
|
||||||
|
USB_LOG_INFO("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
|
||||||
|
USB_LOG_INFO("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable);
|
||||||
|
USB_LOG_INFO("PortPwrCtrlMask: 0x%02x \r\n", desc->PortPwrCtrlMask);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_hub_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_hub *hub_class = usb_malloc(sizeof(struct usbh_hub));
|
||||||
|
if (hub_class == NULL) {
|
||||||
|
USB_LOG_ERR("Fail to alloc hub_class\r\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(hub_class, 0, sizeof(struct usbh_hub));
|
||||||
|
usbh_hub_devno_alloc(hub_class);
|
||||||
|
hub_class->dev_addr = hport->dev_addr;
|
||||||
|
hub_class->parent = hport;
|
||||||
|
|
||||||
|
hub_class->port_status = usb_iomalloc(sizeof(struct hub_port_status));
|
||||||
|
if (hub_class->port_status == NULL) {
|
||||||
|
USB_LOG_ERR("Fail to alloc port_status\r\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
hport->config.intf[intf].priv = hub_class;
|
||||||
|
|
||||||
|
uint8_t *hub_desc_buffer = usb_iomalloc(32);
|
||||||
|
|
||||||
|
ret = usbh_hub_get_hub_descriptor(hub_class, hub_desc_buffer);
|
||||||
|
if (ret != 0) {
|
||||||
|
usb_iofree(hub_desc_buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_hub_descriptor((struct usb_hub_descriptor *)hub_desc_buffer, USB_SIZEOF_HUB_DESC);
|
||||||
|
memcpy(&hub_class->hub_desc, hub_desc_buffer, USB_SIZEOF_HUB_DESC);
|
||||||
|
usb_iofree(hub_desc_buffer);
|
||||||
|
|
||||||
|
hub_class->nports = hub_class->hub_desc.bNbrPorts;
|
||||||
|
|
||||||
|
for (uint8_t port = 1; port <= hub_class->nports; port++) {
|
||||||
|
hub_class->child[port - 1].port = port;
|
||||||
|
hub_class->child[port - 1].parent = hub_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
hub_class->int_buffer = int_buffer[hub_class->index - 2];
|
||||||
|
usbh_hub_register(hub_class);
|
||||||
|
|
||||||
|
ep_desc = &hport->config.intf[intf].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;
|
||||||
|
if (ep_desc->bEndpointAddress & 0x80) {
|
||||||
|
usbh_ep_alloc(&hub_class->intin, &ep_cfg);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t port = 1; port <= hub_class->nports; port++) {
|
||||||
|
ret = usbh_hub_set_feature(hub_class, 1, HUB_PORT_FEATURE_POWER);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t port = 1; port <= hub_class->nports; port++) {
|
||||||
|
ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status);
|
||||||
|
USB_LOG_INFO("Port:%d, status:0x%02x, change:0x%02x\r\n", port, hub_class->port_status->wPortStatus, hub_class->port_status->wPortChange);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, hub_class->index);
|
||||||
|
USB_LOG_INFO("Register HUB Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
|
||||||
|
ret = usbh_ep_intr_async_transfer(hub_class->intin, hub_class->int_buffer, USBH_HUB_INTIN_BUFSIZE, usbh_external_hub_callback, hub_class);
|
||||||
|
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_class = (struct usbh_hub *)hport->config.intf[intf].priv;
|
||||||
|
|
||||||
|
if (hub_class) {
|
||||||
|
usbh_hub_devno_free(hub_class);
|
||||||
|
|
||||||
|
if (hub_class->intin) {
|
||||||
|
ret = usb_ep_cancel(hub_class->intin);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(hub_class->intin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hub_class->port_status)
|
||||||
|
usb_iofree(hub_class->port_status);
|
||||||
|
|
||||||
|
for (uint8_t port = 1; port <= hub_class->nports; port++) {
|
||||||
|
child = &hub_class->child[port - 1];
|
||||||
|
usbh_hport_deactivate(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_class);
|
||||||
|
usb_free(hub_class);
|
||||||
|
|
||||||
|
if (hport->config.intf[intf].devname[0] != '\0')
|
||||||
|
USB_LOG_INFO("Unregister HUB 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 void usbh_extern_hub_psc_event(void *arg)
|
||||||
|
{
|
||||||
|
struct usbh_hub *hub_class;
|
||||||
|
struct usbh_hubport *connport;
|
||||||
|
uint8_t port_change;
|
||||||
|
uint16_t status;
|
||||||
|
uint16_t change;
|
||||||
|
uint16_t mask;
|
||||||
|
uint16_t feat;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
hub_class = (struct usbh_hub *)arg;
|
||||||
|
|
||||||
|
/* Has the hub been disconnected? */
|
||||||
|
if (!hub_class->parent->connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
port_change = hub_class->int_buffer[0];
|
||||||
|
USB_LOG_DBG("port_change:0x%02x\r\n", port_change);
|
||||||
|
|
||||||
|
/* Check for status change on any port */
|
||||||
|
for (uint8_t port = USBH_HUB_PORT_START_INDEX; port <= hub_class->nports; port++) {
|
||||||
|
/* Check if port status has changed */
|
||||||
|
if ((port_change & (1 << port)) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
USB_LOG_DBG("Port %d change\r\n", port);
|
||||||
|
|
||||||
|
/* Port status changed, check what happened */
|
||||||
|
port_change &= ~(1 << port);
|
||||||
|
|
||||||
|
/* Read hub port status */
|
||||||
|
ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Failed to read port:%d status, errorcode: %d\r\n", port, ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
status = hub_class->port_status->wPortStatus;
|
||||||
|
change = hub_class->port_status->wPortChange;
|
||||||
|
|
||||||
|
USB_LOG_DBG("Port:%d, status:0x%02x, change:0x%02x\r\n", port, status, change);
|
||||||
|
|
||||||
|
/* First, clear all change bits */
|
||||||
|
mask = 1;
|
||||||
|
feat = HUB_PORT_FEATURE_C_CONNECTION;
|
||||||
|
while (change) {
|
||||||
|
if (change & mask) {
|
||||||
|
ret = usbh_hub_clear_feature(hub_class, port, feat);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Failed to clear port:%d, change mask:%04x, errorcode:%d\r\n", port, mask, ret);
|
||||||
|
}
|
||||||
|
change &= (~mask);
|
||||||
|
}
|
||||||
|
mask <<= 1;
|
||||||
|
feat++;
|
||||||
|
}
|
||||||
|
|
||||||
|
change = hub_class->port_status->wPortChange;
|
||||||
|
|
||||||
|
/* Handle connect or disconnect, no power management */
|
||||||
|
if (change & HUB_PORT_STATUS_C_CONNECTION) {
|
||||||
|
uint16_t debouncetime = 0;
|
||||||
|
uint16_t debouncestable = 0;
|
||||||
|
uint16_t connection = 0xffff;
|
||||||
|
|
||||||
|
/* Debounce */
|
||||||
|
while (debouncetime < 1500) {
|
||||||
|
ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Failed to read port:%d status, errorcode: %d\r\n", port, ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
status = hub_class->port_status->wPortStatus;
|
||||||
|
change = hub_class->port_status->wPortChange;
|
||||||
|
|
||||||
|
if ((change & HUB_PORT_STATUS_C_CONNECTION) == 0 &&
|
||||||
|
(status & HUB_PORT_STATUS_CONNECTION) == connection) {
|
||||||
|
debouncestable += 25;
|
||||||
|
if (debouncestable >= 100) {
|
||||||
|
USB_LOG_DBG("Port %d debouncestable=%d\r\n",
|
||||||
|
port, debouncestable);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debouncestable = 0;
|
||||||
|
connection = status & HUB_PORT_STATUS_CONNECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((change & HUB_PORT_STATUS_C_CONNECTION) != 0) {
|
||||||
|
ret = usbh_hub_clear_feature(hub_class, port, HUB_PORT_FEATURE_C_CONNECTION);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Failed to clear port:%d, change mask:%04x, errorcode:%d\r\n", port, mask, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debouncetime += 25;
|
||||||
|
usb_osal_msleep(25);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0 || debouncetime >= 1500) {
|
||||||
|
USB_LOG_ERR("ERROR: Failed to debounce port %d: %d\r\n", port, ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & HUB_PORT_STATUS_CONNECTION) {
|
||||||
|
/* Device connected to a port on the hub */
|
||||||
|
USB_LOG_DBG("Connection on port:%d\n", port);
|
||||||
|
|
||||||
|
ret = usbh_hub_set_feature(hub_class, port, HUB_PORT_FEATURE_RESET);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Failed to reset port:%d,errorcode:%d\r\n", port, ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_osal_msleep(100);
|
||||||
|
|
||||||
|
ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Failed to read port:%d status, errorcode: %d\r\n", port, ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
status = hub_class->port_status->wPortStatus;
|
||||||
|
change = hub_class->port_status->wPortChange;
|
||||||
|
|
||||||
|
USB_LOG_DBG("Port:%d, status:0x%02x, change:0x%02x after reset\r\n", port, status, change);
|
||||||
|
|
||||||
|
if ((status & HUB_PORT_STATUS_RESET) == 0 && (status & HUB_PORT_STATUS_ENABLE) != 0) {
|
||||||
|
if (change & HUB_PORT_STATUS_C_RESET) {
|
||||||
|
ret = usbh_hub_clear_feature(hub_class, port, HUB_PORT_FEATURE_C_RESET);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("Failed to clear port:%d reset change, errorcode: %d\r\n", port, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connport = &hub_class->child[port - 1];
|
||||||
|
|
||||||
|
if (status & HUB_PORT_STATUS_HIGH_SPEED) {
|
||||||
|
connport->speed = USB_SPEED_HIGH;
|
||||||
|
} else if (status & HUB_PORT_STATUS_LOW_SPEED) {
|
||||||
|
connport->speed = USB_SPEED_LOW;
|
||||||
|
} else {
|
||||||
|
connport->speed = USB_SPEED_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Device connected from a port on the hub, wakeup psc thread. */
|
||||||
|
usbh_external_hport_connect(connport);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
USB_LOG_ERR("Failed to enable port:%d\r\n", port);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Device disconnected from a port on the hub, wakeup psc thread. */
|
||||||
|
connport = &hub_class->child[port - 1];
|
||||||
|
usbh_external_hport_disconnect(connport);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
USB_LOG_WRN("status %04x change %04x not handled\r\n", status, change);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for hub status change */
|
||||||
|
|
||||||
|
if ((port_change & 1) != 0) {
|
||||||
|
/* Hub status changed */
|
||||||
|
USB_LOG_WRN("Hub status changed, not handled\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hub_class->parent->connected) {
|
||||||
|
ret = usbh_ep_intr_async_transfer(hub_class->intin, hub_class->int_buffer, USBH_HUB_INTIN_BUFSIZE, usbh_external_hub_callback, hub_class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbh_external_hub_callback(void *arg, int nbytes)
|
||||||
|
{
|
||||||
|
struct usbh_hub *hub_class = (struct usbh_hub *)arg;
|
||||||
|
uint32_t delay = 0;
|
||||||
|
if (nbytes < 0) {
|
||||||
|
hub_class->int_buffer[0] = 0;
|
||||||
|
delay = 100;
|
||||||
|
}
|
||||||
|
if (hub_class->parent->connected) {
|
||||||
|
usb_workqueue_submit(&g_lpworkq, &hub_class->work, usbh_extern_hub_psc_event, (void *)hub_class, delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct usbh_class_driver hub_class_driver = {
|
||||||
|
.driver_name = "hub",
|
||||||
|
.connect = usbh_hub_connect,
|
||||||
|
.disconnect = usbh_hub_disconnect
|
||||||
|
};
|
||||||
|
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info hub_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_INTF_CLASS,
|
||||||
|
.class = USB_DEVICE_CLASS_HUB,
|
||||||
|
.subclass = 0,
|
||||||
|
.protocol = 0,
|
||||||
|
.vid = 0x00,
|
||||||
|
.pid = 0x00,
|
||||||
|
.class_driver = &hub_class_driver
|
||||||
|
};
|
||||||
42
main/utilities/usb_cherry/CherryUSB/class/hub/usbh_hub.h
Normal file
42
main/utilities/usb_cherry/CherryUSB/class/hub/usbh_hub.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_hub.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBH_HUB_H_
|
||||||
|
#define _USBH_HUB_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
|
||||||
|
int usbh_hub_initialize(void);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _USBH_HUB_H_ */
|
||||||
214
main/utilities/usb_cherry/CherryUSB/class/midi/usb_midi.h
Normal file
214
main/utilities/usb_cherry/CherryUSB/class/midi/usb_midi.h
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief USB MIDI Class public header
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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_ */
|
||||||
121
main/utilities/usb_cherry/CherryUSB/class/msc/usb_msc.h
Normal file
121
main/utilities/usb_cherry/CherryUSB/class/msc/usb_msc.h
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief USB Mass Storage Class public header
|
||||||
|
*
|
||||||
|
* Header follows the Mass Storage Class Specification
|
||||||
|
* (Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf) and
|
||||||
|
* Mass Storage Class Bulk-Only Transport Specification
|
||||||
|
* (usbmassbulk_10.pdf).
|
||||||
|
* Header is limited to Bulk-Only Transfer protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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_ */
|
||||||
986
main/utilities/usb_cherry/CherryUSB/class/msc/usb_scsi.h
Normal file
986
main/utilities/usb_cherry/CherryUSB/class/msc/usb_scsi.h
Normal file
@ -0,0 +1,986 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* include/nuttx/scsi.h
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __INCLUDE_NUTTX_SCSI_H
|
||||||
|
#define __INCLUDE_NUTTX_SCSI_H
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* 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 */
|
||||||
1117
main/utilities/usb_cherry/CherryUSB/class/msc/usbd_msc.c
Normal file
1117
main/utilities/usb_cherry/CherryUSB/class/msc/usbd_msc.c
Normal file
File diff suppressed because it is too large
Load Diff
30
main/utilities/usb_cherry/CherryUSB/class/msc/usbd_msc.h
Normal file
30
main/utilities/usb_cherry/CherryUSB/class/msc/usbd_msc.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief USB Mass Storage Class public header
|
||||||
|
*
|
||||||
|
* Header follows the Mass Storage Class Specification
|
||||||
|
* (Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf) and
|
||||||
|
* Mass Storage Class Bulk-Only Transport Specification
|
||||||
|
* (usbmassbulk_10.pdf).
|
||||||
|
* Header is limited to Bulk-Only Transfer protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _USBD_MSC_H__
|
||||||
|
#define _USBD_MSC_H__
|
||||||
|
|
||||||
|
#include "usb_msc.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void usbd_msc_class_init(uint8_t out_ep, 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);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USBD_MSC_H_ */
|
||||||
453
main/utilities/usb_cherry/CherryUSB/class/msc/usbh_msc.c
Normal file
453
main/utilities/usb_cherry/CherryUSB/class/msc/usbh_msc.c
Normal file
@ -0,0 +1,453 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_msc.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_msc.h"
|
||||||
|
#include "usb_scsi.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/sd%c"
|
||||||
|
|
||||||
|
static uint32_t g_devinuse = 0;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: usbh_msc_devno_alloc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate a unique /dev/sd[n] minor number in the range 0-31.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int usbh_msc_devno_alloc(struct usbh_msc *msc_class)
|
||||||
|
{
|
||||||
|
size_t flags;
|
||||||
|
int devno;
|
||||||
|
|
||||||
|
flags = usb_osal_enter_critical_section();
|
||||||
|
for (devno = 0; devno < 26; devno++) {
|
||||||
|
uint32_t bitno = 1 << devno;
|
||||||
|
if ((g_devinuse & bitno) == 0) {
|
||||||
|
g_devinuse |= bitno;
|
||||||
|
msc_class->sdchar = 'a' + devno;
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
return -EMFILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: usbh_msc_devno_free
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Free a /dev/sd[n] minor number so that it can be used.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void usbh_msc_devno_free(struct usbh_msc *msc_class)
|
||||||
|
{
|
||||||
|
int devno = msc_class->sdchar - 'a';
|
||||||
|
|
||||||
|
if (devno >= 0 && devno < 26) {
|
||||||
|
size_t flags = usb_osal_enter_critical_section();
|
||||||
|
g_devinuse &= ~(1 << devno);
|
||||||
|
usb_osal_leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_scsi_testunitready(struct usbh_msc *msc_class)
|
||||||
|
{
|
||||||
|
int nbytes;
|
||||||
|
struct CBW *cbw;
|
||||||
|
|
||||||
|
/* Construct the CBW */
|
||||||
|
cbw = (struct CBW *)msc_class->tx_buffer;
|
||||||
|
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_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
/* Receive the CSW */
|
||||||
|
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 *)msc_class->tx_buffer;
|
||||||
|
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_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
/* Receive the sense data response */
|
||||||
|
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
/* Receive the CSW */
|
||||||
|
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 *)msc_class->tx_buffer;
|
||||||
|
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_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
/* Receive the sense data response */
|
||||||
|
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_INQUIRY_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
/* Receive the CSW */
|
||||||
|
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 *)msc_class->tx_buffer;
|
||||||
|
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_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
/* Receive the sense data response */
|
||||||
|
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_READCAPACITY10_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
/* Save the capacity information */
|
||||||
|
msc_class->blocknum = GET_BE32(&msc_class->tx_buffer[0]) + 1;
|
||||||
|
msc_class->blocksize = GET_BE32(&msc_class->tx_buffer[4]);
|
||||||
|
/* Receive the CSW */
|
||||||
|
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 *)msc_class->tx_buffer;
|
||||||
|
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_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
/* Send the user data */
|
||||||
|
nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
/* Receive the CSW */
|
||||||
|
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 *)msc_class->tx_buffer;
|
||||||
|
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_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
/* Receive the user data */
|
||||||
|
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
/* Receive the CSW */
|
||||||
|
nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT);
|
||||||
|
if (nbytes >= 0) {
|
||||||
|
usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nbytes < 0 ? (int)nbytes : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_msc_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_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;
|
||||||
|
|
||||||
|
msc_class->tx_buffer = usb_iomalloc(64);
|
||||||
|
if (msc_class->tx_buffer == NULL) {
|
||||||
|
USB_LOG_ERR("Fail to alloc tx_buffer\r\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = usbh_msc_get_maxlun(msc_class, msc_class->tx_buffer);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_INFO("Get max LUN:%u\r\n", msc_class->tx_buffer[0] + 1);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < hport->config.intf[intf].intf_desc.bNumEndpoints; i++) {
|
||||||
|
ep_desc = &hport->config.intf[intf].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_ep_alloc(&msc_class->bulkin, &ep_cfg);
|
||||||
|
} else {
|
||||||
|
usbh_ep_alloc(&msc_class->bulkout, &ep_cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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("Fail to read capacity10\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);
|
||||||
|
|
||||||
|
extern int msc_test();
|
||||||
|
msc_test();
|
||||||
|
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) {
|
||||||
|
ret = usb_ep_cancel(msc_class->bulkin);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(msc_class->bulkin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msc_class->bulkout) {
|
||||||
|
ret = usb_ep_cancel(msc_class->bulkout);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(msc_class->bulkout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msc_class->tx_buffer)
|
||||||
|
usb_iofree(msc_class->tx_buffer);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
memset(hport->config.intf[intf].devname, 0, CONFIG_USBHOST_DEV_NAMELEN);
|
||||||
|
hport->config.intf[intf].priv = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
52
main/utilities/usb_cherry/CherryUSB/class/msc/usbh_msc.h
Normal file
52
main/utilities/usb_cherry/CherryUSB/class/msc/usbh_msc.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_msc.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#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_epinfo_t bulkin; /* Bulk IN endpoint */
|
||||||
|
usbh_epinfo_t bulkout; /* Bulk OUT endpoint */
|
||||||
|
uint8_t *tx_buffer;
|
||||||
|
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
|
||||||
344
main/utilities/usb_cherry/CherryUSB/class/mtp/usb_mtp.h
Normal file
344
main/utilities/usb_cherry/CherryUSB/class/mtp/usb_mtp.h
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
#ifndef _USB_MTP_H
|
||||||
|
#define _USB_MTP_H
|
||||||
|
|
||||||
|
#define USB_MTP_CLASS 0x06
|
||||||
|
|
||||||
|
#define USB_MTP_SUB_CLASS 0x01U
|
||||||
|
#define USB_MTP_PROTOCOL 0x01U
|
||||||
|
|
||||||
|
#define MTP_REQUEST_CANCEL 0x64U
|
||||||
|
#define MTP_REQUEST_GET_EXT_EVENT_DATA 0x65U
|
||||||
|
#define MTP_REQUEST_RESET 0x66U
|
||||||
|
#define MTP_REQUEST_GET_DEVICE_STATUS 0x67U
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MTP Class specification Revision 1.1
|
||||||
|
* Appendix B. Object Properties
|
||||||
|
*/
|
||||||
|
/* MTP OBJECT PROPERTIES supported*/
|
||||||
|
#define MTP_OB_PROP_STORAGE_ID 0xDC01U
|
||||||
|
#define MTP_OB_PROP_OBJECT_FORMAT 0xDC02U
|
||||||
|
#define MTP_OB_PROP_PROTECTION_STATUS 0xDC03U
|
||||||
|
#define MTP_OB_PROP_OBJECT_SIZE 0xDC04U
|
||||||
|
#define MTP_OB_PROP_ASSOC_TYPE 0xDC05U
|
||||||
|
#define MTP_OB_PROP_ASSOC_DESC 0xDC06U
|
||||||
|
#define MTP_OB_PROP_OBJ_FILE_NAME 0xDC07U
|
||||||
|
#define MTP_OB_PROP_DATE_CREATED 0xDC08U
|
||||||
|
#define MTP_OB_PROP_DATE_MODIFIED 0xDC09U
|
||||||
|
#define MTP_OB_PROP_KEYWORDS 0xDC0AU
|
||||||
|
#define MTP_OB_PROP_PARENT_OBJECT 0xDC0BU
|
||||||
|
#define MTP_OB_PROP_ALLOWED_FOLD_CONTENTS 0xDC0CU
|
||||||
|
#define MTP_OB_PROP_HIDDEN 0xDC0DU
|
||||||
|
#define MTP_OB_PROP_SYSTEM_OBJECT 0xDC0EU
|
||||||
|
#define MTP_OB_PROP_PERS_UNIQ_OBJ_IDEN 0xDC41U
|
||||||
|
#define MTP_OB_PROP_SYNCID 0xDC42U
|
||||||
|
#define MTP_OB_PROP_PROPERTY_BAG 0xDC43U
|
||||||
|
#define MTP_OB_PROP_NAME 0xDC44U
|
||||||
|
#define MTP_OB_PROP_CREATED_BY 0xDC45U
|
||||||
|
#define MTP_OB_PROP_ARTIST 0xDC46U
|
||||||
|
#define MTP_OB_PROP_DATE_AUTHORED 0xDC47U
|
||||||
|
#define MTP_OB_PROP_DESCRIPTION 0xDC48U
|
||||||
|
#define MTP_OB_PROP_URL_REFERENCE 0xDC49U
|
||||||
|
#define MTP_OB_PROP_LANGUAGELOCALE 0xDC4AU
|
||||||
|
#define MTP_OB_PROP_COPYRIGHT_INFORMATION 0xDC4BU
|
||||||
|
#define MTP_OB_PROP_SOURCE 0xDC4CU
|
||||||
|
#define MTP_OB_PROP_ORIGIN_LOCATION 0xDC4DU
|
||||||
|
#define MTP_OB_PROP_DATE_ADDED 0xDC4EU
|
||||||
|
#define MTP_OB_PROP_NON_CONSUMABLE 0xDC4FU
|
||||||
|
#define MTP_OB_PROP_CORRUPTUNPLAYABLE 0xDC50U
|
||||||
|
#define MTP_OB_PROP_PRODUCERSERIALNUMBER 0xDC51U
|
||||||
|
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_FORMAT 0xDC81U
|
||||||
|
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_SIZE 0xDC82U
|
||||||
|
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_HEIGHT 0xDC83U
|
||||||
|
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_WIDTH 0xDC84U
|
||||||
|
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_DURATION 0xDC85U
|
||||||
|
#define MTP_OB_PROP_REPRESENTATIVE_SAMPLE_DATA 0xDC86U
|
||||||
|
#define MTP_OB_PROP_WIDTH 0xDC87U
|
||||||
|
#define MTP_OB_PROP_HEIGHT 0xDC88U
|
||||||
|
#define MTP_OB_PROP_DURATION 0xDC89U
|
||||||
|
#define MTP_OB_PROP_RATING 0xDC8AU
|
||||||
|
#define MTP_OB_PROP_TRACK 0xDC8BU
|
||||||
|
#define MTP_OB_PROP_GENRE 0xDC8CU
|
||||||
|
#define MTP_OB_PROP_CREDITS 0xDC8DU
|
||||||
|
#define MTP_OB_PROP_LYRICS 0xDC8EU
|
||||||
|
#define MTP_OB_PROP_SUBSCRIPTION_CONTENT_ID 0xDC8FU
|
||||||
|
#define MTP_OB_PROP_PRODUCED_BY 0xDC90U
|
||||||
|
#define MTP_OB_PROP_USE_COUNT 0xDC91U
|
||||||
|
#define MTP_OB_PROP_SKIP_COUNT 0xDC92U
|
||||||
|
#define MTP_OB_PROP_LAST_ACCESSED 0xDC93U
|
||||||
|
#define MTP_OB_PROP_PARENTAL_RATING 0xDC94U
|
||||||
|
#define MTP_OB_PROP_META_GENRE 0xDC95U
|
||||||
|
#define MTP_OB_PROP_COMPOSER 0xDC96U
|
||||||
|
#define MTP_OB_PROP_EFFECTIVE_RATING 0xDC97U
|
||||||
|
#define MTP_OB_PROP_SUBTITLE 0xDC98U
|
||||||
|
#define MTP_OB_PROP_ORIGINAL_RELEASE_DATE 0xDC99U
|
||||||
|
#define MTP_OB_PROP_ALBUM_NAME 0xDC9AU
|
||||||
|
#define MTP_OB_PROP_ALBUM_ARTIST 0xDC9BU
|
||||||
|
#define MTP_OB_PROP_MOOD 0xDC9CU
|
||||||
|
#define MTP_OB_PROP_DRM_STATUS 0xDC9DU
|
||||||
|
#define MTP_OB_PROP_SUB_DESCRIPTION 0xDC9EU
|
||||||
|
#define MTP_OB_PROP_IS_CROPPED 0xDCD1U
|
||||||
|
#define MTP_OB_PROP_IS_COLOUR_CORRECTED 0xDCD2U
|
||||||
|
#define MTP_OB_PROP_IMAGE_BIT_DEPTH 0xDCD3U
|
||||||
|
#define MTP_OB_PROP_FNUMBER 0xDCD4U
|
||||||
|
#define MTP_OB_PROP_EXPOSURE_TIME 0xDCD5U
|
||||||
|
#define MTP_OB_PROP_EXPOSURE_INDEX 0xDCD6U
|
||||||
|
#define MTP_OB_PROP_TOTAL_BITRATE 0xDE91U
|
||||||
|
#define MTP_OB_PROP_BITRATE_TYPE 0xDE92U
|
||||||
|
#define MTP_OB_PROP_SAMPLE_RATE 0xDE93U
|
||||||
|
#define MTP_OB_PROP_NUMBER_OF_CHANNELS 0xDE94U
|
||||||
|
#define MTP_OB_PROP_AUDIO_BITDEPTH 0xDE95U
|
||||||
|
#define MTP_OB_PROP_SCAN_TYPE 0xDE97U
|
||||||
|
#define MTP_OB_PROP_AUDIO_WAVE_CODEC 0xDE99U
|
||||||
|
#define MTP_OB_PROP_AUDIO_BITRATE 0xDE9AU
|
||||||
|
#define MTP_OB_PROP_VIDEO_FOURCC_CODEC 0xDE9BU
|
||||||
|
#define MTP_OB_PROP_VIDEO_BITRATE 0xDE9CU
|
||||||
|
#define MTP_OB_PROP_FRAMES_PER_THOUSAND_SECONDS 0xDE9DU
|
||||||
|
#define MTP_OB_PROP_KEYFRAME_DISTANCE 0xDE9EU
|
||||||
|
#define MTP_OB_PROP_BUFFER_SIZE 0xDE9FU
|
||||||
|
#define MTP_OB_PROP_ENCODING_QUALITY 0xDEA0U
|
||||||
|
#define MTP_OB_PROP_ENCODING_PROFILE 0xDEA1U
|
||||||
|
#define MTP_OB_PROP_DISPLAY_NAME 0xDCE0U
|
||||||
|
#define MTP_OB_PROP_BODY_TEXT 0xDCE1U
|
||||||
|
#define MTP_OB_PROP_SUBJECT 0xDCE2U
|
||||||
|
#define MTP_OB_PROP_PRIORITY 0xDCE3U
|
||||||
|
#define MTP_OB_PROP_GIVEN_NAME 0xDD00U
|
||||||
|
#define MTP_OB_PROP_MIDDLE_NAMES 0xDD01U
|
||||||
|
#define MTP_OB_PROP_FAMILY_NAME 0xDD02U
|
||||||
|
#define MTP_OB_PROP_PREFIX 0xDD03U
|
||||||
|
#define MTP_OB_PROP_SUFFIX 0xDD04U
|
||||||
|
#define MTP_OB_PROP_PHONETIC_GIVEN_NAME 0xDD05U
|
||||||
|
#define MTP_OB_PROP_PHONETIC_FAMILY_NAME 0xDD06U
|
||||||
|
#define MTP_OB_PROP_EMAIL_PRIMARY 0xDD07U
|
||||||
|
#define MTP_OB_PROP_EMAIL_PERSONAL_1 0xDD08U
|
||||||
|
#define MTP_OB_PROP_EMAIL_PERSONAL_2 0xDD09U
|
||||||
|
#define MTP_OB_PROP_EMAIL_BUSINESS_1 0xDD0AU
|
||||||
|
#define MTP_OB_PROP_EMAIL_BUSINESS_2 0xDD0BU
|
||||||
|
#define MTP_OB_PROP_EMAIL_OTHERS 0xDD0CU
|
||||||
|
#define MTP_OB_PROP_PHONE_NUMBER_PRIMARY 0xDD0DU
|
||||||
|
#define MTP_OB_PROP_PHONE_NUMBER_PERSONAL 0xDD0EU
|
||||||
|
#define MTP_OB_PROP_PHONE_NUMBER_PERSONAL_2 0xDD0FU
|
||||||
|
#define MTP_OB_PROP_PHONE_NUMBER_BUSINESS 0xDD10U
|
||||||
|
#define MTP_OB_PROP_PHONE_NUMBER_BUSINESS_2 0xDD11U
|
||||||
|
#define MTP_OB_PROP_PHONE_NUMBER_MOBILE 0xDD12U
|
||||||
|
#define MTP_OB_PROP_PHONE_NUMBER_MOBILE_2 0xDD13U
|
||||||
|
#define MTP_OB_PROP_FAX_NUMBER_PRIMARY 0xDD14U
|
||||||
|
#define MTP_OB_PROP_FAX_NUMBER_PERSONAL 0xDD15U
|
||||||
|
#define MTP_OB_PROP_FAX_NUMBER_BUSINESS 0xDD16U
|
||||||
|
#define MTP_OB_PROP_PAGER_NUMBER 0xDD17U
|
||||||
|
#define MTP_OB_PROP_PHONE_NUMBER_OTHERS 0xDD18U
|
||||||
|
#define MTP_OB_PROP_PRIMARY_WEB_ADDRESS 0xDD19U
|
||||||
|
#define MTP_OB_PROP_PERSONAL_WEB_ADDRESS 0xDD1AU
|
||||||
|
#define MTP_OB_PROP_BUSINESS_WEB_ADDRESS 0xDD1BU
|
||||||
|
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS 0xDD1CU
|
||||||
|
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS_2 0xDD1DU
|
||||||
|
#define MTP_OB_PROP_INSTANT_MESSENGER_ADDRESS_3 0xDD1EU
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_FULL 0xDD1FU
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_LINE_1 0xDD20U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_LINE_2 0xDD21U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_CITY 0xDD22U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_REGION 0xDD23U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE 0xDD24U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_PERSONAL_COUNTRY 0xDD25U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_FULL 0xDD26U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_LINE_1 0xDD27U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_LINE_2 0xDD28U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_CITY 0xDD29U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_REGION 0xDD2AU
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE 0xDD2BU
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_BUSINESS_COUNTRY 0xDD2CU
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_FULL 0xDD2DU
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_LINE_1 0xDD2EU
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_LINE_2 0xDD2FU
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_CITY 0xDD30U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_REGION 0xDD31U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_POSTAL_CODE 0xDD32U
|
||||||
|
#define MTP_OB_PROP_POSTAL_ADDRESS_OTHER_COUNTRY 0xDD33U
|
||||||
|
#define MTP_OB_PROP_ORGANIZATION_NAME 0xDD34U
|
||||||
|
#define MTP_OB_PROP_PHONETIC_ORGANIZATION_NAME 0xDD35U
|
||||||
|
#define MTP_OB_PROP_ROLE 0xDD36U
|
||||||
|
#define MTP_OB_PROP_BIRTHDATE 0xDD37U
|
||||||
|
#define MTP_OB_PROP_MESSAGE_TO 0xDD40U
|
||||||
|
#define MTP_OB_PROP_MESSAGE_CC 0xDD41U
|
||||||
|
#define MTP_OB_PROP_MESSAGE_BCC 0xDD42U
|
||||||
|
#define MTP_OB_PROP_MESSAGE_READ 0xDD43U
|
||||||
|
#define MTP_OB_PROP_MESSAGE_RECEIVED_TIME 0xDD44U
|
||||||
|
#define MTP_OB_PROP_MESSAGE_SENDER 0xDD45U
|
||||||
|
#define MTP_OB_PROP_ACT_BEGIN_TIME 0xDD50U
|
||||||
|
#define MTP_OB_PROP_ACT_END_TIME 0xDD51U
|
||||||
|
#define MTP_OB_PROP_ACT_LOCATION 0xDD52U
|
||||||
|
#define MTP_OB_PROP_ACT_REQUIRED_ATTENDEES 0xDD54U
|
||||||
|
#define MTP_OB_PROP_ACT_OPTIONAL_ATTENDEES 0xDD55U
|
||||||
|
#define MTP_OB_PROP_ACT_RESOURCES 0xDD56U
|
||||||
|
#define MTP_OB_PROP_ACT_ACCEPTED 0xDD57U
|
||||||
|
#define MTP_OB_PROP_OWNER 0xDD5DU
|
||||||
|
#define MTP_OB_PROP_EDITOR 0xDD5EU
|
||||||
|
#define MTP_OB_PROP_WEBMASTER 0xDD5FU
|
||||||
|
#define MTP_OB_PROP_URL_SOURCE 0xDD60U
|
||||||
|
#define MTP_OB_PROP_URL_DESTINATION 0xDD61U
|
||||||
|
#define MTP_OB_PROP_TIME_BOOKMARK 0xDD62U
|
||||||
|
#define MTP_OB_PROP_OBJECT_BOOKMARK 0xDD63U
|
||||||
|
#define MTP_OB_PROP_BYTE_BOOKMARK 0xDD64U
|
||||||
|
#define MTP_OB_PROP_LAST_BUILD_DATE 0xDD70U
|
||||||
|
#define MTP_OB_PROP_TIME_TO_LIVE 0xDD71U
|
||||||
|
#define MTP_OB_PROP_MEDIA_GUID 0xDD72U
|
||||||
|
|
||||||
|
/* MTP event codes*/
|
||||||
|
#define MTP_EVENT_UNDEFINED 0x4000U
|
||||||
|
#define MTP_EVENT_CANCELTRANSACTION 0x4001U
|
||||||
|
#define MTP_EVENT_OBJECTADDED 0x4002U
|
||||||
|
#define MTP_EVENT_OBJECTREMOVED 0x4003U
|
||||||
|
#define MTP_EVENT_STOREADDED 0x4004U
|
||||||
|
#define MTP_EVENT_STOREREMOVED 0x4005U
|
||||||
|
#define MTP_EVENT_DEVICEPROPCHANGED 0x4006U
|
||||||
|
#define MTP_EVENT_OBJECTINFOCHANGED 0x4007U
|
||||||
|
#define MTP_EVENT_DEVICEINFOCHANGED 0x4008U
|
||||||
|
#define MTP_EVENT_REQUESTOBJECTTRANSFER 0x4009U
|
||||||
|
#define MTP_EVENT_STOREFULL 0x400AU
|
||||||
|
#define MTP_EVENT_DEVICERESET 0x400BU
|
||||||
|
#define MTP_EVENT_STORAGEINFOCHANGED 0x400CU
|
||||||
|
#define MTP_EVENT_CAPTURECOMPLETE 0x400DU
|
||||||
|
#define MTP_EVENT_UNREPORTEDSTATUS 0x400EU
|
||||||
|
#define MTP_EVENT_OBJECTPROPCHANGED 0xC801U
|
||||||
|
#define MTP_EVENT_OBJECTPROPDESCCHANGED 0xC802U
|
||||||
|
#define MTP_EVENT_OBJECTREFERENCESCHANGED 0xC803U
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MTP Class specification Revision 1.1
|
||||||
|
* Appendix D. Operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Operations code */
|
||||||
|
#define MTP_OP_GET_DEVICE_INFO 0x1001U
|
||||||
|
#define MTP_OP_OPEN_SESSION 0x1002U
|
||||||
|
#define MTP_OP_CLOSE_SESSION 0x1003U
|
||||||
|
#define MTP_OP_GET_STORAGE_IDS 0x1004U
|
||||||
|
#define MTP_OP_GET_STORAGE_INFO 0x1005U
|
||||||
|
#define MTP_OP_GET_NUM_OBJECTS 0x1006U
|
||||||
|
#define MTP_OP_GET_OBJECT_HANDLES 0x1007U
|
||||||
|
#define MTP_OP_GET_OBJECT_INFO 0x1008U
|
||||||
|
#define MTP_OP_GET_OBJECT 0x1009U
|
||||||
|
#define MTP_OP_GET_THUMB 0x100AU
|
||||||
|
#define MTP_OP_DELETE_OBJECT 0x100BU
|
||||||
|
#define MTP_OP_SEND_OBJECT_INFO 0x100CU
|
||||||
|
#define MTP_OP_SEND_OBJECT 0x100DU
|
||||||
|
#define MTP_OP_FORMAT_STORE 0x100FU
|
||||||
|
#define MTP_OP_RESET_DEVICE 0x1010U
|
||||||
|
#define MTP_OP_GET_DEVICE_PROP_DESC 0x1014U
|
||||||
|
#define MTP_OP_GET_DEVICE_PROP_VALUE 0x1015U
|
||||||
|
#define MTP_OP_SET_DEVICE_PROP_VALUE 0x1016U
|
||||||
|
#define MTP_OP_RESET_DEVICE_PROP_VALUE 0x1017U
|
||||||
|
#define MTP_OP_TERMINATE_OPEN_CAPTURE 0x1018U
|
||||||
|
#define MTP_OP_MOVE_OBJECT 0x1019U
|
||||||
|
#define MTP_OP_COPY_OBJECT 0x101AU
|
||||||
|
#define MTP_OP_GET_PARTIAL_OBJECT 0x101BU
|
||||||
|
#define MTP_OP_INITIATE_OPEN_CAPTURE 0x101CU
|
||||||
|
#define MTP_OP_GET_OBJECT_PROPS_SUPPORTED 0x9801U
|
||||||
|
#define MTP_OP_GET_OBJECT_PROP_DESC 0x9802U
|
||||||
|
#define MTP_OP_GET_OBJECT_PROP_VALUE 0x9803U
|
||||||
|
#define MTP_OP_SET_OBJECT_PROP_VALUE 0x9804U
|
||||||
|
#define MTP_OP_GET_OBJECT_PROPLIST 0x9805U
|
||||||
|
#define MTP_OP_GET_OBJECT_PROP_REFERENCES 0x9810U
|
||||||
|
#define MTP_OP_GETSERVICEIDS 0x9301U
|
||||||
|
#define MTP_OP_GETSERVICEINFO 0x9302U
|
||||||
|
#define MTP_OP_GETSERVICECAPABILITIES 0x9303U
|
||||||
|
#define MTP_OP_GETSERVICEPROPDESC 0x9304U
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MTP Class specification Revision 1.1
|
||||||
|
* Appendix C. Device Properties
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* MTP device properties code*/
|
||||||
|
#define MTP_DEV_PROP_UNDEFINED 0x5000U
|
||||||
|
#define MTP_DEV_PROP_BATTERY_LEVEL 0x5001U
|
||||||
|
#define MTP_DEV_PROP_FUNCTIONAL_MODE 0x5002U
|
||||||
|
#define MTP_DEV_PROP_IMAGE_SIZE 0x5003U
|
||||||
|
#define MTP_DEV_PROP_COMPRESSION_SETTING 0x5004U
|
||||||
|
#define MTP_DEV_PROP_WHITE_BALANCE 0x5005U
|
||||||
|
#define MTP_DEV_PROP_RGB_GAIN 0x5006U
|
||||||
|
#define MTP_DEV_PROP_F_NUMBER 0x5007U
|
||||||
|
#define MTP_DEV_PROP_FOCAL_LENGTH 0x5008U
|
||||||
|
#define MTP_DEV_PROP_FOCUS_DISTANCE 0x5009U
|
||||||
|
#define MTP_DEV_PROP_FOCUS_MODE 0x500AU
|
||||||
|
#define MTP_DEV_PROP_EXPOSURE_METERING_MODE 0x500BU
|
||||||
|
#define MTP_DEV_PROP_FLASH_MODE 0x500CU
|
||||||
|
#define MTP_DEV_PROP_EXPOSURE_TIME 0x500DU
|
||||||
|
#define MTP_DEV_PROP_EXPOSURE_PROGRAM_MODE 0x500EU
|
||||||
|
#define MTP_DEV_PROP_EXPOSURE_INDEX 0x500FU
|
||||||
|
#define MTP_DEV_PROP_EXPOSURE_BIAS_COMPENSATION 0x5010U
|
||||||
|
#define MTP_DEV_PROP_DATETIME 0x5011U
|
||||||
|
#define MTP_DEV_PROP_CAPTURE_DELAY 0x5012U
|
||||||
|
#define MTP_DEV_PROP_STILL_CAPTURE_MODE 0x5013U
|
||||||
|
#define MTP_DEV_PROP_CONTRAST 0x5014U
|
||||||
|
#define MTP_DEV_PROP_SHARPNESS 0x5015U
|
||||||
|
#define MTP_DEV_PROP_DIGITAL_ZOOM 0x5016U
|
||||||
|
#define MTP_DEV_PROP_EFFECT_MODE 0x5017U
|
||||||
|
#define MTP_DEV_PROP_BURST_NUMBER 0x5018U
|
||||||
|
#define MTP_DEV_PROP_BURST_INTERVAL 0x5019U
|
||||||
|
#define MTP_DEV_PROP_TIMELAPSE_NUMBER 0x501AU
|
||||||
|
#define MTP_DEV_PROP_TIMELAPSE_INTERVAL 0x501BU
|
||||||
|
#define MTP_DEV_PROP_FOCUS_METERING_MODE 0x501CU
|
||||||
|
#define MTP_DEV_PROP_UPLOAD_URL 0x501DU
|
||||||
|
#define MTP_DEV_PROP_ARTIST 0x501EU
|
||||||
|
#define MTP_DEV_PROP_COPYRIGHT_INFO 0x501FU
|
||||||
|
#define MTP_DEV_PROP_SYNCHRONIZATION_PARTNER 0xD401U
|
||||||
|
#define MTP_DEV_PROP_DEVICE_FRIENDLY_NAME 0xD402U
|
||||||
|
#define MTP_DEV_PROP_VOLUME 0xD403U
|
||||||
|
#define MTP_DEV_PROP_SUPPORTEDFORMATSORDERED 0xD404U
|
||||||
|
#define MTP_DEV_PROP_DEVICEICON 0xD405U
|
||||||
|
#define MTP_DEV_PROP_PLAYBACK_RATE 0xD410U
|
||||||
|
#define MTP_DEV_PROP_PLAYBACK_OBJECT 0xD411U
|
||||||
|
#define MTP_DEV_PROP_PLAYBACK_CONTAINER 0xD412U
|
||||||
|
#define MTP_DEV_PROP_SESSION_INITIATOR_VERSION_INFO 0xD406U
|
||||||
|
#define MTP_DEV_PROP_PERCEIVED_DEVICE_TYPE 0xD407U
|
||||||
|
|
||||||
|
/* Container Types */
|
||||||
|
#define MTP_CONT_TYPE_UNDEFINED 0U
|
||||||
|
#define MTP_CONT_TYPE_COMMAND 1U
|
||||||
|
#define MTP_CONT_TYPE_DATA 2U
|
||||||
|
#define MTP_CONT_TYPE_RESPONSE 3U
|
||||||
|
#define MTP_CONT_TYPE_EVENT 4U
|
||||||
|
|
||||||
|
#ifndef MTP_STORAGE_ID
|
||||||
|
#define MTP_STORAGE_ID 0x00010001U /* SD card is inserted*/
|
||||||
|
#endif /* MTP_STORAGE_ID */
|
||||||
|
|
||||||
|
#define MTP_NBR_STORAGE_ID 1U
|
||||||
|
#define FREE_SPACE_IN_OBJ_NOT_USED 0xFFFFFFFFU
|
||||||
|
|
||||||
|
/* MTP storage type */
|
||||||
|
#define MTP_STORAGE_UNDEFINED 0U
|
||||||
|
#define MTP_STORAGE_FIXED_ROM 0x0001U
|
||||||
|
#define MTP_STORAGE_REMOVABLE_ROM 0x0002U
|
||||||
|
#define MTP_STORAGE_FIXED_RAM 0x0003U
|
||||||
|
#define MTP_STORAGE_REMOVABLE_RAM 0x0004U
|
||||||
|
|
||||||
|
/* MTP file system type */
|
||||||
|
#define MTP_FILESYSTEM_UNDEFINED 0U
|
||||||
|
#define MTP_FILESYSTEM_GENERIC_FLAT 0x0001U
|
||||||
|
#define MTP_FILESYSTEM_GENERIC_HIERARCH 0x0002U
|
||||||
|
#define MTP_FILESYSTEM_DCF 0x0003U
|
||||||
|
|
||||||
|
/* MTP access capability */
|
||||||
|
#define MTP_ACCESS_CAP_RW 0U /* read write */
|
||||||
|
#define MTP_ACCESS_CAP_RO_WITHOUT_DEL 0x0001U
|
||||||
|
#define MTP_ACCESS_CAP_RO_WITH_DEL 0x0002U
|
||||||
|
|
||||||
|
/* MTP standard data types supported */
|
||||||
|
#define MTP_DATATYPE_INT8 0x0001U
|
||||||
|
#define MTP_DATATYPE_UINT8 0x0002U
|
||||||
|
#define MTP_DATATYPE_INT16 0x0003U
|
||||||
|
#define MTP_DATATYPE_UINT16 0x0004U
|
||||||
|
#define MTP_DATATYPE_INT32 0x0005U
|
||||||
|
#define MTP_DATATYPE_UINT32 0x0006U
|
||||||
|
#define MTP_DATATYPE_INT64 0x0007U
|
||||||
|
#define MTP_DATATYPE_UINT64 0x0008U
|
||||||
|
#define MTP_DATATYPE_UINT128 0x000AU
|
||||||
|
#define MTP_DATATYPE_STR 0xFFFFU
|
||||||
|
|
||||||
|
/* MTP reading only or reading/writing */
|
||||||
|
#define MTP_PROP_GET 0x00U
|
||||||
|
#define MTP_PROP_GET_SET 0x01U
|
||||||
|
|
||||||
|
#endif
|
||||||
98
main/utilities/usb_cherry/CherryUSB/class/mtp/usbd_mtp.c
Normal file
98
main/utilities/usb_cherry/CherryUSB/class/mtp/usbd_mtp.c
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_mtp.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_mtp.h"
|
||||||
|
|
||||||
|
/* Device data structure */
|
||||||
|
struct mtp_cfg_priv {
|
||||||
|
USB_MEM_ALIGN32 uint8_t device_status;
|
||||||
|
} usbd_mtp_cfg;
|
||||||
|
|
||||||
|
/* max USB packet size */
|
||||||
|
#ifndef CONFIG_USB_HS
|
||||||
|
#define MTP_BULK_EP_MPS 64
|
||||||
|
#else
|
||||||
|
#define MTP_BULK_EP_MPS 512
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MSD_OUT_EP_IDX 0
|
||||||
|
#define MSD_IN_EP_IDX 1
|
||||||
|
|
||||||
|
/* Describe EndPoints configuration */
|
||||||
|
static usbd_endpoint_t mtp_ep_data[2];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handler called for Class requests not handled by the USB stack.
|
||||||
|
*
|
||||||
|
* @param setup Information about the request to execute.
|
||||||
|
* @param len Size of the buffer.
|
||||||
|
* @param data Buffer containing the request result.
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
static int mtp_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
|
{
|
||||||
|
USB_LOG_DBG("MTP Class request: "
|
||||||
|
"bRequest 0x%02x\r\n",
|
||||||
|
setup->bRequest);
|
||||||
|
|
||||||
|
switch (setup->bRequest) {
|
||||||
|
case MTP_REQUEST_CANCEL:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MTP_REQUEST_GET_EXT_EVENT_DATA:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MTP_REQUEST_RESET:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MTP_REQUEST_GET_DEVICE_STATUS:
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
USB_LOG_WRN("Unhandled MTP Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbd_mtp_bulk_out(uint8_t ep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbd_mtp_bulk_in(uint8_t ep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mtp_notify_handler(uint8_t event, void *arg)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case USBD_EVENT_RESET:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
main/utilities/usb_cherry/CherryUSB/class/mtp/usbd_mtp.h
Normal file
36
main/utilities/usb_cherry/CherryUSB/class/mtp/usbd_mtp.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_mtp.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBD_MTP_H
|
||||||
|
#define _USBD_MTP_H
|
||||||
|
|
||||||
|
#include "usb_mtp.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
130
main/utilities/usb_cherry/CherryUSB/class/mtp/usbh_mtp.c
Normal file
130
main/utilities/usb_cherry/CherryUSB/class/mtp/usbh_mtp.c
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_mtp.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_mtp.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/mtp"
|
||||||
|
|
||||||
|
static int usbh_mtp_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_mtp *mtp_class = usb_malloc(sizeof(struct usbh_mtp));
|
||||||
|
if (mtp_class == NULL) {
|
||||||
|
USB_LOG_ERR("Fail to alloc mtp_class\r\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(mtp_class, 0, sizeof(struct usbh_mtp));
|
||||||
|
|
||||||
|
mtp_class->hport = hport;
|
||||||
|
mtp_class->ctrl_intf = intf;
|
||||||
|
mtp_class->data_intf = intf + 1;
|
||||||
|
|
||||||
|
hport->config.intf[intf].priv = mtp_class;
|
||||||
|
hport->config.intf[intf + 1].priv = NULL;
|
||||||
|
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||||
|
|
||||||
|
#ifdef CONFIG_USBHOST_MTP_NOTIFY
|
||||||
|
ep_desc = &hport->config.intf[intf].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_ep_alloc(&mtp_class->intin, &ep_cfg);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
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_ep_alloc(&mtp_class->bulkin, &ep_cfg);
|
||||||
|
} else {
|
||||||
|
usbh_ep_alloc(&mtp_class->bulkout, &ep_cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||||
|
|
||||||
|
USB_LOG_INFO("Register MTP Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_mtp_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct usbh_mtp *mtp_class = (struct usbh_mtp *)hport->config.intf[intf].priv;
|
||||||
|
|
||||||
|
if (mtp_class) {
|
||||||
|
if (mtp_class->bulkin) {
|
||||||
|
ret = usb_ep_cancel(mtp_class->bulkin);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(mtp_class->bulkin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtp_class->bulkout) {
|
||||||
|
ret = usb_ep_cancel(mtp_class->bulkout);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(mtp_class->bulkout);
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_free(mtp_class);
|
||||||
|
|
||||||
|
if (hport->config.intf[intf].devname[0] != '\0')
|
||||||
|
USB_LOG_INFO("Unregister MTP 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 mtp_class_driver = {
|
||||||
|
.driver_name = "mtp",
|
||||||
|
.connect = usbh_mtp_connect,
|
||||||
|
.disconnect = usbh_mtp_disconnect
|
||||||
|
};
|
||||||
|
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info mtp_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||||
|
.class = USB_MTP_CLASS,
|
||||||
|
.subclass = USB_MTP_SUB_CLASS,
|
||||||
|
.protocol = USB_MTP_PROTOCOL,
|
||||||
|
.vid = 0x00,
|
||||||
|
.pid = 0x00,
|
||||||
|
.class_driver = &mtp_class_driver
|
||||||
|
};
|
||||||
47
main/utilities/usb_cherry/CherryUSB/class/mtp/usbh_mtp.h
Normal file
47
main/utilities/usb_cherry/CherryUSB/class/mtp/usbh_mtp.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_mtp.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBH_MTP_H
|
||||||
|
#define _USBH_MTP_H
|
||||||
|
|
||||||
|
#include "usb_mtp.h"
|
||||||
|
|
||||||
|
struct usbh_mtp {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
|
||||||
|
uint8_t intf; /* interface number */
|
||||||
|
usbh_epinfo_t bulkin; /* BULK IN endpoint */
|
||||||
|
usbh_epinfo_t bulkout; /* BULK OUT endpoint */
|
||||||
|
#ifdef CONFIG_USBHOST_MTP_NOTIFY
|
||||||
|
usbh_epinfo_t intin; /* Interrupt IN endpoint (optional) */
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _USB_PRINTER_H
|
||||||
|
#define _USB_PRINTER_H
|
||||||
|
|
||||||
|
#define PRINTER_SUBCLASS 0x01U
|
||||||
|
|
||||||
|
#define PRINTER_REQUEST_GET_DEVICE_ID 0x00U
|
||||||
|
#define PRINTER_REQUEST_GET_PORT_SATTUS 0x01U
|
||||||
|
#define PRINTER_REQUEST_SOFT_RESET 0x02U
|
||||||
|
|
||||||
|
#define PRINTER_STATUS_NO_ERROR 0x00U
|
||||||
|
#define PRINTER_STATUS_SELECTED 0x08U
|
||||||
|
#define PRINTER_STATUS_PAPER_EMPTY 0x10U
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_printer.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_printer.h"
|
||||||
|
|
||||||
|
/* Device data structure */
|
||||||
|
struct printer_cfg_priv {
|
||||||
|
uint8_t *device_id;
|
||||||
|
uint8_t port_status;
|
||||||
|
} usbd_printer_cfg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handler called for Class requests not handled by the USB stack.
|
||||||
|
*
|
||||||
|
* @param setup Information about the request to execute.
|
||||||
|
* @param len Size of the buffer.
|
||||||
|
* @param data Buffer containing the request result.
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
static int printer_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
|
{
|
||||||
|
USB_LOG_DBG("Printer Class request: "
|
||||||
|
"bRequest 0x%02x\r\n",
|
||||||
|
setup->bRequest);
|
||||||
|
|
||||||
|
switch (setup->bRequest) {
|
||||||
|
case PRINTER_REQUEST_GET_DEVICE_ID:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case PRINTER_REQUEST_GET_PORT_SATTUS:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case PRINTER_REQUEST_SOFT_RESET:
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
USB_LOG_WRN("Unhandled Printer Class bRequest 0x%02x\r\n", setup->bRequest);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printer_notify_handler(uint8_t event, void *arg)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case USBD_EVENT_RESET:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_printer_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
|
||||||
|
{
|
||||||
|
static usbd_class_t *last_class = NULL;
|
||||||
|
|
||||||
|
if (last_class != devclass) {
|
||||||
|
last_class = devclass;
|
||||||
|
usbd_class_register(devclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
intf->class_handler = printer_class_request_handler;
|
||||||
|
intf->custom_handler = NULL;
|
||||||
|
intf->vendor_handler = NULL;
|
||||||
|
intf->notify_handler = printer_notify_handler;
|
||||||
|
|
||||||
|
usbd_class_add_interface(devclass, intf);
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_printer.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBD_PRINTER_H
|
||||||
|
#define _USBD_PRINTER_H
|
||||||
|
|
||||||
|
#include "usb_printer.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void usbd_printer_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
160
main/utilities/usb_cherry/CherryUSB/class/printer/usbh_printer.c
Normal file
160
main/utilities/usb_cherry/CherryUSB/class/printer/usbh_printer.c
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_printer.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_printer.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/printer"
|
||||||
|
|
||||||
|
static int usbh_printer_get_device_id(struct usbh_printer *printer_class, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = printer_class->hport->setup;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
|
setup->bRequest = PRINTER_REQUEST_GET_DEVICE_ID;
|
||||||
|
setup->wValue = 0;
|
||||||
|
setup->wIndex = printer_class->intf;
|
||||||
|
setup->wLength = 256;
|
||||||
|
|
||||||
|
return usbh_control_transfer(printer_class->hport->ep0, setup, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_printer_get_port_status(struct usbh_printer *printer_class, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = printer_class->hport->setup;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
|
setup->bRequest = PRINTER_REQUEST_GET_PORT_SATTUS;
|
||||||
|
setup->wValue = 0;
|
||||||
|
setup->wIndex = printer_class->intf;
|
||||||
|
setup->wLength = 1;
|
||||||
|
|
||||||
|
return usbh_control_transfer(printer_class->hport->ep0, setup, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_printer_soft_reset(struct usbh_printer *printer_class)
|
||||||
|
{
|
||||||
|
struct usb_setup_packet *setup = printer_class->hport->setup;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||||
|
setup->bRequest = PRINTER_REQUEST_SOFT_RESET;
|
||||||
|
setup->wValue = 0;
|
||||||
|
setup->wIndex = printer_class->intf;
|
||||||
|
setup->wLength = 0;
|
||||||
|
|
||||||
|
return usbh_control_transfer(printer_class->hport->ep0, setup, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_printer_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_printer *printer_class = usb_malloc(sizeof(struct usbh_printer));
|
||||||
|
if (printer_class == NULL) {
|
||||||
|
USB_LOG_ERR("Fail to alloc printer_class\r\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(printer_class, 0, sizeof(struct usbh_printer));
|
||||||
|
|
||||||
|
printer_class->hport = hport;
|
||||||
|
printer_class->intf = intf;
|
||||||
|
|
||||||
|
hport->config.intf[intf].priv = printer_class;
|
||||||
|
|
||||||
|
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_ep_alloc(&printer_class->bulkin, &ep_cfg);
|
||||||
|
} else {
|
||||||
|
usbh_ep_alloc(&printer_class->bulkout, &ep_cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// uint8_t *device_id = usb_iomalloc(256);
|
||||||
|
// ret = usbh_printer_get_device_id(printer_class, device_id);
|
||||||
|
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||||
|
|
||||||
|
USB_LOG_INFO("Register Printer Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbh_printer_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
struct usbh_printer *printer_class = (struct usbh_printer *)hport->config.intf[intf].priv;
|
||||||
|
|
||||||
|
if (printer_class) {
|
||||||
|
if (printer_class->bulkin) {
|
||||||
|
ret = usb_ep_cancel(printer_class->bulkin);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(printer_class->bulkin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printer_class->bulkout) {
|
||||||
|
ret = usb_ep_cancel(printer_class->bulkout);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(printer_class->bulkout);
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_free(printer_class);
|
||||||
|
|
||||||
|
if (hport->config.intf[intf].devname[0] != '\0')
|
||||||
|
USB_LOG_INFO("Unregister Printer 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 printer_class_driver = {
|
||||||
|
.driver_name = "printer",
|
||||||
|
.connect = usbh_printer_connect,
|
||||||
|
.disconnect = usbh_printer_disconnect
|
||||||
|
};
|
||||||
|
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info printer_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||||
|
.class = USB_DEVICE_CLASS_PRINTER,
|
||||||
|
.subclass = PRINTER_SUBCLASS,
|
||||||
|
.protocol = 0x00,
|
||||||
|
.vid = 0x00,
|
||||||
|
.pid = 0x00,
|
||||||
|
.class_driver = &printer_class_driver
|
||||||
|
};
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_printer.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBH_PRINTER_H
|
||||||
|
#define _USBH_PRINTER_H
|
||||||
|
|
||||||
|
#include "usb_printer.h"
|
||||||
|
|
||||||
|
struct usbh_printer {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
|
||||||
|
uint8_t intf; /* interface number */
|
||||||
|
usbh_epinfo_t bulkin; /* BULK IN endpoint */
|
||||||
|
usbh_epinfo_t bulkout; /* BULK OUT endpoint */
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
#ifndef _USB_XXX_H
|
||||||
|
#define _USB_XXX_H
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_xxx.h"
|
||||||
|
|
||||||
|
static int xxx_class_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)
|
||||||
|
{
|
||||||
|
static usbd_class_t *last_class = NULL;
|
||||||
|
|
||||||
|
if (last_class != devclass) {
|
||||||
|
last_class = devclass;
|
||||||
|
usbd_class_register(devclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
intf->class_handler = xxx_class_request_handler;
|
||||||
|
intf->custom_handler = NULL;
|
||||||
|
intf->vendor_handler = NULL;
|
||||||
|
intf->notify_handler = xxx_notify_handler;
|
||||||
|
|
||||||
|
usbd_class_add_interface(devclass, intf);
|
||||||
|
}
|
||||||
@ -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_ */
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
#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_ep_alloc(&rndis_class->bulkin, &ep_cfg);
|
||||||
|
} else {
|
||||||
|
usbh_ep_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) {
|
||||||
|
ret = usb_ep_cancel(xxx_class->bulkin);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(xxx_class->bulkin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xxx_class->bulkout) {
|
||||||
|
ret = usb_ep_cancel(xxx_class->bulkout);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_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
|
||||||
|
};
|
||||||
@ -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_epinfo_t intin; /* INTR IN endpoint */
|
||||||
|
usbh_epinfo_t intout; /* INTR OUT endpoint */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
130
main/utilities/usb_cherry/CherryUSB/class/tmc/usb_tmc.h
Normal file
130
main/utilities/usb_cherry/CherryUSB/class/tmc/usb_tmc.h
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief USB TMC Class public header
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _USB_TMC_H_
|
||||||
|
#define _USB_TMC_H_
|
||||||
|
|
||||||
|
/**@addtogroup MODULE_TMC USB TMC class
|
||||||
|
* @brief This module contains USB Device Test and Measurement Class definitions.
|
||||||
|
* @details This module based on
|
||||||
|
* [USB Device Test and Measurement Class Specification, Revision 1.0]
|
||||||
|
* (https://www.usb.org/sites/default/files/USBTMC_1_006a.zip)
|
||||||
|
* @{*/
|
||||||
|
|
||||||
|
/**@name USB TMC class, subclass and protocol definitions
|
||||||
|
* @{*/
|
||||||
|
#define TMC_SUBCLASS_TMC 0x03
|
||||||
|
#define TMC_PROTOCOL_NONE 0x00 /**< No subclass specification applies. */
|
||||||
|
#define TMC_PROTOCOL_USB488 0x01 /**< USBTMC USB488 subclass interface. */
|
||||||
|
/** @}*/
|
||||||
|
|
||||||
|
/**@name USBTMC requests
|
||||||
|
* @{*/
|
||||||
|
#define TMC_REQUEST_INITIATE_ABORT_BULK_OUT 1
|
||||||
|
#define TMC_REQUEST_CHECK_ABORT_BULK_OUT_STATUS 2
|
||||||
|
#define TMC_REQUEST_INITIATE_ABORT_BULK_IN 3
|
||||||
|
#define TMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS 4
|
||||||
|
#define TMC_REQUEST_INITIATE_CLEAR 5
|
||||||
|
#define TMC_REQUEST_CHECK_CLEAR_STATUS 6
|
||||||
|
#define TMC_REQUEST_GET_CAPABILITIES 7
|
||||||
|
#define TMC_REQUEST_INDICATOR_PULSE 64
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
|
/**@name USBTMC status values
|
||||||
|
* @{*/
|
||||||
|
#define TMC_STATUS_SUCCESS 0x01
|
||||||
|
#define TMC_STATUS_PENDING 0x02
|
||||||
|
#define TMC_STATUS_FAILED 0x80
|
||||||
|
#define TMC_STATUS_TRANSFER_NOT_IN_PROGRESS 0x81
|
||||||
|
#define TMC_STATUS_SPLIT_NOT_IN_PROGRESS 0x82
|
||||||
|
#define TMC_STATUS_SPLIT_IN_PROGRESS 0x83
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
|
/** GET_CAPABILITIES request response */
|
||||||
|
struct tmc_get_capabilities_response {
|
||||||
|
uint8_t USBTMC_status;
|
||||||
|
uint8_t Reserved0;
|
||||||
|
uint16_t bcdUSBTMC;
|
||||||
|
uint8_t InterfaceCapabilities;
|
||||||
|
uint8_t DeviceCapabilities;
|
||||||
|
uint8_t Reserved1[18];
|
||||||
|
} __PACKED;
|
||||||
|
|
||||||
|
/**@name MsgId values
|
||||||
|
* @{*/
|
||||||
|
#define TMC_DEV_DEP_MSG_OUT 1
|
||||||
|
#define TMC_REQUEST_DEV_DEP_MSG_IN 2
|
||||||
|
#define TMC_DEV_DEP_MSG_IN 2
|
||||||
|
#define TMC_VENDOR_SPECIFIC_OUT 126
|
||||||
|
#define TMC_REQUEST_VENDOR_SPECIFIC_IN 127
|
||||||
|
#define TMC_VENDOR_SPECIFIC_IN 127
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
|
/**@name Transfer Attributes
|
||||||
|
* @{*/
|
||||||
|
/** The last USBTMC message data byte in the transfer is the last byte of the
|
||||||
|
* USBTMC message. */
|
||||||
|
#define TMC_TRANSFER_ATTR_EOM 0x01
|
||||||
|
/** The Bulk-IN transfer must terminate on the specified TermChar. The Host may
|
||||||
|
* only set this bit if the USBTMC interface indicates it supports TermChar in
|
||||||
|
* the GET_CAPABILITIES response packet */
|
||||||
|
#define TMC_TRANSFER_ATTR_TERM_CHAR 0x02
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
|
/** Message specific part of bulk header */
|
||||||
|
union usb_tmc_bulk_header_specific {
|
||||||
|
struct {
|
||||||
|
uint32_t TransferSize;
|
||||||
|
uint8_t bmTransferAttributes;
|
||||||
|
uint8_t Reserved[3];
|
||||||
|
} dev_dep_msg_out;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t TransferSize;
|
||||||
|
uint8_t bmTransferAttributes;
|
||||||
|
uint8_t TermChar;
|
||||||
|
uint8_t Reserved[2];
|
||||||
|
} request_dev_dep_msg_in;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t TransferSize;
|
||||||
|
uint8_t bmTransferAttributes;
|
||||||
|
uint8_t Reserved[3];
|
||||||
|
} dev_dep_msg_in;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t TransferSize;
|
||||||
|
uint8_t Reserved[4];
|
||||||
|
} vendor_specific_out;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t TransferSize;
|
||||||
|
uint8_t Reserved[4];
|
||||||
|
} request_vendor_specific_in;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t TransferSize;
|
||||||
|
uint8_t Reserved[4];
|
||||||
|
} vendor_specific_in;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Host must begin the first USB transaction in each Bulk transfer of
|
||||||
|
* command message content with a Bulk Header. */
|
||||||
|
struct usb_tmc_bulk_header {
|
||||||
|
/** Specifies the USBTMC message and the type of the USBTMC message. */
|
||||||
|
uint8_t MsgId;
|
||||||
|
/** A transfer identifier. The Host must set bTag different than the
|
||||||
|
* bTag used in the previous Bulk-OUT Header. The Host should increment
|
||||||
|
* the bTag by 1 each time it sends a new Bulk-OUT Header. */
|
||||||
|
uint8_t bTag;
|
||||||
|
/** The inverse (one's complement) of the bTag */
|
||||||
|
uint8_t bTagInverse;
|
||||||
|
uint8_t Reserved;
|
||||||
|
/** USBTMC command message specific */
|
||||||
|
union usb_tmc_bulk_header_specific MsgSpecific;
|
||||||
|
} __PACKED;
|
||||||
|
|
||||||
|
#endif /* _USB_TMC_H_ */
|
||||||
596
main/utilities/usb_cherry/CherryUSB/class/vendor/asix.h
vendored
Normal file
596
main/utilities/usb_cherry/CherryUSB/class/vendor/asix.h
vendored
Normal file
@ -0,0 +1,596 @@
|
|||||||
|
/*
|
||||||
|
* Change Logs
|
||||||
|
* Date Author Notes
|
||||||
|
* 2022-04-17 aozima the first version for CherryUSB.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LINUX_USBNET_ASIX_H
|
||||||
|
#define __LINUX_USBNET_ASIX_H
|
||||||
|
|
||||||
|
// #define __BIG_ENDIAN_BITFIELD
|
||||||
|
#define __LITTLE_ENDIAN_BITFIELD
|
||||||
|
typedef uint8_t u8;
|
||||||
|
typedef uint16_t u16;
|
||||||
|
typedef uint32_t u32;
|
||||||
|
|
||||||
|
#define KERNEL_VERSION(...) (0)
|
||||||
|
#define LINUX_VERSION_CODE (1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn on this flag if the implementation of your USB host controller
|
||||||
|
* cannot handle non-double word aligned buffer.
|
||||||
|
* When turn on this flag, driver will fixup egress packet aligned on double
|
||||||
|
* word boundary before deliver to USB host controller. And will Disable the
|
||||||
|
* function "skb_reserve (skb, NET_IP_ALIGN)" to retain the buffer aligned on
|
||||||
|
* double word alignment for ingress packets.
|
||||||
|
*/
|
||||||
|
#define AX_FORCE_BUFF_ALIGN 0
|
||||||
|
|
||||||
|
//#define RX_SKB_COPY
|
||||||
|
|
||||||
|
#define AX_MONITOR_MODE 0x01
|
||||||
|
#define AX_MONITOR_LINK 0x02
|
||||||
|
#define AX_MONITOR_MAGIC 0x04
|
||||||
|
#define AX_MONITOR_HSFS 0x10
|
||||||
|
|
||||||
|
/* AX88172 Medium Status Register values */
|
||||||
|
#define AX_MEDIUM_FULL_DUPLEX 0x02
|
||||||
|
#define AX_MEDIUM_TX_ABORT_ALLOW 0x04
|
||||||
|
#define AX_MEDIUM_FLOW_CONTROL_EN 0x10
|
||||||
|
#define AX_MCAST_FILTER_SIZE 8
|
||||||
|
#define AX_MAX_MCAST 64
|
||||||
|
|
||||||
|
#define AX_EEPROM_LEN 0x40
|
||||||
|
|
||||||
|
#define AX_SWRESET_CLEAR 0x00
|
||||||
|
#define AX_SWRESET_RR 0x01
|
||||||
|
#define AX_SWRESET_RT 0x02
|
||||||
|
#define AX_SWRESET_PRTE 0x04
|
||||||
|
#define AX_SWRESET_PRL 0x08
|
||||||
|
#define AX_SWRESET_BZ 0x10
|
||||||
|
#define AX_SWRESET_IPRL 0x20
|
||||||
|
#define AX_SWRESET_IPPD 0x40
|
||||||
|
#define AX_SWRESET_IPOSC 0x0080
|
||||||
|
#define AX_SWRESET_IPPSL_0 0x0100
|
||||||
|
#define AX_SWRESET_IPPSL_1 0x0200
|
||||||
|
#define AX_SWRESET_IPCOPS 0x0400
|
||||||
|
#define AX_SWRESET_IPCOPSC 0x0800
|
||||||
|
#define AX_SWRESET_AUTODETACH 0x1000
|
||||||
|
#define AX_SWRESET_WOLLP 0x8000
|
||||||
|
|
||||||
|
#define AX88772_IPG0_DEFAULT 0x15
|
||||||
|
#define AX88772_IPG1_DEFAULT 0x0c
|
||||||
|
#define AX88772_IPG2_DEFAULT 0x0E
|
||||||
|
|
||||||
|
#define AX88772A_IPG0_DEFAULT 0x15
|
||||||
|
#define AX88772A_IPG1_DEFAULT 0x16
|
||||||
|
#define AX88772A_IPG2_DEFAULT 0x1A
|
||||||
|
|
||||||
|
#define AX88772_MEDIUM_FULL_DUPLEX 0x0002
|
||||||
|
#define AX88772_MEDIUM_RESERVED 0x0004
|
||||||
|
#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010
|
||||||
|
#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020
|
||||||
|
#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080
|
||||||
|
#define AX88772_MEDIUM_RX_ENABLE 0x0100
|
||||||
|
#define AX88772_MEDIUM_100MB 0x0200
|
||||||
|
#define AX88772_MEDIUM_DEFAULT \
|
||||||
|
(AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
|
||||||
|
AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
|
||||||
|
AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE)
|
||||||
|
|
||||||
|
#define AX_CMD_SET_SW_MII 0x06
|
||||||
|
#define AX_CMD_READ_MII_REG 0x07
|
||||||
|
#define AX_CMD_WRITE_MII_REG 0x08
|
||||||
|
#define AX_CMD_READ_STATMNGSTS_REG 0x09
|
||||||
|
#define AX_HOST_EN 0x01
|
||||||
|
|
||||||
|
#define AX_CMD_SET_HW_MII 0x0a
|
||||||
|
#define AX_CMD_READ_EEPROM 0x0b
|
||||||
|
#define AX_CMD_WRITE_EEPROM 0x0c
|
||||||
|
#define AX_CMD_WRITE_EEPROM_EN 0x0d
|
||||||
|
#define AX_CMD_WRITE_EEPROM_DIS 0x0e
|
||||||
|
#define AX_CMD_WRITE_RX_CTL 0x10
|
||||||
|
#define AX_CMD_READ_IPG012 0x11
|
||||||
|
#define AX_CMD_WRITE_IPG0 0x12
|
||||||
|
#define AX_CMD_WRITE_IPG1 0x13
|
||||||
|
#define AX_CMD_WRITE_IPG2 0x14
|
||||||
|
#define AX_CMD_WRITE_MULTI_FILTER 0x16
|
||||||
|
#define AX_CMD_READ_NODE_ID 0x17
|
||||||
|
#define AX_CMD_READ_PHY_ID 0x19
|
||||||
|
#define AX_CMD_READ_MEDIUM_MODE 0x1a
|
||||||
|
#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
|
||||||
|
#define AX_CMD_READ_MONITOR_MODE 0x1c
|
||||||
|
#define AX_CMD_WRITE_MONITOR_MODE 0x1d
|
||||||
|
#define AX_CMD_WRITE_GPIOS 0x1f
|
||||||
|
#define AX_CMD_SW_RESET 0x20
|
||||||
|
#define AX_CMD_SW_PHY_STATUS 0x21
|
||||||
|
#define AX_CMD_SW_PHY_SELECT 0x22
|
||||||
|
#define AX_PHYSEL_PSEL (1 << 0)
|
||||||
|
#define AX_PHYSEL_ASEL (1 << 1)
|
||||||
|
#define AX_PHYSEL_SSMII (0 << 2)
|
||||||
|
#define AX_PHYSEL_SSRMII (1 << 2)
|
||||||
|
#define AX_PHYSEL_SSRRMII (3 << 2)
|
||||||
|
#define AX_PHYSEL_SSEN (1 << 4)
|
||||||
|
#define AX88772_CMD_READ_NODE_ID 0x13
|
||||||
|
#define AX88772_CMD_WRITE_NODE_ID 0x14
|
||||||
|
#define AX_CMD_READ_WKFARY 0x23
|
||||||
|
#define AX_CMD_WRITE_WKFARY 0x24
|
||||||
|
#define AX_CMD_READ_RXCOE_CTL 0x2b
|
||||||
|
#define AX_CMD_WRITE_RXCOE_CTL 0x2c
|
||||||
|
#define AX_CMD_READ_TXCOE_CTL 0x2d
|
||||||
|
#define AX_CMD_WRITE_TXCOE_CTL 0x2e
|
||||||
|
|
||||||
|
#define REG_LENGTH 2
|
||||||
|
#define PHY_ID_MASK 0x1f
|
||||||
|
|
||||||
|
#define AX_RXCOE_IPCE 0x0001
|
||||||
|
#define AX_RXCOE_IPVE 0x0002
|
||||||
|
#define AX_RXCOE_V6VE 0x0004
|
||||||
|
#define AX_RXCOE_TCPE 0x0008
|
||||||
|
#define AX_RXCOE_UDPE 0x0010
|
||||||
|
#define AX_RXCOE_ICMP 0x0020
|
||||||
|
#define AX_RXCOE_IGMP 0x0040
|
||||||
|
#define AX_RXCOE_ICV6 0x0080
|
||||||
|
#define AX_RXCOE_TCPV6 0x0100
|
||||||
|
#define AX_RXCOE_UDPV6 0x0200
|
||||||
|
#define AX_RXCOE_ICMV6 0x0400
|
||||||
|
#define AX_RXCOE_IGMV6 0x0800
|
||||||
|
#define AX_RXCOE_ICV6V6 0x1000
|
||||||
|
#define AX_RXCOE_FOPC 0x8000
|
||||||
|
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
|
||||||
|
#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
|
||||||
|
AX_RXCOE_V6VE | AX_RXCOE_TCPE | \
|
||||||
|
AX_RXCOE_UDPE | AX_RXCOE_ICV6 | \
|
||||||
|
AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6)
|
||||||
|
#else
|
||||||
|
#define AX_RXCOE_DEF_CSUM (AX_RXCOE_IPCE | AX_RXCOE_IPVE | \
|
||||||
|
AX_RXCOE_TCPE | AX_RXCOE_UDPE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AX_RXCOE_64TE 0x0100
|
||||||
|
#define AX_RXCOE_PPPOE 0x0200
|
||||||
|
#define AX_RXCOE_RPCE 0x8000
|
||||||
|
|
||||||
|
#define AX_TXCOE_IP 0x0001
|
||||||
|
#define AX_TXCOE_TCP 0x0002
|
||||||
|
#define AX_TXCOE_UDP 0x0004
|
||||||
|
#define AX_TXCOE_ICMP 0x0008
|
||||||
|
#define AX_TXCOE_IGMP 0x0010
|
||||||
|
#define AX_TXCOE_ICV6 0x0020
|
||||||
|
|
||||||
|
#define AX_TXCOE_TCPV6 0x0100
|
||||||
|
#define AX_TXCOE_UDPV6 0x0200
|
||||||
|
#define AX_TXCOE_ICMV6 0x0400
|
||||||
|
#define AX_TXCOE_IGMV6 0x0800
|
||||||
|
#define AX_TXCOE_ICV6V6 0x1000
|
||||||
|
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
|
||||||
|
#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP | \
|
||||||
|
AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6)
|
||||||
|
#else
|
||||||
|
#define AX_TXCOE_DEF_CSUM (AX_TXCOE_TCP | AX_TXCOE_UDP)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AX_TXCOE_64TE 0x0001
|
||||||
|
#define AX_TXCOE_PPPE 0x0002
|
||||||
|
|
||||||
|
#define AX88772B_MAX_BULKIN_2K 0
|
||||||
|
#define AX88772B_MAX_BULKIN_4K 1
|
||||||
|
#define AX88772B_MAX_BULKIN_6K 2
|
||||||
|
#define AX88772B_MAX_BULKIN_8K 3
|
||||||
|
#define AX88772B_MAX_BULKIN_16K 4
|
||||||
|
#define AX88772B_MAX_BULKIN_20K 5
|
||||||
|
#define AX88772B_MAX_BULKIN_24K 6
|
||||||
|
#define AX88772B_MAX_BULKIN_32K 7
|
||||||
|
struct {unsigned short size, byte_cnt, threshold; } AX88772B_BULKIN_SIZE[] = {
|
||||||
|
/* 2k */
|
||||||
|
{2048, 0x8000, 0x8001},
|
||||||
|
/* 4k */
|
||||||
|
{4096, 0x8100, 0x8147},
|
||||||
|
/* 6k */
|
||||||
|
{6144, 0x8200, 0x81EB},
|
||||||
|
/* 8k */
|
||||||
|
{8192, 0x8300, 0x83D7},
|
||||||
|
/* 16 */
|
||||||
|
{16384, 0x8400, 0x851E},
|
||||||
|
/* 20k */
|
||||||
|
{20480, 0x8500, 0x8666},
|
||||||
|
/* 24k */
|
||||||
|
{24576, 0x8600, 0x87AE},
|
||||||
|
/* 32k */
|
||||||
|
{32768, 0x8700, 0x8A3D},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define AX_RX_CTL_RH1M 0x0100 /* Enable RX-Header mode 0 */
|
||||||
|
#define AX_RX_CTL_RH2M 0x0200 /* Enable IP header in receive buffer aligned on 32-bit aligment */
|
||||||
|
#define AX_RX_CTL_RH3M 0x0400 /* checksum value in rx header 3 */
|
||||||
|
#define AX_RX_HEADER_DEFAULT (AX_RX_CTL_RH1M | AX_RX_CTL_RH2M)
|
||||||
|
|
||||||
|
#define AX_RX_CTL_MFB 0x0300 /* Maximum Frame size 16384bytes */
|
||||||
|
#define AX_RX_CTL_START 0x0080 /* Ethernet MAC start */
|
||||||
|
#define AX_RX_CTL_AP 0x0020 /* Accept physcial address from Multicast array */
|
||||||
|
#define AX_RX_CTL_AM 0x0010
|
||||||
|
#define AX_RX_CTL_AB 0x0008 /* Accetp Brocadcast frames*/
|
||||||
|
#define AX_RX_CTL_SEP 0x0004 /* Save error packets */
|
||||||
|
#define AX_RX_CTL_AMALL 0x0002 /* Accetp all multicast frames */
|
||||||
|
#define AX_RX_CTL_PRO 0x0001 /* Promiscuous Mode */
|
||||||
|
#define AX_RX_CTL_STOP 0x0000 /* Stop MAC */
|
||||||
|
|
||||||
|
#define AX_MONITOR_MODE 0x01
|
||||||
|
#define AX_MONITOR_LINK 0x02
|
||||||
|
#define AX_MONITOR_MAGIC 0x04
|
||||||
|
#define AX_MONITOR_HSFS 0x10
|
||||||
|
|
||||||
|
#define AX_MCAST_FILTER_SIZE 8
|
||||||
|
#define AX_MAX_MCAST 64
|
||||||
|
#define AX_INTERRUPT_BUFSIZE 8
|
||||||
|
|
||||||
|
#define AX_EEPROM_LEN 0x40
|
||||||
|
#define AX_EEPROM_MAGIC 0xdeadbeef
|
||||||
|
#define EEPROMMASK 0x7f
|
||||||
|
|
||||||
|
/* GPIO REGISTER */
|
||||||
|
#define AXGPIOS_GPO0EN 0X01 /* 1 << 0 */
|
||||||
|
#define AXGPIOS_GPO0 0X02 /* 1 << 1 */
|
||||||
|
#define AXGPIOS_GPO1EN 0X04 /* 1 << 2 */
|
||||||
|
#define AXGPIOS_GPO1 0X08 /* 1 << 3 */
|
||||||
|
#define AXGPIOS_GPO2EN 0X10 /* 1 << 4 */
|
||||||
|
#define AXGPIOS_GPO2 0X20 /* 1 << 5 */
|
||||||
|
#define AXGPIOS_RSE 0X80 /* 1 << 7 */
|
||||||
|
|
||||||
|
/* TX-header format */
|
||||||
|
#define AX_TX_HDR_CPHI 0x4000
|
||||||
|
#define AX_TX_HDR_DICF 0x8000
|
||||||
|
|
||||||
|
/* GMII register definitions */
|
||||||
|
#define GMII_PHY_CONTROL 0x00 /* control reg */
|
||||||
|
#define GMII_PHY_STATUS 0x01 /* status reg */
|
||||||
|
#define GMII_PHY_OUI 0x02 /* most of the OUI bits */
|
||||||
|
#define GMII_PHY_MODEL 0x03 /* model/rev bits, and rest of OUI */
|
||||||
|
#define GMII_PHY_ANAR 0x04 /* AN advertisement reg */
|
||||||
|
#define GMII_PHY_ANLPAR 0x05 /* AN Link Partner */
|
||||||
|
#define GMII_PHY_ANER 0x06 /* AN expansion reg */
|
||||||
|
#define GMII_PHY_1000BT_CONTROL 0x09 /* control reg for 1000BT */
|
||||||
|
#define GMII_PHY_1000BT_STATUS 0x0A /* status reg for 1000BT */
|
||||||
|
|
||||||
|
/* Bit definitions: GMII Control */
|
||||||
|
#define GMII_CONTROL_RESET 0x8000 /* reset bit in control reg */
|
||||||
|
#define GMII_CONTROL_LOOPBACK 0x4000 /* loopback bit in control reg */
|
||||||
|
#define GMII_CONTROL_10MB 0x0000 /* 10 Mbit */
|
||||||
|
#define GMII_CONTROL_100MB 0x2000 /* 100Mbit */
|
||||||
|
#define GMII_CONTROL_1000MB 0x0040 /* 1000Mbit */
|
||||||
|
#define GMII_CONTROL_SPEED_BITS 0x2040 /* speed bit mask */
|
||||||
|
#define GMII_CONTROL_ENABLE_AUTO 0x1000 /* autonegotiate enable */
|
||||||
|
#define GMII_CONTROL_POWER_DOWN 0x0800
|
||||||
|
#define GMII_CONTROL_ISOLATE 0x0400 /* islolate bit */
|
||||||
|
#define GMII_CONTROL_START_AUTO 0x0200 /* restart autonegotiate */
|
||||||
|
#define GMII_CONTROL_FULL_DUPLEX 0x0100
|
||||||
|
|
||||||
|
/* Bit definitions: GMII Status */
|
||||||
|
#define GMII_STATUS_100MB_MASK 0xE000 /* any of these indicate 100 Mbit */
|
||||||
|
#define GMII_STATUS_10MB_MASK 0x1800 /* either of these indicate 10 Mbit */
|
||||||
|
#define GMII_STATUS_AUTO_DONE 0x0020 /* auto negotiation complete */
|
||||||
|
#define GMII_STATUS_AUTO 0x0008 /* auto negotiation is available */
|
||||||
|
#define GMII_STATUS_LINK_UP 0x0004 /* link status bit */
|
||||||
|
#define GMII_STATUS_EXTENDED 0x0001 /* extended regs exist */
|
||||||
|
#define GMII_STATUS_100T4 0x8000 /* capable of 100BT4 */
|
||||||
|
#define GMII_STATUS_100TXFD 0x4000 /* capable of 100BTX full duplex */
|
||||||
|
#define GMII_STATUS_100TX 0x2000 /* capable of 100BTX */
|
||||||
|
#define GMII_STATUS_10TFD 0x1000 /* capable of 10BT full duplex */
|
||||||
|
#define GMII_STATUS_10T 0x0800 /* capable of 10BT */
|
||||||
|
|
||||||
|
/* Bit definitions: Auto-Negotiation Advertisement */
|
||||||
|
#define GMII_ANAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
|
||||||
|
#define GMII_ANAR_PAUSE 0x0400 /* support pause packets */
|
||||||
|
#define GMII_ANAR_100T4 0x0200 /* support 100BT4 */
|
||||||
|
#define GMII_ANAR_100TXFD 0x0100 /* support 100BTX full duplex */
|
||||||
|
#define GMII_ANAR_100TX 0x0080 /* support 100BTX half duplex */
|
||||||
|
#define GMII_ANAR_10TFD 0x0040 /* support 10BT full duplex */
|
||||||
|
#define GMII_ANAR_10T 0x0020 /* support 10BT half duplex */
|
||||||
|
#define GMII_SELECTOR_FIELD 0x001F /* selector field. */
|
||||||
|
|
||||||
|
/* Bit definitions: Auto-Negotiation Link Partner Ability */
|
||||||
|
#define GMII_ANLPAR_100T4 0x0200 /* support 100BT4 */
|
||||||
|
#define GMII_ANLPAR_100TXFD 0x0100 /* support 100BTX full duplex */
|
||||||
|
#define GMII_ANLPAR_100TX 0x0080 /* support 100BTX half duplex */
|
||||||
|
#define GMII_ANLPAR_10TFD 0x0040 /* support 10BT full duplex */
|
||||||
|
#define GMII_ANLPAR_10T 0x0020 /* support 10BT half duplex */
|
||||||
|
#define GMII_ANLPAR_PAUSE 0x0400 /* support pause packets */
|
||||||
|
#define GMII_ANLPAR_ASYM_PAUSE 0x0800 /* support asymetric pause */
|
||||||
|
#define GMII_ANLPAR_ACK 0x4000 /* means LCB was successfully rx'd */
|
||||||
|
#define GMII_SELECTOR_8023 0x0001;
|
||||||
|
|
||||||
|
/* Bit definitions: 1000BaseT AUX Control */
|
||||||
|
#define GMII_1000_AUX_CTRL_MASTER_SLAVE 0x1000
|
||||||
|
#define GMII_1000_AUX_CTRL_FD_CAPABLE 0x0200 /* full duplex capable */
|
||||||
|
#define GMII_1000_AUX_CTRL_HD_CAPABLE 0x0100 /* half duplex capable */
|
||||||
|
|
||||||
|
/* Bit definitions: 1000BaseT AUX Status */
|
||||||
|
#define GMII_1000_AUX_STATUS_FD_CAPABLE 0x0800 /* full duplex capable */
|
||||||
|
#define GMII_1000_AUX_STATUS_HD_CAPABLE 0x0400 /* half duplex capable */
|
||||||
|
|
||||||
|
/* Cicada MII Registers */
|
||||||
|
#define GMII_AUX_CTRL_STATUS 0x1C
|
||||||
|
#define GMII_AUX_ANEG_CPLT 0x8000
|
||||||
|
#define GMII_AUX_FDX 0x0020
|
||||||
|
#define GMII_AUX_SPEED_1000 0x0010
|
||||||
|
#define GMII_AUX_SPEED_100 0x0008
|
||||||
|
|
||||||
|
#ifndef ADVERTISE_PAUSE_CAP
|
||||||
|
#define ADVERTISE_PAUSE_CAP 0x0400
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MII_STAT1000
|
||||||
|
#define MII_STAT1000 0x000A
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LPA_1000FULL
|
||||||
|
#define LPA_1000FULL 0x0800
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* medium mode register */
|
||||||
|
#define MEDIUM_GIGA_MODE 0x0001
|
||||||
|
#define MEDIUM_FULL_DUPLEX_MODE 0x0002
|
||||||
|
#define MEDIUM_TX_ABORT_MODE 0x0004
|
||||||
|
#define MEDIUM_ENABLE_125MHZ 0x0008
|
||||||
|
#define MEDIUM_ENABLE_RX_FLOWCTRL 0x0010
|
||||||
|
#define MEDIUM_ENABLE_TX_FLOWCTRL 0x0020
|
||||||
|
#define MEDIUM_ENABLE_JUMBO_FRAME 0x0040
|
||||||
|
#define MEDIUM_CHECK_PAUSE_FRAME_MODE 0x0080
|
||||||
|
#define MEDIUM_ENABLE_RECEIVE 0x0100
|
||||||
|
#define MEDIUM_MII_100M_MODE 0x0200
|
||||||
|
#define MEDIUM_ENABLE_JAM_PATTERN 0x0400
|
||||||
|
#define MEDIUM_ENABLE_STOP_BACKPRESSURE 0x0800
|
||||||
|
#define MEDIUM_ENABLE_SUPPER_MAC_SUPPORT 0x1000
|
||||||
|
|
||||||
|
/* PHY mode */
|
||||||
|
#define PHY_MODE_MARVELL 0
|
||||||
|
#define PHY_MODE_CICADA_FAMILY 1
|
||||||
|
#define PHY_MODE_CICADA_V1 1
|
||||||
|
#define PHY_MODE_AGERE_FAMILY 2
|
||||||
|
#define PHY_MODE_AGERE_V0 2
|
||||||
|
#define PHY_MODE_CICADA_V2 5
|
||||||
|
#define PHY_MODE_AGERE_V0_GMII 6
|
||||||
|
#define PHY_MODE_CICADA_V2_ASIX 9
|
||||||
|
#define PHY_MODE_VSC8601 10
|
||||||
|
#define PHY_MODE_RTL8211CL 12
|
||||||
|
#define PHY_MODE_RTL8211BN 13
|
||||||
|
#define PHY_MODE_RTL8251CL 14
|
||||||
|
#define PHY_MODE_ATTANSIC_V0 0x40
|
||||||
|
#define PHY_MODE_ATTANSIC_FAMILY 0x40
|
||||||
|
#define PHY_MODE_MAC_TO_MAC_GMII 0x7C
|
||||||
|
|
||||||
|
/* */
|
||||||
|
#define LED_MODE_MARVELL 0
|
||||||
|
#define LED_MODE_CAMEO 1
|
||||||
|
|
||||||
|
#define MARVELL_LED_CTRL 0x18
|
||||||
|
#define MARVELL_MANUAL_LED 0x19
|
||||||
|
|
||||||
|
#define PHY_IDENTIFIER 0x0002
|
||||||
|
#define PHY_AGERE_IDENTIFIER 0x0282
|
||||||
|
#define PHY_CICADA_IDENTIFIER 0x000f
|
||||||
|
#define PHY_MARVELL_IDENTIFIER 0x0141
|
||||||
|
|
||||||
|
#define PHY_MARVELL_STATUS 0x001b
|
||||||
|
#define MARVELL_STATUS_HWCFG 0x0004 /* SGMII without clock */
|
||||||
|
|
||||||
|
#define PHY_MARVELL_CTRL 0x0014
|
||||||
|
#define MARVELL_CTRL_RXDELAY 0x0080
|
||||||
|
#define MARVELL_CTRL_TXDELAY 0x0002
|
||||||
|
|
||||||
|
#define PHY_CICADA_EXTPAGE 0x001f
|
||||||
|
#define CICADA_EXTPAGE_EN 0x0001
|
||||||
|
#define CICADA_EXTPAGE_DIS 0x0000
|
||||||
|
|
||||||
|
/* External ethernet phy */
|
||||||
|
#define EXTPHY_ID_MASK_OUI(phyid1, phyid2) ((phyid1 << 6) | ((phyid2 & 0xFC00) >> 10))
|
||||||
|
#define EXTPHY_ID_MASK_MODEL(phyid2) ((phyid2 & 0x3F0) >> 4)
|
||||||
|
|
||||||
|
#define EXTPHY_BROADCOM_OUI 0x2B8094
|
||||||
|
#define EXTPHY_BCM89811_MODEL 0x02
|
||||||
|
|
||||||
|
struct {unsigned short value, offset; } CICADA_FAMILY_HWINIT[] = {
|
||||||
|
{0x0001, 0x001f}, {0x1c25, 0x0017}, {0x2a30, 0x001f}, {0x234c, 0x0010},
|
||||||
|
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa7fa, 0x0000},
|
||||||
|
{0x0012, 0x0002}, {0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f},
|
||||||
|
{0xafac, 0x0000}, {0x000d, 0x0002}, {0x001c, 0x0001}, {0x8fac, 0x0000},
|
||||||
|
{0x2a30, 0x001f}, {0x0012, 0x0008}, {0x2a30, 0x001f}, {0x0400, 0x0014},
|
||||||
|
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0xa760, 0x0000},
|
||||||
|
{0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000}, {0x52b5, 0x001f},
|
||||||
|
{0xa760, 0x0000}, {0x0000, 0x0002}, {0xfaff, 0x0001}, {0x8760, 0x0000},
|
||||||
|
{0x52b5, 0x001f}, {0xafae, 0x0000}, {0x0004, 0x0002}, {0x0671, 0x0001},
|
||||||
|
{0x8fae, 0x0000}, {0x2a30, 0x001f}, {0x0012, 0x0008}, {0x0000, 0x001f},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {unsigned short value, offset; } CICADA_V2_HWINIT[] = {
|
||||||
|
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x000f, 0x0002},
|
||||||
|
{0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
|
||||||
|
{0x0000, 0x001f},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {unsigned short value, offset; } CICADA_V2_ASIX_HWINIT[] = {
|
||||||
|
{0x2a30, 0x001f}, {0x0212, 0x0008}, {0x52b5, 0x001f}, {0x0012, 0x0002},
|
||||||
|
{0x3002, 0x0001}, {0x87fa, 0x0000}, {0x52b5, 0x001f}, {0x000f, 0x0002},
|
||||||
|
{0x472a, 0x0001}, {0x8fa4, 0x0000}, {0x2a30, 0x001f}, {0x0212, 0x0008},
|
||||||
|
{0x0000, 0x001f},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {unsigned short value, offset; } AGERE_FAMILY_HWINIT[] = {
|
||||||
|
{0x0800, 0x0000}, {0x0007, 0x0012}, {0x8805, 0x0010}, {0xb03e, 0x0011},
|
||||||
|
{0x8808, 0x0010}, {0xe110, 0x0011}, {0x8806, 0x0010}, {0xb03e, 0x0011},
|
||||||
|
{0x8807, 0x0010}, {0xff00, 0x0011}, {0x880e, 0x0010}, {0xb4d3, 0x0011},
|
||||||
|
{0x880f, 0x0010}, {0xb4d3, 0x0011}, {0x8810, 0x0010}, {0xb4d3, 0x0011},
|
||||||
|
{0x8817, 0x0010}, {0x1c00, 0x0011}, {0x300d, 0x0010}, {0x0001, 0x0011},
|
||||||
|
{0x0002, 0x0012},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ax88178_data {
|
||||||
|
u16 EepromData;
|
||||||
|
u16 MediaLink;
|
||||||
|
int UseGpio0;
|
||||||
|
int UseRgmii;
|
||||||
|
u8 PhyMode;
|
||||||
|
u8 LedMode;
|
||||||
|
u8 BuffaloOld;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum watchdog_state {
|
||||||
|
AX_NOP = 0,
|
||||||
|
CHK_LINK, /* Routine A */
|
||||||
|
CHK_CABLE_EXIST, /* Called by A */
|
||||||
|
CHK_CABLE_EXIST_AGAIN, /* Routine B */
|
||||||
|
PHY_POWER_UP, /* Called by B */
|
||||||
|
PHY_POWER_UP_BH,
|
||||||
|
PHY_POWER_DOWN,
|
||||||
|
CHK_CABLE_STATUS, /* Routine C */
|
||||||
|
WAIT_AUTONEG_COMPLETE,
|
||||||
|
AX_SET_RX_CFG,
|
||||||
|
AX_CHK_AUTODETACH,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
struct ax88772b_data {
|
||||||
|
struct usbnet *dev;
|
||||||
|
struct workqueue_struct *ax_work;
|
||||||
|
struct work_struct check_link;
|
||||||
|
unsigned long time_to_chk;
|
||||||
|
u16 psc;
|
||||||
|
u8 pw_enabled;
|
||||||
|
u8 Event;
|
||||||
|
u8 checksum;
|
||||||
|
u8 PhySelect:1;
|
||||||
|
u8 OperationMode:1;
|
||||||
|
u16 presvd_phy_advertise;
|
||||||
|
u16 presvd_phy_bmcr;
|
||||||
|
|
||||||
|
u32 ext_phy_oui;
|
||||||
|
u8 ext_phy_model;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* define for MAC or PHY mode */
|
||||||
|
#define OPERATION_MAC_MODE 0
|
||||||
|
#define OPERATION_PHY_MODE 1
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
struct ax88772a_data {
|
||||||
|
struct usbnet *dev;
|
||||||
|
struct workqueue_struct *ax_work;
|
||||||
|
struct work_struct check_link;
|
||||||
|
unsigned long autoneg_start;
|
||||||
|
#define AX88772B_WATCHDOG (6 * HZ)
|
||||||
|
u8 Event;
|
||||||
|
u8 TickToExpire;
|
||||||
|
u8 DlyIndex;
|
||||||
|
u8 DlySel;
|
||||||
|
u16 EepromData;
|
||||||
|
u16 presvd_phy_advertise;
|
||||||
|
u16 presvd_phy_bmcr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ax88772_data {
|
||||||
|
struct usbnet *dev;
|
||||||
|
struct workqueue_struct *ax_work;
|
||||||
|
struct work_struct check_link;
|
||||||
|
unsigned long autoneg_start;
|
||||||
|
u8 Event;
|
||||||
|
u8 TickToExpire;
|
||||||
|
u16 presvd_phy_advertise;
|
||||||
|
u16 presvd_phy_bmcr;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AX_RX_CHECKSUM 1
|
||||||
|
#define AX_TX_CHECKSUM 2
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
|
||||||
|
struct ax8817x_data {
|
||||||
|
u8 multi_filter[AX_MCAST_FILTER_SIZE];
|
||||||
|
int (*resume) (struct usb_interface *intf);
|
||||||
|
int (*suspend) (struct usb_interface *intf,
|
||||||
|
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 10)
|
||||||
|
pm_message_t message);
|
||||||
|
#else
|
||||||
|
u32 message);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ax88172_int_data {
|
||||||
|
u16 res1;
|
||||||
|
#define AX_INT_PPLS_LINK (1 << 0)
|
||||||
|
#define AX_INT_SPLS_LINK (1 << 1)
|
||||||
|
#define AX_INT_CABOFF_UNPLUG (1 << 7)
|
||||||
|
u8 link;
|
||||||
|
u16 res2;
|
||||||
|
u8 status;
|
||||||
|
u16 res3;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#define AX_RXHDR_L4_ERR (1 << 8)
|
||||||
|
#define AX_RXHDR_L3_ERR (1 << 9)
|
||||||
|
|
||||||
|
#define AX_RXHDR_L4_TYPE_UDP 1
|
||||||
|
#define AX_RXHDR_L4_TYPE_ICMP 2
|
||||||
|
#define AX_RXHDR_L4_TYPE_IGMP 3
|
||||||
|
#define AX_RXHDR_L4_TYPE_TCP 4
|
||||||
|
#define AX_RXHDR_L4_TYPE_TCMPV6 5
|
||||||
|
#define AX_RXHDR_L4_TYPE_MASK 7
|
||||||
|
|
||||||
|
#define AX_RXHDR_L3_TYPE_IP 1
|
||||||
|
#define AX_RXHDR_L3_TYPE_IPV6 2
|
||||||
|
|
||||||
|
struct ax88772b_rx_header {
|
||||||
|
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||||
|
u16 len:11,
|
||||||
|
res1:1,
|
||||||
|
crc:1,
|
||||||
|
mii:1,
|
||||||
|
runt:1,
|
||||||
|
mc_bc:1;
|
||||||
|
|
||||||
|
u16 len_bar:11,
|
||||||
|
res2:5;
|
||||||
|
|
||||||
|
u8 vlan_ind:3,
|
||||||
|
vlan_tag_striped:1,
|
||||||
|
pri:3,
|
||||||
|
res3:1;
|
||||||
|
|
||||||
|
u8 l4_csum_err:1,
|
||||||
|
l3_csum_err:1,
|
||||||
|
l4_type:3,
|
||||||
|
l3_type:2,
|
||||||
|
ce:1;
|
||||||
|
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||||
|
u16 mc_bc:1,
|
||||||
|
runt:1,
|
||||||
|
mii:1,
|
||||||
|
crc:1,
|
||||||
|
res1:1,
|
||||||
|
len:11;
|
||||||
|
|
||||||
|
u16 res2:5,
|
||||||
|
len_bar:11;
|
||||||
|
|
||||||
|
u8 res3:1,
|
||||||
|
pri:3,
|
||||||
|
vlan_tag_striped:1,
|
||||||
|
vlan_ind:3;
|
||||||
|
|
||||||
|
u8 ce:1,
|
||||||
|
l3_type:2,
|
||||||
|
l4_type:3,
|
||||||
|
l3_csum_err:1,
|
||||||
|
l4_csum_err:1;
|
||||||
|
#else
|
||||||
|
#error "Please fix <asm/byteorder.h>"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __LINUX_USBNET_ASIX_H */
|
||||||
|
|
||||||
1203
main/utilities/usb_cherry/CherryUSB/class/vendor/axusbnet.c
vendored
Normal file
1203
main/utilities/usb_cherry/CherryUSB/class/vendor/axusbnet.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
25
main/utilities/usb_cherry/CherryUSB/class/vendor/axusbnet.h
vendored
Normal file
25
main/utilities/usb_cherry/CherryUSB/class/vendor/axusbnet.h
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Change Logs
|
||||||
|
* Date Author Notes
|
||||||
|
* 2022-04-17 aozima the first version for CherryUSB.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __USB_CLASHH_AXUSBNET_H__
|
||||||
|
#define __USB_CLASHH_AXUSBNET_H__
|
||||||
|
|
||||||
|
#include "usbh_core.h"
|
||||||
|
#include "asix.h"
|
||||||
|
|
||||||
|
struct usbh_axusbnet {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
|
||||||
|
uint8_t intf; /* interface number */
|
||||||
|
|
||||||
|
usbh_epinfo_t int_notify; /* Notify endpoint */
|
||||||
|
usbh_epinfo_t bulkin; /* Bulk IN endpoint */
|
||||||
|
usbh_epinfo_t bulkout; /* Bulk OUT endpoint */
|
||||||
|
|
||||||
|
uint32_t bulkin_buf[2048/sizeof(uint32_t)];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __USB_CLASHH_AXUSBNET_H__ */
|
||||||
92
main/utilities/usb_cherry/CherryUSB/class/vendor/usbh_air724.c
vendored
Normal file
92
main/utilities/usb_cherry/CherryUSB/class/vendor/usbh_air724.c
vendored
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#include "usbh_core.h"
|
||||||
|
|
||||||
|
#define DEV_FORMAT "/dev/air724"
|
||||||
|
|
||||||
|
static uint32_t g_devinuse = 0;
|
||||||
|
|
||||||
|
struct usbh_cdc_custom_air724 {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
|
||||||
|
usbh_epinfo_t bulkin; /* Bulk IN endpoint */
|
||||||
|
usbh_epinfo_t bulkout; /* Bulk OUT endpoint */
|
||||||
|
};
|
||||||
|
|
||||||
|
int usbh_air724_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
struct usbh_endpoint_cfg ep_cfg = { 0 };
|
||||||
|
struct usb_endpoint_descriptor *ep_desc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (intf != 3) {
|
||||||
|
USB_LOG_WRN("ignore intf:%d\r\n", intf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
struct usbh_cdc_custom_air724 *cdc_custom_class = usb_malloc(sizeof(struct usbh_cdc_custom_air724));
|
||||||
|
if (cdc_custom_class == NULL) {
|
||||||
|
USB_LOG_ERR("Fail to alloc cdc_custom_class\r\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(cdc_custom_class, 0, sizeof(struct usbh_cdc_custom_air724));
|
||||||
|
cdc_custom_class->hport = hport;
|
||||||
|
|
||||||
|
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||||
|
|
||||||
|
hport->config.intf[intf].priv = cdc_custom_class;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < hport->config.intf[intf].intf_desc.bNumEndpoints; i++) {
|
||||||
|
ep_desc = &hport->config.intf[intf].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_ep_alloc(&cdc_custom_class->bulkin, &ep_cfg);
|
||||||
|
} else {
|
||||||
|
usbh_ep_alloc(&cdc_custom_class->bulkout, &ep_cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_INFO("Register air724 Class:%s\r\n", hport->config.intf[intf].devname);
|
||||||
|
uint8_t cdc_buffer[32] = {0X41,0X54,0x0d,0x0a};
|
||||||
|
ret = usbh_ep_bulk_transfer(cdc_custom_class->bulkout, cdc_buffer, 4, 3000);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("bulk out error,ret:%d\r\n", ret);
|
||||||
|
} else {
|
||||||
|
USB_LOG_RAW("send over:%d\r\n", ret);
|
||||||
|
}
|
||||||
|
ret = usbh_ep_bulk_transfer(cdc_custom_class->bulkin, cdc_buffer, 10, 3000);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_ERR("bulk in error,ret:%d\r\n", ret);
|
||||||
|
} else {
|
||||||
|
USB_LOG_RAW("recv over:%d\r\n", ret);
|
||||||
|
for (size_t i = 0; i < ret; i++) {
|
||||||
|
USB_LOG_RAW("0x%02x ", cdc_buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbh_air724_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct usbh_class_driver cdc_custom_class_driver = {
|
||||||
|
.driver_name = "cdc_acm",
|
||||||
|
.connect = usbh_air724_connect,
|
||||||
|
.disconnect = usbh_air724_disconnect
|
||||||
|
};
|
||||||
|
|
||||||
|
CLASS_INFO_DEFINE const struct usbh_class_info cdc_custom_class_info = {
|
||||||
|
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||||
|
.class = 0xff,
|
||||||
|
.subclass = 0,
|
||||||
|
.protocol = 0,
|
||||||
|
.vid = 0x1782,
|
||||||
|
.pid = 0x4e00,
|
||||||
|
.class_driver = &cdc_custom_class_driver
|
||||||
|
};
|
||||||
1201
main/utilities/usb_cherry/CherryUSB/class/video/usb_video.h
Normal file
1201
main/utilities/usb_cherry/CherryUSB/class/video/usb_video.h
Normal file
File diff suppressed because it is too large
Load Diff
825
main/utilities/usb_cherry/CherryUSB/class/video/usbd_video.c
Normal file
825
main/utilities/usb_cherry/CherryUSB/class/video/usbd_video.c
Normal file
@ -0,0 +1,825 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_video.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#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;
|
||||||
|
uint8_t vcintf;
|
||||||
|
uint8_t vsintf;
|
||||||
|
struct video_entity_info info[3];
|
||||||
|
} usbd_video_cfg = {
|
||||||
|
.vcintf = 0xff,
|
||||||
|
.vsintf = 0xff,
|
||||||
|
.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_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 (usbd_video_cfg.vcintf == intf_num) { /* 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 (usbd_video_cfg.vsintf == intf_num) { /* 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_SOF:
|
||||||
|
usbd_video_sof_callback();
|
||||||
|
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_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
|
||||||
|
{
|
||||||
|
static usbd_class_t *last_class = NULL;
|
||||||
|
|
||||||
|
if (last_class != devclass) {
|
||||||
|
last_class = devclass;
|
||||||
|
usbd_class_register(devclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
intf->class_handler = video_class_request_handler;
|
||||||
|
intf->custom_handler = NULL;
|
||||||
|
intf->vendor_handler = NULL;
|
||||||
|
intf->notify_handler = video_notify_handler;
|
||||||
|
usbd_class_add_interface(devclass, intf);
|
||||||
|
|
||||||
|
if (usbd_video_cfg.vcintf == 0xff) {
|
||||||
|
usbd_video_cfg.vcintf = intf->intf_num;
|
||||||
|
} else if (usbd_video_cfg.vsintf == 0xff) {
|
||||||
|
usbd_video_cfg.vsintf = intf->intf_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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] = 0x02;
|
||||||
|
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] ^= 0x01;
|
||||||
|
if (i == (packets - 1)) {
|
||||||
|
memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size - 2);
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_len = (input_len + 2 * packets);
|
||||||
|
return packets;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_video_mjpeg_payload_header_toggle(uint8_t *output, uint32_t packets)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < packets; i++) {
|
||||||
|
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] ^= 0x01;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__WEAK void usbd_video_sof_callback(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
45
main/utilities/usb_cherry/CherryUSB/class/video/usbd_video.h
Normal file
45
main/utilities/usb_cherry/CherryUSB/class/video/usbd_video.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_video.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBD_VIDEO_H_
|
||||||
|
#define _USBD_VIDEO_H_
|
||||||
|
|
||||||
|
#include "usb_video.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void usbd_video_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
|
||||||
|
|
||||||
|
void usbd_video_open(uint8_t intf);
|
||||||
|
void usbd_video_close(uint8_t intf);
|
||||||
|
void usbd_video_probe_and_commit_controls_init(uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize);
|
||||||
|
uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
|
||||||
|
void usbd_video_mjpeg_payload_header_toggle(uint8_t *output, uint32_t packets);
|
||||||
|
void usbd_video_sof_callback(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* USBD_VIDEO_H_ */
|
||||||
263
main/utilities/usb_cherry/CherryUSB/class/wireless/ndis.h
Normal file
263
main/utilities/usb_cherry/CherryUSB/class/wireless/ndis.h
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
/* 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 <coflynn@newae.com>
|
||||||
|
* ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de>
|
||||||
|
*
|
||||||
|
* Thanks to the cygwin development team,
|
||||||
|
* espacially to Casper S. Hornstrup <chorns@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
#endif /* _LINUX_NDIS_H */
|
||||||
|
|
||||||
|
/** @} */
|
||||||
@ -0,0 +1,302 @@
|
|||||||
|
/**
|
||||||
|
* \file rndis_protocol.h
|
||||||
|
* RNDIS Defines
|
||||||
|
*
|
||||||
|
* \author
|
||||||
|
* Colin O'Flynn <coflynn@newae.com>
|
||||||
|
*
|
||||||
|
* \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 <stdint.h>
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
||||||
|
/** @} */
|
||||||
424
main/utilities/usb_cherry/CherryUSB/class/wireless/usbd_rndis.c
Normal file
424
main/utilities/usb_cherry/CherryUSB/class/wireless/usbd_rndis.c
Normal file
@ -0,0 +1,424 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_rndis.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_rndis.h"
|
||||||
|
#include "rndis_protocol.h"
|
||||||
|
|
||||||
|
#define RNDIS_INQUIRY_PUT(src, len) (memcpy(infomation_buffer, src, len))
|
||||||
|
#define RNDIS_INQUIRY_PUT_LE32(value) (*(uint32_t *)infomation_buffer = (value))
|
||||||
|
|
||||||
|
/* Device data structure */
|
||||||
|
struct usbd_rndis_cfg_priv {
|
||||||
|
uint32_t drv_version;
|
||||||
|
uint32_t media_status;
|
||||||
|
uint32_t speed;
|
||||||
|
uint32_t mtu;
|
||||||
|
uint32_t net_filter;
|
||||||
|
usb_eth_stat_t eth_state;
|
||||||
|
rndis_state_t init_state;
|
||||||
|
uint8_t mac[6];
|
||||||
|
uint32_t vendor_id;
|
||||||
|
uint8_t *vendor_desc;
|
||||||
|
} usbd_rndis_cfg = { .drv_version = 0x0001,
|
||||||
|
.media_status = NDIS_MEDIA_STATE_DISCONNECTED,
|
||||||
|
.mtu = RNDIS_MTU,
|
||||||
|
.speed = 0,
|
||||||
|
.init_state = rndis_uninitialized,
|
||||||
|
.mac = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 },
|
||||||
|
.vendor_id = 0xffffffff,
|
||||||
|
.vendor_desc = "CherryUSB" };
|
||||||
|
|
||||||
|
/* RNDIS options list */
|
||||||
|
const uint32_t oid_supported_list[] = {
|
||||||
|
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_PROTOCOL_OPTIONS,
|
||||||
|
OID_GEN_MAC_OPTIONS,
|
||||||
|
OID_GEN_MEDIA_CONNECT_STATUS,
|
||||||
|
OID_GEN_MAXIMUM_SEND_PACKETS,
|
||||||
|
OID_802_3_PERMANENT_ADDRESS,
|
||||||
|
OID_802_3_CURRENT_ADDRESS,
|
||||||
|
OID_802_3_MULTICAST_LIST,
|
||||||
|
OID_802_3_MAXIMUM_LIST_SIZE,
|
||||||
|
OID_802_3_MAC_OPTIONS
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t rndis_encapsulated_resp_buffer[CONFIG_RNDIS_RESP_BUFFER_SIZE];
|
||||||
|
|
||||||
|
static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len);
|
||||||
|
// static int rndis_encapsulated_resp_handler(uint8_t *data, uint32_t *len);
|
||||||
|
static void rndis_notify_rsp(void);
|
||||||
|
/**
|
||||||
|
* @brief Handler called for Class requests not handled by the USB stack.
|
||||||
|
*
|
||||||
|
* @param setup Information about the request to execute.
|
||||||
|
* @param len Size of the buffer.
|
||||||
|
* @param data Buffer containing the request result.
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
static int rndis_class_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, len);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rndis_notify_rsp(void)
|
||||||
|
{
|
||||||
|
uint8_t notify_buf[8] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
usbd_ep_write(0x81, notify_buf, 8, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
rndis_init_cmd_handler(data, len);
|
||||||
|
break;
|
||||||
|
case REMOTE_NDIS_HALT_MSG:
|
||||||
|
rndis_halt_cmd_handler(data, len);
|
||||||
|
break;
|
||||||
|
case REMOTE_NDIS_QUERY_MSG:
|
||||||
|
rndis_query_cmd_handler(data, len);
|
||||||
|
break;
|
||||||
|
case REMOTE_NDIS_SET_MSG:
|
||||||
|
rndis_set_cmd_handler(data, len);
|
||||||
|
break;
|
||||||
|
case REMOTE_NDIS_RESET_MSG:
|
||||||
|
rndis_reset_cmd_handler(data, len);
|
||||||
|
break;
|
||||||
|
case REMOTE_NDIS_KEEPALIVE_MSG:
|
||||||
|
rndis_keepalive_cmd_handler(data, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = usbd_rndis_cfg.mtu + ETH_HEADER_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)
|
||||||
|
{
|
||||||
|
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_initialize_msg_t *)data;
|
||||||
|
rndis_query_cmplt_t *resp;
|
||||||
|
uint8_t *infomation_buffer;
|
||||||
|
uint32_t infomation_len = 0;
|
||||||
|
|
||||||
|
resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||||
|
resp->Status = RNDIS_STATUS_SUCCESS;
|
||||||
|
resp->RequestId = cmd->RequestId;
|
||||||
|
resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
|
||||||
|
resp->InformationBufferOffset = 16;
|
||||||
|
|
||||||
|
infomation_buffer = (uint8_t *)resp + sizeof(rndis_initialize_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_VENDOR_DRIVER_VERSION:
|
||||||
|
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.drv_version);
|
||||||
|
infomation_len = 4;
|
||||||
|
break;
|
||||||
|
case OID_802_3_CURRENT_ADDRESS:
|
||||||
|
RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
|
||||||
|
infomation_len = 6;
|
||||||
|
break;
|
||||||
|
case OID_802_3_PERMANENT_ADDRESS:
|
||||||
|
RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
|
||||||
|
infomation_len = 6;
|
||||||
|
break;
|
||||||
|
case OID_GEN_MEDIA_SUPPORTED:
|
||||||
|
RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
|
||||||
|
infomation_len = 4;
|
||||||
|
break;
|
||||||
|
case OID_GEN_MEDIA_IN_USE:
|
||||||
|
RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
|
||||||
|
infomation_len = 4;
|
||||||
|
break;
|
||||||
|
case OID_GEN_PHYSICAL_MEDIUM:
|
||||||
|
RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
|
||||||
|
infomation_len = 4;
|
||||||
|
break;
|
||||||
|
case OID_GEN_HARDWARE_STATUS:
|
||||||
|
RNDIS_INQUIRY_PUT_LE32(0);
|
||||||
|
infomation_len = 4;
|
||||||
|
break;
|
||||||
|
case OID_GEN_LINK_SPEED:
|
||||||
|
RNDIS_INQUIRY_PUT_LE32(RNDIS_LINK_SPEED / 100);
|
||||||
|
infomation_len = 4;
|
||||||
|
break;
|
||||||
|
case OID_GEN_VENDOR_ID:
|
||||||
|
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.vendor_id);
|
||||||
|
infomation_len = 4;
|
||||||
|
break;
|
||||||
|
case OID_GEN_VENDOR_DESCRIPTION:
|
||||||
|
RNDIS_INQUIRY_PUT(usbd_rndis_cfg.vendor_desc, strlen(usbd_rndis_cfg.vendor_desc) + 1);
|
||||||
|
infomation_len = (strlen(usbd_rndis_cfg.vendor_desc) + 1);
|
||||||
|
break;
|
||||||
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||||
|
RNDIS_INQUIRY_PUT_LE32(0x00FFFFFF);
|
||||||
|
infomation_len = 4;
|
||||||
|
break;
|
||||||
|
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
||||||
|
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.mtu);
|
||||||
|
infomation_len = 4;
|
||||||
|
break;
|
||||||
|
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
||||||
|
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
||||||
|
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
||||||
|
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.mtu + ETH_HEADER_SIZE + sizeof(rndis_data_packet_t));
|
||||||
|
infomation_len = 4;
|
||||||
|
break;
|
||||||
|
case OID_GEN_MEDIA_CONNECT_STATUS:
|
||||||
|
RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.media_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 */
|
||||||
|
infomation_len = 4;
|
||||||
|
break;
|
||||||
|
case OID_802_3_MAC_OPTIONS:
|
||||||
|
infomation_len = 0;
|
||||||
|
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_NOT_SUPPORTED;
|
||||||
|
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:
|
||||||
|
break;
|
||||||
|
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||||
|
if (cmd->InformationBufferLength < sizeof(usbd_rndis_cfg.net_filter)) {
|
||||||
|
resp->Status = RNDIS_STATUS_INVALID_DATA;
|
||||||
|
} else {
|
||||||
|
/* Parameter starts at offset buf_offset of the req_id field */
|
||||||
|
param = (rndis_config_parameter_t *)((uint8_t *)&cmd->RequestId + cmd->InformationBufferOffset);
|
||||||
|
|
||||||
|
//usbd_rndis_cfg.net_filter = param->ParameterNameOffset;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_rndis_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
|
||||||
|
{
|
||||||
|
static usbd_class_t *last_class = NULL;
|
||||||
|
|
||||||
|
if (last_class != devclass) {
|
||||||
|
last_class = devclass;
|
||||||
|
usbd_class_register(devclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
intf->class_handler = rndis_class_request_handler;
|
||||||
|
intf->custom_handler = NULL;
|
||||||
|
intf->vendor_handler = NULL;
|
||||||
|
intf->notify_handler = rndis_notify_handler;
|
||||||
|
usbd_class_add_interface(devclass, intf);
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_rndis.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBD_RNDIS_H_
|
||||||
|
#define _USBD_RNDIS_H_
|
||||||
|
|
||||||
|
#include "usb_cdc.h"
|
||||||
|
|
||||||
|
#define ETH_HEADER_SIZE 14
|
||||||
|
#define RNDIS_MTU 1500 /* MTU value */
|
||||||
|
|
||||||
|
#ifdef 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
|
||||||
|
|
||||||
|
#define CONFIG_RNDIS_RESP_BUFFER_SIZE 128
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void usbd_rndis_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
393
main/utilities/usb_cherry/CherryUSB/class/wireless/usbh_rndis.c
Normal file
393
main/utilities/usb_cherry/CherryUSB/class/wireless/usbh_rndis.c
Normal file
@ -0,0 +1,393 @@
|
|||||||
|
#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].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_ep_alloc(&rndis_class->intin, &ep_cfg);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
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_ep_alloc(&rndis_class->bulkin, &ep_cfg);
|
||||||
|
} else {
|
||||||
|
usbh_ep_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) {
|
||||||
|
ret = usb_ep_cancel(rndis_class->bulkin);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_free(rndis_class->bulkin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rndis_class->bulkout) {
|
||||||
|
ret = usb_ep_cancel(rndis_class->bulkout);
|
||||||
|
if (ret < 0) {
|
||||||
|
}
|
||||||
|
usbh_ep_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
|
||||||
|
};
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_rndis.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#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_epinfo_t bulkin; /* Bulk IN endpoint */
|
||||||
|
usbh_epinfo_t bulkout; /* Bulk OUT endpoint */
|
||||||
|
usbh_epinfo_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
|
||||||
231
main/utilities/usb_cherry/CherryUSB/common/usb_dc.h
Normal file
231
main/utilities/usb_cherry/CherryUSB/common/usb_dc.h
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
/**
|
||||||
|
* @file usb_dc.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USB_DC_H
|
||||||
|
#define _USB_DC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief USB Endpoint Configuration.
|
||||||
|
*
|
||||||
|
* Structure containing the USB endpoint configuration.
|
||||||
|
*/
|
||||||
|
struct usbd_endpoint_cfg {
|
||||||
|
/** The number associated with the EP in the device
|
||||||
|
* configuration structure
|
||||||
|
* IN EP = 0x80 | \<endpoint number\>
|
||||||
|
* OUT EP = 0x00 | \<endpoint number\>
|
||||||
|
*/
|
||||||
|
uint8_t ep_addr;
|
||||||
|
/** Endpoint Transfer Type.
|
||||||
|
* May be Bulk, Interrupt, Control or Isochronous
|
||||||
|
*/
|
||||||
|
uint8_t ep_type;
|
||||||
|
/** Endpoint max packet size */
|
||||||
|
uint16_t ep_mps;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief USB Device Core Layer API
|
||||||
|
* @defgroup _usb_device_core_api USB Device Core API
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief init device controller registers.
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int usb_dc_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief deinit device controller registers.
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int usb_dc_deinit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Attach USB for device connection
|
||||||
|
*
|
||||||
|
* Function to attach USB for device connection. Upon success, the USB PLL
|
||||||
|
* is enabled, and the USB device is now capable of transmitting and receiving
|
||||||
|
* on the USB bus and of generating interrupts.
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int usb_dc_attach(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Detach the USB device
|
||||||
|
*
|
||||||
|
* Function to detach the USB device. Upon success, the USB hardware PLL
|
||||||
|
* is powered down and USB communication is disabled.
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int usb_dc_detach(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set USB device address
|
||||||
|
*
|
||||||
|
* @param[in] addr Device address
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int usbd_set_address(const uint8_t addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable the selected endpoint
|
||||||
|
*
|
||||||
|
* Function to disable the selected endpoint. Upon success interrupts are
|
||||||
|
* disabled for the corresponding endpoint and the endpoint is no longer able
|
||||||
|
* for transmitting/receiving data.
|
||||||
|
*
|
||||||
|
* @param[in] ep Endpoint address corresponding to the one
|
||||||
|
* listed in the device configuration table
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int usbd_ep_close(const uint8_t ep);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set stall condition for the selected endpoint
|
||||||
|
*
|
||||||
|
* @param[in] ep Endpoint address corresponding to the one
|
||||||
|
* listed in the device configuration table
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on 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 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int usbd_ep_clear_stall(const uint8_t ep);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if the selected endpoint is stalled
|
||||||
|
*
|
||||||
|
* @param[in] ep Endpoint address corresponding to the one
|
||||||
|
* listed in the device configuration table
|
||||||
|
* @param[out] stalled Endpoint stall status
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write data to the specified endpoint with poll mode.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
* @param[out] ret_bytes Bytes scheduled for transmission. This value
|
||||||
|
* may be NULL if the application expects all
|
||||||
|
* bytes to be written
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *ret_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read data from the specified endpoint
|
||||||
|
*
|
||||||
|
* This function is called by the endpoint handler function, after an OUT
|
||||||
|
* interrupt has been received for that EP. The application must only call this
|
||||||
|
* function through the supplied usbd_ep_callback function. This function clears
|
||||||
|
* the ENDPOINT NAK when max_data_len is 0, if all data in the endpoint FIFO has been read,
|
||||||
|
* so as to accept more data from host.
|
||||||
|
*
|
||||||
|
* @param[in] ep Endpoint address corresponding to the one
|
||||||
|
* listed in the device configuration table
|
||||||
|
* @param[in] data Pointer to data buffer to write to
|
||||||
|
* @param[in] max_data_len Max length of data to read
|
||||||
|
* @param[out] read_bytes Number of bytes read. If data is NULL and
|
||||||
|
* max_data_len is 0 the number of bytes
|
||||||
|
* available for read should be returned.
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *read_bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write data to the specified endpoint with async mode.
|
||||||
|
*
|
||||||
|
* @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_write_async(const uint8_t ep, const uint8_t *data, uint32_t data_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read data from the specified endpoint with async mode.
|
||||||
|
*
|
||||||
|
* @param[in] ep Endpoint address corresponding to the one
|
||||||
|
* listed in the device configuration table
|
||||||
|
* @param[in] data Pointer to data buffer to write to
|
||||||
|
* @param[in] data_len Max length of data to read
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail.
|
||||||
|
*/
|
||||||
|
int usbd_ep_read_async(const uint8_t ep, uint8_t *data, uint32_t data_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
705
main/utilities/usb_cherry/CherryUSB/common/usb_def.h
Normal file
705
main/utilities/usb_cherry/CherryUSB/common/usb_def.h
Normal file
@ -0,0 +1,705 @@
|
|||||||
|
/**
|
||||||
|
* @file usb_def.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#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_VARIABLE 4 /* Wireless USB 2.5 */
|
||||||
|
|
||||||
|
/* 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
|
||||||
340
main/utilities/usb_cherry/CherryUSB/common/usb_errno.h
Normal file
340
main/utilities/usb_cherry/CherryUSB/common/usb_errno.h
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* include/errno.h
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#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 */
|
||||||
233
main/utilities/usb_cherry/CherryUSB/common/usb_hc.h
Normal file
233
main/utilities/usb_cherry/CherryUSB/common/usb_hc.h
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
/**
|
||||||
|
* @file usb_hc.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USB_HC_H
|
||||||
|
#define _USB_HC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (*usbh_asynch_callback_t)(void *arg, int nbytes);
|
||||||
|
typedef void *usbh_epinfo_t;
|
||||||
|
/**
|
||||||
|
* @brief USB Endpoint Configuration.
|
||||||
|
*
|
||||||
|
* Structure containing the USB endpoint configuration.
|
||||||
|
*/
|
||||||
|
struct usbh_endpoint_cfg {
|
||||||
|
struct usbh_hubport *hport;
|
||||||
|
/** The number associated with the EP in the device
|
||||||
|
* configuration structure
|
||||||
|
* IN EP = 0x80 | \<endpoint number\>
|
||||||
|
* OUT EP = 0x00 | \<endpoint number\>
|
||||||
|
*/
|
||||||
|
uint8_t ep_addr;
|
||||||
|
/** Endpoint Transfer Type.
|
||||||
|
* May be Bulk, Interrupt, Control or Isochronous
|
||||||
|
*/
|
||||||
|
uint8_t ep_type;
|
||||||
|
uint8_t ep_interval;
|
||||||
|
/** Endpoint max packet size */
|
||||||
|
uint16_t ep_mps;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief USB Host Core Layer API
|
||||||
|
* @defgroup _usb_host_core_api USB Host Core API
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief usb host software init, used for global reset.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int usb_hc_sw_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief usb host controller hardware init.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int usb_hc_hw_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get port connect status
|
||||||
|
*
|
||||||
|
* @param port
|
||||||
|
* @return true
|
||||||
|
* @return false
|
||||||
|
*/
|
||||||
|
bool usbh_get_port_connect_status(const uint8_t port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief reset roothub port
|
||||||
|
*
|
||||||
|
* @param port port index
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int usbh_reset_port(const uint8_t port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get roothub port speed
|
||||||
|
*
|
||||||
|
* @param port port index
|
||||||
|
* @return return 1 means USB_SPEED_LOW, 2 means USB_SPEED_FULL and 3 means USB_SPEED_HIGH.
|
||||||
|
*/
|
||||||
|
uint8_t usbh_get_port_speed(const uint8_t port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief reconfig control endpoint.
|
||||||
|
*
|
||||||
|
* @param ep A memory location provided by the caller.
|
||||||
|
* @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_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate and config endpoint
|
||||||
|
*
|
||||||
|
* @param ep A memory location provided by the caller in which to save the allocated endpoint info.
|
||||||
|
* @param ep_cfg Describes the endpoint info to be allocated.
|
||||||
|
* @return On success will return 0, and others indicate fail.
|
||||||
|
*/
|
||||||
|
int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free a memory in which saves endpoint info.
|
||||||
|
*
|
||||||
|
* @param ep 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_ep_free(usbh_epinfo_t ep);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform a control transfer.
|
||||||
|
* This is a blocking method; this method will not return until the transfer has completed.
|
||||||
|
*
|
||||||
|
* @param ep 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. This buffer must be large enough to hold the length value
|
||||||
|
* in the request description.
|
||||||
|
* @return On success will return 0, and others indicate fail.
|
||||||
|
*/
|
||||||
|
int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint8_t *buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process a request to handle a transfer descriptor. This method will
|
||||||
|
* enqueue the transfer request and wait for it to complete. Only one transfer may be queued;
|
||||||
|
* This is a blocking method; this method will not return until the transfer has completed.
|
||||||
|
*
|
||||||
|
* @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer.
|
||||||
|
* @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint).
|
||||||
|
* @param buflen The length of the data to be sent or received.
|
||||||
|
* @param timeout Timeout for transfer, unit is ms.
|
||||||
|
* @return On success, a non-negative value is returned that indicates the number
|
||||||
|
* of bytes successfully transferred. On a failure, a negated errno value
|
||||||
|
* is returned that indicates the nature of the failure:
|
||||||
|
*
|
||||||
|
* -EAGAIN - If devices NAKs the transfer (or NYET or other error where
|
||||||
|
* it may be appropriate to restart the entire transaction).
|
||||||
|
* -EPERM - If the endpoint stalls
|
||||||
|
* -EIO - On a TX or data toggle error
|
||||||
|
* -EPIPE - Overrun errors
|
||||||
|
* -ETIMEDOUT - Sem wait timeout
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process a request to handle a transfer descriptor. This method will
|
||||||
|
* enqueue the transfer request and wait for it to complete. Only one transfer may be queued;
|
||||||
|
* This is a blocking method; this method will not return until the transfer has completed.
|
||||||
|
*
|
||||||
|
* @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer.
|
||||||
|
* @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint).
|
||||||
|
* @param buflen The length of the data to be sent or received.
|
||||||
|
* @param timeout Timeout for transfer, unit is ms.
|
||||||
|
* @return On success, a non-negative value is returned that indicates the number
|
||||||
|
* of bytes successfully transferred. On a failure, a negated errno value
|
||||||
|
* is returned that indicates the nature of the failure:
|
||||||
|
*
|
||||||
|
* -EAGAIN - If devices NAKs the transfer (or NYET or other error where
|
||||||
|
* it may be appropriate to restart the entire transaction).
|
||||||
|
* -EPERM - If the endpoint stalls
|
||||||
|
* -EIO - On a TX or data toggle error
|
||||||
|
* -EPIPE - Overrun errors
|
||||||
|
* -ETIMEDOUT - Sem wait timeout
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process a request to handle a transfer asynchronously. This method
|
||||||
|
* will enqueue the transfer request and return immediately. Only one transfer may be queued on a given endpoint
|
||||||
|
* When the transfer completes, the callback will be invoked with the provided argument.
|
||||||
|
*
|
||||||
|
* This method is useful for receiving interrupt transfers which may come infrequently.
|
||||||
|
*
|
||||||
|
* @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer.
|
||||||
|
* @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint).
|
||||||
|
* @param buflen The length of the data to be sent or received.
|
||||||
|
* @param callback This function will be called when the transfer completes.
|
||||||
|
* @param arg The arbitrary parameter that will be passed to the callback function when the transfer completes.
|
||||||
|
*
|
||||||
|
* @return On success will return 0, and others indicate fail.
|
||||||
|
*/
|
||||||
|
int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process a request to handle a transfer asynchronously. This method
|
||||||
|
* will enqueue the transfer request and return immediately. Only one transfer may be queued on a given endpoint
|
||||||
|
* When the transfer completes, the callback will be invoked with the provided argument.
|
||||||
|
*
|
||||||
|
* This method is useful for receiving interrupt transfers which may come infrequently.
|
||||||
|
*
|
||||||
|
* @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer.
|
||||||
|
* @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint).
|
||||||
|
* @param buflen The length of the data to be sent or received.
|
||||||
|
* @param callback This function will be called when the transfer completes.
|
||||||
|
* @param arg The arbitrary parameter that will be passed to the callback function when the transfer completes.
|
||||||
|
*
|
||||||
|
* @return On success will return 0, and others indicate fail.
|
||||||
|
*/
|
||||||
|
int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cancel any pending syncrhonous or asynchronous transfer on an endpoint.
|
||||||
|
*
|
||||||
|
* @param ep The IN or OUT endpoint descriptor for the device endpoint on which to cancel.
|
||||||
|
* @return On success will return 0, and others indicate fail.
|
||||||
|
*/
|
||||||
|
int usb_ep_cancel(usbh_epinfo_t ep);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
473
main/utilities/usb_cherry/CherryUSB/common/usb_list.h
Normal file
473
main/utilities/usb_cherry/CherryUSB/common/usb_list.h
Normal file
@ -0,0 +1,473 @@
|
|||||||
|
/**
|
||||||
|
* @file usb_list.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef __USB_LIST_H__
|
||||||
|
#define __USB_LIST_H__
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
while (l->next) {
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* append the node to the tail */
|
||||||
|
l->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)
|
||||||
|
{
|
||||||
|
/* remove slist head */
|
||||||
|
while (l->next && l->next != n) {
|
||||||
|
l = l->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove node */
|
||||||
|
if (l->next != (usb_slist_t *)0) {
|
||||||
|
l->next = l->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
|
||||||
87
main/utilities/usb_cherry/CherryUSB/common/usb_log.h
Normal file
87
main/utilities/usb_cherry/CherryUSB/common/usb_log.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#ifndef _USB_LOG_H
|
||||||
|
#define _USB_LOG_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* 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
|
||||||
90
main/utilities/usb_cherry/CherryUSB/common/usb_mem.h
Normal file
90
main/utilities/usb_cherry/CherryUSB/common/usb_mem.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
* @file usb_mem.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USB_MEM_H
|
||||||
|
#define _USB_MEM_H
|
||||||
|
|
||||||
|
#ifndef CONFIG_DCACHE_LINE_SIZE
|
||||||
|
#define CONFIG_DCACHE_LINE_SIZE 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||||
|
#define USB_NOCACHE_RAM_SECTION __attribute__((section(".nocache_ram")))
|
||||||
|
#define USB_MEM_ALIGN32 __attribute__((aligned(CONFIG_DCACHE_LINE_SIZE)))
|
||||||
|
#else
|
||||||
|
#define USB_NOCACHE_RAM_SECTION
|
||||||
|
#define USB_MEM_ALIGN32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define usb_malloc(size) malloc(size)
|
||||||
|
#define usb_free(ptr) free(ptr)
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_DCACHE_ENABLE
|
||||||
|
static inline void *usb_iomalloc(size_t size)
|
||||||
|
{
|
||||||
|
void *ptr;
|
||||||
|
void *align_ptr;
|
||||||
|
int uintptr_size;
|
||||||
|
size_t align_size;
|
||||||
|
uint32_t align = CONFIG_DCACHE_LINE_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 (((uint32_t)ptr & (align - 1)) == 0) {
|
||||||
|
align_ptr = (void *)((uint32_t)ptr + align);
|
||||||
|
} else {
|
||||||
|
align_ptr = (void *)(((uint32_t)ptr + (align - 1)) & ~(align - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the pointer before alignment pointer to the real pointer */
|
||||||
|
*((uint32_t *)((uint32_t)align_ptr - sizeof(void *))) = (uint32_t)ptr;
|
||||||
|
|
||||||
|
ptr = align_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void usb_iofree(void *ptr)
|
||||||
|
{
|
||||||
|
void *real_ptr;
|
||||||
|
|
||||||
|
real_ptr = (void *)*(uint32_t *)((uint32_t)ptr - sizeof(void *));
|
||||||
|
usb_free(real_ptr);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define usb_iomalloc(size) usb_malloc(size)
|
||||||
|
#define usb_iofree(ptr) usb_free(ptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
244
main/utilities/usb_cherry/CherryUSB/common/usb_util.h
Normal file
244
main/utilities/usb_cherry/CherryUSB/common/usb_util.h
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
/**
|
||||||
|
* @file usb_util.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def MAX
|
||||||
|
* @brief The larger value between @p a and @p b.
|
||||||
|
* @note Arguments are evaluated twice.
|
||||||
|
*/
|
||||||
|
#ifndef MAX
|
||||||
|
/* Use Z_MAX for a GCC-only, single evaluation version */
|
||||||
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def MIN
|
||||||
|
* @brief The smaller value between @p a and @p b.
|
||||||
|
* @note Arguments are evaluated twice.
|
||||||
|
*/
|
||||||
|
#ifndef MIN
|
||||||
|
/* Use Z_MIN for a GCC-only, single evaluation version */
|
||||||
|
#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 REQTYPE_GET_DIR(x) (((x) >> 7) & 0x01)
|
||||||
|
#define REQTYPE_GET_TYPE(x) (((x) >> 5) & 0x03U)
|
||||||
|
#define REQTYPE_GET_RECIP(x) ((x)&0x1F)
|
||||||
|
|
||||||
|
#define GET_DESC_TYPE(x) (((x) >> 8) & 0xFFU)
|
||||||
|
#define GET_DESC_INDEX(x) ((x)&0xFFU)
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#define USB_DESC_SECTION __attribute__((section("usb_desc"))) __USED __ALIGNED(1)
|
||||||
|
|
||||||
|
#endif
|
||||||
1327
main/utilities/usb_cherry/CherryUSB/core/usbd_core.c
Normal file
1327
main/utilities/usb_cherry/CherryUSB/core/usbd_core.c
Normal file
File diff suppressed because it is too large
Load Diff
149
main/utilities/usb_cherry/CherryUSB/core/usbd_core.h
Normal file
149
main/utilities/usb_cherry/CherryUSB/core/usbd_core.h
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/**
|
||||||
|
* @file usbd_core.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBD_CORE_H
|
||||||
|
#define _USBD_CORE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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 error reported by the controller */
|
||||||
|
USBD_EVENT_ERROR,
|
||||||
|
/** USB reset */
|
||||||
|
USBD_EVENT_RESET,
|
||||||
|
/** Start of Frame received */
|
||||||
|
USBD_EVENT_SOF,
|
||||||
|
/** USB connection established, hardware enumeration is completed */
|
||||||
|
USBD_EVENT_CONNECTED,
|
||||||
|
/** USB configuration done */
|
||||||
|
USBD_EVENT_CONFIGURED,
|
||||||
|
/** USB connection suspended by the HOST */
|
||||||
|
USBD_EVENT_SUSPEND,
|
||||||
|
/** USB connection lost */
|
||||||
|
USBD_EVENT_DISCONNECTED,
|
||||||
|
/** USB connection resumed by the HOST */
|
||||||
|
USBD_EVENT_RESUME,
|
||||||
|
|
||||||
|
/** USB interface selected */
|
||||||
|
USBD_EVENT_SET_INTERFACE,
|
||||||
|
/** USB interface selected */
|
||||||
|
USBD_EVENT_SET_REMOTE_WAKEUP,
|
||||||
|
/** USB interface selected */
|
||||||
|
USBD_EVENT_CLEAR_REMOTE_WAKEUP,
|
||||||
|
/** Set Feature ENDPOINT_HALT received */
|
||||||
|
USBD_EVENT_SET_HALT,
|
||||||
|
/** Clear Feature ENDPOINT_HALT received */
|
||||||
|
USBD_EVENT_CLEAR_HALT,
|
||||||
|
/** setup packet received */
|
||||||
|
USBD_EVENT_SETUP_NOTIFY,
|
||||||
|
/** ep0 in packet received */
|
||||||
|
USBD_EVENT_EP0_IN_NOTIFY,
|
||||||
|
/** ep0 out packet received */
|
||||||
|
USBD_EVENT_EP0_OUT_NOTIFY,
|
||||||
|
/** ep in packet except ep0 received */
|
||||||
|
USBD_EVENT_EP_IN_NOTIFY,
|
||||||
|
/** ep out packet except ep0 received */
|
||||||
|
USBD_EVENT_EP_OUT_NOTIFY,
|
||||||
|
/** Initial USB connection status */
|
||||||
|
USBD_EVENT_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function signature for the USB Endpoint status
|
||||||
|
*/
|
||||||
|
typedef void (*usbd_endpoint_callback)(uint8_t ep);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function signature for class specific requests
|
||||||
|
*
|
||||||
|
* Function which handles Class specific requests corresponding to an
|
||||||
|
* interface number specified in the device descriptor table. For host
|
||||||
|
* to device direction the 'len' and 'payload_data' contain the length
|
||||||
|
* of the received data and the pointer to the received data respectively.
|
||||||
|
* For device to host class requests, 'len' and 'payload_data' should be
|
||||||
|
* set by the callback function with the length and the address of the
|
||||||
|
* data to be transmitted buffer respectively.
|
||||||
|
*/
|
||||||
|
typedef int (*usbd_request_handler)(struct usb_setup_packet *setup,
|
||||||
|
uint8_t **data, uint32_t *transfer_len);
|
||||||
|
|
||||||
|
/* callback function pointer structure for Application to handle events */
|
||||||
|
typedef void (*usbd_notify_handler)(uint8_t event, void *arg);
|
||||||
|
|
||||||
|
typedef struct usbd_endpoint {
|
||||||
|
usb_slist_t list;
|
||||||
|
uint8_t ep_addr;
|
||||||
|
usbd_endpoint_callback ep_cb;
|
||||||
|
} usbd_endpoint_t;
|
||||||
|
|
||||||
|
typedef struct usbd_interface {
|
||||||
|
usb_slist_t list;
|
||||||
|
/** Handler for USB Class specific commands*/
|
||||||
|
usbd_request_handler class_handler;
|
||||||
|
/** Handler for USB Vendor specific commands */
|
||||||
|
usbd_request_handler vendor_handler;
|
||||||
|
/** Handler for USB custom specific commands */
|
||||||
|
usbd_request_handler custom_handler;
|
||||||
|
/** Handler for USB event notify commands */
|
||||||
|
usbd_notify_handler notify_handler;
|
||||||
|
uint8_t intf_num;
|
||||||
|
usb_slist_t ep_list;
|
||||||
|
} usbd_interface_t;
|
||||||
|
|
||||||
|
typedef struct usbd_class {
|
||||||
|
usb_slist_t list;
|
||||||
|
const char *name;
|
||||||
|
usb_slist_t intf_list;
|
||||||
|
} usbd_class_t;
|
||||||
|
|
||||||
|
void usbd_event_notify_handler(uint8_t event, void *arg);
|
||||||
|
|
||||||
|
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_class_register(usbd_class_t *devclass);
|
||||||
|
void usbd_class_add_interface(usbd_class_t *devclass, usbd_interface_t *intf);
|
||||||
|
void usbd_interface_add_endpoint(usbd_interface_t *intf, usbd_endpoint_t *ep);
|
||||||
|
bool usb_device_is_configured(void);
|
||||||
|
int usbd_initialize(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
1031
main/utilities/usb_cherry/CherryUSB/core/usbh_core.c
Normal file
1031
main/utilities/usb_cherry/CherryUSB/core/usbh_core.c
Normal file
File diff suppressed because it is too large
Load Diff
146
main/utilities/usb_cherry/CherryUSB/core/usbh_core.h
Normal file
146
main/utilities/usb_cherry/CherryUSB/core/usbh_core.h
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/**
|
||||||
|
* @file usbh_core.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USBH_CORE_H
|
||||||
|
#define _USBH_CORE_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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_workq.h"
|
||||||
|
#include "usbh_hub.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define USBH_ROOT_HUB_INDEX 1 /* roothub index*/
|
||||||
|
#define USBH_EX_HUB_INDEX 2 /* external hub index */
|
||||||
|
#define USBH_HUB_PORT_START_INDEX 1 /* first hub port index */
|
||||||
|
|
||||||
|
#ifdef CONFIG_USBHOST_HUB
|
||||||
|
#define ROOTHUB(hport) ((hport)->parent == NULL)
|
||||||
|
#else
|
||||||
|
#define ROOTHUB(hport) true
|
||||||
|
#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))
|
||||||
|
#define CLASS_INFO_DEFINE __attribute__((section("usbh_class_info"))) __USED __ALIGNED(1)
|
||||||
|
|
||||||
|
enum usbh_event_type {
|
||||||
|
USBH_EVENT_CONNECTED = (1 << 0),
|
||||||
|
USBH_EVENT_DISCONNECTED = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct usbh_endpoint {
|
||||||
|
struct usb_endpoint_descriptor ep_desc;
|
||||||
|
} usbh_endpoint_t;
|
||||||
|
|
||||||
|
typedef struct usbh_interface {
|
||||||
|
struct usb_interface_descriptor intf_desc;
|
||||||
|
struct usbh_endpoint ep[CONFIG_USBHOST_EP_NUM];
|
||||||
|
char devname[CONFIG_USBHOST_DEV_NAMELEN];
|
||||||
|
struct usbh_class_driver *class_driver;
|
||||||
|
void *priv;
|
||||||
|
} usbh_interface_t;
|
||||||
|
|
||||||
|
typedef struct usbh_configuration {
|
||||||
|
struct usb_configuration_descriptor config_desc;
|
||||||
|
struct usbh_interface intf[CONFIG_USBHOST_INTF_NUM];
|
||||||
|
} usbh_configuration_t;
|
||||||
|
|
||||||
|
typedef struct usbh_hubport {
|
||||||
|
bool connected; /* True: device connected; false: disconnected */
|
||||||
|
bool port_change; /* True: port changed; false: port do not change */
|
||||||
|
uint8_t port; /* Hub port index */
|
||||||
|
uint8_t dev_addr; /* device address */
|
||||||
|
uint8_t speed; /* device speed */
|
||||||
|
usbh_epinfo_t ep0; /* control ep info */
|
||||||
|
struct usb_device_descriptor device_desc;
|
||||||
|
struct usbh_configuration config;
|
||||||
|
#if 0
|
||||||
|
uint8_t* config_desc;
|
||||||
|
#endif
|
||||||
|
struct usb_setup_packet *setup;
|
||||||
|
struct usbh_hub *parent; /*if NULL, is roothub*/
|
||||||
|
} usbh_hubport_t;
|
||||||
|
|
||||||
|
typedef struct usbh_hub {
|
||||||
|
usb_slist_t list;
|
||||||
|
uint8_t index; /* Hub index */
|
||||||
|
uint8_t nports; /* Hub port number */
|
||||||
|
uint8_t dev_addr; /* Hub device address */
|
||||||
|
usbh_epinfo_t intin;
|
||||||
|
uint8_t *int_buffer;
|
||||||
|
struct hub_port_status *port_status;
|
||||||
|
struct usb_hub_descriptor hub_desc;
|
||||||
|
struct usbh_hubport child[CONFIG_USBHOST_EHPORTS];
|
||||||
|
struct usbh_hubport *parent; /* Parent hub port */
|
||||||
|
struct usb_work work;
|
||||||
|
} usbh_hub_t;
|
||||||
|
|
||||||
|
void usbh_event_notify_handler(uint8_t event, uint8_t rhport);
|
||||||
|
|
||||||
|
int usbh_initialize(void);
|
||||||
|
int lsusb(int argc, char **argv);
|
||||||
|
struct usbh_hubport *usbh_find_hubport(uint8_t dev_addr);
|
||||||
|
void *usbh_find_class_instance(const char *devname);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -0,0 +1,190 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_audio.h"
|
||||||
|
|
||||||
|
#define USBD_VID 0xffff
|
||||||
|
#define USBD_PID 0xffff
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define EP_INTERVAL 0x04
|
||||||
|
#else
|
||||||
|
#define EP_INTERVAL 0x01
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AUDIO_IN_EP 0x81
|
||||||
|
|
||||||
|
/* AUDIO Class Config */
|
||||||
|
#define AUDIO_FREQ 16000U
|
||||||
|
|
||||||
|
#define IN_CHANNEL_NUM 1
|
||||||
|
|
||||||
|
#if IN_CHANNEL_NUM == 1
|
||||||
|
#define INPUT_CTRL 0x03
|
||||||
|
#define INPUT_CH_ENABLE 0x0001
|
||||||
|
#elif IN_CHANNEL_NUM == 2
|
||||||
|
#define INPUT_CTRL 0x03, 0x03
|
||||||
|
#define INPUT_CH_ENABLE 0x0003
|
||||||
|
#elif IN_CHANNEL_NUM == 3
|
||||||
|
#define INPUT_CTRL 0x03, 0x03, 0x03
|
||||||
|
#define INPUT_CH_ENABLE 0x0007
|
||||||
|
#elif IN_CHANNEL_NUM == 4
|
||||||
|
#define INPUT_CTRL 0x03, 0x03, 0x03, 0x03
|
||||||
|
#define INPUT_CH_ENABLE 0x000f
|
||||||
|
#elif IN_CHANNEL_NUM == 5
|
||||||
|
#define INPUT_CTRL 0x03, 0x03, 0x03, 0x03, 0x03
|
||||||
|
#define INPUT_CH_ENABLE 0x001f
|
||||||
|
#elif IN_CHANNEL_NUM == 6
|
||||||
|
#define INPUT_CTRL 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
|
||||||
|
#define INPUT_CH_ENABLE 0x003F
|
||||||
|
#elif IN_CHANNEL_NUM == 7
|
||||||
|
#define INPUT_CTRL 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
|
||||||
|
#define INPUT_CH_ENABLE 0x007f
|
||||||
|
#elif IN_CHANNEL_NUM == 8
|
||||||
|
#define INPUT_CTRL 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
|
||||||
|
#define INPUT_CH_ENABLE 0x00ff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* AudioFreq * DataSize (2 bytes) * NumChannels (Stereo: 1) */
|
||||||
|
/* 16bit(2 Bytes) 单声道(Mono:1) */
|
||||||
|
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * 2 * IN_CHANNEL_NUM) / 1000))
|
||||||
|
|
||||||
|
#define USB_AUDIO_CONFIG_DESC_SIZ (unsigned long)(9 + \
|
||||||
|
AUDIO_AC_DESCRIPTOR_INIT_LEN(1) + \
|
||||||
|
AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(1, IN_CHANNEL_NUM) + \
|
||||||
|
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_AS_DESCRIPTOR_INIT_LEN(1))
|
||||||
|
|
||||||
|
#define AUDIO_AC_SIZ (AUDIO_SIZEOF_AC_HEADER_DESC(1) + \
|
||||||
|
AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(1, IN_CHANNEL_NUM) + \
|
||||||
|
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||||
|
|
||||||
|
const uint8_t audio_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, 0x00, 0x01),
|
||||||
|
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, IN_CHANNEL_NUM, INPUT_CH_ENABLE),
|
||||||
|
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x02, 0x01, 0x01, INPUT_CTRL),
|
||||||
|
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, 0x02),
|
||||||
|
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x03, IN_CHANNEL_NUM, AUDIO_IN_EP, AUDIO_IN_PACKET, EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_FREQ)),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'U', 0x00, /* wcChar10 */
|
||||||
|
'A', 0x00, /* wcChar11 */
|
||||||
|
'C', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'1', 0x00, /* wcChar3 */
|
||||||
|
'0', 0x00, /* wcChar4 */
|
||||||
|
'3', 0x00, /* wcChar5 */
|
||||||
|
'1', 0x00, /* wcChar6 */
|
||||||
|
'0', 0x00, /* wcChar7 */
|
||||||
|
'0', 0x00, /* wcChar8 */
|
||||||
|
'0' + IN_CHANNEL_NUM, 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
volatile bool tx_flag = 0;
|
||||||
|
|
||||||
|
void usbd_audio_open(uint8_t intf)
|
||||||
|
{
|
||||||
|
tx_flag = 1;
|
||||||
|
USB_LOG_RAW("OPEN\r\n");
|
||||||
|
}
|
||||||
|
void usbd_audio_close(uint8_t intf)
|
||||||
|
{
|
||||||
|
USB_LOG_RAW("CLOSE\r\n");
|
||||||
|
tx_flag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_class_t audio_class;
|
||||||
|
static usbd_interface_t audio_control_intf;
|
||||||
|
static usbd_interface_t audio_stream_intf;
|
||||||
|
|
||||||
|
void usbd_audio_iso_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_endpoint_t audio_in_ep = {
|
||||||
|
.ep_cb = usbd_audio_iso_callback,
|
||||||
|
.ep_addr = AUDIO_IN_EP
|
||||||
|
};
|
||||||
|
|
||||||
|
void audio_init()
|
||||||
|
{
|
||||||
|
usbd_desc_register(audio_descriptor);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_control_intf);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_stream_intf);
|
||||||
|
usbd_interface_add_endpoint(&audio_stream_intf, &audio_in_ep);
|
||||||
|
usbd_audio_add_entity(0x02, AUDIO_CONTROL_FEATURE_UNIT);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_test()
|
||||||
|
{
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (tx_flag) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,214 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_audio.h"
|
||||||
|
|
||||||
|
#define USBD_VID 0xffff
|
||||||
|
#define USBD_PID 0xffff
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define EP_INTERVAL 0x04
|
||||||
|
#else
|
||||||
|
#define EP_INTERVAL 0x01
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AUDIO_IN_EP 0x81
|
||||||
|
#define AUDIO_OUT_EP 0x02
|
||||||
|
|
||||||
|
/* AUDIO Class Config */
|
||||||
|
#define AUDIO_FREQ 16000U
|
||||||
|
|
||||||
|
#define AUDIO_SAMPLE_FREQ(frq) (uint8_t)(frq), (uint8_t)((frq >> 8)), (uint8_t)((frq >> 16))
|
||||||
|
|
||||||
|
/* AudioFreq * DataSize (2 bytes) * NumChannels (Stereo: 2) */
|
||||||
|
#define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_FREQ * 2 * 2) / 1000))
|
||||||
|
/* 16bit(2 Bytes) 双声道(Mono:2) */
|
||||||
|
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * 2 * 2) / 1000))
|
||||||
|
|
||||||
|
#define USB_AUDIO_CONFIG_DESC_SIZ (unsigned long)(9 + \
|
||||||
|
AUDIO_AC_DESCRIPTOR_INIT_LEN(2) + \
|
||||||
|
AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
|
||||||
|
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
|
||||||
|
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_AS_DESCRIPTOR_INIT_LEN(1) + \
|
||||||
|
AUDIO_AS_DESCRIPTOR_INIT_LEN(1))
|
||||||
|
|
||||||
|
#define AUDIO_AC_SIZ (AUDIO_SIZEOF_AC_HEADER_DESC(2) + \
|
||||||
|
AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
|
||||||
|
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(2, 1) + \
|
||||||
|
AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||||
|
|
||||||
|
const uint8_t audio_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, 0x00, 0x01, 0x02),
|
||||||
|
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, 0x02, 0x0003),
|
||||||
|
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x02, 0x01, 0x01, 0x03, 0x00),
|
||||||
|
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, 0x02),
|
||||||
|
AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x02, 0x0003),
|
||||||
|
AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x05, 0x04, 0x01, 0x03, 0x00),
|
||||||
|
AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_SPEAKER, 0x05),
|
||||||
|
AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x04, 0x02, AUDIO_OUT_EP, AUDIO_OUT_PACKET, EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_FREQ)),
|
||||||
|
AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x03, 0x02, AUDIO_IN_EP, AUDIO_IN_PACKET, EP_INTERVAL, AUDIO_SAMPLE_FREQ_3B(AUDIO_FREQ)),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'U', 0x00, /* wcChar10 */
|
||||||
|
'A', 0x00, /* wcChar11 */
|
||||||
|
'C', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'1', 0x00, /* wcChar3 */
|
||||||
|
'0', 0x00, /* wcChar4 */
|
||||||
|
'3', 0x00, /* wcChar5 */
|
||||||
|
'1', 0x00, /* wcChar6 */
|
||||||
|
'0', 0x00, /* wcChar7 */
|
||||||
|
'0', 0x00, /* wcChar8 */
|
||||||
|
'1', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
volatile bool tx_flag = 0;
|
||||||
|
volatile bool rx_flag = 0;
|
||||||
|
|
||||||
|
void usbd_audio_open(uint8_t intf)
|
||||||
|
{
|
||||||
|
if (intf == 1) {
|
||||||
|
rx_flag = 1;
|
||||||
|
printf("OPEN1\r\n");
|
||||||
|
} else {
|
||||||
|
tx_flag = 1;
|
||||||
|
printf("OPEN2\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void usbd_audio_close(uint8_t intf)
|
||||||
|
{
|
||||||
|
if (intf == 1) {
|
||||||
|
rx_flag = 1;
|
||||||
|
printf("CLOSE1\r\n");
|
||||||
|
} else {
|
||||||
|
tx_flag = 0;
|
||||||
|
printf("CLOSE2\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_class_t audio_class;
|
||||||
|
static usbd_interface_t audio_control_intf;
|
||||||
|
static usbd_interface_t audio_stream_intf;
|
||||||
|
static usbd_interface_t audio_stream_intf2;
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define AUDIO_OUT_EP_MPS 512
|
||||||
|
#else
|
||||||
|
#define AUDIO_OUT_EP_MPS 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
USB_MEM_ALIGN32 uint8_t out_buffer[AUDIO_OUT_EP_MPS];
|
||||||
|
uint32_t actual_read_length = 0;
|
||||||
|
|
||||||
|
void usbd_audio_out_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
if (usbd_ep_read(ep, out_buffer, AUDIO_OUT_EP_MPS, &actual_read_length) < 0) {
|
||||||
|
USB_LOG_RAW("Read DATA Packet failed\r\n");
|
||||||
|
usbd_ep_set_stall(ep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_audio_in_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_endpoint_t audio_in_ep = {
|
||||||
|
.ep_cb = usbd_audio_in_callback,
|
||||||
|
.ep_addr = AUDIO_IN_EP
|
||||||
|
};
|
||||||
|
|
||||||
|
static usbd_endpoint_t audio_out_ep = {
|
||||||
|
.ep_cb = usbd_audio_out_callback,
|
||||||
|
.ep_addr = AUDIO_OUT_EP
|
||||||
|
};
|
||||||
|
|
||||||
|
void audio_init()
|
||||||
|
{
|
||||||
|
usbd_desc_register(audio_descriptor);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_control_intf);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_stream_intf);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_stream_intf2);
|
||||||
|
usbd_interface_add_endpoint(&audio_stream_intf, &audio_in_ep);
|
||||||
|
usbd_interface_add_endpoint(&audio_stream_intf2, &audio_out_ep);
|
||||||
|
usbd_audio_add_entity(0x02, AUDIO_CONTROL_FEATURE_UNIT);
|
||||||
|
usbd_audio_add_entity(0x05, AUDIO_CONTROL_FEATURE_UNIT);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_test()
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
if (tx_flag) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,193 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_audio.h"
|
||||||
|
|
||||||
|
#define USBD_VID 0xffff
|
||||||
|
#define USBD_PID 0xffff
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define EP_INTERVAL 0x04
|
||||||
|
#else
|
||||||
|
#define EP_INTERVAL 0x01
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AUDIO_IN_EP 0x01
|
||||||
|
|
||||||
|
#define AUDIO_FREQ 48000
|
||||||
|
#define HALF_WORD_BYTES 2 //2 half word (one channel)
|
||||||
|
#define SAMPLE_BITS 16 //16 bit per channel
|
||||||
|
|
||||||
|
#define IN_CHANNEL_NUM 2
|
||||||
|
|
||||||
|
#if IN_CHANNEL_NUM == 1
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x00000001
|
||||||
|
#elif IN_CHANNEL_NUM == 2
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x00000003
|
||||||
|
#elif IN_CHANNEL_NUM == 3
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x00000007
|
||||||
|
#elif IN_CHANNEL_NUM == 4
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x0000000f
|
||||||
|
#elif IN_CHANNEL_NUM == 5
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x0000001f
|
||||||
|
#elif IN_CHANNEL_NUM == 6
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x0000003F
|
||||||
|
#elif IN_CHANNEL_NUM == 7
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x0000007f
|
||||||
|
#elif IN_CHANNEL_NUM == 8
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x000000ff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * IN_CHANNEL_NUM) / 1000))
|
||||||
|
|
||||||
|
#define BMCONTROL (AUDIO_V2_FU_CONTROL_MUTE | AUDIO_V2_FU_CONTROL_VOLUME)
|
||||||
|
|
||||||
|
#define USB_AUDIO_CONFIG_DESC_SIZ (9 + \
|
||||||
|
AUDIO_V2_AC_DESCRIPTOR_INIT_LEN + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_AS_DESCRIPTOR_INIT_LEN)
|
||||||
|
|
||||||
|
#define AUDIO_AC_SIZ (AUDIO_V2_SIZEOF_AC_HEADER_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||||
|
|
||||||
|
const uint8_t audio_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_MICROPHONE, 0x00, 0x00),
|
||||||
|
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
|
||||||
|
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_INTERM_MIC, 0x01, IN_CHANNEL_NUM, INPUT_CH_ENABLE, 0x0000),
|
||||||
|
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, INPUT_CTRL),
|
||||||
|
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, 0x03, 0x01, 0x0000),
|
||||||
|
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x04, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, AUDIO_IN_PACKET, EP_INTERVAL),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'U', 0x00, /* wcChar10 */
|
||||||
|
'A', 0x00, /* wcChar11 */
|
||||||
|
'C', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'1', 0x00, /* wcChar3 */
|
||||||
|
'0', 0x00, /* wcChar4 */
|
||||||
|
'3', 0x00, /* wcChar5 */
|
||||||
|
'1', 0x00, /* wcChar6 */
|
||||||
|
'0', 0x00, /* wcChar7 */
|
||||||
|
'0', 0x00, /* wcChar8 */
|
||||||
|
'4', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
volatile bool tx_flag = 0;
|
||||||
|
|
||||||
|
void usbd_audio_open(uint8_t intf)
|
||||||
|
{
|
||||||
|
tx_flag = 1;
|
||||||
|
USB_LOG_RAW("OPEN\r\n");
|
||||||
|
}
|
||||||
|
void usbd_audio_close(uint8_t intf)
|
||||||
|
{
|
||||||
|
USB_LOG_RAW("CLOSE\r\n");
|
||||||
|
tx_flag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_class_t audio_class;
|
||||||
|
static usbd_interface_t audio_control_intf;
|
||||||
|
static usbd_interface_t audio_stream_intf;
|
||||||
|
|
||||||
|
void usbd_audio_iso_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_endpoint_t audio_in_ep = {
|
||||||
|
.ep_cb = usbd_audio_iso_callback,
|
||||||
|
.ep_addr = AUDIO_IN_EP
|
||||||
|
};
|
||||||
|
|
||||||
|
void audio_init()
|
||||||
|
{
|
||||||
|
usbd_desc_register(audio_descriptor);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_control_intf);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_stream_intf);
|
||||||
|
usbd_interface_add_endpoint(&audio_stream_intf, &audio_in_ep);
|
||||||
|
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||||
|
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_test()
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
if (tx_flag) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,269 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_audio.h"
|
||||||
|
|
||||||
|
#define USBD_VID 0xffff
|
||||||
|
#define USBD_PID 0xffff
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define EP_INTERVAL 0x04
|
||||||
|
#else
|
||||||
|
#define EP_INTERVAL 0x01
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AUDIO_OUT_EP 0x02
|
||||||
|
#define AUDIO_IN_EP 0x81
|
||||||
|
|
||||||
|
#define AUDIO_FREQ 48000
|
||||||
|
#define HALF_WORD_BYTES 2 //2 half word (one channel)
|
||||||
|
#define SAMPLE_BITS 16 //16 bit per channel
|
||||||
|
|
||||||
|
#define IN_CHANNEL_NUM 2
|
||||||
|
|
||||||
|
#if IN_CHANNEL_NUM == 1
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x00000001
|
||||||
|
#elif IN_CHANNEL_NUM == 2
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x00000003
|
||||||
|
#elif IN_CHANNEL_NUM == 3
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x00000007
|
||||||
|
#elif IN_CHANNEL_NUM == 4
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x0000000f
|
||||||
|
#elif IN_CHANNEL_NUM == 5
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x0000001f
|
||||||
|
#elif IN_CHANNEL_NUM == 6
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x0000003F
|
||||||
|
#elif IN_CHANNEL_NUM == 7
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x0000007f
|
||||||
|
#elif IN_CHANNEL_NUM == 8
|
||||||
|
#define INPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define INPUT_CH_ENABLE 0x000000ff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define OUT_CHANNEL_NUM 2
|
||||||
|
|
||||||
|
#if OUT_CHANNEL_NUM == 1
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x00000001
|
||||||
|
#elif OUT_CHANNEL_NUM == 2
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x00000003
|
||||||
|
#elif OUT_CHANNEL_NUM == 3
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x00000007
|
||||||
|
#elif OUT_CHANNEL_NUM == 4
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x0000000f
|
||||||
|
#elif OUT_CHANNEL_NUM == 5
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x0000001f
|
||||||
|
#elif OUT_CHANNEL_NUM == 6
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x0000003F
|
||||||
|
#elif OUT_CHANNEL_NUM == 7
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x0000007f
|
||||||
|
#elif OUT_CHANNEL_NUM == 8
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x000000ff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* AudioFreq * DataSize (2 bytes) * NumChannels */
|
||||||
|
#define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * OUT_CHANNEL_NUM) / 1000))
|
||||||
|
#define AUDIO_IN_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * IN_CHANNEL_NUM) / 1000))
|
||||||
|
|
||||||
|
#define BMCONTROL (AUDIO_V2_FU_CONTROL_MUTE | AUDIO_V2_FU_CONTROL_VOLUME)
|
||||||
|
|
||||||
|
#define USB_AUDIO_CONFIG_DESC_SIZ (9 + \
|
||||||
|
AUDIO_V2_AC_DESCRIPTOR_INIT_LEN + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_AS_DESCRIPTOR_INIT_LEN + \
|
||||||
|
AUDIO_V2_AS_DESCRIPTOR_INIT_LEN)
|
||||||
|
|
||||||
|
#define AUDIO_AC_SIZ (AUDIO_V2_SIZEOF_AC_HEADER_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM) + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||||
|
|
||||||
|
uint8_t audio_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, AUDIO_CATEGORY_UNDEF, 0x00, 0x00),
|
||||||
|
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
|
||||||
|
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
|
||||||
|
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, OUTPUT_CTRL),
|
||||||
|
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
|
||||||
|
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x05, 0x03, 0x03),
|
||||||
|
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_INTERM_MIC, 0x05, IN_CHANNEL_NUM, INPUT_CH_ENABLE, 0x0000),
|
||||||
|
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x07, 0x06, INPUT_CTRL),
|
||||||
|
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x08, AUDIO_TERMINAL_STREAMING, 0x07, 0x05, 0x0000),
|
||||||
|
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, AUDIO_OUT_PACKET, EP_INTERVAL),
|
||||||
|
AUDIO_V2_AS_DESCRIPTOR_INIT(0x02, 0x08, IN_CHANNEL_NUM, INPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_IN_EP, AUDIO_IN_PACKET, EP_INTERVAL),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'U', 0x00, /* wcChar10 */
|
||||||
|
'A', 0x00, /* wcChar11 */
|
||||||
|
'C', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'1', 0x00, /* wcChar3 */
|
||||||
|
'0', 0x00, /* wcChar4 */
|
||||||
|
'3', 0x00, /* wcChar5 */
|
||||||
|
'1', 0x00, /* wcChar6 */
|
||||||
|
'0', 0x00, /* wcChar7 */
|
||||||
|
'0', 0x00, /* wcChar8 */
|
||||||
|
'5', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
volatile bool tx_flag = 0;
|
||||||
|
volatile bool rx_flag = 0;
|
||||||
|
|
||||||
|
void usbd_audio_open(uint8_t intf)
|
||||||
|
{
|
||||||
|
if (intf == 1) {
|
||||||
|
rx_flag = 1;
|
||||||
|
USB_LOG_RAW("OPEN1\r\n");
|
||||||
|
} else {
|
||||||
|
tx_flag = 1;
|
||||||
|
USB_LOG_RAW("OPEN2\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void usbd_audio_close(uint8_t intf)
|
||||||
|
{
|
||||||
|
if (intf == 1) {
|
||||||
|
rx_flag = 1;
|
||||||
|
USB_LOG_RAW("CLOSE1\r\n");
|
||||||
|
} else {
|
||||||
|
tx_flag = 0;
|
||||||
|
USB_LOG_RAW("CLOSE2\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_audio_set_sampling_freq(uint8_t entity_id, uint8_t ep_ch, uint32_t sampling_freq)
|
||||||
|
{
|
||||||
|
uint16_t packet_size = 0;
|
||||||
|
if (entity_id == 1) {
|
||||||
|
packet_size = ((sampling_freq * 2 * OUT_CHANNEL_NUM) / 1000);
|
||||||
|
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 11] = packet_size;
|
||||||
|
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - AUDIO_V2_AS_DESCRIPTOR_INIT_LEN - 10] = packet_size >> 8;
|
||||||
|
} else if (entity_id == 5) {
|
||||||
|
packet_size = ((sampling_freq * 2 * IN_CHANNEL_NUM) / 1000);
|
||||||
|
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 11] = packet_size;
|
||||||
|
audio_descriptor[18 + USB_AUDIO_CONFIG_DESC_SIZ - 10] = packet_size >> 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_class_t audio_class;
|
||||||
|
static usbd_interface_t audio_control_intf;
|
||||||
|
static usbd_interface_t audio_stream_intf;
|
||||||
|
|
||||||
|
void usbd_audio_iso_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_endpoint_t audio_in_ep = {
|
||||||
|
.ep_cb = usbd_audio_iso_callback,
|
||||||
|
.ep_addr = AUDIO_IN_EP
|
||||||
|
};
|
||||||
|
|
||||||
|
void audio_init()
|
||||||
|
{
|
||||||
|
usbd_desc_register(audio_descriptor);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_control_intf);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_stream_intf);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_stream_intf2);
|
||||||
|
usbd_interface_add_endpoint(&audio_stream_intf, &audio_out_ep);
|
||||||
|
usbd_interface_add_endpoint(&audio_stream_intf2, &audio_in_ep);
|
||||||
|
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||||
|
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
|
||||||
|
usbd_audio_add_entity(0x05, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||||
|
usbd_audio_add_entity(0x07, AUDIO_CONTROL_FEATURE_UNIT);
|
||||||
|
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_test()
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
if (tx_flag) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,193 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_audio.h"
|
||||||
|
|
||||||
|
#define USBD_VID 0xffff
|
||||||
|
#define USBD_PID 0xffff
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define EP_INTERVAL 0x04
|
||||||
|
#else
|
||||||
|
#define EP_INTERVAL 0x01
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AUDIO_OUT_EP 0x01
|
||||||
|
|
||||||
|
#define AUDIO_FREQ 48000
|
||||||
|
#define HALF_WORD_BYTES 2 //2 half word (one channel)
|
||||||
|
#define SAMPLE_BITS 16 //16 bit per channel
|
||||||
|
|
||||||
|
#define OUT_CHANNEL_NUM 2
|
||||||
|
|
||||||
|
#if OUT_CHANNEL_NUM == 1
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x00000001
|
||||||
|
#elif OUT_CHANNEL_NUM == 2
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x00000003
|
||||||
|
#elif OUT_CHANNEL_NUM == 3
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x00000007
|
||||||
|
#elif OUT_CHANNEL_NUM == 4
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x0000000f
|
||||||
|
#elif OUT_CHANNEL_NUM == 5
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x0000001f
|
||||||
|
#elif OUT_CHANNEL_NUM == 6
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x0000003F
|
||||||
|
#elif OUT_CHANNEL_NUM == 7
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x0000007f
|
||||||
|
#elif OUT_CHANNEL_NUM == 8
|
||||||
|
#define OUTPUT_CTRL DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL), DBVAL(BMCONTROL)
|
||||||
|
#define OUTPUT_CH_ENABLE 0x000000ff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AUDIO_OUT_PACKET ((uint32_t)((AUDIO_FREQ * HALF_WORD_BYTES * OUT_CHANNEL_NUM) / 1000))
|
||||||
|
|
||||||
|
#define BMCONTROL (AUDIO_V2_FU_CONTROL_MUTE | AUDIO_V2_FU_CONTROL_VOLUME)
|
||||||
|
|
||||||
|
#define USB_AUDIO_CONFIG_DESC_SIZ (9 + \
|
||||||
|
AUDIO_V2_AC_DESCRIPTOR_INIT_LEN + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_AS_DESCRIPTOR_INIT_LEN)
|
||||||
|
|
||||||
|
#define AUDIO_AC_SIZ (AUDIO_V2_SIZEOF_AC_HEADER_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_CLOCK_SOURCE_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_INPUT_TERMINAL_DESC + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_FEATURE_UNIT_DESC(OUT_CHANNEL_NUM) + \
|
||||||
|
AUDIO_V2_SIZEOF_AC_OUTPUT_TERMINAL_DESC)
|
||||||
|
|
||||||
|
const uint8_t audio_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
AUDIO_V2_AC_DESCRIPTOR_INIT(0x00, 0x02, AUDIO_AC_SIZ, AUDIO_CATEGORY_SPEAKER, 0x00, 0x00),
|
||||||
|
AUDIO_V2_AC_CLOCK_SOURCE_DESCRIPTOR_INIT(0x01, 0x03, 0x03),
|
||||||
|
AUDIO_V2_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x02, AUDIO_TERMINAL_STREAMING, 0x01, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, 0x0000),
|
||||||
|
AUDIO_V2_AC_FEATURE_UNIT_DESCRIPTOR_INIT(0x03, 0x02, OUTPUT_CTRL),
|
||||||
|
AUDIO_V2_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_OUTTERM_SPEAKER, 0x03, 0x01, 0x0000),
|
||||||
|
AUDIO_V2_AS_DESCRIPTOR_INIT(0x01, 0x02, OUT_CHANNEL_NUM, OUTPUT_CH_ENABLE, HALF_WORD_BYTES, SAMPLE_BITS, AUDIO_OUT_EP, AUDIO_OUT_PACKET, EP_INTERVAL),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'U', 0x00, /* wcChar10 */
|
||||||
|
'A', 0x00, /* wcChar11 */
|
||||||
|
'C', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'1', 0x00, /* wcChar3 */
|
||||||
|
'0', 0x00, /* wcChar4 */
|
||||||
|
'3', 0x00, /* wcChar5 */
|
||||||
|
'1', 0x00, /* wcChar6 */
|
||||||
|
'0', 0x00, /* wcChar7 */
|
||||||
|
'0', 0x00, /* wcChar8 */
|
||||||
|
'3', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
volatile bool rx_flag = 0;
|
||||||
|
|
||||||
|
void usbd_audio_open(uint8_t intf)
|
||||||
|
{
|
||||||
|
rx_flag = 1;
|
||||||
|
USB_LOG_RAW("OPEN\r\n");
|
||||||
|
}
|
||||||
|
void usbd_audio_close(uint8_t intf)
|
||||||
|
{
|
||||||
|
USB_LOG_RAW("CLOSE\r\n");
|
||||||
|
rx_flag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_class_t audio_class;
|
||||||
|
static usbd_interface_t audio_control_intf;
|
||||||
|
static usbd_interface_t audio_stream_intf;
|
||||||
|
|
||||||
|
void usbd_audio_iso_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_endpoint_t audio_in_ep = {
|
||||||
|
.ep_cb = usbd_audio_iso_callback,
|
||||||
|
.ep_addr = AUDIO_OUT_EP
|
||||||
|
};
|
||||||
|
|
||||||
|
void audio_init()
|
||||||
|
{
|
||||||
|
usbd_desc_register(audio_descriptor);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_control_intf);
|
||||||
|
usbd_audio_add_interface(&audio_class, &audio_stream_intf);
|
||||||
|
usbd_interface_add_endpoint(&audio_stream_intf, &audio_in_ep);
|
||||||
|
usbd_audio_add_entity(0x01, AUDIO_CONTROL_CLOCK_SOURCE);
|
||||||
|
usbd_audio_add_entity(0x03, AUDIO_CONTROL_FEATURE_UNIT);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_test()
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
if (rx_flag) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
201
main/utilities/usb_cherry/CherryUSB/demo/cdc_acm_msc_template.c
Normal file
201
main/utilities/usb_cherry/CherryUSB/demo/cdc_acm_msc_template.c
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_cdc.h"
|
||||||
|
#include "usbd_msc.h"
|
||||||
|
|
||||||
|
/*!< endpoint address */
|
||||||
|
#define CDC_IN_EP 0x81
|
||||||
|
#define CDC_OUT_EP 0x02
|
||||||
|
#define CDC_INT_EP 0x83
|
||||||
|
|
||||||
|
#define MSC_IN_EP 0x85
|
||||||
|
#define MSC_OUT_EP 0x04
|
||||||
|
|
||||||
|
#define USBD_VID 0xFFFF
|
||||||
|
#define USBD_PID 0xFFFF
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
/*!< config descriptor size */
|
||||||
|
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN + MSC_DESCRIPTOR_LEN)
|
||||||
|
|
||||||
|
/*!< global descriptor */
|
||||||
|
static const uint8_t cdc_msc_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||||
|
MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, 0x00),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'C', 0x00, /* wcChar10 */
|
||||||
|
'D', 0x00, /* wcChar11 */
|
||||||
|
'C', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'2', 0x00, /* wcChar3 */
|
||||||
|
'1', 0x00, /* wcChar4 */
|
||||||
|
'2', 0x00, /* wcChar5 */
|
||||||
|
'3', 0x00, /* wcChar6 */
|
||||||
|
'4', 0x00, /* wcChar7 */
|
||||||
|
'5', 0x00, /* wcChar8 */
|
||||||
|
'6', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x02,
|
||||||
|
0x02,
|
||||||
|
0x01,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< class */
|
||||||
|
usbd_class_t cdc_class;
|
||||||
|
/*!< interface one */
|
||||||
|
usbd_interface_t cdc_cmd_intf;
|
||||||
|
/*!< interface two */
|
||||||
|
usbd_interface_t cdc_data_intf;
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
void usbd_cdc_acm_out(uint8_t ep)
|
||||||
|
{
|
||||||
|
uint8_t data[64];
|
||||||
|
uint32_t read_byte;
|
||||||
|
|
||||||
|
usbd_ep_read(ep, data, 64, &read_byte);
|
||||||
|
for (uint8_t i = 0; i < read_byte; i++) {
|
||||||
|
USB_LOG_RAW("%02x ", data[i]);
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
USB_LOG_RAW("read len:%d\r\n", read_byte);
|
||||||
|
usbd_ep_read(ep, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_cdc_acm_in(uint8_t ep)
|
||||||
|
{
|
||||||
|
USB_LOG_RAW("in\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!< endpoint call back */
|
||||||
|
usbd_endpoint_t cdc_out_ep = {
|
||||||
|
.ep_addr = CDC_OUT_EP,
|
||||||
|
.ep_cb = usbd_cdc_acm_out
|
||||||
|
};
|
||||||
|
|
||||||
|
usbd_endpoint_t cdc_in_ep = {
|
||||||
|
.ep_addr = CDC_IN_EP,
|
||||||
|
.ep_cb = usbd_cdc_acm_in
|
||||||
|
};
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
void cdc_acm_msc_init(void)
|
||||||
|
{
|
||||||
|
usbd_desc_register(cdc_msc_descriptor);
|
||||||
|
/*!< add interface */
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class, &cdc_cmd_intf);
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class, &cdc_data_intf);
|
||||||
|
/*!< interface add endpoint */
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf, &cdc_out_ep);
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf, &cdc_in_ep);
|
||||||
|
|
||||||
|
usbd_msc_class_init(MSC_OUT_EP, MSC_IN_EP);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile uint8_t dtr_enable = 0;
|
||||||
|
|
||||||
|
void usbd_cdc_acm_set_dtr(bool dtr)
|
||||||
|
{
|
||||||
|
if (dtr) {
|
||||||
|
dtr_enable = 1;
|
||||||
|
} else {
|
||||||
|
dtr_enable = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cdc_acm_data_send_with_dtr_test(void)
|
||||||
|
{
|
||||||
|
if (dtr_enable) {
|
||||||
|
uint8_t data_buffer[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x31, 0x32, 0x33, 0x34, 0x35 };
|
||||||
|
usbd_ep_write(CDC_IN_EP, data_buffer, 10, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 512
|
||||||
|
#define BLOCK_COUNT 10
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t BlockSpace[BLOCK_SIZE];
|
||||||
|
} BLOCK_TYPE;
|
||||||
|
|
||||||
|
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
||||||
|
|
||||||
|
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
||||||
|
{
|
||||||
|
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||||
|
*block_size = BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
|
{
|
||||||
|
if (sector < 10)
|
||||||
|
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
|
{
|
||||||
|
if (sector < 10)
|
||||||
|
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,221 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_cdc.h"
|
||||||
|
|
||||||
|
/*!< endpoint address */
|
||||||
|
#define CDC_IN_EP 0x81
|
||||||
|
#define CDC_OUT_EP 0x01
|
||||||
|
#define CDC_INT_EP 0x85
|
||||||
|
|
||||||
|
#define CDC_IN_EP2 0x82
|
||||||
|
#define CDC_OUT_EP2 0x02
|
||||||
|
#define CDC_INT_EP2 0x86
|
||||||
|
|
||||||
|
#define CDC_IN_EP3 0x83
|
||||||
|
#define CDC_OUT_EP3 0x03
|
||||||
|
#define CDC_INT_EP3 0x87
|
||||||
|
|
||||||
|
#define CDC_IN_EP4 0x84
|
||||||
|
#define CDC_OUT_EP4 0x04
|
||||||
|
#define CDC_INT_EP4 0x88
|
||||||
|
|
||||||
|
#define USBD_VID 0xFFFF
|
||||||
|
#define USBD_PID 0xFFFF
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
/*!< config descriptor size */
|
||||||
|
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN * 4)
|
||||||
|
|
||||||
|
/*!< global descriptor */
|
||||||
|
static const uint8_t cdc_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x08, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||||
|
CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP2, CDC_OUT_EP2, CDC_IN_EP2, 0x02),
|
||||||
|
CDC_ACM_DESCRIPTOR_INIT(0x04, CDC_INT_EP3, CDC_OUT_EP3, CDC_IN_EP3, 0x02),
|
||||||
|
CDC_ACM_DESCRIPTOR_INIT(0x06, CDC_INT_EP4, CDC_OUT_EP4, CDC_IN_EP4, 0x02),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'C', 0x00, /* wcChar10 */
|
||||||
|
'D', 0x00, /* wcChar11 */
|
||||||
|
'C', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'2', 0x00, /* wcChar3 */
|
||||||
|
'1', 0x00, /* wcChar4 */
|
||||||
|
'2', 0x00, /* wcChar5 */
|
||||||
|
'3', 0x00, /* wcChar6 */
|
||||||
|
'4', 0x00, /* wcChar7 */
|
||||||
|
'5', 0x00, /* wcChar8 */
|
||||||
|
'6', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x02,
|
||||||
|
0x02,
|
||||||
|
0x01,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< class */
|
||||||
|
usbd_class_t cdc_class;
|
||||||
|
/*!< interface one */
|
||||||
|
usbd_interface_t cdc_cmd_intf;
|
||||||
|
/*!< interface two */
|
||||||
|
usbd_interface_t cdc_data_intf;
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
void usbd_cdc_acm_bulk_out(uint8_t ep)
|
||||||
|
{
|
||||||
|
uint8_t data[64];
|
||||||
|
uint32_t read_byte;
|
||||||
|
|
||||||
|
usbd_ep_read(ep, data, 64, &read_byte);
|
||||||
|
for (uint8_t i = 0; i < read_byte; i++) {
|
||||||
|
USB_LOG_RAW("%02x ", data[i]);
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
USB_LOG_RAW("read len:%d\r\n", read_byte);
|
||||||
|
usbd_ep_read(ep, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_cdc_acm_bulk_in(uint8_t ep)
|
||||||
|
{
|
||||||
|
USB_LOG_RAW("in\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!< endpoint call back */
|
||||||
|
usbd_class_t cdc_class1;
|
||||||
|
usbd_interface_t cdc_cmd_intf1;
|
||||||
|
usbd_interface_t cdc_data_intf1;
|
||||||
|
|
||||||
|
usbd_endpoint_t cdc_out_ep1 = {
|
||||||
|
.ep_addr = CDC_OUT_EP,
|
||||||
|
.ep_cb = usbd_cdc_acm_bulk_out
|
||||||
|
};
|
||||||
|
|
||||||
|
usbd_endpoint_t cdc_in_ep1 = {
|
||||||
|
.ep_addr = CDC_IN_EP,
|
||||||
|
.ep_cb = usbd_cdc_acm_bulk_in
|
||||||
|
};
|
||||||
|
|
||||||
|
usbd_class_t cdc_class2;
|
||||||
|
usbd_interface_t cdc_cmd_intf2;
|
||||||
|
usbd_interface_t cdc_data_intf2;
|
||||||
|
|
||||||
|
usbd_endpoint_t cdc_out_ep2 = {
|
||||||
|
.ep_addr = CDC_OUT_EP2,
|
||||||
|
.ep_cb = usbd_cdc_acm_bulk_out
|
||||||
|
};
|
||||||
|
|
||||||
|
usbd_endpoint_t cdc_in_ep2 = {
|
||||||
|
.ep_addr = CDC_IN_EP2,
|
||||||
|
.ep_cb = usbd_cdc_acm_bulk_in
|
||||||
|
};
|
||||||
|
|
||||||
|
usbd_class_t cdc_class3;
|
||||||
|
usbd_interface_t cdc_cmd_intf3;
|
||||||
|
usbd_interface_t cdc_data_intf3;
|
||||||
|
|
||||||
|
usbd_endpoint_t cdc_out_ep3 = {
|
||||||
|
.ep_addr = CDC_OUT_EP3,
|
||||||
|
.ep_cb = usbd_cdc_acm_bulk_out
|
||||||
|
};
|
||||||
|
|
||||||
|
usbd_endpoint_t cdc_in_ep3 = {
|
||||||
|
.ep_addr = CDC_IN_EP3,
|
||||||
|
.ep_cb = usbd_cdc_acm_bulk_in
|
||||||
|
};
|
||||||
|
|
||||||
|
usbd_class_t cdc_class4;
|
||||||
|
usbd_interface_t cdc_cmd_intf4;
|
||||||
|
usbd_interface_t cdc_data_intf4;
|
||||||
|
|
||||||
|
usbd_endpoint_t cdc_out_ep4 = {
|
||||||
|
.ep_addr = CDC_OUT_EP4,
|
||||||
|
.ep_cb = usbd_cdc_acm_bulk_out
|
||||||
|
};
|
||||||
|
|
||||||
|
usbd_endpoint_t cdc_in_ep4 = {
|
||||||
|
.ep_addr = CDC_IN_EP4,
|
||||||
|
.ep_cb = usbd_cdc_acm_bulk_in
|
||||||
|
};
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
void cdc_acm_multi_init(void)
|
||||||
|
{
|
||||||
|
usbd_desc_register(cdc_descriptor);
|
||||||
|
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class1, &cdc_cmd_intf1);
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class1, &cdc_data_intf1);
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf1, &cdc_out_ep1);
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf1, &cdc_in_ep1);
|
||||||
|
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class2, &cdc_cmd_intf2);
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class2, &cdc_data_intf2);
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf2, &cdc_out_ep2);
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf2, &cdc_in_ep2);
|
||||||
|
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class3, &cdc_cmd_intf3);
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class3, &cdc_data_intf3);
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf3, &cdc_out_ep3);
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf3, &cdc_in_ep3);
|
||||||
|
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class4, &cdc_cmd_intf4);
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class4, &cdc_data_intf4);
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf4, &cdc_out_ep4);
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf4, &cdc_in_ep4);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
174
main/utilities/usb_cherry/CherryUSB/demo/cdc_acm_template.c
Normal file
174
main/utilities/usb_cherry/CherryUSB/demo/cdc_acm_template.c
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_cdc.h"
|
||||||
|
|
||||||
|
/*!< endpoint address */
|
||||||
|
#define CDC_IN_EP 0x81
|
||||||
|
#define CDC_OUT_EP 0x02
|
||||||
|
#define CDC_INT_EP 0x83
|
||||||
|
|
||||||
|
#define USBD_VID 0xFFFF
|
||||||
|
#define USBD_PID 0xFFFF
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
/*!< config descriptor size */
|
||||||
|
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN)
|
||||||
|
|
||||||
|
/*!< global descriptor */
|
||||||
|
static const uint8_t cdc_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'C', 0x00, /* wcChar10 */
|
||||||
|
'D', 0x00, /* wcChar11 */
|
||||||
|
'C', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'2', 0x00, /* wcChar3 */
|
||||||
|
'1', 0x00, /* wcChar4 */
|
||||||
|
'2', 0x00, /* wcChar5 */
|
||||||
|
'3', 0x00, /* wcChar6 */
|
||||||
|
'4', 0x00, /* wcChar7 */
|
||||||
|
'5', 0x00, /* wcChar8 */
|
||||||
|
'6', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x02,
|
||||||
|
0x02,
|
||||||
|
0x01,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< class */
|
||||||
|
usbd_class_t cdc_class;
|
||||||
|
/*!< interface one */
|
||||||
|
usbd_interface_t cdc_cmd_intf;
|
||||||
|
/*!< interface two */
|
||||||
|
usbd_interface_t cdc_data_intf;
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define CDC_BULK_SIZE 512
|
||||||
|
#else
|
||||||
|
#define CDC_BULK_SIZE 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
void usbd_cdc_acm_out(uint8_t ep)
|
||||||
|
{
|
||||||
|
uint8_t data[CDC_BULK_SIZE];
|
||||||
|
uint32_t read_byte;
|
||||||
|
|
||||||
|
usbd_ep_read(ep, data, CDC_BULK_SIZE, &read_byte);
|
||||||
|
for (uint8_t i = 0; i < read_byte; i++) {
|
||||||
|
USB_LOG_RAW("%02x ", data[i]);
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
USB_LOG_RAW("read len:%d\r\n", read_byte);
|
||||||
|
usbd_ep_read(ep, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_cdc_acm_in(uint8_t ep)
|
||||||
|
{
|
||||||
|
USB_LOG_RAW("in\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!< endpoint call back */
|
||||||
|
usbd_endpoint_t cdc_out_ep = {
|
||||||
|
.ep_addr = CDC_OUT_EP,
|
||||||
|
.ep_cb = usbd_cdc_acm_out
|
||||||
|
};
|
||||||
|
|
||||||
|
usbd_endpoint_t cdc_in_ep = {
|
||||||
|
.ep_addr = CDC_IN_EP,
|
||||||
|
.ep_cb = usbd_cdc_acm_in
|
||||||
|
};
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
void cdc_acm_init(void)
|
||||||
|
{
|
||||||
|
usbd_desc_register(cdc_descriptor);
|
||||||
|
/*!< add interface */
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class, &cdc_cmd_intf);
|
||||||
|
usbd_cdc_add_acm_interface(&cdc_class, &cdc_data_intf);
|
||||||
|
/*!< interface add endpoint */
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf, &cdc_out_ep);
|
||||||
|
usbd_interface_add_endpoint(&cdc_data_intf, &cdc_in_ep);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile uint8_t dtr_enable = 0;
|
||||||
|
|
||||||
|
void usbd_cdc_acm_set_dtr(bool dtr)
|
||||||
|
{
|
||||||
|
if (dtr) {
|
||||||
|
dtr_enable = 1;
|
||||||
|
} else {
|
||||||
|
dtr_enable = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cdc_acm_data_send_with_dtr_test(void)
|
||||||
|
{
|
||||||
|
if (dtr_enable) {
|
||||||
|
uint8_t data_buffer[CDC_BULK_SIZE] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30 };
|
||||||
|
memset(&data_buffer[10],'a',CDC_BULK_SIZE - 10);
|
||||||
|
data_buffer[63] = 'b';
|
||||||
|
usbd_ep_write(CDC_IN_EP, data_buffer, CDC_BULK_SIZE, NULL);// test if zlp is work.
|
||||||
|
usbd_ep_write(CDC_IN_EP, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,449 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_hid.h"
|
||||||
|
|
||||||
|
#define HID_STATE_IDLE 0
|
||||||
|
#define HID_STATE_BUSY 1
|
||||||
|
|
||||||
|
/*!< keyboard in endpoint */
|
||||||
|
#define KBD_IN_EP 0x81 /*!< address */
|
||||||
|
#define KBD_IN_EP_SIZE 8 /*!< max packet length */
|
||||||
|
#define KBD_IN_EP_INTERVAL 10 /*!< polling time */
|
||||||
|
|
||||||
|
/*!< keyboard out endpoint */
|
||||||
|
#define KBD_OUT_EP 0x01 /*!< address */
|
||||||
|
#define KBD_OUT_EP_SIZE 1 /*!< max packet length */
|
||||||
|
#define KBD_OUT_EP_INTERVAL 10 /*!< polling time */
|
||||||
|
|
||||||
|
/*!< hidraw in endpoint */
|
||||||
|
#define HIDRAW_IN_EP 0x82
|
||||||
|
#define HIDRAW_IN_SIZE 64
|
||||||
|
#define HIDRAW_IN_INTERVAL 10
|
||||||
|
|
||||||
|
/*!< hidraw out endpoint */
|
||||||
|
#define HIDRAW_OUT_EP 0x02
|
||||||
|
#define HIDRAW_OUT_EP_SIZE 64
|
||||||
|
#define HIDRAW_OUT_EP_INTERVAL 10
|
||||||
|
|
||||||
|
#define USBD_VID 0xffff
|
||||||
|
#define USBD_PID 0xffff
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
/*!< hid state ! Data can be sent only when state is idle */
|
||||||
|
uint8_t keyboard_state = HID_STATE_IDLE;
|
||||||
|
uint8_t custom_state = HID_STATE_IDLE;
|
||||||
|
|
||||||
|
/*!< config descriptor size */
|
||||||
|
#define USB_HID_CONFIG_DESC_SIZ 73
|
||||||
|
|
||||||
|
/*!< report descriptor size */
|
||||||
|
#define HID_KEYBOARD_REPORT_DESC_SIZE 63
|
||||||
|
|
||||||
|
/*!< custom hid report descriptor size */
|
||||||
|
#define HID_CUSTOM_REPORT_DESC_SIZE 34
|
||||||
|
|
||||||
|
/*!< global descriptor */
|
||||||
|
static const uint8_t hid_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
/************** Descriptor of Keyboard interface ****************/
|
||||||
|
/* 09 */
|
||||||
|
0x09, /* bLength: Interface Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||||
|
0x00, /* bInterfaceNumber: Number of Interface */
|
||||||
|
0x00, /* bAlternateSetting: Alternate setting */
|
||||||
|
0x02, /* bNumEndpoints */
|
||||||
|
0x03, /* bInterfaceClass: HID */
|
||||||
|
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
|
||||||
|
0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
|
||||||
|
0, /* iInterface: Index of string descriptor */
|
||||||
|
/******************** Descriptor of Keyboard HID ********************/
|
||||||
|
/* 18 */
|
||||||
|
0x09, /* bLength: HID Descriptor size */
|
||||||
|
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
|
||||||
|
0x11, /* bcdHID: HID Class Spec release number */
|
||||||
|
0x01,
|
||||||
|
0x00, /* bCountryCode: Hardware target country */
|
||||||
|
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
|
||||||
|
0x22, /* bDescriptorType */
|
||||||
|
HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||||
|
0x00,
|
||||||
|
/******************** Descriptor of Keyboard in endpoint ********************/
|
||||||
|
/* 27 */
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||||
|
KBD_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||||
|
0x03, /* bmAttributes: Interrupt endpoint */
|
||||||
|
KBD_IN_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||||
|
0x00,
|
||||||
|
KBD_IN_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||||
|
/******************** Descriptor of Keyboard out endpoint ********************/
|
||||||
|
/* 34 */
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||||
|
KBD_OUT_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||||
|
0x03, /* bmAttributes: Interrupt endpoint */
|
||||||
|
KBD_OUT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||||
|
0x00,
|
||||||
|
KBD_OUT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||||
|
/************** Descriptor of Custom interface *****************/
|
||||||
|
/* 41 */
|
||||||
|
0x09, /* bLength: Interface Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||||
|
0x01, /* bInterfaceNumber: Number of Interface */
|
||||||
|
0x00, /* bAlternateSetting: Alternate setting */
|
||||||
|
0x02, /* bNumEndpoints */
|
||||||
|
0x03, /* bInterfaceClass: HID */
|
||||||
|
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
|
||||||
|
0x00, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
|
||||||
|
0, /* iInterface: Index of string descriptor */
|
||||||
|
/******************** Descriptor of Custom HID ********************/
|
||||||
|
/* 50 */
|
||||||
|
0x09, /* bLength: HID Descriptor size */
|
||||||
|
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
|
||||||
|
0x11, /* bcdHID: HID Class Spec release number */
|
||||||
|
0x01,
|
||||||
|
0x00, /* bCountryCode: Hardware target country */
|
||||||
|
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
|
||||||
|
0x22, /* bDescriptorType */
|
||||||
|
HID_CUSTOM_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||||
|
0x00,
|
||||||
|
/******************** Descriptor of Custom in endpoint ********************/
|
||||||
|
/* 59 */
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||||
|
HIDRAW_IN_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||||
|
0x03, /* bmAttributes: Interrupt endpoint */
|
||||||
|
HIDRAW_IN_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||||
|
0x00,
|
||||||
|
HIDRAW_IN_INTERVAL, /* bInterval: Polling Interval */
|
||||||
|
/******************** Descriptor of Custom out endpoint ********************/
|
||||||
|
/* 66 */
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||||
|
HIDRAW_OUT_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||||
|
0x03, /* bmAttributes: Interrupt endpoint */
|
||||||
|
HIDRAW_OUT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||||
|
0x00,
|
||||||
|
HIDRAW_OUT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||||
|
/* 73 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'H', 0x00, /* wcChar10 */
|
||||||
|
'I', 0x00, /* wcChar11 */
|
||||||
|
'D', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'2', 0x00, /* wcChar3 */
|
||||||
|
'1', 0x00, /* wcChar4 */
|
||||||
|
'2', 0x00, /* wcChar5 */
|
||||||
|
'3', 0x00, /* wcChar6 */
|
||||||
|
'4', 0x00, /* wcChar7 */
|
||||||
|
'5', 0x00, /* wcChar8 */
|
||||||
|
'6', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< hid keyboard report descriptor */
|
||||||
|
static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
|
||||||
|
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||||
|
0x09, 0x06, // USAGE (Keyboard)
|
||||||
|
0xa1, 0x01, // COLLECTION (Application)
|
||||||
|
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||||
|
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
|
||||||
|
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
|
||||||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||||
|
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||||
|
0x75, 0x01, // REPORT_SIZE (1)
|
||||||
|
0x95, 0x08, // REPORT_COUNT (8)
|
||||||
|
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||||
|
0x95, 0x01, // REPORT_COUNT (1)
|
||||||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||||||
|
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||||
|
0x95, 0x05, // REPORT_COUNT (5)
|
||||||
|
0x75, 0x01, // REPORT_SIZE (1)
|
||||||
|
0x05, 0x08, // USAGE_PAGE (LEDs)
|
||||||
|
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
|
||||||
|
0x29, 0x05, // USAGE_MAXIMUM (Kana)
|
||||||
|
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
||||||
|
0x95, 0x01, // REPORT_COUNT (1)
|
||||||
|
0x75, 0x03, // REPORT_SIZE (3)
|
||||||
|
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
|
||||||
|
0x95, 0x06, // REPORT_COUNT (6)
|
||||||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||||||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||||
|
0x25, 0xFF, // LOGICAL_MAXIMUM (255)
|
||||||
|
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||||
|
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
|
||||||
|
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
|
||||||
|
0x81, 0x00, // INPUT (Data,Ary,Abs)
|
||||||
|
0xc0 // END_COLLECTION
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< custom hid report descriptor */
|
||||||
|
static const uint8_t hid_custom_report_desc[HID_CUSTOM_REPORT_DESC_SIZE] = {
|
||||||
|
/* USER CODE BEGIN 0 */
|
||||||
|
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1)
|
||||||
|
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||||
|
0xa1, 0x01, // COLLECTION (Application)
|
||||||
|
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||||
|
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
||||||
|
0x95, 0x40, // REPORT_COUNT (64)
|
||||||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||||||
|
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||||
|
/* <___________________________________________________> */
|
||||||
|
0x09, 0x01, // USAGE (Vendor Usage 1)
|
||||||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||||
|
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
||||||
|
0x95, 0x40, // REPORT_COUNT (64)
|
||||||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||||||
|
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
||||||
|
/* USER CODE END 0 */
|
||||||
|
0xC0 /* END_COLLECTION */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< class */
|
||||||
|
static usbd_class_t hid_class;
|
||||||
|
|
||||||
|
/*!< interface one */
|
||||||
|
static usbd_interface_t hid_intf_1;
|
||||||
|
|
||||||
|
/*!< interface two */
|
||||||
|
static usbd_interface_t hid_intf_2;
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
static void usbd_hid_kbd_in_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
/*!< endpoint call back */
|
||||||
|
/*!< transfer successfully */
|
||||||
|
if (keyboard_state == HID_STATE_BUSY) {
|
||||||
|
/*!< update the state */
|
||||||
|
keyboard_state = HID_STATE_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbd_hid_kbd_out_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
/*!< here you can write the LED processing from the host */
|
||||||
|
enum hid_kbd_led led_state;
|
||||||
|
/*!< read the led data from host send */
|
||||||
|
usbd_ep_read(ep, &led_state, KBD_OUT_EP_SIZE, NULL);
|
||||||
|
/*!< diy */
|
||||||
|
if (led_state & HID_KBD_LED_NUM_LOCK) {
|
||||||
|
/*!< num lock */
|
||||||
|
/*!< do what you like */
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
if (led_state & HID_KBD_LED_CAPS_LOCK) {
|
||||||
|
/*!< caps lock */
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (led_state & HID_KBD_LED_SCROLL_LOCK) {
|
||||||
|
/*!< scroll lock */
|
||||||
|
/*!< do what you like */
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
if (led_state & HID_KBD_LED_COMPOSE) {
|
||||||
|
/*!< compose led */
|
||||||
|
/*!< do what you like */
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
if (led_state & HID_KBD_LED_KANA) {
|
||||||
|
/*!< kana led */
|
||||||
|
/*!< do what you like */
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbd_hid_custom_in_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
/*!< endpoint call back */
|
||||||
|
/*!< transfer successfully */
|
||||||
|
if (custom_state == HID_STATE_BUSY) {
|
||||||
|
/*!< update the state */
|
||||||
|
custom_state = HID_STATE_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usbd_hid_custom_out_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
/*!< read the data from host send */
|
||||||
|
uint8_t custom_data[HIDRAW_OUT_EP_SIZE];
|
||||||
|
usbd_ep_read(HIDRAW_OUT_EP, custom_data, HIDRAW_OUT_EP_SIZE, NULL);
|
||||||
|
|
||||||
|
/*!< you can use the data do some thing you like */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!< endpoint call back */
|
||||||
|
static usbd_endpoint_t keyboard_in_ep = {
|
||||||
|
.ep_cb = usbd_hid_kbd_in_callback,
|
||||||
|
.ep_addr = 0x81
|
||||||
|
};
|
||||||
|
|
||||||
|
static usbd_endpoint_t keyboard_out_ep = {
|
||||||
|
.ep_cb = usbd_hid_kbd_out_callback,
|
||||||
|
.ep_addr = 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
static usbd_endpoint_t custom_in_ep = {
|
||||||
|
.ep_cb = usbd_hid_custom_in_callback,
|
||||||
|
.ep_addr = 0x82
|
||||||
|
};
|
||||||
|
|
||||||
|
static usbd_endpoint_t custom_out_ep = {
|
||||||
|
.ep_cb = usbd_hid_custom_out_callback,
|
||||||
|
.ep_addr = 0x02
|
||||||
|
};
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @brief hid custom init
|
||||||
|
* @pre none
|
||||||
|
* @param[in] none
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void hid_custom_keyboard_init(void)
|
||||||
|
{
|
||||||
|
usbd_desc_register(hid_descriptor);
|
||||||
|
/*!< add interface ! the first interface */
|
||||||
|
usbd_hid_add_interface(&hid_class, &hid_intf_1);
|
||||||
|
/*!< interface0 add endpoint ! the first endpoint */
|
||||||
|
usbd_interface_add_endpoint(&hid_intf_1, &keyboard_in_ep);
|
||||||
|
/*!< interface0 add endpoint ! the second endpoint */
|
||||||
|
usbd_interface_add_endpoint(&hid_intf_1, &keyboard_out_ep);
|
||||||
|
/*!< add interface the ! second interface */
|
||||||
|
usbd_hid_add_interface(&hid_class, &hid_intf_2);
|
||||||
|
/*!< interface1 add endpoint ! the first endpoint */
|
||||||
|
usbd_interface_add_endpoint(&hid_intf_2, &custom_in_ep);
|
||||||
|
/*!< interface1 add endpoint ! the second endpoint */
|
||||||
|
usbd_interface_add_endpoint(&hid_intf_2, &custom_out_ep);
|
||||||
|
/*!< register report descriptor interface 0 */
|
||||||
|
usbd_hid_report_descriptor_register(0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE);
|
||||||
|
/*!< register report descriptor interface 1 */
|
||||||
|
usbd_hid_report_descriptor_register(1, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief device send report to host
|
||||||
|
* @pre none
|
||||||
|
* @param[in] ep endpoint address
|
||||||
|
* @param[in] data points to the data buffer waiting to be sent
|
||||||
|
* @param[in] len length of data to be sent
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void hid_keyboard_send_report(uint8_t ep, uint8_t *data, uint8_t len)
|
||||||
|
{
|
||||||
|
if (usb_device_is_configured()) {
|
||||||
|
if (keyboard_state == HID_STATE_IDLE) {
|
||||||
|
/*!< updata the state */
|
||||||
|
keyboard_state = HID_STATE_BUSY;
|
||||||
|
/*!< write buffer */
|
||||||
|
usbd_ep_write(ep, data, len, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief device send report to host
|
||||||
|
* @pre none
|
||||||
|
* @param[in] ep endpoint address
|
||||||
|
* @param[in] data points to the data buffer waiting to be sent
|
||||||
|
* @param[in] len length of data to be sent
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void hid_custom_send_report(uint8_t ep, uint8_t *data, uint8_t len)
|
||||||
|
{
|
||||||
|
if (usb_device_is_configured()) {
|
||||||
|
if (custom_state == HID_STATE_IDLE) {
|
||||||
|
/*!< updata the state */
|
||||||
|
custom_state = HID_STATE_BUSY;
|
||||||
|
/*!< write buffer */
|
||||||
|
usbd_ep_write(ep, data, len, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief hid custom test
|
||||||
|
* @pre none
|
||||||
|
* @param[in] none
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void hid_custom_test(void)
|
||||||
|
{
|
||||||
|
/*!< keyboard test */
|
||||||
|
uint8_t sendbuffer1[8] = { 0x00, 0x00, HID_KEY_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; //A
|
||||||
|
hid_keyboard_send_report(KBD_IN_EP, sendbuffer1, KBD_IN_EP_SIZE);
|
||||||
|
/*!< delay 10ms */
|
||||||
|
//HAL_Delay(10);
|
||||||
|
/*!< send button up */
|
||||||
|
sendbuffer1[2] = 0;
|
||||||
|
hid_keyboard_send_report(KBD_IN_EP, sendbuffer1, KBD_IN_EP_SIZE);
|
||||||
|
/*!< delay 1000ms the custom test */
|
||||||
|
//HAL_Delay(1000);
|
||||||
|
/*!< custom test */
|
||||||
|
uint8_t sendbuffer2[64] = { 6 };
|
||||||
|
hid_custom_send_report(HIDRAW_IN_EP, sendbuffer2, HIDRAW_IN_SIZE);
|
||||||
|
//HAL_Delay(1000);
|
||||||
|
}
|
||||||
196
main/utilities/usb_cherry/CherryUSB/demo/hid_keyboard_template.c
Normal file
196
main/utilities/usb_cherry/CherryUSB/demo/hid_keyboard_template.c
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_hid.h"
|
||||||
|
|
||||||
|
#define USBD_VID 0xffff
|
||||||
|
#define USBD_PID 0xffff
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
#define HID_INT_EP 0x81
|
||||||
|
#define HID_INT_EP_SIZE 8
|
||||||
|
#define HID_INT_EP_INTERVAL 10
|
||||||
|
|
||||||
|
#define USB_HID_CONFIG_DESC_SIZ 34
|
||||||
|
#define HID_KEYBOARD_REPORT_DESC_SIZE 63
|
||||||
|
|
||||||
|
static const uint8_t hid_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
|
||||||
|
/************** Descriptor of Joystick Mouse interface ****************/
|
||||||
|
/* 09 */
|
||||||
|
0x09, /* bLength: Interface Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||||
|
0x00, /* bInterfaceNumber: Number of Interface */
|
||||||
|
0x00, /* bAlternateSetting: Alternate setting */
|
||||||
|
0x01, /* bNumEndpoints */
|
||||||
|
0x03, /* bInterfaceClass: HID */
|
||||||
|
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
|
||||||
|
0x01, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
|
||||||
|
0, /* iInterface: Index of string descriptor */
|
||||||
|
/******************** Descriptor of Joystick Mouse HID ********************/
|
||||||
|
/* 18 */
|
||||||
|
0x09, /* bLength: HID Descriptor size */
|
||||||
|
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
|
||||||
|
0x11, /* bcdHID: HID Class Spec release number */
|
||||||
|
0x01,
|
||||||
|
0x00, /* bCountryCode: Hardware target country */
|
||||||
|
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
|
||||||
|
0x22, /* bDescriptorType */
|
||||||
|
HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||||
|
0x00,
|
||||||
|
/******************** Descriptor of Mouse endpoint ********************/
|
||||||
|
/* 27 */
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||||
|
HID_INT_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||||
|
0x03, /* bmAttributes: Interrupt endpoint */
|
||||||
|
HID_INT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||||
|
0x00,
|
||||||
|
HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||||
|
/* 34 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'H', 0x00, /* wcChar10 */
|
||||||
|
'I', 0x00, /* wcChar11 */
|
||||||
|
'D', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'2', 0x00, /* wcChar3 */
|
||||||
|
'1', 0x00, /* wcChar4 */
|
||||||
|
'2', 0x00, /* wcChar5 */
|
||||||
|
'3', 0x00, /* wcChar6 */
|
||||||
|
'4', 0x00, /* wcChar7 */
|
||||||
|
'5', 0x00, /* wcChar8 */
|
||||||
|
'6', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
/* USB HID device Configuration Descriptor */
|
||||||
|
static uint8_t hid_desc[9] __ALIGN_END = {
|
||||||
|
/* 18 */
|
||||||
|
0x09, /* bLength: HID Descriptor size */
|
||||||
|
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
|
||||||
|
0x11, /* bcdHID: HID Class Spec release number */
|
||||||
|
0x01,
|
||||||
|
0x00, /* bCountryCode: Hardware target country */
|
||||||
|
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
|
||||||
|
0x22, /* bDescriptorType */
|
||||||
|
HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||||
|
0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
|
||||||
|
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||||
|
0x09, 0x06, // USAGE (Keyboard)
|
||||||
|
0xa1, 0x01, // COLLECTION (Application)
|
||||||
|
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||||
|
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
|
||||||
|
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
|
||||||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||||
|
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||||
|
0x75, 0x01, // REPORT_SIZE (1)
|
||||||
|
0x95, 0x08, // REPORT_COUNT (8)
|
||||||
|
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||||
|
0x95, 0x01, // REPORT_COUNT (1)
|
||||||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||||||
|
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||||
|
0x95, 0x05, // REPORT_COUNT (5)
|
||||||
|
0x75, 0x01, // REPORT_SIZE (1)
|
||||||
|
0x05, 0x08, // USAGE_PAGE (LEDs)
|
||||||
|
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
|
||||||
|
0x29, 0x05, // USAGE_MAXIMUM (Kana)
|
||||||
|
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
||||||
|
0x95, 0x01, // REPORT_COUNT (1)
|
||||||
|
0x75, 0x03, // REPORT_SIZE (3)
|
||||||
|
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
|
||||||
|
0x95, 0x06, // REPORT_COUNT (6)
|
||||||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||||||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||||
|
0x25, 0xFF, // LOGICAL_MAXIMUM (255)
|
||||||
|
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||||
|
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
|
||||||
|
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
|
||||||
|
0x81, 0x00, // INPUT (Data,Ary,Abs)
|
||||||
|
0xc0 // END_COLLECTION
|
||||||
|
};
|
||||||
|
|
||||||
|
static usbd_class_t hid_class;
|
||||||
|
static usbd_interface_t hid_intf;
|
||||||
|
|
||||||
|
void usbd_hid_int_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KEY_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; //A
|
||||||
|
usbd_ep_write(HID_INT_EP, sendbuffer, 8, NULL);
|
||||||
|
}
|
||||||
|
static usbd_endpoint_t hid_in_ep = {
|
||||||
|
.ep_cb = usbd_hid_int_callback,
|
||||||
|
.ep_addr = 0x81
|
||||||
|
};
|
||||||
|
|
||||||
|
void hid_keyboard_init(void)
|
||||||
|
{
|
||||||
|
usbd_desc_register(hid_descriptor);
|
||||||
|
usbd_hid_add_interface(&hid_class, &hid_intf);
|
||||||
|
usbd_interface_add_endpoint(&hid_intf, &hid_in_ep);
|
||||||
|
usbd_hid_report_descriptor_register(0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
280
main/utilities/usb_cherry/CherryUSB/demo/hid_mouse_template.c
Normal file
280
main/utilities/usb_cherry/CherryUSB/demo/hid_mouse_template.c
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_hid.h"
|
||||||
|
|
||||||
|
#define HID_STATE_IDLE 0
|
||||||
|
#define HID_STATE_BUSY 1
|
||||||
|
|
||||||
|
/*!< endpoint address */
|
||||||
|
#define HID_INT_EP 0x81
|
||||||
|
#define HID_INT_EP_SIZE 8
|
||||||
|
#define HID_INT_EP_INTERVAL 10
|
||||||
|
|
||||||
|
#define USBD_VID 0xffff
|
||||||
|
#define USBD_PID 0xffff
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
/*!< hid state ! Data can be sent only when state is idle */
|
||||||
|
uint8_t hid_state = HID_STATE_IDLE;
|
||||||
|
|
||||||
|
/*!< config descriptor size */
|
||||||
|
#define USB_HID_CONFIG_DESC_SIZ 34
|
||||||
|
/*!< report descriptor size */
|
||||||
|
#define HID_MOUSE_REPORT_DESC_SIZE 74
|
||||||
|
|
||||||
|
/*!< global descriptor */
|
||||||
|
const uint8_t hid_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
|
||||||
|
/************** Descriptor of Joystick Mouse interface ****************/
|
||||||
|
/* 09 */
|
||||||
|
0x09, /* bLength: Interface Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType: Interface descriptor type */
|
||||||
|
0x00, /* bInterfaceNumber: Number of Interface */
|
||||||
|
0x00, /* bAlternateSetting: Alternate setting */
|
||||||
|
0x01, /* bNumEndpoints */
|
||||||
|
0x03, /* bInterfaceClass: HID */
|
||||||
|
0x01, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
|
||||||
|
0x02, /* nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
|
||||||
|
0, /* iInterface: Index of string descriptor */
|
||||||
|
/******************** Descriptor of Joystick Mouse HID ********************/
|
||||||
|
/* 18 */
|
||||||
|
0x09, /* bLength: HID Descriptor size */
|
||||||
|
HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */
|
||||||
|
0x11, /* bcdHID: HID Class Spec release number */
|
||||||
|
0x01,
|
||||||
|
0x00, /* bCountryCode: Hardware target country */
|
||||||
|
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
|
||||||
|
0x22, /* bDescriptorType */
|
||||||
|
HID_MOUSE_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */
|
||||||
|
0x00,
|
||||||
|
/******************** Descriptor of Mouse endpoint ********************/
|
||||||
|
/* 27 */
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: */
|
||||||
|
HID_INT_EP, /* bEndpointAddress: Endpoint Address (IN) */
|
||||||
|
0x03, /* bmAttributes: Interrupt endpoint */
|
||||||
|
HID_INT_EP_SIZE, /* wMaxPacketSize: 4 Byte max */
|
||||||
|
0x00,
|
||||||
|
HID_INT_EP_INTERVAL, /* bInterval: Polling Interval */
|
||||||
|
/* 34 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'H', 0x00, /* wcChar10 */
|
||||||
|
'I', 0x00, /* wcChar11 */
|
||||||
|
'D', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'2', 0x00, /* wcChar3 */
|
||||||
|
'1', 0x00, /* wcChar4 */
|
||||||
|
'2', 0x00, /* wcChar5 */
|
||||||
|
'3', 0x00, /* wcChar6 */
|
||||||
|
'4', 0x00, /* wcChar7 */
|
||||||
|
'5', 0x00, /* wcChar8 */
|
||||||
|
'6', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< hid mouse report descriptor */
|
||||||
|
static const uint8_t hid_mouse_report_desc[HID_MOUSE_REPORT_DESC_SIZE] = {
|
||||||
|
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||||
|
0x09, 0x02, // USAGE (Mouse)
|
||||||
|
0xA1, 0x01, // COLLECTION (Application)
|
||||||
|
0x09, 0x01, // USAGE (Pointer)
|
||||||
|
|
||||||
|
0xA1, 0x00, // COLLECTION (Physical)
|
||||||
|
0x05, 0x09, // USAGE_PAGE (Button)
|
||||||
|
0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
||||||
|
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
|
||||||
|
|
||||||
|
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||||
|
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||||
|
0x95, 0x03, // REPORT_COUNT (3)
|
||||||
|
0x75, 0x01, // REPORT_SIZE (1)
|
||||||
|
|
||||||
|
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||||
|
0x95, 0x01, // REPORT_COUNT (1)
|
||||||
|
0x75, 0x05, // REPORT_SIZE (5)
|
||||||
|
0x81, 0x01, // INPUT (Cnst,Var,Abs)
|
||||||
|
|
||||||
|
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||||
|
0x09, 0x30, // USAGE (X)
|
||||||
|
0x09, 0x31, // USAGE (Y)
|
||||||
|
0x09, 0x38,
|
||||||
|
|
||||||
|
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
||||||
|
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
|
||||||
|
0x75, 0x08, // REPORT_SIZE (8)
|
||||||
|
0x95, 0x03, // REPORT_COUNT (2)
|
||||||
|
|
||||||
|
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||||
|
0xC0, 0x09,
|
||||||
|
0x3c, 0x05,
|
||||||
|
0xff, 0x09,
|
||||||
|
|
||||||
|
0x01, 0x15,
|
||||||
|
0x00, 0x25,
|
||||||
|
0x01, 0x75,
|
||||||
|
0x01, 0x95,
|
||||||
|
|
||||||
|
0x02, 0xb1,
|
||||||
|
0x22, 0x75,
|
||||||
|
0x06, 0x95,
|
||||||
|
0x01, 0xb1,
|
||||||
|
|
||||||
|
0x01, 0xc0 // END_COLLECTION
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< mouse report struct */
|
||||||
|
struct hid_mouse {
|
||||||
|
uint8_t buttons;
|
||||||
|
int8_t x;
|
||||||
|
int8_t y;
|
||||||
|
int8_t wheel;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!< class */
|
||||||
|
static usbd_class_t hid_class;
|
||||||
|
|
||||||
|
/*!< interface */
|
||||||
|
static usbd_interface_t hid_intf;
|
||||||
|
|
||||||
|
/*!< mouse report */
|
||||||
|
static struct hid_mouse mouse_cfg;
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
static void usbd_hid_int_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
/*!< endpoint call back */
|
||||||
|
/*!< transfer successfully */
|
||||||
|
if (hid_state == HID_STATE_BUSY) {
|
||||||
|
/*!< update the state */
|
||||||
|
hid_state = HID_STATE_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!< endpoint call back */
|
||||||
|
static usbd_endpoint_t hid_in_ep = {
|
||||||
|
.ep_cb = usbd_hid_int_callback,
|
||||||
|
.ep_addr = 0x81
|
||||||
|
};
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @brief hid mouse init
|
||||||
|
* @pre none
|
||||||
|
* @param[in] none
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void hid_mouse_init(void)
|
||||||
|
{
|
||||||
|
usbd_desc_register(hid_descriptor);
|
||||||
|
/*!< add interface */
|
||||||
|
usbd_hid_add_interface(&hid_class, &hid_intf);
|
||||||
|
/*!< interface add endpoint */
|
||||||
|
usbd_interface_add_endpoint(&hid_intf, &hid_in_ep);
|
||||||
|
/*!< register report descriptor */
|
||||||
|
usbd_hid_report_descriptor_register(0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
|
||||||
|
/*!< init mouse report data */
|
||||||
|
mouse_cfg.buttons = 0;
|
||||||
|
mouse_cfg.wheel = 0;
|
||||||
|
mouse_cfg.x = 0;
|
||||||
|
mouse_cfg.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief device send report to host
|
||||||
|
* @pre none
|
||||||
|
* @param[in] ep endpoint address
|
||||||
|
* @param[in] data Points to the data buffer waiting to be sent
|
||||||
|
* @param[in] len Length of data to be sent
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void hid_mouse_send_report(uint8_t ep, uint8_t *data, uint8_t len)
|
||||||
|
{
|
||||||
|
if (usb_device_is_configured()) {
|
||||||
|
if (hid_state == HID_STATE_IDLE) {
|
||||||
|
/*!< updata the state */
|
||||||
|
hid_state = HID_STATE_BUSY;
|
||||||
|
/*!< write buffer */
|
||||||
|
usbd_ep_write(ep, data, len, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief hid mouse test
|
||||||
|
* @pre none
|
||||||
|
* @param[in] none
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void hid_mouse_send_report_test(void)
|
||||||
|
{
|
||||||
|
/*!< remove mouse pointer */
|
||||||
|
mouse_cfg.x += 10;
|
||||||
|
mouse_cfg.y = 0;
|
||||||
|
/*!< send repotr to host */
|
||||||
|
hid_mouse_send_report(HID_INT_EP, (uint8_t *)&mouse_cfg, 4);
|
||||||
|
/*!< delay 1000ms */
|
||||||
|
}
|
||||||
166
main/utilities/usb_cherry/CherryUSB/demo/midi_template.c
Normal file
166
main/utilities/usb_cherry/CherryUSB/demo/midi_template.c
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usb_midi.h"
|
||||||
|
|
||||||
|
USB_DESC_SECTION const uint8_t midi_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0100, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
// Standard AC Interface Descriptor
|
||||||
|
0x09,
|
||||||
|
0x04,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
// Class-specific AC Interface Descriptor
|
||||||
|
0x09,
|
||||||
|
0x24,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
0x09,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
0x01,
|
||||||
|
// MIDIStreaming Interface Descriptors
|
||||||
|
0x09,
|
||||||
|
0x04,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x01,
|
||||||
|
0x03,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
// Class-Specific MS Interface Header Descriptor
|
||||||
|
0x07,
|
||||||
|
0x24,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
WBVAL(65),
|
||||||
|
|
||||||
|
// MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, 0x01),
|
||||||
|
// MIDI_IN_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x02),
|
||||||
|
// MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EMBEDDED, 0x03, 0x02),
|
||||||
|
// MIDI_OUT_JACK_DESCRIPTOR_INIT(MIDI_JACK_TYPE_EXTERNAL, 0x04, 0x01),
|
||||||
|
MIDI_JACK_DESCRIPTOR_INIT(0x01),
|
||||||
|
// OUT endpoint descriptor
|
||||||
|
0x09, 0x05, 0x02, 0x02, WBVAL(64), 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x25, 0x01, 0x01, 0x01,
|
||||||
|
|
||||||
|
// IN endpoint descriptor
|
||||||
|
0x09, 0x05, 0x81, 0x02, WBVAL(64), 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x25, 0x01, 0x01, 0x03,
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x28, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'M', 0x00, /* wcChar10 */
|
||||||
|
'I', 0x00, /* wcChar11 */
|
||||||
|
'D', 0x00, /* wcChar12 */
|
||||||
|
'I', 0x00, /* wcChar13 */
|
||||||
|
' ', 0x00, /* wcChar14 */
|
||||||
|
'D', 0x00, /* wcChar15 */
|
||||||
|
'E', 0x00, /* wcChar16 */
|
||||||
|
'M', 0x00, /* wcChar17 */
|
||||||
|
'O', 0x00, /* wcChar18 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'1', 0x00, /* wcChar3 */
|
||||||
|
'0', 0x00, /* wcChar4 */
|
||||||
|
'3', 0x00, /* wcChar5 */
|
||||||
|
'1', 0x00, /* wcChar6 */
|
||||||
|
'0', 0x00, /* wcChar7 */
|
||||||
|
'0', 0x00, /* wcChar8 */
|
||||||
|
'0', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x02,
|
||||||
|
0x02,
|
||||||
|
0x01,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
void usbd_midi_bulk_out(uint8_t ep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbd_midi_bulk_in(uint8_t ep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
usbd_class_t midi_class;
|
||||||
|
usbd_interface_t midi_cmd_intf;
|
||||||
|
usbd_interface_t midi_data_intf;
|
||||||
|
|
||||||
|
usbd_endpoint_t midi_out_ep = {
|
||||||
|
.ep_addr = MIDI_OUT_EP,
|
||||||
|
.ep_cb = usbd_midi_bulk_out
|
||||||
|
};
|
||||||
|
|
||||||
|
usbd_endpoint_t midi_in_ep = {
|
||||||
|
.ep_addr = MIDI_IN_EP,
|
||||||
|
.ep_cb = usbd_midi_bulk_in
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void midi_init(void)
|
||||||
|
{
|
||||||
|
usbd_desc_register(midi_descriptor);
|
||||||
|
|
||||||
|
usbd_class_add_interface(&midi_class, &midi_cmd_intf);
|
||||||
|
usbd_class_add_interface(&midi_class, &midi_data_intf);
|
||||||
|
usbd_interface_add_endpoint(&midi_data_intf, &midi_out_ep);
|
||||||
|
usbd_interface_add_endpoint(&midi_data_intf, &midi_in_ep);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
134
main/utilities/usb_cherry/CherryUSB/demo/msc_ram_template.c
Normal file
134
main/utilities/usb_cherry/CherryUSB/demo/msc_ram_template.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_msc.h"
|
||||||
|
|
||||||
|
#define MSC_IN_EP 0x81
|
||||||
|
#define MSC_OUT_EP 0x02
|
||||||
|
|
||||||
|
#define USBD_VID 0xFFFF
|
||||||
|
#define USBD_PID 0xFFFF
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
#define USB_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN)
|
||||||
|
|
||||||
|
const uint8_t msc_ram_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, 0x02),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'M', 0x00, /* wcChar10 */
|
||||||
|
'S', 0x00, /* wcChar11 */
|
||||||
|
'C', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'2', 0x00, /* wcChar3 */
|
||||||
|
'1', 0x00, /* wcChar4 */
|
||||||
|
'2', 0x00, /* wcChar5 */
|
||||||
|
'3', 0x00, /* wcChar6 */
|
||||||
|
'4', 0x00, /* wcChar7 */
|
||||||
|
'5', 0x00, /* wcChar8 */
|
||||||
|
'6', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BLOCK_SIZE 512
|
||||||
|
#define BLOCK_COUNT 10
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t BlockSpace[BLOCK_SIZE];
|
||||||
|
} BLOCK_TYPE;
|
||||||
|
|
||||||
|
BLOCK_TYPE mass_block[BLOCK_COUNT];
|
||||||
|
|
||||||
|
void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
|
||||||
|
{
|
||||||
|
*block_num = 1000; //Pretend having so many buffer,not has actually.
|
||||||
|
*block_size = BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
|
{
|
||||||
|
if (sector < 10)
|
||||||
|
memcpy(buffer, mass_block[sector].BlockSpace, length);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length)
|
||||||
|
{
|
||||||
|
if (sector < 10)
|
||||||
|
memcpy(mass_block[sector].BlockSpace, buffer, length);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* function ------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @brief msc ram init
|
||||||
|
* @pre none
|
||||||
|
* @param[in] none
|
||||||
|
* @retval none
|
||||||
|
*/
|
||||||
|
void msc_ram_init(void)
|
||||||
|
{
|
||||||
|
usbd_desc_register(msc_ram_descriptor);
|
||||||
|
usbd_msc_class_init(MSC_OUT_EP, MSC_IN_EP);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
109183
main/utilities/usb_cherry/CherryUSB/demo/music_16k_ac1.h
Normal file
109183
main/utilities/usb_cherry/CherryUSB/demo/music_16k_ac1.h
Normal file
File diff suppressed because it is too large
Load Diff
78605
main/utilities/usb_cherry/CherryUSB/demo/music_16k_ac2.h
Normal file
78605
main/utilities/usb_cherry/CherryUSB/demo/music_16k_ac2.h
Normal file
File diff suppressed because it is too large
Load Diff
1163
main/utilities/usb_cherry/CherryUSB/demo/pic_data.h
Normal file
1163
main/utilities/usb_cherry/CherryUSB/demo/pic_data.h
Normal file
File diff suppressed because one or more lines are too long
183
main/utilities/usb_cherry/CherryUSB/demo/usb_host.c
Normal file
183
main/utilities/usb_cherry/CherryUSB/demo/usb_host.c
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
#include "usbh_core.h"
|
||||||
|
#include "usbh_cdc_acm.h"
|
||||||
|
#include "usbh_hid.h"
|
||||||
|
#include "usbh_msc.h"
|
||||||
|
|
||||||
|
USB_MEM_ALIGN32 uint8_t cdc_buffer[512];
|
||||||
|
|
||||||
|
void usbh_cdc_acm_callback(void *arg, int nbytes)
|
||||||
|
{
|
||||||
|
//struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)arg;
|
||||||
|
|
||||||
|
if (nbytes > 0) {
|
||||||
|
for (size_t i = 0; i < nbytes; i++) {
|
||||||
|
USB_LOG_RAW("0x%02x ", cdc_buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_RAW("nbytes:%d\r\n", nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cdc_acm_test(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0");
|
||||||
|
|
||||||
|
if (cdc_acm_class == NULL) {
|
||||||
|
USB_LOG_RAW("do not find /dev/ttyACM0\r\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(cdc_buffer, 0, 512);
|
||||||
|
ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, 3000);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_RAW("bulk in error,ret:%d\r\n", ret);
|
||||||
|
} else {
|
||||||
|
USB_LOG_RAW("recv over:%d\r\n", ret);
|
||||||
|
for (size_t i = 0; i < ret; i++) {
|
||||||
|
USB_LOG_RAW("0x%02x ", cdc_buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
const uint8_t data1[10] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x14 };
|
||||||
|
|
||||||
|
memcpy(cdc_buffer, data1, 8);
|
||||||
|
ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkout, cdc_buffer, 8, 3000);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_RAW("bulk out error,ret:%d\r\n", ret);
|
||||||
|
} else {
|
||||||
|
USB_LOG_RAW("send over:%d\r\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
usbh_ep_bulk_async_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, usbh_cdc_acm_callback, cdc_acm_class);
|
||||||
|
#else
|
||||||
|
ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, 3000);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_RAW("bulk in error,ret:%d\r\n", ret);
|
||||||
|
} else {
|
||||||
|
USB_LOG_RAW("recv over:%d\r\n", ret);
|
||||||
|
for (size_t i = 0; i < ret; i++) {
|
||||||
|
USB_LOG_RAW("0x%02x ", cdc_buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
#include "ff.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
USB_MEM_ALIGN32 uint8_t partition_table[512];
|
||||||
|
|
||||||
|
int msc_test(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct usbh_msc *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");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#if 1
|
||||||
|
/* get the partition table */
|
||||||
|
ret = usbh_msc_scsi_read10(msc_class, 0, partition_table, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_RAW("scsi_read10 error,ret:%d\r\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < 512; i++) {
|
||||||
|
if (i % 16 == 0) {
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("%02x ", partition_table[i]);
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
uint8_t *msc_buffer = usb_iomalloc(8192);
|
||||||
|
ret = usbh_msc_scsi_read10(msc_class, 0, msc_buffer, 16);
|
||||||
|
usb_iofree(msc_buffer);
|
||||||
|
// for (uint32_t i = 0; i < 1024; i++) {
|
||||||
|
// if (i % 16 == 0) {
|
||||||
|
// USB_LOG_RAW("\r\n");
|
||||||
|
// }
|
||||||
|
// USB_LOG_RAW("%02x ", msc_buffer[i]);
|
||||||
|
// }
|
||||||
|
// USB_LOG_RAW("\r\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
FATFS fs;
|
||||||
|
FIL fnew;
|
||||||
|
UINT fnum;
|
||||||
|
FRESULT res_sd = 0;
|
||||||
|
uint8_t *ReadBuffer;
|
||||||
|
|
||||||
|
ReadBuffer = usb_iomalloc(512);
|
||||||
|
f_mount(&fs, "2:", 1);
|
||||||
|
res_sd = f_open(&fnew, "2:test.c", FA_OPEN_EXISTING | FA_READ);
|
||||||
|
if (res_sd == FR_OK) {
|
||||||
|
res_sd = f_read(&fnew, ReadBuffer, 512, &fnum);
|
||||||
|
for (uint32_t i = 0; i < fnum; i++) {
|
||||||
|
if (i % 16 == 0) {
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("%02x ", ReadBuffer[i]);
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("\r\n");
|
||||||
|
f_close(&fnew);
|
||||||
|
/*unmount*/
|
||||||
|
f_mount(NULL, "2:", 1);
|
||||||
|
} else {
|
||||||
|
USB_LOG_RAW("open error:%d\r\n", res_sd);
|
||||||
|
}
|
||||||
|
usb_iofree(ReadBuffer);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_MEM_ALIGN32 uint8_t hid_buffer[128];
|
||||||
|
|
||||||
|
void usbh_hid_callback(void *arg, int nbytes)
|
||||||
|
{
|
||||||
|
//struct usbh_hid *hid_class = (struct usbh_hid *)arg;
|
||||||
|
|
||||||
|
if (nbytes > 0) {
|
||||||
|
for (size_t i = 0; i < nbytes; i++) {
|
||||||
|
USB_LOG_RAW("0x%02x ", hid_buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_LOG_RAW("nbytes:%d\r\n", nbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int hid_test(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct usbh_hid *hid_class = (struct usbh_hid *)usbh_find_class_instance("/dev/input0");
|
||||||
|
if (hid_class == NULL) {
|
||||||
|
USB_LOG_RAW("do not find /dev/input0\r\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#if 1
|
||||||
|
ret = usbh_ep_intr_async_transfer(hid_class->intin, hid_buffer, 128, usbh_hid_callback, hid_class);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_RAW("intr asnyc in error,ret:%d\r\n", ret);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ret = usbh_ep_intr_transfer(hid_class->intin, hid_buffer, 128, 1000);
|
||||||
|
if (ret < 0) {
|
||||||
|
USB_LOG_RAW("intr in error,ret:%d\r\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
USB_LOG_RAW("recv len:%d\r\n", ret);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@ -0,0 +1,200 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
#include "usbd_video.h"
|
||||||
|
#include "pic_data.h"
|
||||||
|
|
||||||
|
#define VIDEO_IN_EP 0x81
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
#define MAX_PAYLOAD_SIZE 1024 // for high speed with one transcations every one micro frame
|
||||||
|
#define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
|
||||||
|
|
||||||
|
// #define MAX_PAYLOAD_SIZE 2048 // for high speed with two transcations every one micro frame
|
||||||
|
// #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 2)) | (0x01 << 11))
|
||||||
|
|
||||||
|
// #define MAX_PAYLOAD_SIZE 3072 // for high speed with three transcations every one micro frame
|
||||||
|
// #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 3)) | (0x02 << 11))
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define MAX_PAYLOAD_SIZE 1023
|
||||||
|
#define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WIDTH (unsigned int)(640)
|
||||||
|
#define HEIGHT (unsigned int)(480)
|
||||||
|
|
||||||
|
#define CAM_FPS (30)
|
||||||
|
#define INTERVAL (unsigned long)(10000000 / CAM_FPS)
|
||||||
|
#define MIN_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS) //16 bit
|
||||||
|
#define MAX_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS)
|
||||||
|
#define MAX_FRAME_SIZE (unsigned long)(WIDTH * HEIGHT * 2)
|
||||||
|
|
||||||
|
#define USB_VIDEO_DESC_SIZ (unsigned long)(9 + \
|
||||||
|
8 + \
|
||||||
|
9 + \
|
||||||
|
13 + \
|
||||||
|
18 + \
|
||||||
|
9 + \
|
||||||
|
12 + \
|
||||||
|
9 + \
|
||||||
|
14 + \
|
||||||
|
11 + \
|
||||||
|
38 + \
|
||||||
|
9 + \
|
||||||
|
7)
|
||||||
|
|
||||||
|
#define VC_TERMINAL_SIZ (unsigned int)(13 + 18 + 12 + 9)
|
||||||
|
#define VS_HEADER_SIZ (unsigned int)(13 + 1 + 11 + 38)
|
||||||
|
|
||||||
|
#define USBD_VID 0xffff
|
||||||
|
#define USBD_PID 0xffff
|
||||||
|
#define USBD_MAX_POWER 100
|
||||||
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
|
const uint8_t video_descriptor[] = {
|
||||||
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||||
|
USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
|
VIDEO_VC_DESCRIPTOR_INIT(0x00, 0, 0x0100, VC_TERMINAL_SIZ, 48000000, 0x02),
|
||||||
|
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
|
||||||
|
VIDEO_VS_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 1, 0x00),
|
||||||
|
VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(0x01, 0x01),
|
||||||
|
VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, INTERVAL, 0x00, DBVAL(INTERVAL), DBVAL(INTERVAL), DBVAL(0)),
|
||||||
|
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
|
||||||
|
/* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
|
||||||
|
0x07, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: ENDPOINT */
|
||||||
|
0x81, /* bEndpointAddress: IN endpoint 2 */
|
||||||
|
0x01, /* bmAttributes: Isochronous transfer type. Asynchronous synchronization type. */
|
||||||
|
WBVAL(VIDEO_PACKET_SIZE), /* wMaxPacketSize */
|
||||||
|
0x01, /* bInterval: One frame interval */
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string0 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
USB_LANGID_INIT(USBD_LANGID_STRING),
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string1 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x14, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string2 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x26, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'C', 0x00, /* wcChar0 */
|
||||||
|
'h', 0x00, /* wcChar1 */
|
||||||
|
'e', 0x00, /* wcChar2 */
|
||||||
|
'r', 0x00, /* wcChar3 */
|
||||||
|
'r', 0x00, /* wcChar4 */
|
||||||
|
'y', 0x00, /* wcChar5 */
|
||||||
|
'U', 0x00, /* wcChar6 */
|
||||||
|
'S', 0x00, /* wcChar7 */
|
||||||
|
'B', 0x00, /* wcChar8 */
|
||||||
|
' ', 0x00, /* wcChar9 */
|
||||||
|
'U', 0x00, /* wcChar10 */
|
||||||
|
'V', 0x00, /* wcChar11 */
|
||||||
|
'C', 0x00, /* wcChar12 */
|
||||||
|
' ', 0x00, /* wcChar13 */
|
||||||
|
'D', 0x00, /* wcChar14 */
|
||||||
|
'E', 0x00, /* wcChar15 */
|
||||||
|
'M', 0x00, /* wcChar16 */
|
||||||
|
'O', 0x00, /* wcChar17 */
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// string3 descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x16, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
'2', 0x00, /* wcChar0 */
|
||||||
|
'0', 0x00, /* wcChar1 */
|
||||||
|
'2', 0x00, /* wcChar2 */
|
||||||
|
'1', 0x00, /* wcChar3 */
|
||||||
|
'0', 0x00, /* wcChar4 */
|
||||||
|
'3', 0x00, /* wcChar5 */
|
||||||
|
'1', 0x00, /* wcChar6 */
|
||||||
|
'0', 0x00, /* wcChar7 */
|
||||||
|
'0', 0x00, /* wcChar8 */
|
||||||
|
'0', 0x00, /* wcChar9 */
|
||||||
|
#ifdef CONFIG_USB_HS
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// device qualifier descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x0a,
|
||||||
|
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
|
||||||
|
0x00,
|
||||||
|
0x02,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x40,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
#endif
|
||||||
|
0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
volatile bool tx_flag = 0;
|
||||||
|
|
||||||
|
void usbd_video_open(uint8_t intf)
|
||||||
|
{
|
||||||
|
tx_flag = 1;
|
||||||
|
USB_LOG_RAW("OPEN\r\n");
|
||||||
|
}
|
||||||
|
void usbd_video_close(uint8_t intf)
|
||||||
|
{
|
||||||
|
USB_LOG_RAW("CLOSE\r\n");
|
||||||
|
tx_flag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_class_t video_class;
|
||||||
|
static usbd_interface_t video_control_intf;
|
||||||
|
static usbd_interface_t video_stream_intf;
|
||||||
|
|
||||||
|
void usbd_video_iso_callback(uint8_t ep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static usbd_endpoint_t video_in_ep = {
|
||||||
|
.ep_cb = usbd_video_iso_callback,
|
||||||
|
.ep_addr = VIDEO_IN_EP
|
||||||
|
};
|
||||||
|
|
||||||
|
void video_init()
|
||||||
|
{
|
||||||
|
usbd_desc_register(video_descriptor);
|
||||||
|
usbd_video_add_interface(&video_class, &video_control_intf);
|
||||||
|
usbd_video_add_interface(&video_class, &video_stream_intf);
|
||||||
|
usbd_interface_add_endpoint(&video_stream_intf, &video_in_ep);
|
||||||
|
|
||||||
|
usbd_video_probe_and_commit_controls_init(CAM_FPS, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE);
|
||||||
|
|
||||||
|
usbd_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t packet_buffer[10 * 1024];
|
||||||
|
|
||||||
|
void video_test()
|
||||||
|
{
|
||||||
|
uint32_t out_len;
|
||||||
|
uint32_t packets;
|
||||||
|
while (1) {
|
||||||
|
if (tx_flag) {
|
||||||
|
packets = usbd_video_mjpeg_payload_fill((uint8_t *)jpeg_data, sizeof(jpeg_data), packet_buffer, &out_len);
|
||||||
|
for (uint32_t i = 0; i < packets; i++) {
|
||||||
|
if (i == (packets - 1)) {
|
||||||
|
usbd_ep_write(VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE, NULL);
|
||||||
|
} else {
|
||||||
|
usbd_ep_write(VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
#include "usbd_core.h"
|
||||||
|
|
||||||
|
#define WCID_VENDOR_CODE 0x01
|
||||||
|
|
||||||
|
__ALIGN_BEGIN const uint8_t WCID_StringDescriptor_MSOS[18] __ALIGN_END = {
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// MS OS string descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x12, /* bLength */
|
||||||
|
USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
|
||||||
|
/* MSFT100 */
|
||||||
|
'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, /* wcChar_7 */
|
||||||
|
'1', 0x00, '0', 0x00, '0', 0x00, /* wcChar_7 */
|
||||||
|
WCID_VENDOR_CODE, /* bVendorCode */
|
||||||
|
0x00, /* bReserved */
|
||||||
|
};
|
||||||
|
|
||||||
|
__ALIGN_BEGIN const uint8_t WINUSB_WCIDDescriptor[40] __ALIGN_END = {
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// WCID descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x28, 0x00, 0x00, 0x00, /* dwLength */
|
||||||
|
0x00, 0x01, /* bcdVersion */
|
||||||
|
0x04, 0x00, /* wIndex */
|
||||||
|
0x01, /* bCount */
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_7 */
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// WCID function descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x00, /* bFirstInterfaceNumber */
|
||||||
|
0x01, /* bReserved */
|
||||||
|
/* WINUSB */
|
||||||
|
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, /* cCID_8 */
|
||||||
|
/* */
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* cSubCID_8 */
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* bReserved_6 */
|
||||||
|
};
|
||||||
|
|
||||||
|
__ALIGN_BEGIN const uint8_t WINUSB_IF0_WCIDProperties[142] __ALIGN_END = {
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// WCID property descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x8e, 0x00, 0x00, 0x00, /* dwLength */
|
||||||
|
0x00, 0x01, /* bcdVersion */
|
||||||
|
0x05, 0x00, /* wIndex */
|
||||||
|
0x01, 0x00, /* wCount */
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
/// registry propter descriptor
|
||||||
|
///////////////////////////////////////
|
||||||
|
0x84, 0x00, 0x00, 0x00, /* dwSize */
|
||||||
|
0x01, 0x00, 0x00, 0x00, /* dwPropertyDataType */
|
||||||
|
0x28, 0x00, /* wPropertyNameLength */
|
||||||
|
/* DeviceInterfaceGUID */
|
||||||
|
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, /* wcName_20 */
|
||||||
|
'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, /* wcName_20 */
|
||||||
|
't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, /* wcName_20 */
|
||||||
|
'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, /* wcName_20 */
|
||||||
|
'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, /* wcName_20 */
|
||||||
|
0x4e, 0x00, 0x00, 0x00, /* dwPropertyDataLength */
|
||||||
|
/* {CDB3B5AD-293B-4663-AA36-1AAE46463776} */
|
||||||
|
'{', 0x00, 'C', 0x00, 'D', 0x00, 'B', 0x00, /* wcData_39 */
|
||||||
|
'3', 0x00, 'B', 0x00, '5', 0x00, 'A', 0x00, /* wcData_39 */
|
||||||
|
'D', 0x00, '-', 0x00, '2', 0x00, '9', 0x00, /* wcData_39 */
|
||||||
|
'3', 0x00, 'B', 0x00, '-', 0x00, '4', 0x00, /* wcData_39 */
|
||||||
|
'6', 0x00, '6', 0x00, '3', 0x00, '-', 0x00, /* wcData_39 */
|
||||||
|
'A', 0x00, 'A', 0x00, '3', 0x00, '6', 0x00, /* wcData_39 */
|
||||||
|
'-', 0x00, '1', 0x00, 'A', 0x00, 'A', 0x00, /* wcData_39 */
|
||||||
|
'E', 0x00, '4', 0x00, '6', 0x00, '4', 0x00, /* wcData_39 */
|
||||||
|
'6', 0x00, '3', 0x00, '7', 0x00, '7', 0x00, /* wcData_39 */
|
||||||
|
'6', 0x00, '}', 0x00, 0x00, 0x00, /* wcData_39 */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usb_msosv1_descriptor msosv1_desc = {
|
||||||
|
.string = (uint8_t *)WCID_StringDescriptor_MSOS,
|
||||||
|
.string_len = 18,
|
||||||
|
.vendor_code = WCID_VENDOR_CODE,
|
||||||
|
.compat_id = (uint8_t *)WINUSB_WCIDDescriptor,
|
||||||
|
.compat_id_len = sizeof(WINUSB_WCIDDescriptor),
|
||||||
|
.comp_id_property = (uint8_t *)WINUSB_IF0_WCIDProperties,
|
||||||
|
.comp_id_property_len = sizeof(WINUSB_IF0_WCIDProperties),
|
||||||
|
};
|
||||||
61
main/utilities/usb_cherry/CherryUSB/osal/usb_osal.h
Normal file
61
main/utilities/usb_cherry/CherryUSB/osal/usb_osal.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* @file usb_osal.h
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _USB_OSAL_H
|
||||||
|
#define _USB_OSAL_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef void *usb_osal_thread_t;
|
||||||
|
typedef void *usb_osal_sem_t;
|
||||||
|
typedef void *usb_osal_mutex_t;
|
||||||
|
typedef void *usb_osal_event_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);
|
||||||
|
void usb_osal_thread_delete(usb_osal_thread_t thread);
|
||||||
|
void usb_osal_thread_suspend(usb_osal_thread_t thread);
|
||||||
|
void usb_osal_thread_resume(usb_osal_thread_t thread);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
usb_osal_event_t usb_osal_event_create(void);
|
||||||
|
void usb_osal_event_delete(usb_osal_event_t event);
|
||||||
|
int usb_osal_event_recv(usb_osal_event_t event, uint32_t set, uint32_t *recved);
|
||||||
|
int usb_osal_event_send(usb_osal_event_t event, uint32_t set);
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
149
main/utilities/usb_cherry/CherryUSB/osal/usb_osal_freertos.c
Normal file
149
main/utilities/usb_cherry/CherryUSB/osal/usb_osal_freertos.c
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/**
|
||||||
|
* @file usb_osal_freertos.c
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 sakumisu
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "usb_osal.h"
|
||||||
|
#include "usb_errno.h"
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_osal_thread_suspend(usb_osal_thread_t thread)
|
||||||
|
{
|
||||||
|
vTaskSuspend(thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_osal_thread_resume(usb_osal_thread_t thread)
|
||||||
|
{
|
||||||
|
vTaskResume(thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
uint32_t intstatus = 0;
|
||||||
|
int ret;
|
||||||
|
#ifdef __riscv
|
||||||
|
/* Obtain the level of the currently executing interrupt. */
|
||||||
|
__asm volatile("csrr %0, mintstatus" : "=r"(intstatus)::"memory");
|
||||||
|
#else
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile ( "mrs %0, ipsr" : "=r" ( intstatus )::"memory" );
|
||||||
|
#endif
|
||||||
|
if (intstatus == 0) {
|
||||||
|
ret = xSemaphoreGive((SemaphoreHandle_t)sem);
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_osal_event_t usb_osal_event_create(void)
|
||||||
|
{
|
||||||
|
return (usb_osal_event_t)xEventGroupCreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_osal_event_delete(usb_osal_event_t event)
|
||||||
|
{
|
||||||
|
vEventGroupDelete((EventGroupHandle_t)event);
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_osal_event_recv(usb_osal_event_t event, uint32_t set, uint32_t *recved)
|
||||||
|
{
|
||||||
|
*recved = xEventGroupWaitBits((EventGroupHandle_t)event, set, pdTRUE, pdFALSE, portMAX_DELAY);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_osal_event_send(usb_osal_event_t event, uint32_t set)
|
||||||
|
{
|
||||||
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = xEventGroupSetBitsFromISR((EventGroupHandle_t)event, set, &xHigherPriorityTaskWoken);
|
||||||
|
if (ret == pdPASS) {
|
||||||
|
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||||
|
}
|
||||||
|
return (ret == 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));
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user