Просмотр исходного кода

change TUSB_CFG_CONTROLLER0/1_MODE to TUSB_CFG_CONTROLLER_0/1_MODE for clearance
adding configuration docs for tinyusb_config.h
document HID mouse & keyboard API

hathach 12 лет назад
Родитель
Сommit
b71ffe3d5a

+ 2351 - 0
Doxyfile

@@ -0,0 +1,2351 @@
+# Doxyfile 1.8.5
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+# 
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+# 
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = tinyusb
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         = 
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = 
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO           = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-
+# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi,
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en,
+# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
+# Turkish, Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+# 
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+# 
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+# 
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                = 
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C.
+# 
+# Note For files without extension you can use no_extension as a placeholder.
+# 
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      = 
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+# 
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    = 
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+# 
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            = 
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
+
+CITE_BIB_FILES         = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+# 
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = tinyusb \
+                         readme.md
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.idl \
+                         *.ddl \
+                         *.odl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.cs \
+                         *.d \
+                         *.php \
+                         *.php4 \
+                         *.php5 \
+                         *.phtml \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.f90 \
+                         *.f \
+                         *.for \
+                         *.tcl \
+                         *.vhd \
+                         *.vhdl \
+                         *.ucf \
+                         *.qsf \
+                         *.as \
+                         *.js
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# 
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                = tinyusb/device/romdriver
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+# 
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+# 
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+# 
+# <filter> <input-file>
+# 
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+# 
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS = 
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+# 
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+# 
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+# 
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+# 
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more acurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS          = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+# 
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        = 
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  = 
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       = 
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+# 
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               = 
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           = 
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     = 
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               = 
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   = 
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  = 
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  = 
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           = 
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+# 
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+# 
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     = 
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       = 
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+# 
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+# 
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+# 
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       = 
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     = 
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+# 
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+# 
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           = 
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+# 
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           = 
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+# 
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+# 
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+# 
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+# 
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+# 
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+# 
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# 
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           = 
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+# 
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES

+ 137 - 137
demos/device/keyboard/tusb_config.h

@@ -1,137 +1,137 @@
-/**************************************************************************/
-/*!
-    @file     tusb_config.h
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \file
- *  \brief TBD
- *
- *  \note TBD
- */
-
-/** \ingroup TBD
- *  \defgroup TBD
- *  \brief TBD
- *
- *  @{
- */
-
-#ifndef _TUSB_TUSB_CONFIG_H_
-#define _TUSB_TUSB_CONFIG_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-//--------------------------------------------------------------------+
-// CONTROLLER CONFIGURATION
-//--------------------------------------------------------------------+
-#define TUSB_CFG_CONTROLLER0_MODE  (TUSB_MODE_DEVICE)
-#define TUSB_CFG_CONTROLLER1_MODE  (TUSB_MODE_NONE)
-
-//--------------------------------------------------------------------+
-// HOST CONFIGURATION
-//--------------------------------------------------------------------+
-#define TUSB_CFG_HOST_DEVICE_MAX     2
-#define TUSB_CFG_CONFIGURATION_MAX   1
-
-//------------- USBD -------------//
-#define TUSB_CFG_HOST_ENUM_BUFFER_SIZE 256
-
-//------------- CLASS -------------//
-#define TUSB_CFG_HOST_HUB           0
-#define TUSB_CFG_HOST_HID_KEYBOARD  1
-#define TUSB_CFG_HOST_HID_MOUSE     1
-#define TUSB_CFG_HOST_HID_GENERIC   0
-#define TUSB_CFG_HOST_MSC           0
-
-//--------------------------------------------------------------------+
-// DEVICE CONFIGURATION
-//--------------------------------------------------------------------+
-#define TUSB_CFG_DEVICE_USE_ROM_DRIVER  1
-
-//------------- descriptors -------------//
-#define TUSB_CFG_DEVICE_STRING_MANUFACTURER   "tinyusb.org"
-#define TUSB_CFG_DEVICE_STRING_PRODUCT        "Device Example"
-#define TUSB_CFG_DEVICE_STRING_SERIAL         "1234"
-#define TUSB_CFG_DEVICE_VENDORID              0x1FC9 // NXP
-//#define TUSB_CFG_DEVICE_PRODUCTID           0x4567
-
-#define TUSB_CFG_DEVICE_CONTROL_PACKET_SIZE   64
-
-//------------- CLASS -------------//
-#define TUSB_CFG_DEVICE_HID_KEYBOARD  1
-#define TUSB_CFG_DEVICE_HID_MOUSE     0
-#define TUSB_CFG_DEVICE_HID_GENERIC   0
-#define TUSB_CFG_DEVICE_MSC           0
-#define TUSB_CFG_DEVICE_CDC           0
-
-//--------------------------------------------------------------------+
-// COMMON CONFIGURATION
-//--------------------------------------------------------------------+
-
-#define TUSB_CFG_DEBUG                3
-
-#define TUSB_CFG_OS                   TUSB_OS_NONE // defined using eclipse build
-//#define TUSB_CFG_OS_TASK_PRIO
-#define TUSB_CFG_OS_TICKS_PER_SECOND  1000
-
-#ifdef __CODE_RED // make use of code red's support for ram region macros
-  #if (MCU == MCU_LPC11UXX) || (MCU == MCU_LPC13UXX)
-    #define TUSB_RAM_SECTION  ".data.$RAM1" // TODO overflow usb ram
-  #elif  (MCU == MCU_LPC43XX)
-    #define TUSB_RAM_SECTION  ".data.$RAM3"
-  #elif (MCU == MCU_LPC175X_6X)
-    #define TUSB_RAM_SECTION  ".data.$RAM2"
-  #else
-    forgot something thach ?
-  #endif
-
-  #define TUSB_CFG_ATTR_USBRAM   __attribute__ ((section(TUSB_RAM_SECTION)))
-#elif defined  __CC_ARM // Compiled with Keil armcc
-  #define TUSB_CFG_ATTR_USBRAM
-#else
-  #error compiler not specified
-#endif
-
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_TUSB_CONFIG_H_ */
-
-/** @} */
+/**************************************************************************/
+/*!
+    @file     tusb_config.h
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/** \file
+ *  \brief TBD
+ *
+ *  \note TBD
+ */
+
+/** \ingroup TBD
+ *  \defgroup TBD
+ *  \brief TBD
+ *
+ *  @{
+ */
+
+#ifndef _TUSB_TUSB_CONFIG_H_
+#define _TUSB_TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// CONTROLLER CONFIGURATION
+//--------------------------------------------------------------------+
+#define TUSB_CFG_CONTROLLER_0_MODE  (TUSB_MODE_DEVICE)
+#define TUSB_CFG_CONTROLLER_1_MODE  (TUSB_MODE_NONE)
+
+//--------------------------------------------------------------------+
+// HOST CONFIGURATION
+//--------------------------------------------------------------------+
+#define TUSB_CFG_HOST_DEVICE_MAX     2
+#define TUSB_CFG_CONFIGURATION_MAX   1
+
+//------------- USBD -------------//
+#define TUSB_CFG_HOST_ENUM_BUFFER_SIZE 256
+
+//------------- CLASS -------------//
+#define TUSB_CFG_HOST_HUB           0
+#define TUSB_CFG_HOST_HID_KEYBOARD  1
+#define TUSB_CFG_HOST_HID_MOUSE     1
+#define TUSB_CFG_HOST_HID_GENERIC   0
+#define TUSB_CFG_HOST_MSC           0
+
+//--------------------------------------------------------------------+
+// DEVICE CONFIGURATION
+//--------------------------------------------------------------------+
+#define TUSB_CFG_DEVICE_USE_ROM_DRIVER  1
+
+//------------- descriptors -------------//
+#define TUSB_CFG_DEVICE_STRING_MANUFACTURER   "tinyusb.org"
+#define TUSB_CFG_DEVICE_STRING_PRODUCT        "Device Example"
+#define TUSB_CFG_DEVICE_STRING_SERIAL         "1234"
+#define TUSB_CFG_DEVICE_VENDORID              0x1FC9 // NXP
+//#define TUSB_CFG_DEVICE_PRODUCTID           0x4567
+
+#define TUSB_CFG_DEVICE_CONTROL_PACKET_SIZE   64
+
+//------------- CLASS -------------//
+#define TUSB_CFG_DEVICE_HID_KEYBOARD  1
+#define TUSB_CFG_DEVICE_HID_MOUSE     0
+#define TUSB_CFG_DEVICE_HID_GENERIC   0
+#define TUSB_CFG_DEVICE_MSC           0
+#define TUSB_CFG_DEVICE_CDC           0
+
+//--------------------------------------------------------------------+
+// COMMON CONFIGURATION
+//--------------------------------------------------------------------+
+
+#define TUSB_CFG_DEBUG                3
+
+#define TUSB_CFG_OS                   TUSB_OS_NONE // defined using eclipse build
+//#define TUSB_CFG_OS_TASK_PRIO
+#define TUSB_CFG_OS_TICKS_PER_SECOND  1000
+
+#ifdef __CODE_RED // make use of code red's support for ram region macros
+  #if (MCU == MCU_LPC11UXX) || (MCU == MCU_LPC13UXX)
+    #define TUSB_RAM_SECTION  ".data.$RAM1" // TODO overflow usb ram
+  #elif  (MCU == MCU_LPC43XX)
+    #define TUSB_RAM_SECTION  ".data.$RAM3"
+  #elif (MCU == MCU_LPC175X_6X)
+    #define TUSB_RAM_SECTION  ".data.$RAM2"
+  #else
+    forgot something thach ?
+  #endif
+
+  #define TUSB_CFG_ATTR_USBRAM   __attribute__ ((section(TUSB_RAM_SECTION)))
+#elif defined  __CC_ARM // Compiled with Keil armcc
+  #define TUSB_CFG_ATTR_USBRAM
+#else
+  #error compiler not specified
+#endif
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_TUSB_CONFIG_H_ */
+
+/** @} */

+ 126 - 126
demos/host/host_bulk_xfer/tusb_config.h

@@ -1,126 +1,126 @@
-/**************************************************************************/
-/*!
-    @file     tusb_config.h
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \file
- *  \brief TBD
- *
- *  \note TBD
- */
-
-/** \ingroup TBD
- *  \defgroup TBD
- *  \brief TBD
- *
- *  @{
- */
-
-#ifndef _TUSB_TUSB_CONFIG_H_
-#define _TUSB_TUSB_CONFIG_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-//--------------------------------------------------------------------+
-// CONTROLLER CONFIGURATION
-//--------------------------------------------------------------------+
-#define TUSB_CFG_CONTROLLER0_MODE  (TUSB_MODE_HOST)
-#define TUSB_CFG_CONTROLLER1_MODE  (TUSB_MODE_NONE)
-
-//--------------------------------------------------------------------+
-// HOST CONFIGURATION
-//--------------------------------------------------------------------+
-#define TUSB_CFG_HOST_DEVICE_MAX     2
-#define TUSB_CFG_CONFIGURATION_MAX   1
-
-//------------- USBD -------------//
-#define TUSB_CFG_HOST_ENUM_BUFFER_SIZE 256
-
-//------------- CLASS -------------//
-#define TUSB_CFG_HOST_HUB           0
-#define TUSB_CFG_HOST_HID_KEYBOARD  0
-#define TUSB_CFG_HOST_HID_MOUSE     0
-#define TUSB_CFG_HOST_HID_GENERIC   0
-#define TUSB_CFG_HOST_MSC           0
-#define TUSB_CFG_HOST_CUSTOM_CLASS  1
-
-//--------------------------------------------------------------------+
-// DEVICE CONFIGURATION
-//--------------------------------------------------------------------+
-//#define TUSB_CFG_DEVICE
-
-//------------- CORE/CONTROLLER -------------//
-
-//------------- CLASS -------------//
-//#define TUSB_CFG_DEVICE_CDC
-//#define TUSB_CFG_DEVICE_HID_KEYBOARD  1
-//#define TUSB_CFG_DEVICE_HID_MOUSE     1
-
-//--------------------------------------------------------------------+
-// COMMON CONFIGURATION
-//--------------------------------------------------------------------+
-
-#define TUSB_CFG_DEBUG                3
-
-//#define TUSB_CFG_OS                   TUSB_OS_NONE // defined using eclipse build
-//#define TUSB_CFG_OS_TASK_PRIO
-
-#define TUSB_CFG_OS_TICKS_PER_SECOND  1000
-
-#ifdef __CODE_RED // make use of code red's support for ram region macros
-  #if (MCU == MCU_LPC11UXX) || (MCU == MCU_LPC13UXX)
-    #define TUSB_RAM_SECTION  ".data.$RAM2"
-  #elif  (MCU == MCU_LPC43XX)
-    #define TUSB_RAM_SECTION  ".data.$RAM3"
-  #endif
-
-  #define TUSB_CFG_ATTR_USBRAM   __attribute__ ((section(TUSB_RAM_SECTION)))
-#elif defined  __CC_ARM // Compiled with Keil armcc
-  #define TUSB_CFG_ATTR_USBRAM
-#else
-  #error compiler not specified
-#endif
-
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_TUSB_CONFIG_H_ */
-
-/** @} */
+/**************************************************************************/
+/*!
+    @file     tusb_config.h
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/** \file
+ *  \brief TBD
+ *
+ *  \note TBD
+ */
+
+/** \ingroup TBD
+ *  \defgroup TBD
+ *  \brief TBD
+ *
+ *  @{
+ */
+
+#ifndef _TUSB_TUSB_CONFIG_H_
+#define _TUSB_TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// CONTROLLER CONFIGURATION
+//--------------------------------------------------------------------+
+#define TUSB_CFG_CONTROLLER_0_MODE  (TUSB_MODE_HOST)
+#define TUSB_CFG_CONTROLLER_1_MODE  (TUSB_MODE_NONE)
+
+//--------------------------------------------------------------------+
+// HOST CONFIGURATION
+//--------------------------------------------------------------------+
+#define TUSB_CFG_HOST_DEVICE_MAX     2
+#define TUSB_CFG_CONFIGURATION_MAX   1
+
+//------------- USBD -------------//
+#define TUSB_CFG_HOST_ENUM_BUFFER_SIZE 256
+
+//------------- CLASS -------------//
+#define TUSB_CFG_HOST_HUB           0
+#define TUSB_CFG_HOST_HID_KEYBOARD  0
+#define TUSB_CFG_HOST_HID_MOUSE     0
+#define TUSB_CFG_HOST_HID_GENERIC   0
+#define TUSB_CFG_HOST_MSC           0
+#define TUSB_CFG_HOST_CUSTOM_CLASS  1
+
+//--------------------------------------------------------------------+
+// DEVICE CONFIGURATION
+//--------------------------------------------------------------------+
+//#define TUSB_CFG_DEVICE
+
+//------------- CORE/CONTROLLER -------------//
+
+//------------- CLASS -------------//
+//#define TUSB_CFG_DEVICE_CDC
+//#define TUSB_CFG_DEVICE_HID_KEYBOARD  1
+//#define TUSB_CFG_DEVICE_HID_MOUSE     1
+
+//--------------------------------------------------------------------+
+// COMMON CONFIGURATION
+//--------------------------------------------------------------------+
+
+#define TUSB_CFG_DEBUG                3
+
+//#define TUSB_CFG_OS                   TUSB_OS_NONE // defined using eclipse build
+//#define TUSB_CFG_OS_TASK_PRIO
+
+#define TUSB_CFG_OS_TICKS_PER_SECOND  1000
+
+#ifdef __CODE_RED // make use of code red's support for ram region macros
+  #if (MCU == MCU_LPC11UXX) || (MCU == MCU_LPC13UXX)
+    #define TUSB_RAM_SECTION  ".data.$RAM2"
+  #elif  (MCU == MCU_LPC43XX)
+    #define TUSB_RAM_SECTION  ".data.$RAM3"
+  #endif
+
+  #define TUSB_CFG_ATTR_USBRAM   __attribute__ ((section(TUSB_RAM_SECTION)))
+#elif defined  __CC_ARM // Compiled with Keil armcc
+  #define TUSB_CFG_ATTR_USBRAM
+#else
+  #error compiler not specified
+#endif
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_TUSB_CONFIG_H_ */
+
+/** @} */

+ 23 - 23
demos/host/host_os_none/host_os_none.uvopt

@@ -458,10 +458,10 @@
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <Focus>0</Focus>
-      <ColumnNumber>25</ColumnNumber>
+      <ColumnNumber>11</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>156</TopLine>
-      <CurrentLine>160</CurrentLine>
+      <TopLine>144</TopLine>
+      <CurrentLine>152</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\src\main.c</PathWithFileName>
       <FilenameWithoutPath>main.c</FilenameWithoutPath>
@@ -554,10 +554,10 @@
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <Focus>0</Focus>
-      <ColumnNumber>18</ColumnNumber>
+      <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>226</TopLine>
-      <CurrentLine>237</CurrentLine>
+      <TopLine>242</TopLine>
+      <CurrentLine>250</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\src\cli.c</PathWithFileName>
       <FilenameWithoutPath>cli.c</FilenameWithoutPath>
@@ -812,7 +812,7 @@
       <Focus>0</Focus>
       <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>357</TopLine>
+      <TopLine>359</TopLine>
       <CurrentLine>362</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\tinyusb\host\usbh.c</PathWithFileName>
@@ -828,8 +828,8 @@
       <Focus>0</Focus>
       <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>1</TopLine>
-      <CurrentLine>1</CurrentLine>
+      <TopLine>276</TopLine>
+      <CurrentLine>284</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\tinyusb\host\ehci\ehci.c</PathWithFileName>
       <FilenameWithoutPath>ehci.c</FilenameWithoutPath>
@@ -874,10 +874,10 @@
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <Focus>0</Focus>
-      <ColumnNumber>40</ColumnNumber>
+      <ColumnNumber>26</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>0</TopLine>
-      <CurrentLine>0</CurrentLine>
+      <TopLine>61</TopLine>
+      <CurrentLine>69</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\tinyusb\hal\hal_lpc43xx.c</PathWithFileName>
       <FilenameWithoutPath>hal_lpc43xx.c</FilenameWithoutPath>
@@ -908,8 +908,8 @@
       <Focus>0</Focus>
       <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>0</TopLine>
-      <CurrentLine>0</CurrentLine>
+      <TopLine>1</TopLine>
+      <CurrentLine>9</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\tinyusb\common\errors.c</PathWithFileName>
       <FilenameWithoutPath>errors.c</FilenameWithoutPath>
@@ -1060,7 +1060,7 @@
       <Focus>0</Focus>
       <ColumnNumber>3</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>577</TopLine>
+      <TopLine>579</TopLine>
       <CurrentLine>580</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\bsp\lpc43xx\CMSIS_LPC43xx_DriverLib\src\lpc43xx_cgu.c</PathWithFileName>
@@ -1116,7 +1116,7 @@
       <Focus>0</Focus>
       <ColumnNumber>19</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>147</TopLine>
+      <TopLine>149</TopLine>
       <CurrentLine>152</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\bsp\lpc43xx\startup_keil\startup_LPC43xx.s</PathWithFileName>
@@ -1128,7 +1128,7 @@
 
   <Group>
     <GroupName>fatfs</GroupName>
-    <tvExp>0</tvExp>
+    <tvExp>1</tvExp>
     <tvExpOptDlg>0</tvExpOptDlg>
     <cbSel>0</cbSel>
     <RteFlg>0</RteFlg>
@@ -1140,7 +1140,7 @@
       <Focus>0</Focus>
       <ColumnNumber>47</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>50</TopLine>
+      <TopLine>51</TopLine>
       <CurrentLine>59</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\vendor\fatfs\diskio.c</PathWithFileName>
@@ -1154,10 +1154,10 @@
       <FileType>1</FileType>
       <tvExp>0</tvExp>
       <Focus>0</Focus>
-      <ColumnNumber>12</ColumnNumber>
+      <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>91</TopLine>
-      <CurrentLine>97</CurrentLine>
+      <TopLine>1705</TopLine>
+      <CurrentLine>1713</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\vendor\fatfs\ff.c</PathWithFileName>
       <FilenameWithoutPath>ff.c</FilenameWithoutPath>
@@ -1172,8 +1172,8 @@
       <Focus>0</Focus>
       <ColumnNumber>0</ColumnNumber>
       <tvExpOptDlg>0</tvExpOptDlg>
-      <TopLine>0</TopLine>
-      <CurrentLine>0</CurrentLine>
+      <TopLine>1</TopLine>
+      <CurrentLine>1</CurrentLine>
       <bDave2>0</bDave2>
       <PathWithFileName>..\..\..\vendor\fatfs\ccsbcs.c</PathWithFileName>
       <FilenameWithoutPath>ccsbcs.c</FilenameWithoutPath>

+ 2 - 5
demos/host/src/tusb_config.h

@@ -59,8 +59,8 @@
 //--------------------------------------------------------------------+
 // CONTROLLER CONFIGURATION
 //--------------------------------------------------------------------+
-#define TUSB_CFG_CONTROLLER0_MODE  (TUSB_MODE_HOST)
-#define TUSB_CFG_CONTROLLER1_MODE  (TUSB_MODE_NONE)
+#define TUSB_CFG_CONTROLLER_0_MODE  (TUSB_MODE_HOST)
+#define TUSB_CFG_CONTROLLER_1_MODE  (TUSB_MODE_NONE)
 
 //--------------------------------------------------------------------+
 // HOST CONFIGURATION
@@ -83,9 +83,6 @@
 //--------------------------------------------------------------------+
 // DEVICE CONFIGURATION
 //--------------------------------------------------------------------+
-//#define TUSB_CFG_DEVICE
-
-//------------- CORE/CONTROLLER -------------//
 
 //------------- CLASS -------------//
 //#define TUSB_CFG_DEVICE_CDC

+ 5 - 5
tests/.project

@@ -78,16 +78,16 @@
 			<type>2</type>
 			<locationURI>PARENT-1-PROJECT_LOC/demos</locationURI>
 		</link>
-		<link>
-			<name>doxygen.Doxyfile</name>
-			<type>1</type>
-			<locationURI>PARENT-1-PROJECT_LOC/doxygen.Doxyfile</locationURI>
-		</link>
 		<link>
 			<name>tinyusb</name>
 			<type>2</type>
 			<locationURI>PARENT-1-PROJECT_LOC/tinyusb</locationURI>
 		</link>
+		<link>
+			<name>tinyusb.Doxyfile</name>
+			<type>1</type>
+			<locationURI>PARENT-1-PROJECT_LOC/tinyusb.Doxyfile</locationURI>
+		</link>
 	</linkedResources>
 	<filteredResources>
 		<filter>

+ 131 - 131
tests/support/tusb_config.h

@@ -1,131 +1,131 @@
-/**************************************************************************/
-/*!
-    @file     tusb_config.h
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \file
- *  \brief TBD
- *
- *  \note TBD
- */
-
-/** \ingroup TBD
- *  \defgroup TBD
- *  \brief TBD
- *
- *  @{
- */
-
-#ifndef _TUSB_TUSB_CONFIG_H_
-#define _TUSB_TUSB_CONFIG_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-//--------------------------------------------------------------------+
-// CONTROLLER CONFIGURATION
-//--------------------------------------------------------------------+
-#define TUSB_CFG_CONTROLLER0_MODE  (TUSB_MODE_HOST | TUSB_MODE_DEVICE)
-#define TUSB_CFG_CONTROLLER1_MODE  (TUSB_MODE_NONE)
-
-//--------------------------------------------------------------------+
-// HOST CONFIGURATION
-//--------------------------------------------------------------------+
-//------------- CORE -------------//
-#define TUSB_CFG_HOST_DEVICE_MAX                 2
-#define TUSB_CFG_CONFIGURATION_MAX               1
-
-#define TUSB_CFG_HOST_ENUM_BUFFER_SIZE           255
-
-//------------- CLASS -------------//
-#define TUSB_CFG_HOST_HUB                        1
-#define TUSB_CFG_HOST_HID_KEYBOARD               1
-#define TUSB_CFG_HOST_HID_MOUSE                  1
-#define TUSB_CFG_HOST_MSC                        1
-#define TUSB_CFG_HOST_CDC                        1
-#define TUSB_CFG_HOST_CDC_RNDIS                  1
-
-#define HOST_HCD_XFER_INTERRUPT
-#define HOST_HCD_XFER_BULK
-//#define HOST_HCD_XFER_ISOCHRONOUS
-
-// Test support
-#define TEST_CONTROLLER_HOST_START_INDEX \
- ( ((CONTROLLER_HOST_NUMBER == 1) && (TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST)) ? 1 : 0)
-
-//--------------------------------------------------------------------+
-// DEVICE CONFIGURATION
-//--------------------------------------------------------------------+
-#define TUSB_CFG_DEVICE_USE_ROM_DRIVER  1
-
-//------------- descriptors -------------//
-#define TUSB_CFG_DEVICE_STRING_MANUFACTURER   "tinyusb.org"
-#define TUSB_CFG_DEVICE_STRING_PRODUCT        "Device Example"
-#define TUSB_CFG_DEVICE_STRING_SERIAL         "1234"
-#define TUSB_CFG_DEVICE_VENDORID              0x1FC9 // NXP
-//#define TUSB_CFG_DEVICE_PRODUCTID           0x4567
-
-#define TUSB_CFG_DEVICE_CONTROL_PACKET_SIZE   64
-
-//------------- CLASS -------------//
-#define TUSB_CFG_DEVICE_HID_KEYBOARD  1
-#define TUSB_CFG_DEVICE_HID_MOUSE     1
-#define TUSB_CFG_DEVICE_HID_GENERIC   0
-#define TUSB_CFG_DEVICE_MSC           0
-#define TUSB_CFG_DEVICE_CDC           0
-
-
-//--------------------------------------------------------------------+
-// COMMON CONFIGURATION
-//--------------------------------------------------------------------+
-
-#define TUSB_CFG_DEBUG 3
-
-#define TUSB_CFG_OS TUSB_OS_NONE
-#define TUSB_CFG_OS_TICKS_PER_SECOND 1000 // 1 ms tick
-#define TUSB_CFG_ATTR_USBRAM
-
-#ifdef __cplusplus
- }
-#endif
-
-
-#define RANDOM(n) (rand()%(n))
-
-#endif /* _TUSB_TUSB_CONFIG_H_ */
-
-/** @} */
+/**************************************************************************/
+/*!
+    @file     tusb_config.h
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/** \file
+ *  \brief TBD
+ *
+ *  \note TBD
+ */
+
+/** \ingroup TBD
+ *  \defgroup TBD
+ *  \brief TBD
+ *
+ *  @{
+ */
+
+#ifndef _TUSB_TUSB_CONFIG_H_
+#define _TUSB_TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// CONTROLLER CONFIGURATION
+//--------------------------------------------------------------------+
+#define TUSB_CFG_CONTROLLER_0_MODE  (TUSB_MODE_HOST | TUSB_MODE_DEVICE)
+#define TUSB_CFG_CONTROLLER_1_MODE  (TUSB_MODE_NONE)
+
+//--------------------------------------------------------------------+
+// HOST CONFIGURATION
+//--------------------------------------------------------------------+
+//------------- CORE -------------//
+#define TUSB_CFG_HOST_DEVICE_MAX                 2
+#define TUSB_CFG_CONFIGURATION_MAX               1
+
+#define TUSB_CFG_HOST_ENUM_BUFFER_SIZE           255
+
+//------------- CLASS -------------//
+#define TUSB_CFG_HOST_HUB                        1
+#define TUSB_CFG_HOST_HID_KEYBOARD               1
+#define TUSB_CFG_HOST_HID_MOUSE                  1
+#define TUSB_CFG_HOST_MSC                        1
+#define TUSB_CFG_HOST_CDC                        1
+#define TUSB_CFG_HOST_CDC_RNDIS                  1
+
+#define HOST_HCD_XFER_INTERRUPT
+#define HOST_HCD_XFER_BULK
+//#define HOST_HCD_XFER_ISOCHRONOUS
+
+// Test support
+#define TEST_CONTROLLER_HOST_START_INDEX \
+ ( ((CONTROLLER_HOST_NUMBER == 1) && (TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST)) ? 1 : 0)
+
+//--------------------------------------------------------------------+
+// DEVICE CONFIGURATION
+//--------------------------------------------------------------------+
+#define TUSB_CFG_DEVICE_USE_ROM_DRIVER  1
+
+//------------- descriptors -------------//
+#define TUSB_CFG_DEVICE_STRING_MANUFACTURER   "tinyusb.org"
+#define TUSB_CFG_DEVICE_STRING_PRODUCT        "Device Example"
+#define TUSB_CFG_DEVICE_STRING_SERIAL         "1234"
+#define TUSB_CFG_DEVICE_VENDORID              0x1FC9 // NXP
+//#define TUSB_CFG_DEVICE_PRODUCTID           0x4567
+
+#define TUSB_CFG_DEVICE_CONTROL_PACKET_SIZE   64
+
+//------------- CLASS -------------//
+#define TUSB_CFG_DEVICE_HID_KEYBOARD  1
+#define TUSB_CFG_DEVICE_HID_MOUSE     1
+#define TUSB_CFG_DEVICE_HID_GENERIC   0
+#define TUSB_CFG_DEVICE_MSC           0
+#define TUSB_CFG_DEVICE_CDC           0
+
+
+//--------------------------------------------------------------------+
+// COMMON CONFIGURATION
+//--------------------------------------------------------------------+
+
+#define TUSB_CFG_DEBUG 3
+
+#define TUSB_CFG_OS TUSB_OS_NONE
+#define TUSB_CFG_OS_TICKS_PER_SECOND 1000 // 1 ms tick
+#define TUSB_CFG_ATTR_USBRAM
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#define RANDOM(n) (rand()%(n))
+
+#endif /* _TUSB_TUSB_CONFIG_H_ */
+
+/** @} */

+ 343 - 343
tinyusb/class/cdc.h

@@ -1,343 +1,343 @@
-/**************************************************************************/
-/*!
-    @file     cdc.h
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \file
- *  \brief CDC Class Driver
- *
- *  \note TBD
- */
-
-/** 
- *  \addtogroup Group_ClassDriver Class Driver
- *  @{
- *  \defgroup Group_CDC Communication Device Class
- *  @{
- */
-
-#ifndef _TUSB_CDC_H__
-#define _TUSB_CDC_H__
-
-#include "common/common.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-//--------------------------------------------------------------------+
-// CDC COMMUNICATION INTERFACE CLASS
-//--------------------------------------------------------------------+
-enum {
-  CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01  ,
-  CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL            ,
-  CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL           ,
-  CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL        ,
-  CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL                ,
-  CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL ,
-  CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL      ,
-  CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL    ,
-  CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT                 ,
-  CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL          ,
-  CDC_COMM_SUBCLASS_OBEX                              ,
-  CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL
-};
-
-enum {
-  CDC_COMM_PROTOCOL_ATCOMMAND              = 0x01 , // ITU-T V2.50
-  CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101            ,
-  CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO ,
-  CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707             ,
-  CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007          ,
-  CDC_COMM_PROTOCOL_ATCOMMAND_CDMA                , // defined by TIA
-  CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL
-};
-
-//------------- SubType Descriptor in COMM Functional Descriptor -------------//
-enum {
-  CDC_FUNC_DESC_HEADER                                           = 0x00 ,
-  CDC_FUNC_DESC_CALL_MANAGEMENT                                  = 0x01 ,
-  CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT                      = 0x02 ,
-  CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT                           = 0x03 ,
-  CDC_FUNC_DESC_TELEPHONE_RINGER                                 = 0x04 ,
-  CDC_FUNC_DESC_TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPACITY = 0x05 ,
-  CDC_FUNC_DESC_UNION                                            = 0x06 ,
-  CDC_FUNC_DESC_COUNTRY_SELECTION                                = 0x07 ,
-  CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES                      = 0x08 ,
-  CDC_FUNC_DESC_USB_TERMINAL                                     = 0x09 ,
-  CDC_FUNC_DESC_NETWORK_CHANNEL_TERMINAL                         = 0x0A ,
-  CDC_FUNC_DESC_PROTOCOL_UNIT                                    = 0x0B ,
-  CDC_FUNC_DESC_EXTENSION_UNIT                                   = 0x0C ,
-  CDC_FUNC_DESC_MULTICHANEL_MANAGEMENT                           = 0x0D ,
-  CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT                          = 0x0E ,
-  CDC_FUNC_DESC_ETHERNET_NETWORKING                              = 0x0F ,
-  CDC_FUNC_DESC_ATM_NETWORKING                                   = 0x10 ,
-  CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL                   = 0x11 ,
-  CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL                         = 0x12 ,
-  CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL                  = 0x13 ,
-  CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL                          = 0x14 ,
-  CDC_FUNC_DESC_OBEX                                             = 0x15 ,
-  CDC_FUNC_DESC_COMMAND_SET                                      = 0x16 ,
-  CDC_FUNC_DESC_COMMAND_SET_DETAIL                               = 0x17 ,
-  CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL                          = 0x18 ,
-  CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER                          = 0x19
-};
-
-//--------------------------------------------------------------------+
-// CDC DATA INTERFACE CLASS
-//--------------------------------------------------------------------+
-
-// SUBCLASS code of Data Interface is not used and should/must be zero
-
-enum{
-  CDC_DATA_PROTOCOL_ISDN_BRI                               = 0x30,
-  CDC_DATA_PROTOCOL_HDLC                                   = 0x31,
-  CDC_DATA_PROTOCOL_TRANSPARENT                            = 0x32,
-  CDC_DATA_PROTOCOL_Q921_MANAGEMENT                        = 0x50,
-  CDC_DATA_PROTOCOL_Q921_DATA_LINK                         = 0x51,
-  CDC_DATA_PROTOCOL_Q921_TEI_MULTIPLEXOR                   = 0x52,
-  CDC_DATA_PROTOCOL_V42BIS_DATA_COMPRESSION                = 0x90,
-  CDC_DATA_PROTOCOL_EURO_ISDN                              = 0x91,
-  CDC_DATA_PROTOCOL_V24_RATE_ADAPTION_TO_ISDN              = 0x92,
-  CDC_DATA_PROTOCOL_CAPI_COMMAND                           = 0x93,
-  CDC_DATA_PROTOCOL_HOST_BASED_DRIVER                      = 0xFD,
-  CDC_DATA_PROTOCOL_IN_PROTOCOL_UNIT_FUNCTIONAL_DESCRIPTOR = 0xFE
-};
-
-//--------------------------------------------------------------------+
-// MANAGEMENT ELEMENT REQUEST (CONTROL ENDPOINT)
-//--------------------------------------------------------------------+
-typedef enum {
-  SEND_ENCAPSULATED_COMMAND                    = 0x00,
-  GET_ENCAPSULATED_RESPONSE                    = 0x01,
-
-  SET_COMM_FEATURE                             = 0x02,
-  GET_COMM_FEATURE                             = 0x03,
-  CLEAR_COMM_FEATURE                           = 0x04,
-
-  SET_AUX_LINE_STATE                           = 0x10,
-  SET_HOOK_STATE                               = 0x11,
-  PULSE_SETUP                                  = 0x12,
-  SEND_PULSE                                   = 0x13,
-  SET_PULSE_TIME                               = 0x14,
-  RING_AUX_JACK                                = 0x15,
-
-  SET_LINE_CODING                              = 0x20,
-  GET_LINE_CODING                              = 0x21,
-  SET_CONTROL_LINE_STATE                       = 0x22,
-  SEND_BREAK                                   = 0x23,
-
-  SET_RINGER_PARMS                             = 0x30,
-  GET_RINGER_PARMS                             = 0x31,
-  SET_OPERATION_PARMS                          = 0x32,
-  GET_OPERATION_PARMS                          = 0x33,
-  SET_LINE_PARMS                               = 0x34,
-  GET_LINE_PARMS                               = 0x35,
-  DIAL_DIGITS                                  = 0x36,
-  SET_UNIT_PARAMETER                           = 0x37,
-  GET_UNIT_PARAMETER                           = 0x38,
-  CLEAR_UNIT_PARAMETER                         = 0x39,
-  GET_PROFILE                                  = 0x3A,
-
-  SET_ETHERNET_MULTICAST_FILTERS               = 0x40,
-  SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41,
-  GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42,
-  SET_ETHERNET_PACKET_FILTER                   = 0x43,
-  GET_ETHERNET_STATISTIC                       = 0x44,
-
-  SET_ATM_DATA_FORMAT                          = 0x50,
-  GET_ATM_DEVICE_STATISTICS                    = 0x51,
-  SET_ATM_DEFAULT_VC                           = 0x52,
-  GET_ATM_VC_STATISTICS                        = 0x53,
-
-  MDLM_SEMANTIC_MODEL                          = 0x60,
-}cdc_management_request_t;
-
-//--------------------------------------------------------------------+
-// MANAGEMENT ELEMENENT NOTIFICATION (NOTIFICATION ENDPOINT)
-//--------------------------------------------------------------------+
-typedef enum {
-  NETWORK_CONNECTION               = 0x00,
-  RESPONSE_AVAILABLE               = 0x01,
-
-  AUX_JACK_HOOK_STATE              = 0x08,
-  RING_DETECT                      = 0x09,
-
-  SERIAL_STATE                     = 0x20,
-
-  CALL_STATE_CHANGE                = 0x28,
-  LINE_STATE_CHANGE                = 0x29,
-  CONNECTION_SPEED_CHANGE          = 0x2A,
-  MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40,
-}cdc_notification_request_t;
-
-//--------------------------------------------------------------------+
-// FUNCTIONAL DESCRIPTOR
-//--------------------------------------------------------------------+
-typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t bLength            ; ///< Size of this descriptor in bytes.
-  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
-  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
-  uint16_t bcdCDC            ; ///< CDC release number in Binary-Coded Decimal
-}cdc_desc_func_header_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t bLength                  ; ///< Size of this descriptor in bytes.
-  uint8_t bDescriptorType          ; ///< Descriptor Type, must be Class-Specific
-  uint8_t bDescriptorSubType       ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
-  uint8_t bControlInterface        ; ///< Interface number of Communication Interface
-  uint8_t bSubordinateInterface    ; ///< Array of Interface number of Data Interface
-}cdc_desc_func_union_t;
-
-#define cdc_desc_func_union_n_t(no_slave)\
- ATTR_PACKED_STRUCT(struct) { \
-  uint8_t bLength                         ;\
-  uint8_t bDescriptorType                 ;\
-  uint8_t bDescriptorSubType              ;\
-  uint8_t bControlInterface               ;\
-  uint8_t bSubordinateInterface[no_slave] ;\
-}
-
-typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t bLength             ; ///< Size of this descriptor in bytes.
-  uint8_t bDescriptorType     ; ///< Descriptor Type, must be Class-Specific
-  uint8_t bDescriptorSubType  ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
-  uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes.
-  uint16_t wCountryCode[]     ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country.
-}cdc_desc_func_country_selection_t;
-
-#define cdc_desc_func_country_selection_n_t(no_country) \
-  ATTR_PACKED_STRUCT(struct) {\
-  uint8_t bLength                   ;\
-  uint8_t bDescriptorType           ;\
-  uint8_t bDescriptorSubType        ;\
-  uint8_t iCountryCodeRelDate       ;\
-  uint16_t wCountryCode[no_country] ;\
-}
-
-//--------------------------------------------------------------------+
-// PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS
-//--------------------------------------------------------------------+
-typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t bLength            ; ///< Size of this descriptor in bytes.
-  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
-  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
-
-  struct {
-    uint8_t handle_call    : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface.
-    uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself.
-    uint8_t : 0;
-  } bmCapabilities;
-
-  uint8_t bDataInterface;
-}cdc_desc_func_call_management_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t support_comm_request                    : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature.
-  uint8_t support_line_request                    : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.
-  uint8_t support_send_break                      : 1; ///< Device supports the request Send_Break
-  uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection.
-  uint8_t : 0;
-}cdc_acm_capability_t;
-
-STATIC_ASSERT(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler");
-
-typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t bLength                  ; ///< Size of this descriptor in bytes.
-  uint8_t bDescriptorType          ; ///< Descriptor Type, must be Class-Specific
-  uint8_t bDescriptorSubType       ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
-  cdc_acm_capability_t bmCapabilities ;
-}cdc_desc_func_abstract_control_management_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t bLength            ; ///< Size of this descriptor in bytes.
-  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
-  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
-  struct {
-    uint8_t require_pulse_setup   : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit.
-    uint8_t support_aux_request   : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State.
-    uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time.
-    uint8_t : 0;
-  } bmCapabilities;
-}cdc_desc_func_direct_line_management_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t bLength            ; ///< Size of this descriptor in bytes.
-  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
-  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
-  uint8_t bRingerVolSteps    ;
-  uint8_t bNumRingerPatterns ;
-}cdc_desc_func_telephone_ringer_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t bLength            ; ///< Size of this descriptor in bytes.
-  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
-  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
-  struct {
-    uint8_t simple_mode           : 1;
-    uint8_t standalone_mode       : 1;
-    uint8_t computer_centric_mode : 1;
-    uint8_t : 0;
-  } bmCapabilities;
-}cdc_desc_func_telephone_operational_modes_t;
-
-typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t bLength            ; ///< Size of this descriptor in bytes.
-  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
-  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
-  struct {
-    uint32_t interrupted_dialtone   : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone
-    uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states.
-    uint32_t caller_id              : 1; ///< 0 : Does not report caller ID. 1 : Reports caller ID information.
-    uint32_t incoming_distinctive   : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns.
-    uint32_t dual_tone_multi_freq   : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line.
-    uint32_t line_state_change      : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification
-    uint32_t : 0;
-  } bmCapabilities;
-}cdc_desc_func_telephone_call_state_reporting_capabilities_t;
-
-static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) ATTR_PURE ATTR_ALWAYS_INLINE;
-static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc)
-{
-  return p_desc[2];
-}
-
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
+/**************************************************************************/
+/*!
+    @file     cdc.h
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/** \file
+ *  \brief CDC Class Driver
+ *
+ *  \note TBD
+ */
+
+/** 
+ *  \addtogroup ClassDriver Class Driver
+ *  @{
+ *  \defgroup ClassDriver_CDC Communication Device Class
+ *  @{
+ */
+
+#ifndef _TUSB_CDC_H__
+#define _TUSB_CDC_H__
+
+#include "common/common.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// CDC COMMUNICATION INTERFACE CLASS
+//--------------------------------------------------------------------+
+enum {
+  CDC_COMM_SUBCLASS_DIRECT_LINE_CONTROL_MODEL = 0x01  ,
+  CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL            ,
+  CDC_COMM_SUBCLASS_TELEPHONE_CONTROL_MODEL           ,
+  CDC_COMM_SUBCLASS_MULTICHANNEL_CONTROL_MODEL        ,
+  CDC_COMM_SUBCLASS_CAPI_CONTROL_MODEL                ,
+  CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL ,
+  CDC_COMM_SUBCLASS_ATM_NETWORKING_CONTROL_MODEL      ,
+  CDC_COMM_SUBCLASS_WIRELESS_HANDSET_CONTROL_MODEL    ,
+  CDC_COMM_SUBCLASS_DEVICE_MANAGEMENT                 ,
+  CDC_COMM_SUBCLASS_MOBILE_DIRECT_LINE_MODEL          ,
+  CDC_COMM_SUBCLASS_OBEX                              ,
+  CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL
+};
+
+enum {
+  CDC_COMM_PROTOCOL_ATCOMMAND              = 0x01 , // ITU-T V2.50
+  CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101            ,
+  CDC_COMM_PROTOCOL_ATCOMMAND_PCCA_101_AND_ANNEXO ,
+  CDC_COMM_PROTOCOL_ATCOMMAND_GSM_707             ,
+  CDC_COMM_PROTOCOL_ATCOMMAND_3GPP_27007          ,
+  CDC_COMM_PROTOCOL_ATCOMMAND_CDMA                , // defined by TIA
+  CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL
+};
+
+//------------- SubType Descriptor in COMM Functional Descriptor -------------//
+enum {
+  CDC_FUNC_DESC_HEADER                                           = 0x00 ,
+  CDC_FUNC_DESC_CALL_MANAGEMENT                                  = 0x01 ,
+  CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT                      = 0x02 ,
+  CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT                           = 0x03 ,
+  CDC_FUNC_DESC_TELEPHONE_RINGER                                 = 0x04 ,
+  CDC_FUNC_DESC_TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPACITY = 0x05 ,
+  CDC_FUNC_DESC_UNION                                            = 0x06 ,
+  CDC_FUNC_DESC_COUNTRY_SELECTION                                = 0x07 ,
+  CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES                      = 0x08 ,
+  CDC_FUNC_DESC_USB_TERMINAL                                     = 0x09 ,
+  CDC_FUNC_DESC_NETWORK_CHANNEL_TERMINAL                         = 0x0A ,
+  CDC_FUNC_DESC_PROTOCOL_UNIT                                    = 0x0B ,
+  CDC_FUNC_DESC_EXTENSION_UNIT                                   = 0x0C ,
+  CDC_FUNC_DESC_MULTICHANEL_MANAGEMENT                           = 0x0D ,
+  CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT                          = 0x0E ,
+  CDC_FUNC_DESC_ETHERNET_NETWORKING                              = 0x0F ,
+  CDC_FUNC_DESC_ATM_NETWORKING                                   = 0x10 ,
+  CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL                   = 0x11 ,
+  CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL                         = 0x12 ,
+  CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL                  = 0x13 ,
+  CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL                          = 0x14 ,
+  CDC_FUNC_DESC_OBEX                                             = 0x15 ,
+  CDC_FUNC_DESC_COMMAND_SET                                      = 0x16 ,
+  CDC_FUNC_DESC_COMMAND_SET_DETAIL                               = 0x17 ,
+  CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL                          = 0x18 ,
+  CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER                          = 0x19
+};
+
+//--------------------------------------------------------------------+
+// CDC DATA INTERFACE CLASS
+//--------------------------------------------------------------------+
+
+// SUBCLASS code of Data Interface is not used and should/must be zero
+
+enum{
+  CDC_DATA_PROTOCOL_ISDN_BRI                               = 0x30,
+  CDC_DATA_PROTOCOL_HDLC                                   = 0x31,
+  CDC_DATA_PROTOCOL_TRANSPARENT                            = 0x32,
+  CDC_DATA_PROTOCOL_Q921_MANAGEMENT                        = 0x50,
+  CDC_DATA_PROTOCOL_Q921_DATA_LINK                         = 0x51,
+  CDC_DATA_PROTOCOL_Q921_TEI_MULTIPLEXOR                   = 0x52,
+  CDC_DATA_PROTOCOL_V42BIS_DATA_COMPRESSION                = 0x90,
+  CDC_DATA_PROTOCOL_EURO_ISDN                              = 0x91,
+  CDC_DATA_PROTOCOL_V24_RATE_ADAPTION_TO_ISDN              = 0x92,
+  CDC_DATA_PROTOCOL_CAPI_COMMAND                           = 0x93,
+  CDC_DATA_PROTOCOL_HOST_BASED_DRIVER                      = 0xFD,
+  CDC_DATA_PROTOCOL_IN_PROTOCOL_UNIT_FUNCTIONAL_DESCRIPTOR = 0xFE
+};
+
+//--------------------------------------------------------------------+
+// MANAGEMENT ELEMENT REQUEST (CONTROL ENDPOINT)
+//--------------------------------------------------------------------+
+typedef enum {
+  SEND_ENCAPSULATED_COMMAND                    = 0x00,
+  GET_ENCAPSULATED_RESPONSE                    = 0x01,
+
+  SET_COMM_FEATURE                             = 0x02,
+  GET_COMM_FEATURE                             = 0x03,
+  CLEAR_COMM_FEATURE                           = 0x04,
+
+  SET_AUX_LINE_STATE                           = 0x10,
+  SET_HOOK_STATE                               = 0x11,
+  PULSE_SETUP                                  = 0x12,
+  SEND_PULSE                                   = 0x13,
+  SET_PULSE_TIME                               = 0x14,
+  RING_AUX_JACK                                = 0x15,
+
+  SET_LINE_CODING                              = 0x20,
+  GET_LINE_CODING                              = 0x21,
+  SET_CONTROL_LINE_STATE                       = 0x22,
+  SEND_BREAK                                   = 0x23,
+
+  SET_RINGER_PARMS                             = 0x30,
+  GET_RINGER_PARMS                             = 0x31,
+  SET_OPERATION_PARMS                          = 0x32,
+  GET_OPERATION_PARMS                          = 0x33,
+  SET_LINE_PARMS                               = 0x34,
+  GET_LINE_PARMS                               = 0x35,
+  DIAL_DIGITS                                  = 0x36,
+  SET_UNIT_PARAMETER                           = 0x37,
+  GET_UNIT_PARAMETER                           = 0x38,
+  CLEAR_UNIT_PARAMETER                         = 0x39,
+  GET_PROFILE                                  = 0x3A,
+
+  SET_ETHERNET_MULTICAST_FILTERS               = 0x40,
+  SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x41,
+  GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER = 0x42,
+  SET_ETHERNET_PACKET_FILTER                   = 0x43,
+  GET_ETHERNET_STATISTIC                       = 0x44,
+
+  SET_ATM_DATA_FORMAT                          = 0x50,
+  GET_ATM_DEVICE_STATISTICS                    = 0x51,
+  SET_ATM_DEFAULT_VC                           = 0x52,
+  GET_ATM_VC_STATISTICS                        = 0x53,
+
+  MDLM_SEMANTIC_MODEL                          = 0x60,
+}cdc_management_request_t;
+
+//--------------------------------------------------------------------+
+// MANAGEMENT ELEMENENT NOTIFICATION (NOTIFICATION ENDPOINT)
+//--------------------------------------------------------------------+
+typedef enum {
+  NETWORK_CONNECTION               = 0x00,
+  RESPONSE_AVAILABLE               = 0x01,
+
+  AUX_JACK_HOOK_STATE              = 0x08,
+  RING_DETECT                      = 0x09,
+
+  SERIAL_STATE                     = 0x20,
+
+  CALL_STATE_CHANGE                = 0x28,
+  LINE_STATE_CHANGE                = 0x29,
+  CONNECTION_SPEED_CHANGE          = 0x2A,
+  MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40,
+}cdc_notification_request_t;
+
+//--------------------------------------------------------------------+
+// FUNCTIONAL DESCRIPTOR
+//--------------------------------------------------------------------+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t bLength            ; ///< Size of this descriptor in bytes.
+  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
+  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+  uint16_t bcdCDC            ; ///< CDC release number in Binary-Coded Decimal
+}cdc_desc_func_header_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t bLength                  ; ///< Size of this descriptor in bytes.
+  uint8_t bDescriptorType          ; ///< Descriptor Type, must be Class-Specific
+  uint8_t bDescriptorSubType       ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+  uint8_t bControlInterface        ; ///< Interface number of Communication Interface
+  uint8_t bSubordinateInterface    ; ///< Array of Interface number of Data Interface
+}cdc_desc_func_union_t;
+
+#define cdc_desc_func_union_n_t(no_slave)\
+ ATTR_PACKED_STRUCT(struct) { \
+  uint8_t bLength                         ;\
+  uint8_t bDescriptorType                 ;\
+  uint8_t bDescriptorSubType              ;\
+  uint8_t bControlInterface               ;\
+  uint8_t bSubordinateInterface[no_slave] ;\
+}
+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t bLength             ; ///< Size of this descriptor in bytes.
+  uint8_t bDescriptorType     ; ///< Descriptor Type, must be Class-Specific
+  uint8_t bDescriptorSubType  ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+  uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes.
+  uint16_t wCountryCode[]     ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country.
+}cdc_desc_func_country_selection_t;
+
+#define cdc_desc_func_country_selection_n_t(no_country) \
+  ATTR_PACKED_STRUCT(struct) {\
+  uint8_t bLength                   ;\
+  uint8_t bDescriptorType           ;\
+  uint8_t bDescriptorSubType        ;\
+  uint8_t iCountryCodeRelDate       ;\
+  uint16_t wCountryCode[no_country] ;\
+}
+
+//--------------------------------------------------------------------+
+// PUBLIC SWITCHED TELEPHONE NETWORK (PSTN) SUBCLASS
+//--------------------------------------------------------------------+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t bLength            ; ///< Size of this descriptor in bytes.
+  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
+  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+
+  struct {
+    uint8_t handle_call    : 1; ///< 0 - Device sends/receives call management information only over the Communications Class interface. 1 - Device can send/receive call management information over a Data Class interface.
+    uint8_t send_recv_call : 1; ///< 0 - Device does not handle call management itself. 1 - Device handles call management itself.
+    uint8_t : 0;
+  } bmCapabilities;
+
+  uint8_t bDataInterface;
+}cdc_desc_func_call_management_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t support_comm_request                    : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature.
+  uint8_t support_line_request                    : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.
+  uint8_t support_send_break                      : 1; ///< Device supports the request Send_Break
+  uint8_t support_notification_network_connection : 1; ///< Device supports the notification Network_Connection.
+  uint8_t : 0;
+}cdc_acm_capability_t;
+
+STATIC_ASSERT(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compiler");
+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t bLength                  ; ///< Size of this descriptor in bytes.
+  uint8_t bDescriptorType          ; ///< Descriptor Type, must be Class-Specific
+  uint8_t bDescriptorSubType       ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+  cdc_acm_capability_t bmCapabilities ;
+}cdc_desc_func_abstract_control_management_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t bLength            ; ///< Size of this descriptor in bytes.
+  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
+  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+  struct {
+    uint8_t require_pulse_setup   : 1; ///< Device requires extra Pulse_Setup request during pulse dialing sequence to disengage holding circuit.
+    uint8_t support_aux_request   : 1; ///< Device supports the request combination of Set_Aux_Line_State, Ring_Aux_Jack, and notification Aux_Jack_Hook_State.
+    uint8_t support_pulse_request : 1; ///< Device supports the request combination of Pulse_Setup, Send_Pulse, and Set_Pulse_Time.
+    uint8_t : 0;
+  } bmCapabilities;
+}cdc_desc_func_direct_line_management_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t bLength            ; ///< Size of this descriptor in bytes.
+  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
+  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+  uint8_t bRingerVolSteps    ;
+  uint8_t bNumRingerPatterns ;
+}cdc_desc_func_telephone_ringer_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t bLength            ; ///< Size of this descriptor in bytes.
+  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
+  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+  struct {
+    uint8_t simple_mode           : 1;
+    uint8_t standalone_mode       : 1;
+    uint8_t computer_centric_mode : 1;
+    uint8_t : 0;
+  } bmCapabilities;
+}cdc_desc_func_telephone_operational_modes_t;
+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t bLength            ; ///< Size of this descriptor in bytes.
+  uint8_t bDescriptorType    ; ///< Descriptor Type, must be Class-Specific
+  uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
+  struct {
+    uint32_t interrupted_dialtone   : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : Reports interrupted dialtone in addition to normal dialtone
+    uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states.
+    uint32_t caller_id              : 1; ///< 0 : Does not report caller ID. 1 : Reports caller ID information.
+    uint32_t incoming_distinctive   : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns.
+    uint32_t dual_tone_multi_freq   : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line. 1 : Can report DTMF digits input remotely over the telephone line.
+    uint32_t line_state_change      : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notification
+    uint32_t : 0;
+  } bmCapabilities;
+}cdc_desc_func_telephone_call_state_reporting_capabilities_t;
+
+static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) ATTR_PURE ATTR_ALWAYS_INLINE;
+static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc)
+{
+  return p_desc[2];
+}
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif

+ 505 - 505
tinyusb/class/hid.h

@@ -1,505 +1,505 @@
-/**************************************************************************/
-/*!
-    @file     hid.h
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/**
- *  \addtogroup Group_ClassDriver Class Driver
- *  @{
- *  \defgroup Group_HID Human Interface Device
- *  @{
- */
-
-#ifndef _TUSB_HID_H_
-#define _TUSB_HID_H_
-
-#include "common/common.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-enum {
-  HID_SUBCLASS_NONE = 0,
-  HID_SUBCLASS_BOOT = 1
-};
-
-enum {
-  HID_PROTOCOL_NONE     = 0,
-  HID_PROTOCOL_KEYBOARD = 1,
-  HID_PROTOCOL_MOUSE    = 2
-};
-
-enum {
-  HID_DESC_TYPE_HID      = 0x21,
-  HID_DESC_TYPE_REPORT   = 0x22,
-  HID_DESC_TYPE_PHYSICAL = 0x23
-};
-
-enum {
-  HID_REQUEST_REPORT_INPUT = 1,
-  HID_REQUEST_REPORT_OUTPUT,
-  HID_REQUEST_REPORT_FEATURE
-};
-
-enum {
-  HID_REQUEST_CONTROL_GET_REPORT   = 0x01,
-  HID_REQUEST_CONTROL_GET_IDLE     = 0x02,
-  HID_REQUEST_CONTROL_GET_PROTOCOL = 0x03,
-  HID_REQUEST_CONTROL_SET_REPORT   = 0x09,
-  HID_REQUEST_CONTROL_SET_IDLE     = 0x0a,
-  HID_REQUEST_CONTROL_SET_PROTOCOL = 0x0b
-};
-
-typedef ATTR_PACKED_STRUCT(struct) {
-  uint8_t  bLength;         /**< Numeric expression that is the total size of the HID descriptor */
-  uint8_t  bDescriptorType; /**< Constant name specifying type of HID descriptor. */
-
-  uint16_t bcdHID;          /**< Numeric expression identifying the HID Class Specification release */
-  uint8_t  bCountryCode;    /**< Numeric expression identifying country code of the localized hardware.  */
-  uint8_t  bNumDescriptors; /**< Numeric expression specifying the number of class descriptors */
-
-  uint8_t  bReportType;     /**< Type of HID class report. */
-  uint16_t wReportLength;   /**< the total size of the Report descriptor. */
-} tusb_hid_descriptor_hid_t;
-
-/**
- *  \brief Standard HID Boot Protocol Mouse Report.
- *
- *  Type define for a standard Boot Protocol Mouse report
- */
-typedef ATTR_PACKED_STRUCT(struct)
-{
-  uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */
-  int8_t  x;       /**< Current delta x movement of the mouse. */
-  int8_t  y;       /**< Current delta y movement on the mouse. */
-  int8_t  wheel;   /**< Current delta wheel movement on the mouse. */
-} tusb_mouse_report_t;
-
-/**
- *  \brief Standard HID Boot Protocol Keyboard Report.
- *
- *  Type define for a standard Boot Protocol Keyboard report
- */
-typedef ATTR_PACKED_STRUCT(struct)
-{
-  uint8_t modifier; /**< Keyboard modifier byte, indicating pressed modifier keys (a combination of HID_KEYBOARD_MODIFER_* masks). */
-  uint8_t reserved; /**< Reserved for OEM use, always set to 0. */
-  uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */
-} tusb_keyboard_report_t;
-
-/**
- * \brief buttons codes for HID mouse
- */
-enum {
-	MOUSE_BUTTON_LEFT   = BIT_(0),
-	MOUSE_BUTTON_RIGHT  = BIT_(1),
-	MOUSE_BUTTON_MIDDLE = BIT_(2)
-};
-
-/**
- * \brief KB modifier codes for HID KB
- */
-enum {
-	KEYBOARD_MODIFIER_LEFTCTRL   = BIT_(0),
-	KEYBOARD_MODIFIER_LEFTSHIFT  = BIT_(1),
-	KEYBOARD_MODIFIER_LEFTALT    = BIT_(2),
-	KEYBOARD_MODIFIER_LEFTGUI    = BIT_(3),
-	KEYBOARD_MODIFIER_RIGHTCTRL  = BIT_(4),
-	KEYBOARD_MODIFIER_RIGHTSHIFT = BIT_(5),
-	KEYBOARD_MODIFIER_RIGHTALT   = BIT_(6),
-	KEYBOARD_MODIFIER_RIGHTGUI   = BIT_(7)
-};
-
-#define HID_KEYCODE_TABLE(ENTRY) \
-    ENTRY( 0x04, 'a', 'A' )\
-    ENTRY( 0x05, 'b', 'B' )\
-    ENTRY( 0x06, 'c', 'C' )\
-    ENTRY( 0x07, 'd', 'D' )\
-    ENTRY( 0x08, 'e', 'E' )\
-    ENTRY( 0x09, 'f', 'F' )\
-    ENTRY( 0x0a, 'g', 'G' )\
-    ENTRY( 0x0b, 'h', 'H' )\
-    ENTRY( 0x0c, 'i', 'I' )\
-    ENTRY( 0x0d, 'j', 'J' )\
-    ENTRY( 0x0e, 'k', 'K' )\
-    ENTRY( 0x0f, 'l', 'L' )\
-    \
-    ENTRY( 0x10, 'm', 'M' )\
-    ENTRY( 0x11, 'n', 'N' )\
-    ENTRY( 0x12, 'o', 'O' )\
-    ENTRY( 0x13, 'p', 'P' )\
-    ENTRY( 0x14, 'q', 'Q' )\
-    ENTRY( 0x15, 'r', 'R' )\
-    ENTRY( 0x16, 's', 'S' )\
-    ENTRY( 0x17, 't', 'T' )\
-    ENTRY( 0x18, 'u', 'U' )\
-    ENTRY( 0x19, 'v', 'V' )\
-    ENTRY( 0x1a, 'w', 'W' )\
-    ENTRY( 0x1b, 'x', 'X' )\
-    ENTRY( 0x1c, 'y', 'Y' )\
-    ENTRY( 0x1d, 'z', 'Z' )\
-    ENTRY( 0x1e, '1', '!' )\
-    ENTRY( 0x1f, '2', '@' )\
-    \
-    ENTRY( 0x20, '3', '#' )\
-    ENTRY( 0x21, '4', '$' )\
-    ENTRY( 0x22, '5', '%' )\
-    ENTRY( 0x23, '6', '^' )\
-    ENTRY( 0x24, '7', '&' )\
-    ENTRY( 0x25, '8', '*' )\
-    ENTRY( 0x26, '9', '(' )\
-    ENTRY( 0x27, '0', ')' )\
-    ENTRY( 0x28, '\r', '\r' )\
-    ENTRY( 0x29, '\e', '\e' )\
-    ENTRY( 0x2a, '\b', '\b' )\
-    ENTRY( 0x2b, '\t', '\t' )\
-    ENTRY( 0x2c, ' ', ' '  )\
-    ENTRY( 0x2d, '-', '_' )\
-    ENTRY( 0x2e, '=', '+' )\
-    ENTRY( 0x2f, '[', '{' )\
-    \
-    ENTRY( 0x30, ']', '}' )\
-    ENTRY( 0x31, '\\', '|' )\
-    ENTRY( 0x32, '#', '~' ) /* TODO non-US keyboard */ \
-    ENTRY( 0x33, ';', ':' )\
-    ENTRY( 0x34, '\'', '\"' )\
-    ENTRY( 0x35, 0, 0 )\
-    ENTRY( 0x36, ',', '<' )\
-    ENTRY( 0x37, '.', '>' )\
-    ENTRY( 0x38, '/', '?' )\
-    ENTRY( 0x39, 0, 0 ) /* TODO CapsLock, non-locking key implementation*/ \
-    \
-    ENTRY( 0x54, '/', '/' )\
-    ENTRY( 0x55, '*', '*' )\
-    ENTRY( 0x56, '-', '-' )\
-    ENTRY( 0x57, '+', '+' )\
-    ENTRY( 0x58, '\r', '\r' )\
-    ENTRY( 0x59, '1', 0 ) /* numpad1 & end */ \
-    ENTRY( 0x5a, '2', 0 )\
-    ENTRY( 0x5b, '3', 0 )\
-    ENTRY( 0x5c, '4', 0 )\
-    ENTRY( 0x5d, '5', '5' )\
-    ENTRY( 0x5e, '6', 0 )\
-    ENTRY( 0x5f, '7', 0 )\
-    ENTRY( 0x60, '8', 0 )\
-    ENTRY( 0x61, '9', 0 )\
-    ENTRY( 0x62, '0', 0 )\
-    ENTRY( 0x63, '0', 0 )\
-    \
-    ENTRY( 0x67, '=', '=' )\
-
-// TODO HID complete keycode table
-
-//enum
-//{
-//  KEYBOARD_KEYCODE_A     = 0x04,
-//  KEYBOARD_KEYCODE_Z     = 0x1d,
-//
-//  KEYBOARD_KEYCODE_1     = 0x1e,
-//  KEYBOARD_KEYCODE_0     = 0x27,
-//
-//  KEYBOARD_KEYCODE_ENTER = 0x28,
-//  KEYBOARD_KEYCODE_ESCAPE = 0x29,
-//  KEYBOARD_KEYCODE_BACKSPACE = 0x2a,
-//  KEYBOARD_KEYCODE_TAB = 0x2b,
-//  KEYBOARD_KEYCODE_SPACEBAR = 0x2c,
-//
-//};
-
-/**
- * \brief Local Country code for HID
- */
-enum USB_HID_LOCAL_CODE
-{
-  HID_Local_NotSupported = 0,
-  HID_Local_Arabic,
-  HID_Local_Belgian,
-  HID_Local_Canadian_Bilingual,
-  HID_Local_Canadian_French,
-  HID_Local_Czech_Republic,
-  HID_Local_Danish,
-  HID_Local_Finnish,
-  HID_Local_French,
-  HID_Local_German,
-  HID_Local_Greek,
-  HID_Local_Hebrew,
-  HID_Local_Hungary,
-  HID_Local_International,
-  HID_Local_Italian,
-  HID_Local_Japan_Katakana,
-  HID_Local_Korean,
-  HID_Local_Latin_American,
-  HID_Local_Netherlands_Dutch,
-  HID_Local_Norwegian,
-  HID_Local_Persian_Farsi,
-  HID_Local_Poland,
-  HID_Local_Portuguese,
-  HID_Local_Russia,
-  HID_Local_Slovakia,
-  HID_Local_Spanish,
-  HID_Local_Swedish,
-  HID_Local_Swiss_French,
-  HID_Local_Swiss_German,
-  HID_Local_Switzerland,
-  HID_Local_Taiwan,
-  HID_Local_Turkish_Q,
-  HID_Local_UK,
-  HID_Local_US,
-  HID_Local_Yugoslavia,
-  HID_Local_Turkish_F
-};
-
-//--------------------------------------------------------------------+
-// REPORT DESCRIPTOR
-//--------------------------------------------------------------------+
-//------------- ITEM & TAG -------------//
-#define HID_REPORT_DATA_0(data)
-#define HID_REPORT_DATA_1(data) , data
-#define HID_REPORT_DATA_2(data) , U16_TO_U8S_LE(data)
-#define HID_REPORT_DATA_3(data) , U32_TO_U8S_LE(data)
-
-#define HID_REPORT_ITEM(data, tag, type, size) \
-  (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data)
-
-#define RI_TYPE_MAIN   0
-#define RI_TYPE_GLOBAL 1
-#define RI_TYPE_LOCAL  2
-
-//------------- MAIN ITEMS 6.2.2.4 -------------//
-#define HID_INPUT(x)           HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1)
-#define HID_OUTPUT(x)          HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1)
-#define HID_COLLECTION(x)      HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1)
-#define HID_FEATURE(x)         HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1)
-#define HID_COLLECTION_END     HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0)
-
-//------------- INPUT, OUTPUT, FEATURE 6.2.2.5 -------------//
-#define HID_DATA             (0<<0)
-#define HID_CONSTANT         (1<<0)
-
-#define HID_ARRAY            (0<<1)
-#define HID_VARIABLE         (1<<1)
-
-#define HID_ABSOLUTE         (0<<2)
-#define HID_RELATIVE         (1<<2)
-
-#define HID_WRAP_NO          (0<<3)
-#define HID_WRAP             (1<<3)
-
-#define HID_LINEAR           (0<<4)
-#define HID_NONLINEAR        (1<<4)
-
-#define HID_PREFERRED_STATE  (0<<5)
-#define HID_PREFERRED_NO     (1<<5)
-
-#define HID_NO_NULL_POSITION (0<<6)
-#define HID_NULL_STATE       (1<<6)
-
-#define HID_NON_VOLATILE     (0<<7)
-#define HID_VOLATILE         (1<<7)
-
-#define HID_BITFIELD         (0<<8)
-#define HID_BUFFERED_BYTES   (1<<8)
-
-//------------- COLLECTION ITEM 6.2.2.6 -------------//
-enum {
-  HID_COLLECTION_PHYSICAL = 0,
-  HID_COLLECTION_APPLICATION,
-  HID_COLLECTION_LOGICAL,
-  HID_COLLECTION_REPORT,
-  HID_COLLECTION_NAMED_ARRAY,
-  HID_COLLECTION_USAGE_SWITCH,
-  HID_COLLECTION_USAGE_MODIFIER
-};
-
-//------------- GLOBAL ITEMS 6.2.2.7 -------------//
-#define HID_USAGE_PAGE(x)         HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1)
-#define HID_USAGE_PAGE_N(x, n)    HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n)
-
-#define HID_LOGICAL_MIN(x)        HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, 1)
-#define HID_LOGICAL_MIN_N(x, n)   HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, n)
-
-#define HID_LOGICAL_MAX(x)        HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, 1)
-#define HID_LOGICAL_MAX_N(x, n)   HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, n)
-
-#define HID_PHYSICAL_MIN(x)       HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, 1)
-#define HID_PHYSICAL_MIN_N(x, n)  HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, n)
-
-#define HID_PHYSICAL_MAX(x)       HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, 1)
-#define HID_PHYSICAL_MAX_N(x, n)  HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, n)
-
-#define HID_UNIT_EXPONENT(x)      HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, 1)
-#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, n)
-
-#define HID_UNIT(x)               HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, 1)
-#define HID_UNIT_N(x, n)          HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, n)
-
-#define HID_REPORT_SIZE(x)        HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, 1)
-#define HID_REPORT_SIZE_N(x, n)   HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, n)
-
-#define HID_REPORT_ID(x)          HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1)
-#define HID_REPORT_ID_N(x)        HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n)
-
-#define HID_REPORT_COUNT(x)       HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, 1)
-#define HID_REPORT_COUNT_N(x, n)  HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, n)
-
-#define HID_PUSH                  HID_REPORT_ITEM(x, 10, RI_TYPE_GLOBAL, 0)
-#define HID_POP                   HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0)
-
-//------------- LOCAL ITEMS 6.2.2.8 -------------//
-#define HID_USAGE(x)              HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1)
-#define HID_USAGE_N(x, n)         HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n)
-
-#define HID_USAGE_MIN(x)          HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, 1)
-#define HID_USAGE_MIN_N(x, n)     HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, n)
-
-#define HID_USAGE_MAX(x)          HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, 1)
-#define HID_USAGE_MAX_N(x, n)     HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, n)
-
-//--------------------------------------------------------------------+
-// Usage Table
-//--------------------------------------------------------------------+
-
-/// HID Usage Table - Table 1: Usage Page Summary
-enum {
-  HID_USAGE_PAGE_DESKTOP         = 0x01,
-  HID_USAGE_PAGE_SIMULATE        = 0x02,
-  HID_USAGE_PAGE_VIRTUAL_REALITY = 0x03,
-  HID_USAGE_PAGE_SPORT           = 0x04,
-  HID_USAGE_PAGE_GAME            = 0x05,
-  HID_USAGE_PAGE_GENERIC_DEVICE  = 0x06,
-  HID_USAGE_PAGE_KEYBOARD        = 0x07,
-  HID_USAGE_PAGE_LED             = 0x08,
-  HID_USAGE_PAGE_BUTTON          = 0x09,
-  HID_USAGE_PAGE_ORDINAL         = 0x0a,
-  HID_USAGE_PAGE_TELEPHONY       = 0x0b,
-  HID_USAGE_PAGE_CONSUMER        = 0x0c,
-  HID_USAGE_PAGE_DIGITIZER       = 0x0d,
-  HID_USAGE_PAGE_PID             = 0x0f,
-  HID_USAGE_PAGE_UNICODE         = 0x10,
-  HID_USAGE_PAGE_ALPHA_DISPLAY   = 0x14,
-  HID_USAGE_PAGE_MEDICAL         = 0x40,
-  HID_USAGE_PAGE_MONITOR         = 0x80, //0x80 - 0x83
-  HID_USAGE_PAGE_POWER           = 0x84, // 0x084 - 0x87
-  HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c,
-  HID_USAGE_PAGE_SCALE           = 0x8d,
-  HID_USAGE_PAGE_MSR             = 0x8e,
-  HID_USAGE_PAGE_CAMERA          = 0x90,
-  HID_USAGE_PAGE_ARCADE          = 0x91,
-  HID_USAGE_PAGE_VENDOR          = 0xFFFF // 0xFF00 - 0xFFFF
-};
-
-/// HID Usage Table - Table 6: Generic Desktop Page
-enum {
-  HID_USAGE_DESKTOP_POINTER                               = 0x01,
-  HID_USAGE_DESKTOP_MOUSE                                 = 0x02,
-  HID_USAGE_DESKTOP_JOYSTICK                              = 0x04,
-  HID_USAGE_DESKTOP_GAMEPAD                               = 0x05,
-  HID_USAGE_DESKTOP_KEYBOARD                              = 0x06,
-  HID_USAGE_DESKTOP_KEYPAD                                = 0x07,
-  HID_USAGE_DESKTOP_MULTI_AXIS_CONTROLLER                 = 0x08,
-  HID_USAGE_DESKTOP_TABLET_PC_SYSTEM                      = 0x09,
-  HID_USAGE_DESKTOP_X                                     = 0x30,
-  HID_USAGE_DESKTOP_Y                                     = 0x31,
-  HID_USAGE_DESKTOP_Z                                     = 0x32,
-  HID_USAGE_DESKTOP_RX                                    = 0x33,
-  HID_USAGE_DESKTOP_RY                                    = 0x34,
-  HID_USAGE_DESKTOP_RZ                                    = 0x35,
-  HID_USAGE_DESKTOP_SLIDER                                = 0x36,
-  HID_USAGE_DESKTOP_DIAL                                  = 0x37,
-  HID_USAGE_DESKTOP_WHEEL                                 = 0x38,
-  HID_USAGE_DESKTOP_HAT_SWITCH                            = 0x39,
-  HID_USAGE_DESKTOP_COUNTED_BUFFER                        = 0x3a,
-  HID_USAGE_DESKTOP_BYTE_COUNT                            = 0x3b,
-  HID_USAGE_DESKTOP_MOTION_WAKEUP                         = 0x3c,
-  HID_USAGE_DESKTOP_START                                 = 0x3d,
-  HID_USAGE_DESKTOP_SELECT                                = 0x3e,
-  HID_USAGE_DESKTOP_VX                                    = 0x40,
-  HID_USAGE_DESKTOP_VY                                    = 0x41,
-  HID_USAGE_DESKTOP_VZ                                    = 0x42,
-  HID_USAGE_DESKTOP_VBRX                                  = 0x43,
-  HID_USAGE_DESKTOP_VBRY                                  = 0x44,
-  HID_USAGE_DESKTOP_VBRZ                                  = 0x45,
-  HID_USAGE_DESKTOP_VNO                                   = 0x46,
-  HID_USAGE_DESKTOP_FEATURE_NOTIFICATION                  = 0x47,
-  HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER                 = 0x48,
-  HID_USAGE_DESKTOP_SYSTEM_CONTROL                        = 0x80,
-  HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN                     = 0x81,
-  HID_USAGE_DESKTOP_SYSTEM_SLEEP                          = 0x82,
-  HID_USAGE_DESKTOP_SYSTEM_WAKE_UP                        = 0x83,
-  HID_USAGE_DESKTOP_SYSTEM_CONTEXT_MENU                   = 0x84,
-  HID_USAGE_DESKTOP_SYSTEM_MAIN_MENU                      = 0x85,
-  HID_USAGE_DESKTOP_SYSTEM_APP_MENU                       = 0x86,
-  HID_USAGE_DESKTOP_SYSTEM_MENU_HELP                      = 0x87,
-  HID_USAGE_DESKTOP_SYSTEM_MENU_EXIT                      = 0x88,
-  HID_USAGE_DESKTOP_SYSTEM_MENU_SELECT                    = 0x89,
-  HID_USAGE_DESKTOP_SYSTEM_MENU_RIGHT                     = 0x8A,
-  HID_USAGE_DESKTOP_SYSTEM_MENU_LEFT                      = 0x8B,
-  HID_USAGE_DESKTOP_SYSTEM_MENU_UP                        = 0x8C,
-  HID_USAGE_DESKTOP_SYSTEM_MENU_DOWN                      = 0x8D,
-  HID_USAGE_DESKTOP_SYSTEM_COLD_RESTART                   = 0x8E,
-  HID_USAGE_DESKTOP_SYSTEM_WARM_RESTART                   = 0x8F,
-  HID_USAGE_DESKTOP_DPAD_UP                               = 0x90,
-  HID_USAGE_DESKTOP_DPAD_DOWN                             = 0x91,
-  HID_USAGE_DESKTOP_DPAD_RIGHT                            = 0x92,
-  HID_USAGE_DESKTOP_DPAD_LEFT                             = 0x93,
-  HID_USAGE_DESKTOP_SYSTEM_DOCK                           = 0xA0,
-  HID_USAGE_DESKTOP_SYSTEM_UNDOCK                         = 0xA1,
-  HID_USAGE_DESKTOP_SYSTEM_SETUP                          = 0xA2,
-  HID_USAGE_DESKTOP_SYSTEM_BREAK                          = 0xA3,
-  HID_USAGE_DESKTOP_SYSTEM_DEBUGGER_BREAK                 = 0xA4,
-  HID_USAGE_DESKTOP_APPLICATION_BREAK                     = 0xA5,
-  HID_USAGE_DESKTOP_APPLICATION_DEBUGGER_BREAK            = 0xA6,
-  HID_USAGE_DESKTOP_SYSTEM_SPEAKER_MUTE                   = 0xA7,
-  HID_USAGE_DESKTOP_SYSTEM_HIBERNATE                      = 0xA8,
-  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INVERT                 = 0xB0,
-  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INTERNAL               = 0xB1,
-  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_EXTERNAL               = 0xB2,
-  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_BOTH                   = 0xB3,
-  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_DUAL                   = 0xB4,
-  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_TOGGLE_INT_EXT         = 0xB5,
-  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_SWAP_PRIMARY_SECONDARY = 0xB6,
-  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE          = 0xB7
-};
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_HID_H__ */
-
-/// @}
-/// @}
+/**************************************************************************/
+/*!
+    @file     hid.h
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/**
+ *  \addtogroup ClassDriver Class Driver
+ *  @{
+ *  \defgroup ClassDriver_HID Human Interface Device (HID)
+ *  @{
+ */
+
+#ifndef _TUSB_HID_H_
+#define _TUSB_HID_H_
+
+#include "common/common.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+enum {
+  HID_SUBCLASS_NONE = 0,
+  HID_SUBCLASS_BOOT = 1
+};
+
+enum {
+  HID_PROTOCOL_NONE     = 0,
+  HID_PROTOCOL_KEYBOARD = 1,
+  HID_PROTOCOL_MOUSE    = 2
+};
+
+enum {
+  HID_DESC_TYPE_HID      = 0x21,
+  HID_DESC_TYPE_REPORT   = 0x22,
+  HID_DESC_TYPE_PHYSICAL = 0x23
+};
+
+enum {
+  HID_REQUEST_REPORT_INPUT = 1,
+  HID_REQUEST_REPORT_OUTPUT,
+  HID_REQUEST_REPORT_FEATURE
+};
+
+enum {
+  HID_REQUEST_CONTROL_GET_REPORT   = 0x01,
+  HID_REQUEST_CONTROL_GET_IDLE     = 0x02,
+  HID_REQUEST_CONTROL_GET_PROTOCOL = 0x03,
+  HID_REQUEST_CONTROL_SET_REPORT   = 0x09,
+  HID_REQUEST_CONTROL_SET_IDLE     = 0x0a,
+  HID_REQUEST_CONTROL_SET_PROTOCOL = 0x0b
+};
+
+typedef ATTR_PACKED_STRUCT(struct) {
+  uint8_t  bLength;         /**< Numeric expression that is the total size of the HID descriptor */
+  uint8_t  bDescriptorType; /**< Constant name specifying type of HID descriptor. */
+
+  uint16_t bcdHID;          /**< Numeric expression identifying the HID Class Specification release */
+  uint8_t  bCountryCode;    /**< Numeric expression identifying country code of the localized hardware.  */
+  uint8_t  bNumDescriptors; /**< Numeric expression specifying the number of class descriptors */
+
+  uint8_t  bReportType;     /**< Type of HID class report. */
+  uint16_t wReportLength;   /**< the total size of the Report descriptor. */
+} tusb_hid_descriptor_hid_t;
+
+/**
+ *  \brief Standard HID Boot Protocol Mouse Report.
+ *
+ *  Type define for a standard Boot Protocol Mouse report
+ */
+typedef ATTR_PACKED_STRUCT(struct)
+{
+  uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */
+  int8_t  x;       /**< Current delta x movement of the mouse. */
+  int8_t  y;       /**< Current delta y movement on the mouse. */
+  int8_t  wheel;   /**< Current delta wheel movement on the mouse. */
+} tusb_mouse_report_t;
+
+/**
+ *  \brief Standard HID Boot Protocol Keyboard Report.
+ *
+ *  Type define for a standard Boot Protocol Keyboard report
+ */
+typedef ATTR_PACKED_STRUCT(struct)
+{
+  uint8_t modifier; /**< Keyboard modifier byte, indicating pressed modifier keys (a combination of HID_KEYBOARD_MODIFER_* masks). */
+  uint8_t reserved; /**< Reserved for OEM use, always set to 0. */
+  uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */
+} tusb_keyboard_report_t;
+
+/**
+ * \brief buttons codes for HID mouse
+ */
+enum {
+	MOUSE_BUTTON_LEFT   = BIT_(0),
+	MOUSE_BUTTON_RIGHT  = BIT_(1),
+	MOUSE_BUTTON_MIDDLE = BIT_(2)
+};
+
+/**
+ * \brief KB modifier codes for HID KB
+ */
+enum {
+	KEYBOARD_MODIFIER_LEFTCTRL   = BIT_(0),
+	KEYBOARD_MODIFIER_LEFTSHIFT  = BIT_(1),
+	KEYBOARD_MODIFIER_LEFTALT    = BIT_(2),
+	KEYBOARD_MODIFIER_LEFTGUI    = BIT_(3),
+	KEYBOARD_MODIFIER_RIGHTCTRL  = BIT_(4),
+	KEYBOARD_MODIFIER_RIGHTSHIFT = BIT_(5),
+	KEYBOARD_MODIFIER_RIGHTALT   = BIT_(6),
+	KEYBOARD_MODIFIER_RIGHTGUI   = BIT_(7)
+};
+
+#define HID_KEYCODE_TABLE(ENTRY) \
+    ENTRY( 0x04, 'a', 'A' )\
+    ENTRY( 0x05, 'b', 'B' )\
+    ENTRY( 0x06, 'c', 'C' )\
+    ENTRY( 0x07, 'd', 'D' )\
+    ENTRY( 0x08, 'e', 'E' )\
+    ENTRY( 0x09, 'f', 'F' )\
+    ENTRY( 0x0a, 'g', 'G' )\
+    ENTRY( 0x0b, 'h', 'H' )\
+    ENTRY( 0x0c, 'i', 'I' )\
+    ENTRY( 0x0d, 'j', 'J' )\
+    ENTRY( 0x0e, 'k', 'K' )\
+    ENTRY( 0x0f, 'l', 'L' )\
+    \
+    ENTRY( 0x10, 'm', 'M' )\
+    ENTRY( 0x11, 'n', 'N' )\
+    ENTRY( 0x12, 'o', 'O' )\
+    ENTRY( 0x13, 'p', 'P' )\
+    ENTRY( 0x14, 'q', 'Q' )\
+    ENTRY( 0x15, 'r', 'R' )\
+    ENTRY( 0x16, 's', 'S' )\
+    ENTRY( 0x17, 't', 'T' )\
+    ENTRY( 0x18, 'u', 'U' )\
+    ENTRY( 0x19, 'v', 'V' )\
+    ENTRY( 0x1a, 'w', 'W' )\
+    ENTRY( 0x1b, 'x', 'X' )\
+    ENTRY( 0x1c, 'y', 'Y' )\
+    ENTRY( 0x1d, 'z', 'Z' )\
+    ENTRY( 0x1e, '1', '!' )\
+    ENTRY( 0x1f, '2', '@' )\
+    \
+    ENTRY( 0x20, '3', '#' )\
+    ENTRY( 0x21, '4', '$' )\
+    ENTRY( 0x22, '5', '%' )\
+    ENTRY( 0x23, '6', '^' )\
+    ENTRY( 0x24, '7', '&' )\
+    ENTRY( 0x25, '8', '*' )\
+    ENTRY( 0x26, '9', '(' )\
+    ENTRY( 0x27, '0', ')' )\
+    ENTRY( 0x28, '\r', '\r' )\
+    ENTRY( 0x29, '\e', '\e' )\
+    ENTRY( 0x2a, '\b', '\b' )\
+    ENTRY( 0x2b, '\t', '\t' )\
+    ENTRY( 0x2c, ' ', ' '  )\
+    ENTRY( 0x2d, '-', '_' )\
+    ENTRY( 0x2e, '=', '+' )\
+    ENTRY( 0x2f, '[', '{' )\
+    \
+    ENTRY( 0x30, ']', '}' )\
+    ENTRY( 0x31, '\\', '|' )\
+    ENTRY( 0x32, '#', '~' ) /* TODO non-US keyboard */ \
+    ENTRY( 0x33, ';', ':' )\
+    ENTRY( 0x34, '\'', '\"' )\
+    ENTRY( 0x35, 0, 0 )\
+    ENTRY( 0x36, ',', '<' )\
+    ENTRY( 0x37, '.', '>' )\
+    ENTRY( 0x38, '/', '?' )\
+    ENTRY( 0x39, 0, 0 ) /* TODO CapsLock, non-locking key implementation*/ \
+    \
+    ENTRY( 0x54, '/', '/' )\
+    ENTRY( 0x55, '*', '*' )\
+    ENTRY( 0x56, '-', '-' )\
+    ENTRY( 0x57, '+', '+' )\
+    ENTRY( 0x58, '\r', '\r' )\
+    ENTRY( 0x59, '1', 0 ) /* numpad1 & end */ \
+    ENTRY( 0x5a, '2', 0 )\
+    ENTRY( 0x5b, '3', 0 )\
+    ENTRY( 0x5c, '4', 0 )\
+    ENTRY( 0x5d, '5', '5' )\
+    ENTRY( 0x5e, '6', 0 )\
+    ENTRY( 0x5f, '7', 0 )\
+    ENTRY( 0x60, '8', 0 )\
+    ENTRY( 0x61, '9', 0 )\
+    ENTRY( 0x62, '0', 0 )\
+    ENTRY( 0x63, '0', 0 )\
+    \
+    ENTRY( 0x67, '=', '=' )\
+
+// TODO HID complete keycode table
+
+//enum
+//{
+//  KEYBOARD_KEYCODE_A     = 0x04,
+//  KEYBOARD_KEYCODE_Z     = 0x1d,
+//
+//  KEYBOARD_KEYCODE_1     = 0x1e,
+//  KEYBOARD_KEYCODE_0     = 0x27,
+//
+//  KEYBOARD_KEYCODE_ENTER = 0x28,
+//  KEYBOARD_KEYCODE_ESCAPE = 0x29,
+//  KEYBOARD_KEYCODE_BACKSPACE = 0x2a,
+//  KEYBOARD_KEYCODE_TAB = 0x2b,
+//  KEYBOARD_KEYCODE_SPACEBAR = 0x2c,
+//
+//};
+
+/**
+ * \brief Local Country code for HID
+ */
+enum USB_HID_LOCAL_CODE
+{
+  HID_Local_NotSupported = 0,
+  HID_Local_Arabic,
+  HID_Local_Belgian,
+  HID_Local_Canadian_Bilingual,
+  HID_Local_Canadian_French,
+  HID_Local_Czech_Republic,
+  HID_Local_Danish,
+  HID_Local_Finnish,
+  HID_Local_French,
+  HID_Local_German,
+  HID_Local_Greek,
+  HID_Local_Hebrew,
+  HID_Local_Hungary,
+  HID_Local_International,
+  HID_Local_Italian,
+  HID_Local_Japan_Katakana,
+  HID_Local_Korean,
+  HID_Local_Latin_American,
+  HID_Local_Netherlands_Dutch,
+  HID_Local_Norwegian,
+  HID_Local_Persian_Farsi,
+  HID_Local_Poland,
+  HID_Local_Portuguese,
+  HID_Local_Russia,
+  HID_Local_Slovakia,
+  HID_Local_Spanish,
+  HID_Local_Swedish,
+  HID_Local_Swiss_French,
+  HID_Local_Swiss_German,
+  HID_Local_Switzerland,
+  HID_Local_Taiwan,
+  HID_Local_Turkish_Q,
+  HID_Local_UK,
+  HID_Local_US,
+  HID_Local_Yugoslavia,
+  HID_Local_Turkish_F
+};
+
+//--------------------------------------------------------------------+
+// REPORT DESCRIPTOR
+//--------------------------------------------------------------------+
+//------------- ITEM & TAG -------------//
+#define HID_REPORT_DATA_0(data)
+#define HID_REPORT_DATA_1(data) , data
+#define HID_REPORT_DATA_2(data) , U16_TO_U8S_LE(data)
+#define HID_REPORT_DATA_3(data) , U32_TO_U8S_LE(data)
+
+#define HID_REPORT_ITEM(data, tag, type, size) \
+  (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data)
+
+#define RI_TYPE_MAIN   0
+#define RI_TYPE_GLOBAL 1
+#define RI_TYPE_LOCAL  2
+
+//------------- MAIN ITEMS 6.2.2.4 -------------//
+#define HID_INPUT(x)           HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1)
+#define HID_OUTPUT(x)          HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1)
+#define HID_COLLECTION(x)      HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1)
+#define HID_FEATURE(x)         HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1)
+#define HID_COLLECTION_END     HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0)
+
+//------------- INPUT, OUTPUT, FEATURE 6.2.2.5 -------------//
+#define HID_DATA             (0<<0)
+#define HID_CONSTANT         (1<<0)
+
+#define HID_ARRAY            (0<<1)
+#define HID_VARIABLE         (1<<1)
+
+#define HID_ABSOLUTE         (0<<2)
+#define HID_RELATIVE         (1<<2)
+
+#define HID_WRAP_NO          (0<<3)
+#define HID_WRAP             (1<<3)
+
+#define HID_LINEAR           (0<<4)
+#define HID_NONLINEAR        (1<<4)
+
+#define HID_PREFERRED_STATE  (0<<5)
+#define HID_PREFERRED_NO     (1<<5)
+
+#define HID_NO_NULL_POSITION (0<<6)
+#define HID_NULL_STATE       (1<<6)
+
+#define HID_NON_VOLATILE     (0<<7)
+#define HID_VOLATILE         (1<<7)
+
+#define HID_BITFIELD         (0<<8)
+#define HID_BUFFERED_BYTES   (1<<8)
+
+//------------- COLLECTION ITEM 6.2.2.6 -------------//
+enum {
+  HID_COLLECTION_PHYSICAL = 0,
+  HID_COLLECTION_APPLICATION,
+  HID_COLLECTION_LOGICAL,
+  HID_COLLECTION_REPORT,
+  HID_COLLECTION_NAMED_ARRAY,
+  HID_COLLECTION_USAGE_SWITCH,
+  HID_COLLECTION_USAGE_MODIFIER
+};
+
+//------------- GLOBAL ITEMS 6.2.2.7 -------------//
+#define HID_USAGE_PAGE(x)         HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1)
+#define HID_USAGE_PAGE_N(x, n)    HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n)
+
+#define HID_LOGICAL_MIN(x)        HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, 1)
+#define HID_LOGICAL_MIN_N(x, n)   HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, n)
+
+#define HID_LOGICAL_MAX(x)        HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, 1)
+#define HID_LOGICAL_MAX_N(x, n)   HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, n)
+
+#define HID_PHYSICAL_MIN(x)       HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, 1)
+#define HID_PHYSICAL_MIN_N(x, n)  HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, n)
+
+#define HID_PHYSICAL_MAX(x)       HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, 1)
+#define HID_PHYSICAL_MAX_N(x, n)  HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, n)
+
+#define HID_UNIT_EXPONENT(x)      HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, 1)
+#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, n)
+
+#define HID_UNIT(x)               HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, 1)
+#define HID_UNIT_N(x, n)          HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, n)
+
+#define HID_REPORT_SIZE(x)        HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, 1)
+#define HID_REPORT_SIZE_N(x, n)   HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, n)
+
+#define HID_REPORT_ID(x)          HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1)
+#define HID_REPORT_ID_N(x)        HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n)
+
+#define HID_REPORT_COUNT(x)       HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, 1)
+#define HID_REPORT_COUNT_N(x, n)  HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, n)
+
+#define HID_PUSH                  HID_REPORT_ITEM(x, 10, RI_TYPE_GLOBAL, 0)
+#define HID_POP                   HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0)
+
+//------------- LOCAL ITEMS 6.2.2.8 -------------//
+#define HID_USAGE(x)              HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1)
+#define HID_USAGE_N(x, n)         HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n)
+
+#define HID_USAGE_MIN(x)          HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, 1)
+#define HID_USAGE_MIN_N(x, n)     HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, n)
+
+#define HID_USAGE_MAX(x)          HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, 1)
+#define HID_USAGE_MAX_N(x, n)     HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, n)
+
+//--------------------------------------------------------------------+
+// Usage Table
+//--------------------------------------------------------------------+
+
+/// HID Usage Table - Table 1: Usage Page Summary
+enum {
+  HID_USAGE_PAGE_DESKTOP         = 0x01,
+  HID_USAGE_PAGE_SIMULATE        = 0x02,
+  HID_USAGE_PAGE_VIRTUAL_REALITY = 0x03,
+  HID_USAGE_PAGE_SPORT           = 0x04,
+  HID_USAGE_PAGE_GAME            = 0x05,
+  HID_USAGE_PAGE_GENERIC_DEVICE  = 0x06,
+  HID_USAGE_PAGE_KEYBOARD        = 0x07,
+  HID_USAGE_PAGE_LED             = 0x08,
+  HID_USAGE_PAGE_BUTTON          = 0x09,
+  HID_USAGE_PAGE_ORDINAL         = 0x0a,
+  HID_USAGE_PAGE_TELEPHONY       = 0x0b,
+  HID_USAGE_PAGE_CONSUMER        = 0x0c,
+  HID_USAGE_PAGE_DIGITIZER       = 0x0d,
+  HID_USAGE_PAGE_PID             = 0x0f,
+  HID_USAGE_PAGE_UNICODE         = 0x10,
+  HID_USAGE_PAGE_ALPHA_DISPLAY   = 0x14,
+  HID_USAGE_PAGE_MEDICAL         = 0x40,
+  HID_USAGE_PAGE_MONITOR         = 0x80, //0x80 - 0x83
+  HID_USAGE_PAGE_POWER           = 0x84, // 0x084 - 0x87
+  HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c,
+  HID_USAGE_PAGE_SCALE           = 0x8d,
+  HID_USAGE_PAGE_MSR             = 0x8e,
+  HID_USAGE_PAGE_CAMERA          = 0x90,
+  HID_USAGE_PAGE_ARCADE          = 0x91,
+  HID_USAGE_PAGE_VENDOR          = 0xFFFF // 0xFF00 - 0xFFFF
+};
+
+/// HID Usage Table - Table 6: Generic Desktop Page
+enum {
+  HID_USAGE_DESKTOP_POINTER                               = 0x01,
+  HID_USAGE_DESKTOP_MOUSE                                 = 0x02,
+  HID_USAGE_DESKTOP_JOYSTICK                              = 0x04,
+  HID_USAGE_DESKTOP_GAMEPAD                               = 0x05,
+  HID_USAGE_DESKTOP_KEYBOARD                              = 0x06,
+  HID_USAGE_DESKTOP_KEYPAD                                = 0x07,
+  HID_USAGE_DESKTOP_MULTI_AXIS_CONTROLLER                 = 0x08,
+  HID_USAGE_DESKTOP_TABLET_PC_SYSTEM                      = 0x09,
+  HID_USAGE_DESKTOP_X                                     = 0x30,
+  HID_USAGE_DESKTOP_Y                                     = 0x31,
+  HID_USAGE_DESKTOP_Z                                     = 0x32,
+  HID_USAGE_DESKTOP_RX                                    = 0x33,
+  HID_USAGE_DESKTOP_RY                                    = 0x34,
+  HID_USAGE_DESKTOP_RZ                                    = 0x35,
+  HID_USAGE_DESKTOP_SLIDER                                = 0x36,
+  HID_USAGE_DESKTOP_DIAL                                  = 0x37,
+  HID_USAGE_DESKTOP_WHEEL                                 = 0x38,
+  HID_USAGE_DESKTOP_HAT_SWITCH                            = 0x39,
+  HID_USAGE_DESKTOP_COUNTED_BUFFER                        = 0x3a,
+  HID_USAGE_DESKTOP_BYTE_COUNT                            = 0x3b,
+  HID_USAGE_DESKTOP_MOTION_WAKEUP                         = 0x3c,
+  HID_USAGE_DESKTOP_START                                 = 0x3d,
+  HID_USAGE_DESKTOP_SELECT                                = 0x3e,
+  HID_USAGE_DESKTOP_VX                                    = 0x40,
+  HID_USAGE_DESKTOP_VY                                    = 0x41,
+  HID_USAGE_DESKTOP_VZ                                    = 0x42,
+  HID_USAGE_DESKTOP_VBRX                                  = 0x43,
+  HID_USAGE_DESKTOP_VBRY                                  = 0x44,
+  HID_USAGE_DESKTOP_VBRZ                                  = 0x45,
+  HID_USAGE_DESKTOP_VNO                                   = 0x46,
+  HID_USAGE_DESKTOP_FEATURE_NOTIFICATION                  = 0x47,
+  HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER                 = 0x48,
+  HID_USAGE_DESKTOP_SYSTEM_CONTROL                        = 0x80,
+  HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN                     = 0x81,
+  HID_USAGE_DESKTOP_SYSTEM_SLEEP                          = 0x82,
+  HID_USAGE_DESKTOP_SYSTEM_WAKE_UP                        = 0x83,
+  HID_USAGE_DESKTOP_SYSTEM_CONTEXT_MENU                   = 0x84,
+  HID_USAGE_DESKTOP_SYSTEM_MAIN_MENU                      = 0x85,
+  HID_USAGE_DESKTOP_SYSTEM_APP_MENU                       = 0x86,
+  HID_USAGE_DESKTOP_SYSTEM_MENU_HELP                      = 0x87,
+  HID_USAGE_DESKTOP_SYSTEM_MENU_EXIT                      = 0x88,
+  HID_USAGE_DESKTOP_SYSTEM_MENU_SELECT                    = 0x89,
+  HID_USAGE_DESKTOP_SYSTEM_MENU_RIGHT                     = 0x8A,
+  HID_USAGE_DESKTOP_SYSTEM_MENU_LEFT                      = 0x8B,
+  HID_USAGE_DESKTOP_SYSTEM_MENU_UP                        = 0x8C,
+  HID_USAGE_DESKTOP_SYSTEM_MENU_DOWN                      = 0x8D,
+  HID_USAGE_DESKTOP_SYSTEM_COLD_RESTART                   = 0x8E,
+  HID_USAGE_DESKTOP_SYSTEM_WARM_RESTART                   = 0x8F,
+  HID_USAGE_DESKTOP_DPAD_UP                               = 0x90,
+  HID_USAGE_DESKTOP_DPAD_DOWN                             = 0x91,
+  HID_USAGE_DESKTOP_DPAD_RIGHT                            = 0x92,
+  HID_USAGE_DESKTOP_DPAD_LEFT                             = 0x93,
+  HID_USAGE_DESKTOP_SYSTEM_DOCK                           = 0xA0,
+  HID_USAGE_DESKTOP_SYSTEM_UNDOCK                         = 0xA1,
+  HID_USAGE_DESKTOP_SYSTEM_SETUP                          = 0xA2,
+  HID_USAGE_DESKTOP_SYSTEM_BREAK                          = 0xA3,
+  HID_USAGE_DESKTOP_SYSTEM_DEBUGGER_BREAK                 = 0xA4,
+  HID_USAGE_DESKTOP_APPLICATION_BREAK                     = 0xA5,
+  HID_USAGE_DESKTOP_APPLICATION_DEBUGGER_BREAK            = 0xA6,
+  HID_USAGE_DESKTOP_SYSTEM_SPEAKER_MUTE                   = 0xA7,
+  HID_USAGE_DESKTOP_SYSTEM_HIBERNATE                      = 0xA8,
+  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INVERT                 = 0xB0,
+  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INTERNAL               = 0xB1,
+  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_EXTERNAL               = 0xB2,
+  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_BOTH                   = 0xB3,
+  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_DUAL                   = 0xB4,
+  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_TOGGLE_INT_EXT         = 0xB5,
+  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_SWAP_PRIMARY_SECONDARY = 0xB6,
+  HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE          = 0xB7
+};
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_HID_H__ */
+
+/// @}
+/// @}

+ 304 - 304
tinyusb/class/hid_host.c

@@ -1,304 +1,304 @@
-/**************************************************************************/
-/*!
-    @file     hid_host.c
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-#include "tusb_option.h"
-
-#if (MODE_HOST_SUPPORTED && HOST_CLASS_HID)
-
-#define _TINY_USB_SOURCE_FILE_
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "common/common.h"
-#include "hid_host.h"
-
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
-
-//--------------------------------------------------------------------+
-// HID Interface common functions
-//--------------------------------------------------------------------+
-static inline tusb_error_t hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_descriptor_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
-static inline tusb_error_t hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_descriptor_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid)
-{
-  p_hid->pipe_hdl         = hcd_pipe_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID);
-  p_hid->report_size      = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor
-  p_hid->interface_number = interface_number;
-
-  ASSERT (pipehandle_is_valid(p_hid->pipe_hdl), TUSB_ERROR_HCD_FAILED);
-
-  return TUSB_ERROR_NONE;
-}
-
-static inline void hidh_interface_close(uint8_t dev_addr, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
-static inline void hidh_interface_close(uint8_t dev_addr, hidh_interface_info_t *p_hid)
-{
-  (void) hcd_pipe_close(p_hid->pipe_hdl);
-  memclr_(p_hid, sizeof(hidh_interface_info_t));
-}
-
-// called from public API need to validate parameters
-tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
-tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_info_t *p_hid)
-{
-  //------------- parameters validation -------------//
-  // TODO change to use is configured function
-  ASSERT_INT  (TUSB_DEVICE_STATE_CONFIGURED, tusbh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY);
-  ASSERT_PTR  (report, TUSB_ERROR_INVALID_PARA);
-  ASSERT_FALSE(hcd_pipe_is_busy(p_hid->pipe_hdl), TUSB_ERROR_INTERFACE_IS_BUSY);
-
-  ASSERT_STATUS( hcd_pipe_xfer(p_hid->pipe_hdl, report, p_hid->report_size, true) ) ;
-
-  return TUSB_ERROR_NONE;
-}
-
-//--------------------------------------------------------------------+
-// KEYBOARD
-//--------------------------------------------------------------------+
-#if TUSB_CFG_HOST_HID_KEYBOARD
-
-#define EXPAND_KEYCODE_TO_ASCII(keycode, ascii, shift_modified)  \
-  [0][keycode] = ascii,\
-  [1][keycode] = shift_modified,\
-
-// TODO size of table should be a macro for application to check boundary
-uint8_t const hid_keycode_to_ascii_tbl[2][128] =
-{
-    HID_KEYCODE_TABLE(EXPAND_KEYCODE_TO_ASCII)
-};
-
-STATIC_VAR hidh_interface_info_t keyboardh_data[TUSB_CFG_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1
-
-//------------- KEYBOARD PUBLIC API (parameter validation required) -------------//
-bool  tusbh_hid_keyboard_is_mounted(uint8_t dev_addr)
-{
-  return tusbh_device_is_configured(dev_addr) && pipehandle_is_valid(keyboardh_data[dev_addr-1].pipe_hdl);
-}
-
-tusb_error_t tusbh_hid_keyboard_get_report(uint8_t dev_addr, void* report)
-{
-  return hidh_interface_get_report(dev_addr, report, &keyboardh_data[dev_addr-1]);
-}
-
-bool tusbh_hid_keyboard_is_busy(uint8_t dev_addr)
-{
-  return  tusbh_hid_keyboard_is_mounted(dev_addr) &&
-          hcd_pipe_is_busy( keyboardh_data[dev_addr-1].pipe_hdl );
-}
-
-#endif
-
-//--------------------------------------------------------------------+
-// MOUSE
-//--------------------------------------------------------------------+
-#if TUSB_CFG_HOST_HID_MOUSE
-
-STATIC_VAR hidh_interface_info_t mouseh_data[TUSB_CFG_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1
-
-//------------- Public API -------------//
-bool tusbh_hid_mouse_is_mounted(uint8_t dev_addr)
-{
-  return tusbh_device_is_configured(dev_addr) && pipehandle_is_valid(mouseh_data[dev_addr-1].pipe_hdl);
-}
-
-bool tusbh_hid_mouse_is_busy(uint8_t dev_addr)
-{
-  return  tusbh_hid_mouse_is_mounted(dev_addr) &&
-          hcd_pipe_is_busy( mouseh_data[dev_addr-1].pipe_hdl );
-}
-
-tusb_error_t tusbh_hid_mouse_get_report(uint8_t dev_addr, void * report)
-{
-  return hidh_interface_get_report(dev_addr, report, &mouseh_data[dev_addr-1]);
-}
-
-#endif
-
-//--------------------------------------------------------------------+
-// GENERIC
-//--------------------------------------------------------------------+
-#if TUSB_CFG_HOST_HID_GENERIC
-
-//STATIC_ struct {
-//  hidh_interface_info_t
-//} generic_data[TUSB_CFG_HOST_DEVICE_MAX];
-
-#endif
-
-//--------------------------------------------------------------------+
-// CLASS-USBH API (don't require to verify parameters)
-//--------------------------------------------------------------------+
-void hidh_init(void)
-{
-#if TUSB_CFG_HOST_HID_KEYBOARD
-  memclr_(&keyboardh_data, sizeof(hidh_interface_info_t)*TUSB_CFG_HOST_DEVICE_MAX);
-#endif
-
-#if TUSB_CFG_HOST_HID_MOUSE
-  memclr_(&mouseh_data, sizeof(hidh_interface_info_t)*TUSB_CFG_HOST_DEVICE_MAX);
-#endif
-
-#if TUSB_CFG_HOST_HID_GENERIC
-  hidh_generic_init();
-#endif
-}
-
-#if 0
-uint8_t report_descriptor[256] TUSB_CFG_ATTR_USBRAM;
-#endif
-
-tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
-{
-  tusb_error_t error;
-  uint8_t const *p_desc = (uint8_t const *) p_interface_desc;
-
-  //------------- HID descriptor -------------//
-  p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
-  tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc;
-  ASSERT_INT(HID_DESC_TYPE_HID, p_desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA);
-
-  //------------- Endpoint Descriptor -------------//
-  p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
-  tusb_descriptor_endpoint_t const * p_endpoint_desc = (tusb_descriptor_endpoint_t const *) p_desc;
-  ASSERT_INT(TUSB_DESC_TYPE_ENDPOINT, p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA);
-
-  OSAL_SUBTASK_BEGIN
-
-  //------------- SET IDLE (0) request -------------//
-  OSAL_SUBTASK_INVOKED_AND_WAIT(
-    usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE),
-                               HID_REQUEST_CONTROL_SET_IDLE, 0, p_interface_desc->bInterfaceNumber,
-                               0, NULL ),
-    error
-  );
-
-#if 0
-  //------------- Get Report Descriptor TODO HID parser -------------//
-  if ( p_desc_hid->bNumDescriptors )
-  {
-    OSAL_SUBTASK_INVOKED_AND_WAIT(
-        usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_STANDARD, TUSB_REQUEST_RECIPIENT_INTERFACE),
-                                   TUSB_REQUEST_GET_DESCRIPTOR, (p_desc_hid->bReportType << 8), 0,
-                                   p_desc_hid->wReportLength, report_descriptor ),
-        error
-    );
-    // if error in getting report descriptor --> treating like there is none
-  }
-#endif
-
-  if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass )
-  {
-    #if TUSB_CFG_HOST_HID_KEYBOARD
-    if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol)
-    {
-      SUBTASK_ASSERT_STATUS ( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) );
-      tusbh_hid_keyboard_mounted_cb(dev_addr);
-    } else
-    #endif
-
-    #if TUSB_CFG_HOST_HID_MOUSE
-    if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol)
-    {
-      SUBTASK_ASSERT_STATUS ( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) );
-      tusbh_hid_mouse_mounted_cb(dev_addr);
-    } else
-    #endif
-
-    {
-      SUBTASK_EXIT(TUSB_ERROR_HIDH_NOT_SUPPORTED_PROTOCOL); // exit & restart task
-    }
-  }else
-  {
-    SUBTASK_EXIT(TUSB_ERROR_HIDH_NOT_SUPPORTED_SUBCLASS); // exit & restart task
-  }
-
-  *p_length = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_descriptor_endpoint_t);
-
-  OSAL_SUBTASK_END
-}
-
-void hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
-{
-#if TUSB_CFG_HOST_HID_KEYBOARD
-  if ( pipehandle_is_equal(pipe_hdl, keyboardh_data[pipe_hdl.dev_addr-1].pipe_hdl) )
-  {
-    tusbh_hid_keyboard_isr(pipe_hdl.dev_addr, event);
-    return;
-  }
-#endif
-
-#if TUSB_CFG_HOST_HID_MOUSE
-  if ( pipehandle_is_equal(pipe_hdl, mouseh_data[pipe_hdl.dev_addr-1].pipe_hdl) )
-  {
-    tusbh_hid_mouse_isr(pipe_hdl.dev_addr, event);
-    return;
-  }
-#endif
-
-#if TUSB_CFG_HOST_HID_GENERIC
-
-#endif
-}
-
-void hidh_close(uint8_t dev_addr)
-{
-#if TUSB_CFG_HOST_HID_KEYBOARD
-  if ( pipehandle_is_valid( keyboardh_data[dev_addr-1].pipe_hdl ) )
-  {
-    hidh_interface_close(dev_addr, &keyboardh_data[dev_addr-1]);
-    tusbh_hid_keyboard_unmounted_cb(dev_addr);
-  }
-#endif
-
-#if TUSB_CFG_HOST_HID_MOUSE
-  if( pipehandle_is_valid( mouseh_data[dev_addr-1].pipe_hdl ) )
-  {
-    hidh_interface_close(dev_addr, &mouseh_data[dev_addr-1]);
-    tusbh_hid_mouse_unmounted_cb( dev_addr );
-  }
-#endif
-
-#if TUSB_CFG_HOST_HID_GENERIC
-  hidh_generic_close(dev_addr);
-#endif
-}
-
-
-
-#endif
+/**************************************************************************/
+/*!
+    @file     hid_host.c
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#include "tusb_option.h"
+
+#if (MODE_HOST_SUPPORTED && HOST_CLASS_HID)
+
+#define _TINY_USB_SOURCE_FILE_
+//--------------------------------------------------------------------+
+// INCLUDE
+//--------------------------------------------------------------------+
+#include "common/common.h"
+#include "hid_host.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+
+//--------------------------------------------------------------------+
+// HID Interface common functions
+//--------------------------------------------------------------------+
+static inline tusb_error_t hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_descriptor_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
+static inline tusb_error_t hidh_interface_open(uint8_t dev_addr, uint8_t interface_number, tusb_descriptor_endpoint_t const *p_endpoint_desc, hidh_interface_info_t *p_hid)
+{
+  p_hid->pipe_hdl         = hcd_pipe_open(dev_addr, p_endpoint_desc, TUSB_CLASS_HID);
+  p_hid->report_size      = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor
+  p_hid->interface_number = interface_number;
+
+  ASSERT (pipehandle_is_valid(p_hid->pipe_hdl), TUSB_ERROR_HCD_FAILED);
+
+  return TUSB_ERROR_NONE;
+}
+
+static inline void hidh_interface_close(uint8_t dev_addr, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
+static inline void hidh_interface_close(uint8_t dev_addr, hidh_interface_info_t *p_hid)
+{
+  (void) hcd_pipe_close(p_hid->pipe_hdl);
+  memclr_(p_hid, sizeof(hidh_interface_info_t));
+}
+
+// called from public API need to validate parameters
+tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_info_t *p_hid) ATTR_ALWAYS_INLINE;
+tusb_error_t hidh_interface_get_report(uint8_t dev_addr, void * report, hidh_interface_info_t *p_hid)
+{
+  //------------- parameters validation -------------//
+  // TODO change to use is configured function
+  ASSERT_INT  (TUSB_DEVICE_STATE_CONFIGURED, tusbh_device_get_state(dev_addr), TUSB_ERROR_DEVICE_NOT_READY);
+  ASSERT_PTR  (report, TUSB_ERROR_INVALID_PARA);
+  ASSERT_FALSE(hcd_pipe_is_busy(p_hid->pipe_hdl), TUSB_ERROR_INTERFACE_IS_BUSY);
+
+  ASSERT_STATUS( hcd_pipe_xfer(p_hid->pipe_hdl, report, p_hid->report_size, true) ) ;
+
+  return TUSB_ERROR_NONE;
+}
+
+//--------------------------------------------------------------------+
+// KEYBOARD
+//--------------------------------------------------------------------+
+#if TUSB_CFG_HOST_HID_KEYBOARD
+
+#define EXPAND_KEYCODE_TO_ASCII(keycode, ascii, shift_modified)  \
+  [0][keycode] = ascii,\
+  [1][keycode] = shift_modified,\
+
+// TODO size of table should be a macro for application to check boundary
+uint8_t const hid_keycode_to_ascii_tbl[2][128] =
+{
+    HID_KEYCODE_TABLE(EXPAND_KEYCODE_TO_ASCII)
+};
+
+STATIC_VAR hidh_interface_info_t keyboardh_data[TUSB_CFG_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1
+
+//------------- KEYBOARD PUBLIC API (parameter validation required) -------------//
+bool  tusbh_hid_keyboard_is_mounted(uint8_t dev_addr)
+{
+  return tusbh_device_is_configured(dev_addr) && pipehandle_is_valid(keyboardh_data[dev_addr-1].pipe_hdl);
+}
+
+tusb_error_t tusbh_hid_keyboard_get_report(uint8_t dev_addr, void* p_report)
+{
+  return hidh_interface_get_report(dev_addr, p_report, &keyboardh_data[dev_addr-1]);
+}
+
+bool tusbh_hid_keyboard_is_busy(uint8_t dev_addr)
+{
+  return  tusbh_hid_keyboard_is_mounted(dev_addr) &&
+          hcd_pipe_is_busy( keyboardh_data[dev_addr-1].pipe_hdl );
+}
+
+#endif
+
+//--------------------------------------------------------------------+
+// MOUSE
+//--------------------------------------------------------------------+
+#if TUSB_CFG_HOST_HID_MOUSE
+
+STATIC_VAR hidh_interface_info_t mouseh_data[TUSB_CFG_HOST_DEVICE_MAX]; // does not have addr0, index = dev_address-1
+
+//------------- Public API -------------//
+bool tusbh_hid_mouse_is_mounted(uint8_t dev_addr)
+{
+  return tusbh_device_is_configured(dev_addr) && pipehandle_is_valid(mouseh_data[dev_addr-1].pipe_hdl);
+}
+
+bool tusbh_hid_mouse_is_busy(uint8_t dev_addr)
+{
+  return  tusbh_hid_mouse_is_mounted(dev_addr) &&
+          hcd_pipe_is_busy( mouseh_data[dev_addr-1].pipe_hdl );
+}
+
+tusb_error_t tusbh_hid_mouse_get_report(uint8_t dev_addr, void * report)
+{
+  return hidh_interface_get_report(dev_addr, report, &mouseh_data[dev_addr-1]);
+}
+
+#endif
+
+//--------------------------------------------------------------------+
+// GENERIC
+//--------------------------------------------------------------------+
+#if TUSB_CFG_HOST_HID_GENERIC
+
+//STATIC_ struct {
+//  hidh_interface_info_t
+//} generic_data[TUSB_CFG_HOST_DEVICE_MAX];
+
+#endif
+
+//--------------------------------------------------------------------+
+// CLASS-USBH API (don't require to verify parameters)
+//--------------------------------------------------------------------+
+void hidh_init(void)
+{
+#if TUSB_CFG_HOST_HID_KEYBOARD
+  memclr_(&keyboardh_data, sizeof(hidh_interface_info_t)*TUSB_CFG_HOST_DEVICE_MAX);
+#endif
+
+#if TUSB_CFG_HOST_HID_MOUSE
+  memclr_(&mouseh_data, sizeof(hidh_interface_info_t)*TUSB_CFG_HOST_DEVICE_MAX);
+#endif
+
+#if TUSB_CFG_HOST_HID_GENERIC
+  hidh_generic_init();
+#endif
+}
+
+#if 0
+uint8_t report_descriptor[256] TUSB_CFG_ATTR_USBRAM;
+#endif
+
+tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length)
+{
+  tusb_error_t error;
+  uint8_t const *p_desc = (uint8_t const *) p_interface_desc;
+
+  //------------- HID descriptor -------------//
+  p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
+  tusb_hid_descriptor_hid_t const *p_desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc;
+  ASSERT_INT(HID_DESC_TYPE_HID, p_desc_hid->bDescriptorType, TUSB_ERROR_INVALID_PARA);
+
+  //------------- Endpoint Descriptor -------------//
+  p_desc += p_desc[DESCRIPTOR_OFFSET_LENGTH];
+  tusb_descriptor_endpoint_t const * p_endpoint_desc = (tusb_descriptor_endpoint_t const *) p_desc;
+  ASSERT_INT(TUSB_DESC_TYPE_ENDPOINT, p_endpoint_desc->bDescriptorType, TUSB_ERROR_INVALID_PARA);
+
+  OSAL_SUBTASK_BEGIN
+
+  //------------- SET IDLE (0) request -------------//
+  OSAL_SUBTASK_INVOKED_AND_WAIT(
+    usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_HOST_TO_DEV, TUSB_REQUEST_TYPE_CLASS, TUSB_REQUEST_RECIPIENT_INTERFACE),
+                               HID_REQUEST_CONTROL_SET_IDLE, 0, p_interface_desc->bInterfaceNumber,
+                               0, NULL ),
+    error
+  );
+
+#if 0
+  //------------- Get Report Descriptor TODO HID parser -------------//
+  if ( p_desc_hid->bNumDescriptors )
+  {
+    OSAL_SUBTASK_INVOKED_AND_WAIT(
+        usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_DEV_TO_HOST, TUSB_REQUEST_TYPE_STANDARD, TUSB_REQUEST_RECIPIENT_INTERFACE),
+                                   TUSB_REQUEST_GET_DESCRIPTOR, (p_desc_hid->bReportType << 8), 0,
+                                   p_desc_hid->wReportLength, report_descriptor ),
+        error
+    );
+    // if error in getting report descriptor --> treating like there is none
+  }
+#endif
+
+  if ( HID_SUBCLASS_BOOT == p_interface_desc->bInterfaceSubClass )
+  {
+    #if TUSB_CFG_HOST_HID_KEYBOARD
+    if ( HID_PROTOCOL_KEYBOARD == p_interface_desc->bInterfaceProtocol)
+    {
+      SUBTASK_ASSERT_STATUS ( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &keyboardh_data[dev_addr-1]) );
+      tusbh_hid_keyboard_mounted_cb(dev_addr);
+    } else
+    #endif
+
+    #if TUSB_CFG_HOST_HID_MOUSE
+    if ( HID_PROTOCOL_MOUSE == p_interface_desc->bInterfaceProtocol)
+    {
+      SUBTASK_ASSERT_STATUS ( hidh_interface_open(dev_addr, p_interface_desc->bInterfaceNumber, p_endpoint_desc, &mouseh_data[dev_addr-1]) );
+      tusbh_hid_mouse_mounted_cb(dev_addr);
+    } else
+    #endif
+
+    {
+      SUBTASK_EXIT(TUSB_ERROR_HIDH_NOT_SUPPORTED_PROTOCOL); // exit & restart task
+    }
+  }else
+  {
+    SUBTASK_EXIT(TUSB_ERROR_HIDH_NOT_SUPPORTED_SUBCLASS); // exit & restart task
+  }
+
+  *p_length = sizeof(tusb_descriptor_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + sizeof(tusb_descriptor_endpoint_t);
+
+  OSAL_SUBTASK_END
+}
+
+void hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes)
+{
+#if TUSB_CFG_HOST_HID_KEYBOARD
+  if ( pipehandle_is_equal(pipe_hdl, keyboardh_data[pipe_hdl.dev_addr-1].pipe_hdl) )
+  {
+    tusbh_hid_keyboard_isr(pipe_hdl.dev_addr, event);
+    return;
+  }
+#endif
+
+#if TUSB_CFG_HOST_HID_MOUSE
+  if ( pipehandle_is_equal(pipe_hdl, mouseh_data[pipe_hdl.dev_addr-1].pipe_hdl) )
+  {
+    tusbh_hid_mouse_isr(pipe_hdl.dev_addr, event);
+    return;
+  }
+#endif
+
+#if TUSB_CFG_HOST_HID_GENERIC
+
+#endif
+}
+
+void hidh_close(uint8_t dev_addr)
+{
+#if TUSB_CFG_HOST_HID_KEYBOARD
+  if ( pipehandle_is_valid( keyboardh_data[dev_addr-1].pipe_hdl ) )
+  {
+    hidh_interface_close(dev_addr, &keyboardh_data[dev_addr-1]);
+    tusbh_hid_keyboard_unmounted_cb(dev_addr);
+  }
+#endif
+
+#if TUSB_CFG_HOST_HID_MOUSE
+  if( pipehandle_is_valid( mouseh_data[dev_addr-1].pipe_hdl ) )
+  {
+    hidh_interface_close(dev_addr, &mouseh_data[dev_addr-1]);
+    tusbh_hid_mouse_unmounted_cb( dev_addr );
+  }
+#endif
+
+#if TUSB_CFG_HOST_HID_GENERIC
+  hidh_generic_close(dev_addr);
+#endif
+}
+
+
+
+#endif

+ 213 - 119
tinyusb/class/hid_host.h

@@ -1,119 +1,213 @@
-/**************************************************************************/
-/*!
-    @file     hid_host.h
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \ingroup TBD
- *  \defgroup TBD
- *  \brief TBD
- *
- *  @{
- */
-
-#ifndef _TUSB_HID_HOST_H_
-#define _TUSB_HID_HOST_H_
-
-#include "common/common.h"
-#include "host/usbh.h"
-#include "hid.h"
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-//--------------------------------------------------------------------+
-// KEYBOARD Application API
-//--------------------------------------------------------------------+
-extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; // TODO used weak attr if build failed without KEYBOARD enabled
-
-bool          tusbh_hid_keyboard_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-bool          tusbh_hid_keyboard_is_busy(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-tusb_error_t  tusbh_hid_keyboard_get_report(uint8_t dev_addr, void * report) /*ATTR_WARN_UNUSED_RESULT*/;
-
-//------------- Application Callback -------------//
-void tusbh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event);
-void tusbh_hid_keyboard_mounted_cb(uint8_t dev_addr);
-void tusbh_hid_keyboard_unmounted_cb(uint8_t dev_addr);
-
-//--------------------------------------------------------------------+
-// MOUSE Application API
-//--------------------------------------------------------------------+
-bool          tusbh_hid_mouse_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-bool          tusbh_hid_mouse_is_busy(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-tusb_error_t  tusbh_hid_mouse_get_report(uint8_t dev_addr, void* report) /*ATTR_WARN_UNUSED_RESULT*/;
-
-//------------- Application Callback -------------//
-void tusbh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event);
-void tusbh_hid_mouse_mounted_cb(uint8_t dev_addr);
-void tusbh_hid_mouse_unmounted_cb(uint8_t dev_addr);
-
-//--------------------------------------------------------------------+
-// GENERIC Application API
-//--------------------------------------------------------------------+
-bool          tusbh_hid_generic_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-tusb_error_t  tusbh_hid_generic_get_report(uint8_t dev_addr, void* report, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
-tusb_error_t  tusbh_hid_generic_set_report(uint8_t dev_addr, void* report, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
-tusb_interface_status_t tusbh_hid_generic_get_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
-tusb_interface_status_t tusbh_hid_generic_set_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
-
-//------------- Application Callback -------------//
-void tusbh_hid_generic_isr(uint8_t dev_addr, tusb_event_t event);
-
-//--------------------------------------------------------------------+
-// USBH-CLASS DRIVER API
-//--------------------------------------------------------------------+
-#ifdef _TINY_USB_SOURCE_FILE_
-
-typedef struct {
-  pipe_handle_t pipe_hdl;
-  uint16_t report_size;
-  uint8_t interface_number;
-}hidh_interface_info_t;
-
-void         hidh_init(void);
-tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
-void         hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes);
-void         hidh_close(uint8_t dev_addr);
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TUSB_HID_HOST_H_ */
-
-/** @} */
+/**************************************************************************/
+/*!
+    @file     hid_host.h
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/** \addtogroup ClassDriver_HID
+ *  @{ */
+
+#ifndef _TUSB_HID_HOST_H_
+#define _TUSB_HID_HOST_H_
+
+#include "common/common.h"
+#include "host/usbh.h"
+#include "hid.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/** \defgroup hid_keyboard Keyboard
+ *  The interface API includes status checking function, data transferring function and callback functions
+ *  @{ */
+//--------------------------------------------------------------------+
+// KEYBOARD Application API
+//--------------------------------------------------------------------+
+extern uint8_t const hid_keycode_to_ascii_tbl[2][128]; // TODO used weak attr if build failed without KEYBOARD enabled
+
+/** \brief      Check if device supports Keyboard interface or not
+ * \param[in]   dev_addr    device address
+ * \retval      true if device supports Keyboard interface
+ * \retval      false if device does not support Keyboard interface or is not mounted
+ */
+bool          tusbh_hid_keyboard_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+/** \brief      Check if the interface is currently busy or not
+ * \param[in]   dev_addr device address
+ * \retval      true if the interface is busy meaning the stack is still transferring/waiting data from/to device
+ * \retval      false if the interface is not busy meaning the stack successfully transferred data from/to device
+ * \note        This function is primarily used for polling/waiting result after \ref tusbh_hid_keyboard_get_report.
+ *              Alternatively, asynchronous event API can be used
+ */
+bool          tusbh_hid_keyboard_is_busy(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+/** \brief        Perform a get report from Keyboard interface
+ * \param[in]		  dev_addr device address
+ * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref TUSB_CFG_ATTR_USBRAM)
+ * \returns       \ref tusb_error_t type to indicate success or error condition.
+ * \retval        TUSB_ERROR_NONE on success
+ * \retval        TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
+ * \retval        TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
+ * \retval        TUSB_ERROR_INVALID_PARA if inputs parameter are not correct
+ * \note          This function is non-blocking and returns immediately. The result of usb transfer will be reported by the interface's callback function
+ */
+tusb_error_t  tusbh_hid_keyboard_get_report(uint8_t dev_addr, void * p_report) /*ATTR_WARN_UNUSED_RESULT*/;
+
+//------------- Application Callback -------------//
+/** \brief      Callback function that is invoked when an transferring event occurred
+ * \param[in]		dev_addr	Address of device
+ * \param[in]   event an value from \ref tusb_event_t
+ * \note        event can be one of following
+ *              - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully.
+ *              - TUSB_EVENT_XFER_ERROR   : previously scheduled transfer encountered a transaction error.
+ *              - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device.
+ * \note        Application should schedule the next report by calling \ref tusbh_hid_keyboard_get_report within this callback
+ */
+void tusbh_hid_keyboard_isr(uint8_t dev_addr, tusb_event_t event);
+
+/** \brief 			Callback function that will be invoked when a device with Keyboard interface is mounted
+ * \param[in] 	dev_addr Address of newly mounted device
+ * \note        This callback should be used by Application to set-up interface-related data
+ */
+void tusbh_hid_keyboard_mounted_cb(uint8_t dev_addr);
+
+/** \brief 			Callback function that will be invoked when a device with Keyboard interface is unmounted
+ * \param[in] 	dev_addr Address of newly unmounted device
+ * \note        This callback should be used by Application to tear-down interface-related data
+ */
+void tusbh_hid_keyboard_unmounted_cb(uint8_t dev_addr);
+/** @} */
+
+/** \defgroup hid_mouse Mouse
+ *  The interface API includes status checking function, data transferring function and callback functions
+ *  @{ */
+//--------------------------------------------------------------------+
+// MOUSE Application API
+//--------------------------------------------------------------------+
+/** \brief      Check if device supports Mouse interface or not
+ * \param[in]   dev_addr    device address
+ * \retval      true if device supports Mouse interface
+ * \retval      false if device does not support Mouse interface or is not mounted
+ */
+bool          tusbh_hid_mouse_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+/** \brief      Check if the interface is currently busy or not
+ * \param[in]   dev_addr device address
+ * \retval      true if the interface is busy meaning the stack is still transferring/waiting data from/to device
+ * \retval      false if the interface is not busy meaning the stack successfully transferred data from/to device
+ * \note        This function is primarily used for polling/waiting result after \ref tusbh_hid_mouse_get_report.
+ *              Alternatively, asynchronous event API can be used
+ */
+bool          tusbh_hid_mouse_is_busy(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+/** \brief        Perform a get report from Mouse interface
+ * \param[in]		  dev_addr device address
+ * \param[in,out] p_report address that is used to store data from device. Must be accessible by usb controller (see \ref TUSB_CFG_ATTR_USBRAM)
+ * \returns       \ref tusb_error_t type to indicate success or error condition.
+ * \retval        TUSB_ERROR_NONE on success
+ * \retval        TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
+ * \retval        TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
+ * \retval        TUSB_ERROR_INVALID_PARA if inputs parameter are not correct
+ * \note          This function is non-blocking and returns immediately. The result of usb transfer will be reported by the interface's callback function
+ */
+tusb_error_t  tusbh_hid_mouse_get_report(uint8_t dev_addr, void* p_report) /*ATTR_WARN_UNUSED_RESULT*/;
+
+//------------- Application Callback -------------//
+/** \brief      Callback function that is invoked when an transferring event occurred
+ * \param[in]		dev_addr	Address of device
+ * \param[in]   event an value from \ref tusb_event_t
+ * \note        event can be one of following
+ *              - TUSB_EVENT_XFER_COMPLETE : previously scheduled transfer completes successfully.
+ *              - TUSB_EVENT_XFER_ERROR   : previously scheduled transfer encountered a transaction error.
+ *              - TUSB_EVENT_XFER_STALLED : previously scheduled transfer is stalled by device.
+ * \note        Application should schedule the next report by calling \ref tusbh_hid_mouse_get_report within this callback
+ */
+void tusbh_hid_mouse_isr(uint8_t dev_addr, tusb_event_t event);
+
+/** \brief 			Callback function that will be invoked when a device with Mouse interface is mounted
+ * \param[in]	  dev_addr Address of newly mounted device
+ * \note        This callback should be used by Application to set-up interface-related data
+ */
+void tusbh_hid_mouse_mounted_cb(uint8_t dev_addr);
+
+/** \brief 			Callback function that will be invoked when a device with Mouse  interface is unmounted
+ * \param[in] 	dev_addr Address of newly unmounted device
+ * \note        This callback should be used by Application to tear-down interface-related data
+ */
+void tusbh_hid_mouse_unmounted_cb(uint8_t dev_addr);
+/** @} */
+
+/** \defgroup hid_generic Generic (not supported yet)
+ * The interface API includes status checking function, data transferring function and callback functions
+ *  @{ */
+//--------------------------------------------------------------------+
+// GENERIC Application API
+//--------------------------------------------------------------------+
+bool          tusbh_hid_generic_is_mounted(uint8_t dev_addr) ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+tusb_error_t  tusbh_hid_generic_get_report(uint8_t dev_addr, void* p_report, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
+tusb_error_t  tusbh_hid_generic_set_report(uint8_t dev_addr, void* p_report, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
+tusb_interface_status_t tusbh_hid_generic_get_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
+tusb_interface_status_t tusbh_hid_generic_set_status(uint8_t dev_addr) ATTR_WARN_UNUSED_RESULT;
+
+//------------- Application Callback -------------//
+void tusbh_hid_generic_isr(uint8_t dev_addr, tusb_event_t event);
+/** @} */
+
+//--------------------------------------------------------------------+
+// USBH-CLASS DRIVER API
+//--------------------------------------------------------------------+
+#ifdef _TINY_USB_SOURCE_FILE_
+
+typedef struct {
+  pipe_handle_t pipe_hdl;
+  uint16_t report_size;
+  uint8_t interface_number;
+}hidh_interface_info_t;
+
+void         hidh_init(void);
+tusb_error_t hidh_open_subtask(uint8_t dev_addr, tusb_descriptor_interface_t const *p_interface_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
+void         hidh_isr(pipe_handle_t pipe_hdl, tusb_event_t event, uint32_t xferred_bytes);
+void         hidh_close(uint8_t dev_addr);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TUSB_HID_HOST_H_ */
+
+/** @} */

+ 39 - 0
tinyusb/doxygen/configuration.h

@@ -0,0 +1,39 @@
+/** \addtogroup group_configuration
+ *  @{ */
+
+/**
+  USB controller in MCU often has limited access to specific RAM section. The Stack will use this macro to place internal variables
+  into the USB RAM section as follows. if your mcu's usb controller has no such limit, define TUSB_CFG_ATTR_USBRAM as empty macro.
+
+  @code
+  uint8_t tinyusb_data[10] TUSB_CFG_ATTR_USBRAM;
+  @endcode
+ */
+#define TUSB_CFG_ATTR_USBRAM
+
+
+/** \defgroup TUSB_CFG_HOST Host
+ *  @{ */
+
+/// Maximum number of device host stack can manage
+/// - If hub class is not enabled, set this equal to number of controllers in host mode
+/// - if hub class is enabled, make sure hub is also counted
+#define TUSB_CFG_HOST_DEVICE_MAX
+
+/// Buffer size used for getting device configuration descriptor. You may want to increase this from default
+/// to support lengthy composite device especially with Audio or Video class
+#define TUSB_CFG_HOST_ENUM_BUFFER_SIZE
+
+#define TUSB_CFG_HOST_HUB           ///< Enable Hub Class
+#define TUSB_CFG_HOST_HID_KEYBOARD  ///< Enable HID Class for Keyboard
+#define TUSB_CFG_HOST_HID_MOUSE     ///< Enable HID Class for Mouse
+#define TUSB_CFG_HOST_HID_GENERIC   ///< Enable HID Class for Generic (not supported yet)
+#define TUSB_CFG_HOST_MSC           ///< Enable Mass Storage Class (SCSI subclass only)
+#define TUSB_CFG_HOST_CDC           ///< Enable Virtual Serial (Communication Device Class)
+#define TUSB_CFG_HOST_CDC_RNDIS     ///< Enable Remote Network Device (require TUSB_CFG_HOST_CDC to be enabled)
+
+/** @} */ // group Host
+
+
+
+/** @} */

+ 0 - 3
tinyusb/doxygen/overview.md

@@ -1,3 +0,0 @@
-# What is tinyUSB
-
-![tinyUSB diagram](overview.png)

+ 123 - 123
tinyusb/hal/hal_lpc43xx.c

@@ -1,123 +1,123 @@
-/**************************************************************************/
-/*!
-    @file     hal_lpc43xx.c
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-#include "common/common.h"
-#include "hal.h"
-
-#if MCU == MCU_LPC43XX
-
-#include "lpc43xx_cgu.h"
-#include "lpc43xx_scu.h"
-
-enum {
-  LPC43XX_USBMODE_DEVICE = 2,
-  LPC43XX_USBMODE_HOST   = 3
-};
-
-enum {
-  LPC43XX_USBMODE_VBUS_LOW  = 0,
-  LPC43XX_USBMODE_VBUS_HIGH = 1
-};
-
-tusb_error_t hal_init(void)
-{
-  //------------- USB0 Clock -------------//
-#if TUSB_CFG_CONTROLLER0_MODE
-  CGU_EnableEntity(CGU_CLKSRC_PLL0, DISABLE); /* Disable PLL first */
-  ASSERT_INT( CGU_ERROR_SUCCESS, CGU_SetPLL0(), TUSB_ERROR_FAILED); /* the usb core require output clock = 480MHz */
-  CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL0);
-  CGU_EnableEntity(CGU_CLKSRC_PLL0, ENABLE);   /* Enable PLL after all setting is done */
-  LPC_CREG->CREG0 &= ~(1<<5); /* Turn on the phy */
-
-  // reset controller & set role
-  #if TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_HOST
-    hcd_controller_reset(0); // TODO where to place prototype
-    LPC_USB0->USBMODE_H = LPC43XX_USBMODE_HOST | (LPC43XX_USBMODE_VBUS_HIGH << 5);
-  #else // TODO OTG
-//    dcd_controller_reset(0);
-//    LPC_USB0->USBMODE_D = LPC43XX_USBMODE_DEVICE;
-//    LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/;
-//    LPC_USB0->PORTSC1_D |= (1<<24); // force full speed
-//    dcd_controller_connect(0);
-  #endif
-
-  hal_interrupt_enable(0);
-#endif
-
-  //------------- USB1 Clock, only use on-chip FS PHY -------------//
-#if TUSB_CFG_CONTROLLER1_MODE
-  // TODO confirm whether device mode require P2_5 or not
-  scu_pinmux(0x2, 5, MD_PLN | MD_EZI | MD_ZI, FUNC2);	// USB1_VBUS monitor presence, must be high for bus reset occur
-
-  /* connect CLK_USB1 to 60 MHz clock */
-  CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_USB1); /* FIXME Run base BASE_USB1_CLK clock from PLL1 (assume PLL1 is 60 MHz, no division required) */
-  //LPC_CREG->CREG0 &= ~(1<<5); /* Turn on the phy */
-  LPC_SCU->SFSUSB = (TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST) ? 0x16 : 0x12; // enable USB1 with on-chip FS PHY
-
-  #if TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST
-    hcd_controller_reset(1); // TODO where to place prototype
-    LPC_USB1->USBMODE_H = LPC43XX_USBMODE_HOST | (LPC43XX_USBMODE_VBUS_HIGH << 5);
-  #else // TODO OTG
-//    dcd_controller_reset(1);
-    LPC_USB0->USBMODE_D = LPC43XX_USBMODE_DEVICE;
-    dcd_controller_connect(1);
-  #endif
-
-  LPC_USB1->PORTSC1_D |= (1<<24); // TODO abtract, force port to fullspeed
-
-  hal_interrupt_enable(1);
-#endif
-
-  return TUSB_ERROR_NONE;
-}
-
-#if TUSB_CFG_CONTROLLER0_MODE
-void USB0_IRQHandler(void)
-{
-  tusb_isr(0);
-}
-#endif
-
-#if TUSB_CFG_CONTROLLER1_MODE
-void USB1_IRQHandler(void)
-{
-  tusb_isr(1);
-}
-#endif
-
-#endif
+/**************************************************************************/
+/*!
+    @file     hal_lpc43xx.c
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#include "common/common.h"
+#include "hal.h"
+
+#if MCU == MCU_LPC43XX
+
+#include "lpc43xx_cgu.h"
+#include "lpc43xx_scu.h"
+
+enum {
+  LPC43XX_USBMODE_DEVICE = 2,
+  LPC43XX_USBMODE_HOST   = 3
+};
+
+enum {
+  LPC43XX_USBMODE_VBUS_LOW  = 0,
+  LPC43XX_USBMODE_VBUS_HIGH = 1
+};
+
+tusb_error_t hal_init(void)
+{
+  //------------- USB0 Clock -------------//
+#if TUSB_CFG_CONTROLLER_0_MODE
+  CGU_EnableEntity(CGU_CLKSRC_PLL0, DISABLE); /* Disable PLL first */
+  ASSERT_INT( CGU_ERROR_SUCCESS, CGU_SetPLL0(), TUSB_ERROR_FAILED); /* the usb core require output clock = 480MHz */
+  CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL0);
+  CGU_EnableEntity(CGU_CLKSRC_PLL0, ENABLE);   /* Enable PLL after all setting is done */
+  LPC_CREG->CREG0 &= ~(1<<5); /* Turn on the phy */
+
+  // reset controller & set role
+  #if TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_HOST
+    hcd_controller_reset(0); // TODO where to place prototype
+    LPC_USB0->USBMODE_H = LPC43XX_USBMODE_HOST | (LPC43XX_USBMODE_VBUS_HIGH << 5);
+  #else // TODO OTG
+//    dcd_controller_reset(0);
+//    LPC_USB0->USBMODE_D = LPC43XX_USBMODE_DEVICE;
+//    LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/;
+//    LPC_USB0->PORTSC1_D |= (1<<24); // force full speed
+//    dcd_controller_connect(0);
+  #endif
+
+  hal_interrupt_enable(0);
+#endif
+
+  //------------- USB1 Clock, only use on-chip FS PHY -------------//
+#if TUSB_CFG_CONTROLLER_1_MODE
+  // TODO confirm whether device mode require P2_5 or not
+  scu_pinmux(0x2, 5, MD_PLN | MD_EZI | MD_ZI, FUNC2);	// USB1_VBUS monitor presence, must be high for bus reset occur
+
+  /* connect CLK_USB1 to 60 MHz clock */
+  CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_USB1); /* FIXME Run base BASE_USB1_CLK clock from PLL1 (assume PLL1 is 60 MHz, no division required) */
+  //LPC_CREG->CREG0 &= ~(1<<5); /* Turn on the phy */
+  LPC_SCU->SFSUSB = (TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST) ? 0x16 : 0x12; // enable USB1 with on-chip FS PHY
+
+  #if TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST
+    hcd_controller_reset(1); // TODO where to place prototype
+    LPC_USB1->USBMODE_H = LPC43XX_USBMODE_HOST | (LPC43XX_USBMODE_VBUS_HIGH << 5);
+  #else // TODO OTG
+//    dcd_controller_reset(1);
+    LPC_USB0->USBMODE_D = LPC43XX_USBMODE_DEVICE;
+    dcd_controller_connect(1);
+  #endif
+
+  LPC_USB1->PORTSC1_D |= (1<<24); // TODO abtract, force port to fullspeed
+
+  hal_interrupt_enable(1);
+#endif
+
+  return TUSB_ERROR_NONE;
+}
+
+#if TUSB_CFG_CONTROLLER_0_MODE
+void USB0_IRQHandler(void)
+{
+  tusb_isr(0);
+}
+#endif
+
+#if TUSB_CFG_CONTROLLER_1_MODE
+void USB1_IRQHandler(void)
+{
+  tusb_isr(1);
+}
+#endif
+
+#endif

+ 1098 - 1098
tinyusb/host/ehci/ehci.c

@@ -1,1098 +1,1098 @@
-/**************************************************************************/
-/*!
-    @file     ehci.c
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-#include "common/common.h"
-
-#if MODE_HOST_SUPPORTED && (MCU == MCU_LPC43XX || MCU == MCU_LPC18XX)
-//--------------------------------------------------------------------+
-// INCLUDE
-//--------------------------------------------------------------------+
-#include "hal/hal.h"
-#include "osal/osal.h"
-#include "common/timeout_timer.h"
-
-#include "../hcd.h"
-#include "../usbh_hcd.h"
-#include "ehci.h"
-
-//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
-//--------------------------------------------------------------------+
-
-//--------------------------------------------------------------------+
-// INTERNAL OBJECT & FUNCTION DECLARATION
-//--------------------------------------------------------------------+
-STATIC_VAR ehci_data_t ehci_data TUSB_CFG_ATTR_USBRAM;
-
-#if EHCI_PERIODIC_LIST
-
-  #if (TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_HOST)
-  ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list0[EHCI_FRAMELIST_SIZE] TUSB_CFG_ATTR_USBRAM;
-
-    #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma
-    STATIC_ASSERT( ALIGN_OF(period_frame_list0) == 4096, "Period Framelist must be 4k alginment"); // validation
-    #endif
-  #endif
-
-  #if (TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST)
-  STATIC_VAR ehci_link_t period_frame_list1[EHCI_FRAMELIST_SIZE] ATTR_ALIGNED(4096) TUSB_CFG_ATTR_USBRAM;
-
-    #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma
-    STATIC_ASSERT( ALIGN_OF(period_frame_list1) == 4096, "Period Framelist must be 4k alginment"); // validation
-    #endif
-  #endif
-#endif
-
-//------------- Validation -------------//
-// TODO static assert for memory placement on some known MCU such as lpc43xx
-
-//--------------------------------------------------------------------+
-// PROTOTYPE
-//--------------------------------------------------------------------+
-STATIC_ INLINE_ ehci_registers_t*  get_operational_register(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
-STATIC_ INLINE_ ehci_link_t*       get_period_frame_list(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
-STATIC_ INLINE_ uint8_t            hostid_to_data_idx(uint8_t hostid) ATTR_ALWAYS_INLINE ATTR_CONST ATTR_WARN_UNUSED_RESULT;
-
-STATIC_ INLINE_ ehci_qhd_t*  get_async_head(uint8_t hostid) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-STATIC_ INLINE_ ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-
-STATIC_ INLINE_ ehci_qhd_t* get_control_qhd(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-STATIC_ INLINE_ ehci_qtd_t* get_control_qtds(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
-
-static inline uint8_t        qhd_get_index(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
-static inline ehci_qhd_t*    qhd_next(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
-static inline ehci_qhd_t*    qhd_find_free (uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE;
-static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
-STATIC_ INLINE_ ehci_qhd_t*  qhd_get_from_pipe_handle(pipe_handle_t pipe_hdl) ATTR_PURE ATTR_ALWAYS_INLINE;
-static inline pipe_handle_t  qhd_create_pipe_handle(ehci_qhd_t const * p_qhd, tusb_xfer_type_t xfer_type) ATTR_PURE ATTR_ALWAYS_INLINE;
-// determine if a queue head has bus-related error
-static inline bool qhd_has_xact_error(ehci_qhd_t * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
-static inline bool qhd_has_xact_error(ehci_qhd_t * p_qhd)
-{
-  return ( p_qhd->qtd_overlay.buffer_err ||p_qhd->qtd_overlay.babble_err || p_qhd->qtd_overlay.xact_err );
-  //p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error
-}
-
-static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval);
-
-
-STATIC_ INLINE_ ehci_qtd_t*  qtd_find_free(uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE;
-static inline ehci_qtd_t*    qtd_next(ehci_qtd_t const * p_qtd ) ATTR_PURE ATTR_ALWAYS_INLINE;
-static inline void           qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) ATTR_ALWAYS_INLINE;
-static inline void           qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) ATTR_ALWAYS_INLINE;
-static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes);
-
-static inline void  list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type) ATTR_ALWAYS_INLINE;
-static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) ATTR_PURE ATTR_ALWAYS_INLINE;
-static ehci_link_t*  list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_current);
-static tusb_error_t list_remove_qhd(ehci_link_t* p_head, ehci_link_t* p_remove);
-
-static tusb_error_t hcd_controller_init(uint8_t hostid) ATTR_WARN_UNUSED_RESULT;
-static tusb_error_t hcd_controller_stop(uint8_t hostid) ATTR_WARN_UNUSED_RESULT;
-
-//--------------------------------------------------------------------+
-// USBH-HCD API
-//--------------------------------------------------------------------+
-tusb_error_t hcd_init(void)
-{
-  //------------- Data Structure init -------------//
-  memclr_(&ehci_data, sizeof(ehci_data_t));
-
-  #if (TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_HOST)
-    ASSERT_STATUS (hcd_controller_init(0));
-  #endif
-
-  #if (TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST)
-    ASSERT_STATUS (hcd_controller_init(1));
-  #endif
-
-  return TUSB_ERROR_NONE;
-}
-
-//--------------------------------------------------------------------+
-// PORT API
-//--------------------------------------------------------------------+
-void hcd_port_reset(uint8_t hostid)
-{
-  ehci_registers_t* const regs = get_operational_register(hostid);
-
-  regs->portsc_bit.port_enable = 0; // disable port before reset
-  regs->portsc_bit.port_reset = 1;
-
-#ifndef _TEST_
-  // NXP specific, port reset will automatically be 0 when reset sequence complete
-  // there is chance device is unplugged while reset sequence is not complete
-  while( regs->portsc_bit.port_reset) {} // TODO use task delay to remove blocking
-#endif
-}
-
-bool hcd_port_connect_status(uint8_t hostid)
-{
-  return get_operational_register(hostid)->portsc_bit.current_connect_status;
-}
-
-tusb_speed_t hcd_port_speed_get(uint8_t hostid)
-{
-  return (tusb_speed_t) get_operational_register(hostid)->portsc_bit.nxp_port_speed; // NXP specific port speed
-}
-
-//--------------------------------------------------------------------+
-// Controller API
-//--------------------------------------------------------------------+
-static tusb_error_t hcd_controller_init(uint8_t hostid)
-{
-  ehci_registers_t* const regs = get_operational_register(hostid);
-
-  //------------- CTRLDSSEGMENT Register (skip) -------------//
-  //------------- USB INT Register -------------//
-  regs->usb_int_enable = 0;                 // 1. disable all the interrupt
-#ifndef _TEST_ // the fake controller does not have write-to-clear behavior
-  regs->usb_sts        = EHCI_INT_MASK_ALL; // 2. clear all status
-#endif
-  regs->usb_int_enable = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE |
-#if EHCI_PERIODIC_LIST
-                         EHCI_INT_MASK_NXP_PERIODIC |
-#endif
-                         EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_ASYNC;
-
-  //------------- Asynchronous List -------------//
-  ehci_qhd_t * const async_head = get_async_head(hostid);
-  memclr_(async_head, sizeof(ehci_qhd_t));
-
-  async_head->next.address                    = (uint32_t) async_head; // circular list, next is itself
-  async_head->next.type                       = EHCI_QUEUE_ELEMENT_QHD;
-  async_head->head_list_flag                  = 1;
-  async_head->qtd_overlay.halted              = 1; // inactive most of time
-  async_head->qtd_overlay.next.terminate      = 1; // TODO removed if verified
-
-  regs->async_list_base = (uint32_t) async_head;
-
-#if EHCI_PERIODIC_LIST
-  //------------- Periodic List -------------//
-  // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only
-
-  for(uint32_t i=0; i<4; i++)
-  {
-    ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ][i].interrupt_smask    = 1; // queue head in period list must have smask non-zero
-    ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ][i].qtd_overlay.halted = 1; // dummy node, always inactive
-  }
-
-  ehci_link_t * const framelist  = get_period_frame_list(hostid);
-  ehci_link_t * const period_1ms = get_period_head(hostid, 1);
-  // all links --> period_head_arr[0] (1ms)
-  // 0, 2, 4, 6 etc --> period_head_arr[1] (2ms)
-  // 1, 5 --> period_head_arr[2] (4ms)
-  // 3 --> period_head_arr[3] (8ms)
-
-  // TODO EHCI_FRAMELIST_SIZE with other size than 8
-  for(uint32_t i=0; i<EHCI_FRAMELIST_SIZE; i++)
-  {
-    framelist[i].address = (uint32_t) period_1ms;
-    framelist[i].type    = EHCI_QUEUE_ELEMENT_QHD;
-  }
-
-  for(uint32_t i=0; i<EHCI_FRAMELIST_SIZE; i+=2)
-  {
-    list_insert(framelist + i, get_period_head(hostid, 2), EHCI_QUEUE_ELEMENT_QHD);
-  }
-
-  for(uint32_t i=1; i<EHCI_FRAMELIST_SIZE; i+=4)
-  {
-    list_insert(framelist + i, get_period_head(hostid, 4), EHCI_QUEUE_ELEMENT_QHD);
-  }
-
-  list_insert(framelist+3, get_period_head(hostid, 8), EHCI_QUEUE_ELEMENT_QHD);
-
-  period_1ms->terminate    = 1;
-
-  regs->periodic_list_base = (uint32_t) framelist;
-#else
-  regs->periodic_list_base = 0;
-#endif
-
-  //------------- TT Control (NXP only) -------------//
-  regs->tt_control = 0;
-
-  //------------- USB CMD Register -------------//
-
-  regs->usb_cmd |= BIT_(EHCI_USBCMD_POS_RUN_STOP) | BIT_(EHCI_USBCMD_POS_ASYNC_ENABLE)
-#if EHCI_PERIODIC_LIST
-                  | BIT_(EHCI_USBCMD_POS_PERIOD_ENABLE) // TODO enable period list only there is int/iso endpoint
-#endif
-                  | ((EHCI_CFG_FRAMELIST_SIZE_BITS & BIN8(011)) << EHCI_USBCMD_POS_FRAMELIST_SZIE)
-                  | ((EHCI_CFG_FRAMELIST_SIZE_BITS >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB);
-
-  //------------- ConfigFlag Register (skip) -------------//
-
-  regs->portsc_bit.port_power = 1; // enable port power
-
-  return TUSB_ERROR_NONE;
-}
-
-static tusb_error_t hcd_controller_stop(uint8_t hostid)
-{
-  ehci_registers_t* const regs = get_operational_register(hostid);
-  timeout_timer_t timeout;
-
-  regs->usb_cmd_bit.run_stop = 0;
-
-  timeout_set(&timeout, 2); // USB Spec: controller has to stop within 16 uframe = 2 frames
-  while( regs->usb_sts_bit.hc_halted == 0 && !timeout_expired(&timeout)) {}
-
-  return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE;
-}
-
-tusb_error_t hcd_controller_reset(uint8_t hostid)
-{
-  ehci_registers_t* const regs = get_operational_register(hostid);
-  timeout_timer_t timeout;
-
-// NXP chip powered with non-host mode --> sts bit is not correctly reflected
-  regs->usb_cmd_bit.reset = 1;
-
-  timeout_set(&timeout, 2); // should not take longer the time to stop controller
-  while( regs->usb_cmd_bit.reset && !timeout_expired(&timeout)) {}
-
-  return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE;
-}
-
-//--------------------------------------------------------------------+
-// CONTROL PIPE API
-//--------------------------------------------------------------------+
-tusb_error_t  hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size)
-{
-  ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
-
-  qhd_init(p_qhd, dev_addr, max_packet_size, 0, TUSB_XFER_CONTROL, 1); // TODO binterval of control is ignored
-
-  if (dev_addr != 0)
-  {
-    //------------- insert to async list -------------//
-    // TODO might need to to disable async list first
-    list_insert( (ehci_link_t*) get_async_head(usbh_devices[dev_addr].core_id),
-                 (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
-  }
-
-  return TUSB_ERROR_NONE;
-}
-
-tusb_error_t  hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[])
-{
-  ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
-
-  ehci_qtd_t *p_setup      = get_control_qtds(dev_addr);
-  ehci_qtd_t *p_data       = p_setup + 1;
-  ehci_qtd_t *p_status     = p_setup + 2;
-
-  //------------- SETUP Phase -------------//
-  qtd_init(p_setup, (uint32_t) p_request, 8);
-  p_setup->pid          = EHCI_PID_SETUP;
-  p_setup->next.address = (uint32_t) p_data;
-
-  //------------- DATA Phase -------------//
-  if (p_request->wLength > 0)
-  {
-    qtd_init(p_data, (uint32_t) data, p_request->wLength);
-    p_data->data_toggle = 1;
-    p_data->pid         = p_request->bmRequestType_bit.direction ? EHCI_PID_IN : EHCI_PID_OUT;
-  }else
-  {
-    p_data = p_setup;
-  }
-  p_data->next.address = (uint32_t) p_status;
-
-  //------------- STATUS Phase -------------//
-  qtd_init(p_status, 0, 0); // zero-length data
-  p_status->int_on_complete = 1;
-  p_status->data_toggle     = 1;
-  p_status->pid             = p_request->bmRequestType_bit.direction ? EHCI_PID_OUT : EHCI_PID_IN; // reverse direction of data phase
-  p_status->next.terminate  = 1;
-
-  //------------- Attach TDs list to Control Endpoint -------------//
-  p_qhd->p_qtd_list_head = p_setup;
-  p_qhd->p_qtd_list_tail = p_status;
-
-  p_qhd->qtd_overlay.next.address = (uint32_t) p_setup;
-
-  return TUSB_ERROR_NONE;
-}
-
-tusb_error_t  hcd_pipe_control_close(uint8_t dev_addr)
-{
-  //------------- TODO pipe handle validate -------------//
-  ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
-
-  p_qhd->is_removing = 1;
-
-  if (dev_addr != 0)
-  {
-    ASSERT_STATUS( list_remove_qhd( (ehci_link_t*) get_async_head( usbh_devices[dev_addr].core_id ),
-                                    (ehci_link_t*) p_qhd) );
-  }
-
-  return TUSB_ERROR_NONE;
-}
-
-//--------------------------------------------------------------------+
-// BULK/INT/ISO PIPE API
-//--------------------------------------------------------------------+
-pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code)
-{
-  pipe_handle_t const null_handle = { .dev_addr = 0, .xfer_type = 0, .index = 0 };
-
-  ASSERT(dev_addr > 0, null_handle);
-
-  if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
-    return null_handle; // TODO not support ISO yet
-
-  //------------- Prepare Queue Head -------------//
-  ehci_qhd_t * const p_qhd = qhd_find_free(dev_addr);
-  ASSERT_PTR(p_qhd, null_handle);
-
-  qhd_init( p_qhd, dev_addr, p_endpoint_desc->wMaxPacketSize.size, p_endpoint_desc->bEndpointAddress,
-            p_endpoint_desc->bmAttributes.xfer, p_endpoint_desc->bInterval );
-  p_qhd->class_code = class_code;
-
-  //------------- Insert to Async List -------------//
-  ehci_link_t * list_head;
-
-  if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_BULK)
-  {
-    list_head = (ehci_link_t*) get_async_head(usbh_devices[dev_addr].core_id);
-  }
-  #if EHCI_PERIODIC_LIST // TODO refractor/group this together
-  else if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_INTERRUPT)
-  {
-    list_head = get_period_head(usbh_devices[dev_addr].core_id, p_qhd->interval_ms);
-  }
-  #endif
-
-  //------------- insert to async/period list TODO might need to disable async/period list -------------//
-  list_insert( list_head,
-               (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
-
-  return (pipe_handle_t) { .dev_addr = dev_addr, .xfer_type = p_endpoint_desc->bmAttributes.xfer, .index = qhd_get_index(p_qhd) };
-}
-
-tusb_error_t  hcd_pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes)
-{
-  //------------- TODO pipe handle validate -------------//
-
-  //------------- set up QTD -------------//
-  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(pipe_hdl);
-  ehci_qtd_t *p_qtd = qtd_find_free(pipe_hdl.dev_addr);
-
-  ASSERT_PTR(p_qtd, TUSB_ERROR_EHCI_NOT_ENOUGH_QTD);
-
-  qtd_init(p_qtd, (uint32_t) buffer, total_bytes);
-  p_qtd->pid = p_qhd->pid_non_control;
-
-  //------------- insert TD to TD list -------------//
-  qtd_insert_to_qhd(p_qhd, p_qtd);
-
-  return TUSB_ERROR_NONE;
-}
-
-tusb_error_t  hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete)
-{
-  ASSERT_STATUS ( hcd_pipe_queue_xfer(pipe_hdl, buffer, total_bytes) );
-
-  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(pipe_hdl);
-
-  if ( int_on_complete )
-  { // the just added qtd is pointed by list_tail
-    p_qhd->p_qtd_list_tail->int_on_complete = 1;
-  }
-  p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; // attach to queue head to start transferring
-
-  return TUSB_ERROR_NONE;
-}
-
-/// pipe_close should only be called as a part of unmount/safe-remove process
-tusb_error_t  hcd_pipe_close(pipe_handle_t pipe_hdl)
-{
-  ASSERT(pipe_hdl.dev_addr > 0, TUSB_ERROR_INVALID_PARA);
-
-  ASSERT(pipe_hdl.xfer_type != TUSB_XFER_ISOCHRONOUS, TUSB_ERROR_INVALID_PARA);
-
-  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
-
-  // async list needs async advance handshake to make sure host controller has released cached data
-  // non-control does not use async advance, it will eventually free by control pipe close
-  // period list queue element is guarantee to be free in the next frame (1 ms)
-  p_qhd->is_removing = 1; // TODO redundant, only apply to control queue head
-
-  if ( pipe_hdl.xfer_type == TUSB_XFER_BULK )
-  {
-    ASSERT_STATUS( list_remove_qhd(
-        (ehci_link_t*) get_async_head( usbh_devices[pipe_hdl.dev_addr].core_id ),
-        (ehci_link_t*) p_qhd) );
-  }
-  #if EHCI_PERIODIC_LIST // TODO refractor/group this together
-  else
-  {
-    ASSERT_STATUS( list_remove_qhd(
-        get_period_head( usbh_devices[pipe_hdl.dev_addr].core_id, p_qhd->interval_ms ),
-        (ehci_link_t*) p_qhd) );
-  }
-  #endif
-
-  return TUSB_ERROR_NONE;
-}
-
-bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl)
-{
-  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
-  return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL);
-}
-
-bool hcd_pipe_is_error(pipe_handle_t pipe_hdl)
-{
-  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
-  return p_qhd->qtd_overlay.halted;
-}
-
-bool hcd_pipe_is_idle(pipe_handle_t pipe_hdl)
-{ // TODO to be remove
-  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
-  return (p_qhd->p_qtd_list_head == NULL);
-}
-
-bool hcd_pipe_is_stalled(pipe_handle_t pipe_hdl)
-{
-  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
-  return p_qhd->qtd_overlay.halted && !qhd_has_xact_error(p_qhd);
-}
-
-uint8_t hcd_pipe_get_endpoint_addr(pipe_handle_t pipe_hdl)
-{
-  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
-  return p_qhd->endpoint_number + ( (p_qhd->pid_non_control == EHCI_PID_IN) ? 0x80 : 0);
-}
-
-tusb_error_t hcd_pipe_clear_stall(pipe_handle_t pipe_hdl)
-{
-  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
-  p_qhd->qtd_overlay.halted = 0;
-
-  return TUSB_ERROR_NONE;
-}
-
-//--------------------------------------------------------------------+
-// EHCI Interrupt Handler
-//--------------------------------------------------------------------+
-
-// async_advance is handshake between sw stack & ehci controller where ehci free all memory from an deleted queue head.
-// In tinyusb, queue head is only removed when device is unplugged. So only control queue head is checked if removing
-static void async_advance_isr(ehci_qhd_t * const async_head)
-{
-  // TODO do we need to close addr0
-  if (async_head->is_removing) // closing control pipe of addr0
-  {
-    async_head->is_removing        = 0;
-    async_head->p_qtd_list_head    = async_head->p_qtd_list_tail = NULL;
-    async_head->qtd_overlay.halted = 1;
-
-    usbh_devices[0].state          = TUSB_DEVICE_STATE_UNPLUG;
-  }
-
-  for(uint8_t relative_dev_addr=0; relative_dev_addr < TUSB_CFG_HOST_DEVICE_MAX; relative_dev_addr++)
-  {
-    // check if control endpoint is removing
-    ehci_qhd_t *p_control_qhd = &ehci_data.device[relative_dev_addr].control.qhd;
-    if ( p_control_qhd->is_removing )
-    {
-      p_control_qhd->is_removing = 0;
-      p_control_qhd->used        = 0;
-
-      // Host Controller has cleaned up its cached data for this device, set state to unplug
-      usbh_devices[relative_dev_addr+1].state = TUSB_DEVICE_STATE_UNPLUG;
-
-      for (uint8_t i=0; i<EHCI_MAX_QHD; i++) // free all qhd
-      {
-        ehci_data.device[relative_dev_addr].qhd[i].used        = 0;
-        ehci_data.device[relative_dev_addr].qhd[i].is_removing = 0;
-      }
-      for (uint8_t i=0; i<EHCI_MAX_QTD; i++) // free all qtd
-      {
-        ehci_data.device[relative_dev_addr].qtd[i].used = 0;
-      }
-      // TODO free all itd & sitd
-    }
-  } // end for device[] loop
-}
-
-static void port_connect_status_change_isr(uint8_t hostid)
-{
-  ehci_registers_t* const regs = get_operational_register(hostid);
-
-  // NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device
-  if (regs->portsc_bit.current_connect_status)
-  {
-    usbh_hcd_rhport_plugged_isr(hostid);
-  }else // device unplugged
-  {
-    usbh_hcd_rhport_unplugged_isr(hostid);
-//    regs->usb_cmd_bit.advacne_async = 1; // Async doorbell check EHCI 4.8.2 for operational details
-  }
-}
-
-// TODO refractor abtract later
-void hcd_port_unplug(uint8_t hostid)
-{
-	ehci_registers_t* const regs = get_operational_register(hostid);
-  regs->usb_cmd_bit.advacne_async = 1; // Async doorbell check EHCI 4.8.2 for operational details
-}
-
-static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
-{
-  uint8_t max_loop = 0;
-  tusb_xfer_type_t const xfer_type = qhd_get_xfer_type(p_qhd);
-
-  // free all TDs from the head td to the first active TD
-  while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active
-      && max_loop < EHCI_MAX_QTD)
-  {
-    // TD need to be freed and removed from qhd, before invoking callback
-    bool is_ioc = (p_qhd->p_qtd_list_head->int_on_complete != 0);
-    p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes;
-
-    p_qhd->p_qtd_list_head->used = 0; // free QTD
-    qtd_remove_1st_from_qhd(p_qhd);
-
-    if (is_ioc) // end of request
-    { // call USBH callback
-      usbh_xfer_isr( qhd_create_pipe_handle(p_qhd, xfer_type),
-                     p_qhd->class_code, TUSB_EVENT_XFER_COMPLETE,
-                     p_qhd->total_xferred_bytes - (xfer_type == TUSB_XFER_CONTROL ? 8 : 0) ); // subtract setup packet size if control,
-      p_qhd->total_xferred_bytes = 0;
-    }
-
-    max_loop++;
-  }
-}
-
-static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head)
-{
-  uint8_t max_loop = 0;
-  ehci_qhd_t *p_qhd = async_head;
-  do
-  {
-    if ( !p_qhd->qtd_overlay.halted ) // halted or error is processed in error isr
-    {
-      qhd_xfer_complete_isr(p_qhd);
-    }
-    p_qhd = qhd_next(p_qhd);
-    max_loop++;
-  }while(p_qhd != async_head && max_loop < EHCI_MAX_QHD); // async list traversal, stop if loop around
-  // TODO abstract max loop guard for async
-}
-
-#if EHCI_PERIODIC_LIST // TODO refractor/group this together
-static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms)
-{
-  uint8_t max_loop = 0;
-  uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
-  ehci_link_t next_item = * get_period_head(hostid, interval_ms);
-
-  // TODO abstract max loop guard for period
-  while( !next_item.terminate &&
-      !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) &&
-      max_loop < (EHCI_MAX_QHD + EHCI_MAX_ITD + EHCI_MAX_SITD))
-  {
-    switch ( next_item.type )
-    {
-      case EHCI_QUEUE_ELEMENT_QHD:
-      {
-        ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address);
-        if ( !p_qhd_int->qtd_overlay.halted )
-        {
-          qhd_xfer_complete_isr(p_qhd_int);
-        }
-      }
-      break;
-
-      case EHCI_QUEUE_ELEMENT_ITD:
-      case EHCI_QUEUE_ELEMENT_SITD:
-      case EHCI_QUEUE_ELEMENT_FSTN:
-      default:
-        ASSERT (false, VOID_RETURN); // TODO support hs/fs ISO
-      break;
-    }
-
-    next_item = *list_next(&next_item);
-    max_loop++;
-  }
-}
-#endif
-
-static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
-{
-  if ( (p_qhd->device_address != 0 && p_qhd->qtd_overlay.halted) || // addr0 cannot be protocol STALL
-        qhd_has_xact_error(p_qhd) )
-  { // current qhd has error in transaction
-    tusb_xfer_type_t const xfer_type = qhd_get_xfer_type(p_qhd);
-    tusb_event_t error_event;
-
-    // no error bits are set, endpoint is halted due to STALL
-    error_event = qhd_has_xact_error(p_qhd) ? TUSB_EVENT_XFER_ERROR : TUSB_EVENT_XFER_STALLED;
-
-    p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes;
-
-    // TODO skip unplugged device
-    if ( TUSB_EVENT_XFER_ERROR == error_event )    hal_debugger_breakpoint();
-
-    p_qhd->p_qtd_list_head->used = 0; // free QTD
-    qtd_remove_1st_from_qhd(p_qhd);
-
-    if ( TUSB_XFER_CONTROL == xfer_type )
-    {
-      p_qhd->total_xferred_bytes -= min8_of(8, p_qhd->total_xferred_bytes); // subtract setup size
-
-      // control cannot be halted --> clear all qtd list
-      p_qhd->p_qtd_list_head = NULL;
-      p_qhd->p_qtd_list_tail = NULL;
-
-      p_qhd->qtd_overlay.next.terminate      = 1;
-      p_qhd->qtd_overlay.alternate.terminate = 1;
-      p_qhd->qtd_overlay.halted              = 0;
-
-      ehci_qtd_t *p_setup  = get_control_qtds(p_qhd->device_address);
-      ehci_qtd_t *p_data   = p_setup + 1;
-      ehci_qtd_t *p_status = p_setup + 2;
-
-      p_setup->used = p_data->used = p_status->used = 0;
-    }
-
-    // call USBH callback
-    usbh_xfer_isr( qhd_create_pipe_handle(p_qhd, xfer_type),
-                   p_qhd->class_code, error_event,
-                   p_qhd->total_xferred_bytes);
-
-    p_qhd->total_xferred_bytes = 0;
-  }
-}
-
-static void xfer_error_isr(uint8_t hostid)
-{
-  //------------- async list -------------//
-  uint8_t max_loop = 0;
-  ehci_qhd_t * const async_head = get_async_head(hostid);
-  ehci_qhd_t *p_qhd = async_head;
-  do
-  {
-    qhd_xfer_error_isr( p_qhd );
-    p_qhd = qhd_next(p_qhd);
-    max_loop++;
-  }while(p_qhd != async_head && max_loop < EHCI_MAX_QHD); // async list traversal, stop if loop around
-
-  #if EHCI_PERIODIC_LIST
-  //------------- TODO refractor period list -------------//
-  uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
-  for (uint8_t interval_ms=1; interval_ms <= EHCI_FRAMELIST_SIZE; interval_ms *= 2)
-  {
-    uint8_t period_max_loop = 0;
-    ehci_link_t next_item = * get_period_head(hostid, interval_ms);
-
-    // TODO abstract max loop guard for period
-    while( !next_item.terminate &&
-        !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) &&
-        period_max_loop < (EHCI_MAX_QHD + EHCI_MAX_ITD + EHCI_MAX_SITD))
-    {
-      switch ( next_item.type )
-      {
-        case EHCI_QUEUE_ELEMENT_QHD:
-        {
-          ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address);
-          qhd_xfer_error_isr(p_qhd_int);
-        }
-        break;
-
-        case EHCI_QUEUE_ELEMENT_ITD:
-        case EHCI_QUEUE_ELEMENT_SITD:
-        case EHCI_QUEUE_ELEMENT_FSTN:
-        default:
-          ASSERT (false, VOID_RETURN); // TODO support hs/fs ISO
-        break;
-      }
-
-      next_item = *list_next(&next_item);
-      period_max_loop++;
-    }
-  }
-  #endif
-}
-
-//------------- Host Controller Driver's Interrupt Handler -------------//
-void hcd_isr(uint8_t hostid)
-{
-  ehci_registers_t* const regs = get_operational_register(hostid);
-
-  uint32_t int_status = regs->usb_sts;
-  int_status &= regs->usb_int_enable;
-  
-  regs->usb_sts |= int_status; // Acknowledge handled interrupt
-
-  if (int_status == 0)
-    return;
-
-  if (int_status & EHCI_INT_MASK_PORT_CHANGE)
-  {
-    uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL;
-
-    if (regs->portsc_bit.connect_status_change)
-    {
-      port_connect_status_change_isr(hostid);
-    }
-
-    regs->portsc |= port_status; // Acknowledge change bits in portsc
-  }
-
-  if (int_status & EHCI_INT_MASK_ERROR)
-  {
-    xfer_error_isr(hostid);
-  }
-
-  //------------- some QTD/SITD/ITD with IOC set is completed -------------//
-  if (int_status & EHCI_INT_MASK_NXP_ASYNC)
-  {
-    async_list_xfer_complete_isr( get_async_head(hostid) );
-  }
-
-#if EHCI_PERIODIC_LIST // TODO refractor/group this together
-  if (int_status & EHCI_INT_MASK_NXP_PERIODIC)
-  {
-    for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2)
-    {
-      period_list_xfer_complete_isr( hostid, i );
-    }
-  }
-#endif
-
-  //------------- There is some removed async previously -------------//
-  if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC
-  {
-    async_advance_isr( get_async_head(hostid) );
-  }
-}
-
-//--------------------------------------------------------------------+
-// HELPER
-//--------------------------------------------------------------------+
-STATIC_ INLINE_ ehci_registers_t* get_operational_register(uint8_t hostid)
-{
-  return (ehci_registers_t*) (hostid ? (&LPC_USB1->USBCMD_H) : (&LPC_USB0->USBCMD_H) );
-}
-
-#if EHCI_PERIODIC_LIST // TODO refractor/group this together
-STATIC_ INLINE_ ehci_link_t* get_period_frame_list(uint8_t hostid)
-{
-  switch(hostid)
-  {
-#if (TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_HOST)
-    case 0:
-      return period_frame_list0;
-#endif
-
-#if (TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST)
-    case 1:
-      return period_frame_list1;
-#endif
-	 
-    default: return NULL;
-  }
-}
-#endif
-
-STATIC_ INLINE_ uint8_t hostid_to_data_idx(uint8_t hostid)
-{
-  #if (CONTROLLER_HOST_NUMBER == 1) && (TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST)
-    (void) hostid;
-    return 0;
-  #else
-    return hostid;
-  #endif
-}
-
-//------------- queue head helper -------------//
-STATIC_ INLINE_ ehci_qhd_t* get_async_head(uint8_t hostid)
-{
-  return &ehci_data.async_head[ hostid_to_data_idx(hostid) ];
-}
-
-#if EHCI_PERIODIC_LIST // TODO refractor/group this together
-STATIC_ INLINE_ ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms)
-{
-  return (ehci_link_t*) (&ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ]
-                                                    [ log2_of( min8_of(EHCI_FRAMELIST_SIZE, interval_ms) ) ] );
-}
-#endif
-
-STATIC_ INLINE_ ehci_qhd_t* get_control_qhd(uint8_t dev_addr)
-{
-  return (dev_addr == 0) ?
-      get_async_head( usbh_devices[dev_addr].core_id ) :
-      &ehci_data.device[dev_addr-1].control.qhd;
-}
-STATIC_ INLINE_ ehci_qtd_t* get_control_qtds(uint8_t dev_addr)
-{
-  return (dev_addr == 0) ?
-      ehci_data.addr0_qtd :
-      ehci_data.device[ dev_addr-1 ].control.qtd;
-
-}
-
-static inline ehci_qhd_t* qhd_find_free (uint8_t dev_addr)
-{
-  uint8_t relative_address = dev_addr-1;
-  uint8_t index=0;
-  while( index<EHCI_MAX_QHD && ehci_data.device[relative_address].qhd[index].used )
-  {
-    index++;
-  }
-  return (index < EHCI_MAX_QHD) ? &ehci_data.device[relative_address].qhd[index] : NULL;
-}
-
-static inline uint8_t qhd_get_index(ehci_qhd_t const * p_qhd)
-{
-  return p_qhd - ehci_data.device[p_qhd->device_address-1].qhd;
-}
-static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd)
-{
-  return  ( p_qhd->endpoint_number == 0 ) ? TUSB_XFER_CONTROL :
-          ( p_qhd->interrupt_smask != 0 ) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK;
-}
-
-static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd)
-{
-  return (ehci_qhd_t*) align32(p_qhd->next.address);
-}
-
-STATIC_ INLINE_ ehci_qhd_t* qhd_get_from_pipe_handle(pipe_handle_t pipe_hdl)
-{
-  return &ehci_data.device[ pipe_hdl.dev_addr-1 ].qhd[ pipe_hdl.index ];
-}
-
-static inline pipe_handle_t qhd_create_pipe_handle(ehci_qhd_t const * p_qhd, tusb_xfer_type_t xfer_type)
-{
-  pipe_handle_t pipe_hdl = {
-      .dev_addr  = p_qhd->device_address,
-      .xfer_type = xfer_type
-  };
-
-  // TODO Isochronous transfer support
-  if (TUSB_XFER_CONTROL != xfer_type) // qhd index for control is meaningless
-  {
-    pipe_hdl.index = qhd_get_index(p_qhd);
-  }
-
-  return pipe_hdl;
-}
-
-//------------- TD helper -------------//
-STATIC_ INLINE_ ehci_qtd_t* qtd_find_free(uint8_t dev_addr)
-{
-  uint8_t index=0;
-  while( index<EHCI_MAX_QTD && ehci_data.device[dev_addr-1].qtd[index].used )
-  {
-    index++;
-  }
-
-  return (index < EHCI_MAX_QTD) ? &ehci_data.device[dev_addr-1].qtd[index] : NULL;
-}
-
-static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd )
-{
-  return (ehci_qtd_t*) align32(p_qtd->next.address);
-}
-
-static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd)
-{
-  if (p_qhd->p_qtd_list_head == p_qhd->p_qtd_list_tail) // last TD --> make it NULL
-  {
-    p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = NULL;
-  }else
-  {
-    p_qhd->p_qtd_list_head = qtd_next( p_qhd->p_qtd_list_head );
-  }
-}
-
-static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new)
-{
-  if (p_qhd->p_qtd_list_head == NULL) // empty list
-  {
-    p_qhd->p_qtd_list_head               = p_qhd->p_qtd_list_tail = p_qtd_new;
-  }else
-  {
-    p_qhd->p_qtd_list_tail->next.address = (uint32_t) p_qtd_new;
-    p_qhd->p_qtd_list_tail               = p_qtd_new;
-  }
-}
-
-static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval)
-{
-  // address 0 uses async head, which always on the list --> cannot be cleared (ehci halted otherwise)
-  if (dev_addr != 0)
-  {
-    memclr_(p_qhd, sizeof(ehci_qhd_t));
-  }
-
-  p_qhd->device_address                   = dev_addr;
-  p_qhd->non_hs_period_inactive_next_xact = 0;
-  p_qhd->endpoint_number                  = endpoint_addr & 0x0F;
-  p_qhd->endpoint_speed                   = usbh_devices[dev_addr].speed;
-  p_qhd->data_toggle_control              = (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0;
-  p_qhd->head_list_flag                   = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head
-  p_qhd->max_package_size                 = max_packet_size;
-  p_qhd->non_hs_control_endpoint          = ((TUSB_XFER_CONTROL == xfer_type) && (p_qhd->endpoint_speed != TUSB_SPEED_HIGH))  ? 1 : 0;
-  p_qhd->nak_count_reload                 = 0;
-
-  // Bulk/Control -> smask = cmask = 0
-  // TODO Isochronous
-  if (TUSB_XFER_INTERRUPT == xfer_type)
-  {
-    if (TUSB_SPEED_HIGH == p_qhd->endpoint_speed)
-    {
-      ASSERT_INT_WITHIN(1, 16, interval, VOID_RETURN);
-      if ( interval < 4) // sub milisecond interval
-      {
-        p_qhd->interval_ms     = 0;
-        p_qhd->interrupt_smask = (interval == 1) ? BIN8(11111111) :
-                                 (interval == 2) ? BIN8(10101010) : BIN8(01000100);
-      }else
-      {
-        p_qhd->interval_ms     = (uint8_t) min16_of( 1 << (interval-4), 255 );
-        p_qhd->interrupt_smask = BIT_(interval % 8);
-      }
-    }else
-    {
-      ASSERT( 0 != interval, VOID_RETURN);
-      // Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes
-      p_qhd->interrupt_smask        = 0x01;
-      p_qhd->non_hs_interrupt_cmask = BIN8(11100);
-      p_qhd->interval_ms            = interval;
-    }
-  }else
-  {
-    p_qhd->interrupt_smask = p_qhd->non_hs_interrupt_cmask = 0;
-  }
-
-  p_qhd->hub_address             = usbh_devices[dev_addr].hub_addr;
-  p_qhd->hub_port                = usbh_devices[dev_addr].hub_port;
-  p_qhd->mult                    = 1; // TODO not use high bandwidth/park mode yet
-
-  //------------- HCD Management Data -------------//
-  p_qhd->used            = 1;
-  p_qhd->is_removing     = 0;
-  p_qhd->p_qtd_list_head = NULL;
-  p_qhd->p_qtd_list_tail = NULL;
-  p_qhd->pid_non_control = (endpoint_addr & 0x80) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint
-
-  //------------- active, but no TD list -------------//
-  p_qhd->qtd_overlay.halted              = 0;
-  p_qhd->qtd_overlay.next.terminate      = 1;
-  p_qhd->qtd_overlay.alternate.terminate = 1;
-  if (TUSB_XFER_BULK == xfer_type && p_qhd->endpoint_speed == TUSB_SPEED_HIGH && p_qhd->pid_non_control == EHCI_PID_OUT)
-  {
-    p_qhd->qtd_overlay.pingstate_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11
-  }
-}
-
-static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes)
-{
-  memclr_(p_qtd, sizeof(ehci_qtd_t));
-
-  p_qtd->used                = 1;
-
-  p_qtd->next.terminate      = 1; // init to null
-  p_qtd->alternate.terminate = 1; // not used, always set to terminated
-  p_qtd->active              = 1;
-  p_qtd->cerr                = 3; // TODO 3 consecutive errors tolerance
-  p_qtd->data_toggle         = 0;
-  p_qtd->total_bytes         = total_bytes;
-  p_qtd->expected_bytes      = total_bytes;
-
-  p_qtd->buffer[0]           = data_ptr;
-  for(uint8_t i=1; i<5; i++)
-  {
-    p_qtd->buffer[i] |= align4k( p_qtd->buffer[i-1] ) + 4096;
-  }
-}
-
-//------------- List Managing Helper -------------//
-static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type)
-{
-  new->address = current->address;
-  current->address = ((uint32_t) new) | (new_type << 1);
-}
-
-static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer)
-{
-  return (ehci_link_t*) align32(p_link_pointer->address);
-}
-
-static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_current)
-{
-  ehci_link_t *p_prev = p_head;
-  uint32_t max_loop = 0;
-  while( (align32(p_prev->address) != (uint32_t) p_head)    && // not loop around
-         (align32(p_prev->address) != (uint32_t) p_current) && // not found yet
-         !p_prev->terminate                                 && // not advanceable
-         max_loop < EHCI_MAX_QHD)
-  {
-    p_prev = list_next(p_prev);
-    max_loop++;
-  }
-
-  return  (align32(p_prev->address) != (uint32_t) p_head) ? p_prev : NULL;
-}
-
-static tusb_error_t list_remove_qhd(ehci_link_t* p_head, ehci_link_t* p_remove)
-{
-  ehci_link_t *p_prev = list_find_previous_item(p_head, p_remove);
-
-  ASSERT_PTR(p_prev, TUSB_ERROR_INVALID_PARA);
-
-  p_prev->address   = p_remove->address;
-  // EHCI 4.8.2 link the removing queue head to async/period head (which always reachable by Host Controller)
-  p_remove->address = ((uint32_t) p_head) | (EHCI_QUEUE_ELEMENT_QHD << 1);
-
-  return TUSB_ERROR_NONE;
-}
-
-#endif
+/**************************************************************************/
+/*!
+    @file     ehci.c
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#include "common/common.h"
+
+#if MODE_HOST_SUPPORTED && (MCU == MCU_LPC43XX || MCU == MCU_LPC18XX)
+//--------------------------------------------------------------------+
+// INCLUDE
+//--------------------------------------------------------------------+
+#include "hal/hal.h"
+#include "osal/osal.h"
+#include "common/timeout_timer.h"
+
+#include "../hcd.h"
+#include "../usbh_hcd.h"
+#include "ehci.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+
+//--------------------------------------------------------------------+
+// INTERNAL OBJECT & FUNCTION DECLARATION
+//--------------------------------------------------------------------+
+STATIC_VAR ehci_data_t ehci_data TUSB_CFG_ATTR_USBRAM;
+
+#if EHCI_PERIODIC_LIST
+
+  #if (TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_HOST)
+  ATTR_ALIGNED(4096) STATIC_VAR ehci_link_t period_frame_list0[EHCI_FRAMELIST_SIZE] TUSB_CFG_ATTR_USBRAM;
+
+    #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma
+    STATIC_ASSERT( ALIGN_OF(period_frame_list0) == 4096, "Period Framelist must be 4k alginment"); // validation
+    #endif
+  #endif
+
+  #if (TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST)
+  STATIC_VAR ehci_link_t period_frame_list1[EHCI_FRAMELIST_SIZE] ATTR_ALIGNED(4096) TUSB_CFG_ATTR_USBRAM;
+
+    #ifndef __ICCARM__ // IAR cannot able to determine the alignment with datalignment pragma
+    STATIC_ASSERT( ALIGN_OF(period_frame_list1) == 4096, "Period Framelist must be 4k alginment"); // validation
+    #endif
+  #endif
+#endif
+
+//------------- Validation -------------//
+// TODO static assert for memory placement on some known MCU such as lpc43xx
+
+//--------------------------------------------------------------------+
+// PROTOTYPE
+//--------------------------------------------------------------------+
+STATIC_ INLINE_ ehci_registers_t*  get_operational_register(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+STATIC_ INLINE_ ehci_link_t*       get_period_frame_list(uint8_t hostid) ATTR_PURE ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+STATIC_ INLINE_ uint8_t            hostid_to_data_idx(uint8_t hostid) ATTR_ALWAYS_INLINE ATTR_CONST ATTR_WARN_UNUSED_RESULT;
+
+STATIC_ INLINE_ ehci_qhd_t*  get_async_head(uint8_t hostid) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+STATIC_ INLINE_ ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+STATIC_ INLINE_ ehci_qhd_t* get_control_qhd(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+STATIC_ INLINE_ ehci_qtd_t* get_control_qtds(uint8_t dev_addr) ATTR_ALWAYS_INLINE ATTR_PURE ATTR_WARN_UNUSED_RESULT;
+
+static inline uint8_t        qhd_get_index(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
+static inline ehci_qhd_t*    qhd_next(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
+static inline ehci_qhd_t*    qhd_find_free (uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE;
+static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
+STATIC_ INLINE_ ehci_qhd_t*  qhd_get_from_pipe_handle(pipe_handle_t pipe_hdl) ATTR_PURE ATTR_ALWAYS_INLINE;
+static inline pipe_handle_t  qhd_create_pipe_handle(ehci_qhd_t const * p_qhd, tusb_xfer_type_t xfer_type) ATTR_PURE ATTR_ALWAYS_INLINE;
+// determine if a queue head has bus-related error
+static inline bool qhd_has_xact_error(ehci_qhd_t * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
+static inline bool qhd_has_xact_error(ehci_qhd_t * p_qhd)
+{
+  return ( p_qhd->qtd_overlay.buffer_err ||p_qhd->qtd_overlay.babble_err || p_qhd->qtd_overlay.xact_err );
+  //p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error
+}
+
+static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval);
+
+
+STATIC_ INLINE_ ehci_qtd_t*  qtd_find_free(uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE;
+static inline ehci_qtd_t*    qtd_next(ehci_qtd_t const * p_qtd ) ATTR_PURE ATTR_ALWAYS_INLINE;
+static inline void           qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) ATTR_ALWAYS_INLINE;
+static inline void           qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd) ATTR_ALWAYS_INLINE;
+static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes);
+
+static inline void  list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type) ATTR_ALWAYS_INLINE;
+static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer) ATTR_PURE ATTR_ALWAYS_INLINE;
+static ehci_link_t*  list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_current);
+static tusb_error_t list_remove_qhd(ehci_link_t* p_head, ehci_link_t* p_remove);
+
+static tusb_error_t hcd_controller_init(uint8_t hostid) ATTR_WARN_UNUSED_RESULT;
+static tusb_error_t hcd_controller_stop(uint8_t hostid) ATTR_WARN_UNUSED_RESULT;
+
+//--------------------------------------------------------------------+
+// USBH-HCD API
+//--------------------------------------------------------------------+
+tusb_error_t hcd_init(void)
+{
+  //------------- Data Structure init -------------//
+  memclr_(&ehci_data, sizeof(ehci_data_t));
+
+  #if (TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_HOST)
+    ASSERT_STATUS (hcd_controller_init(0));
+  #endif
+
+  #if (TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST)
+    ASSERT_STATUS (hcd_controller_init(1));
+  #endif
+
+  return TUSB_ERROR_NONE;
+}
+
+//--------------------------------------------------------------------+
+// PORT API
+//--------------------------------------------------------------------+
+void hcd_port_reset(uint8_t hostid)
+{
+  ehci_registers_t* const regs = get_operational_register(hostid);
+
+  regs->portsc_bit.port_enable = 0; // disable port before reset
+  regs->portsc_bit.port_reset = 1;
+
+#ifndef _TEST_
+  // NXP specific, port reset will automatically be 0 when reset sequence complete
+  // there is chance device is unplugged while reset sequence is not complete
+  while( regs->portsc_bit.port_reset) {} // TODO use task delay to remove blocking
+#endif
+}
+
+bool hcd_port_connect_status(uint8_t hostid)
+{
+  return get_operational_register(hostid)->portsc_bit.current_connect_status;
+}
+
+tusb_speed_t hcd_port_speed_get(uint8_t hostid)
+{
+  return (tusb_speed_t) get_operational_register(hostid)->portsc_bit.nxp_port_speed; // NXP specific port speed
+}
+
+//--------------------------------------------------------------------+
+// Controller API
+//--------------------------------------------------------------------+
+static tusb_error_t hcd_controller_init(uint8_t hostid)
+{
+  ehci_registers_t* const regs = get_operational_register(hostid);
+
+  //------------- CTRLDSSEGMENT Register (skip) -------------//
+  //------------- USB INT Register -------------//
+  regs->usb_int_enable = 0;                 // 1. disable all the interrupt
+#ifndef _TEST_ // the fake controller does not have write-to-clear behavior
+  regs->usb_sts        = EHCI_INT_MASK_ALL; // 2. clear all status
+#endif
+  regs->usb_int_enable = EHCI_INT_MASK_ERROR | EHCI_INT_MASK_PORT_CHANGE |
+#if EHCI_PERIODIC_LIST
+                         EHCI_INT_MASK_NXP_PERIODIC |
+#endif
+                         EHCI_INT_MASK_ASYNC_ADVANCE | EHCI_INT_MASK_NXP_ASYNC;
+
+  //------------- Asynchronous List -------------//
+  ehci_qhd_t * const async_head = get_async_head(hostid);
+  memclr_(async_head, sizeof(ehci_qhd_t));
+
+  async_head->next.address                    = (uint32_t) async_head; // circular list, next is itself
+  async_head->next.type                       = EHCI_QUEUE_ELEMENT_QHD;
+  async_head->head_list_flag                  = 1;
+  async_head->qtd_overlay.halted              = 1; // inactive most of time
+  async_head->qtd_overlay.next.terminate      = 1; // TODO removed if verified
+
+  regs->async_list_base = (uint32_t) async_head;
+
+#if EHCI_PERIODIC_LIST
+  //------------- Periodic List -------------//
+  // Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only
+
+  for(uint32_t i=0; i<4; i++)
+  {
+    ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ][i].interrupt_smask    = 1; // queue head in period list must have smask non-zero
+    ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ][i].qtd_overlay.halted = 1; // dummy node, always inactive
+  }
+
+  ehci_link_t * const framelist  = get_period_frame_list(hostid);
+  ehci_link_t * const period_1ms = get_period_head(hostid, 1);
+  // all links --> period_head_arr[0] (1ms)
+  // 0, 2, 4, 6 etc --> period_head_arr[1] (2ms)
+  // 1, 5 --> period_head_arr[2] (4ms)
+  // 3 --> period_head_arr[3] (8ms)
+
+  // TODO EHCI_FRAMELIST_SIZE with other size than 8
+  for(uint32_t i=0; i<EHCI_FRAMELIST_SIZE; i++)
+  {
+    framelist[i].address = (uint32_t) period_1ms;
+    framelist[i].type    = EHCI_QUEUE_ELEMENT_QHD;
+  }
+
+  for(uint32_t i=0; i<EHCI_FRAMELIST_SIZE; i+=2)
+  {
+    list_insert(framelist + i, get_period_head(hostid, 2), EHCI_QUEUE_ELEMENT_QHD);
+  }
+
+  for(uint32_t i=1; i<EHCI_FRAMELIST_SIZE; i+=4)
+  {
+    list_insert(framelist + i, get_period_head(hostid, 4), EHCI_QUEUE_ELEMENT_QHD);
+  }
+
+  list_insert(framelist+3, get_period_head(hostid, 8), EHCI_QUEUE_ELEMENT_QHD);
+
+  period_1ms->terminate    = 1;
+
+  regs->periodic_list_base = (uint32_t) framelist;
+#else
+  regs->periodic_list_base = 0;
+#endif
+
+  //------------- TT Control (NXP only) -------------//
+  regs->tt_control = 0;
+
+  //------------- USB CMD Register -------------//
+
+  regs->usb_cmd |= BIT_(EHCI_USBCMD_POS_RUN_STOP) | BIT_(EHCI_USBCMD_POS_ASYNC_ENABLE)
+#if EHCI_PERIODIC_LIST
+                  | BIT_(EHCI_USBCMD_POS_PERIOD_ENABLE) // TODO enable period list only there is int/iso endpoint
+#endif
+                  | ((EHCI_CFG_FRAMELIST_SIZE_BITS & BIN8(011)) << EHCI_USBCMD_POS_FRAMELIST_SZIE)
+                  | ((EHCI_CFG_FRAMELIST_SIZE_BITS >> 2) << EHCI_USBCMD_POS_NXP_FRAMELIST_SIZE_MSB);
+
+  //------------- ConfigFlag Register (skip) -------------//
+
+  regs->portsc_bit.port_power = 1; // enable port power
+
+  return TUSB_ERROR_NONE;
+}
+
+static tusb_error_t hcd_controller_stop(uint8_t hostid)
+{
+  ehci_registers_t* const regs = get_operational_register(hostid);
+  timeout_timer_t timeout;
+
+  regs->usb_cmd_bit.run_stop = 0;
+
+  timeout_set(&timeout, 2); // USB Spec: controller has to stop within 16 uframe = 2 frames
+  while( regs->usb_sts_bit.hc_halted == 0 && !timeout_expired(&timeout)) {}
+
+  return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE;
+}
+
+tusb_error_t hcd_controller_reset(uint8_t hostid)
+{
+  ehci_registers_t* const regs = get_operational_register(hostid);
+  timeout_timer_t timeout;
+
+// NXP chip powered with non-host mode --> sts bit is not correctly reflected
+  regs->usb_cmd_bit.reset = 1;
+
+  timeout_set(&timeout, 2); // should not take longer the time to stop controller
+  while( regs->usb_cmd_bit.reset && !timeout_expired(&timeout)) {}
+
+  return timeout_expired(&timeout) ? TUSB_ERROR_OSAL_TIMEOUT : TUSB_ERROR_NONE;
+}
+
+//--------------------------------------------------------------------+
+// CONTROL PIPE API
+//--------------------------------------------------------------------+
+tusb_error_t  hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size)
+{
+  ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+
+  qhd_init(p_qhd, dev_addr, max_packet_size, 0, TUSB_XFER_CONTROL, 1); // TODO binterval of control is ignored
+
+  if (dev_addr != 0)
+  {
+    //------------- insert to async list -------------//
+    // TODO might need to to disable async list first
+    list_insert( (ehci_link_t*) get_async_head(usbh_devices[dev_addr].core_id),
+                 (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
+  }
+
+  return TUSB_ERROR_NONE;
+}
+
+tusb_error_t  hcd_pipe_control_xfer(uint8_t dev_addr, tusb_control_request_t const * p_request, uint8_t data[])
+{
+  ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+
+  ehci_qtd_t *p_setup      = get_control_qtds(dev_addr);
+  ehci_qtd_t *p_data       = p_setup + 1;
+  ehci_qtd_t *p_status     = p_setup + 2;
+
+  //------------- SETUP Phase -------------//
+  qtd_init(p_setup, (uint32_t) p_request, 8);
+  p_setup->pid          = EHCI_PID_SETUP;
+  p_setup->next.address = (uint32_t) p_data;
+
+  //------------- DATA Phase -------------//
+  if (p_request->wLength > 0)
+  {
+    qtd_init(p_data, (uint32_t) data, p_request->wLength);
+    p_data->data_toggle = 1;
+    p_data->pid         = p_request->bmRequestType_bit.direction ? EHCI_PID_IN : EHCI_PID_OUT;
+  }else
+  {
+    p_data = p_setup;
+  }
+  p_data->next.address = (uint32_t) p_status;
+
+  //------------- STATUS Phase -------------//
+  qtd_init(p_status, 0, 0); // zero-length data
+  p_status->int_on_complete = 1;
+  p_status->data_toggle     = 1;
+  p_status->pid             = p_request->bmRequestType_bit.direction ? EHCI_PID_OUT : EHCI_PID_IN; // reverse direction of data phase
+  p_status->next.terminate  = 1;
+
+  //------------- Attach TDs list to Control Endpoint -------------//
+  p_qhd->p_qtd_list_head = p_setup;
+  p_qhd->p_qtd_list_tail = p_status;
+
+  p_qhd->qtd_overlay.next.address = (uint32_t) p_setup;
+
+  return TUSB_ERROR_NONE;
+}
+
+tusb_error_t  hcd_pipe_control_close(uint8_t dev_addr)
+{
+  //------------- TODO pipe handle validate -------------//
+  ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
+
+  p_qhd->is_removing = 1;
+
+  if (dev_addr != 0)
+  {
+    ASSERT_STATUS( list_remove_qhd( (ehci_link_t*) get_async_head( usbh_devices[dev_addr].core_id ),
+                                    (ehci_link_t*) p_qhd) );
+  }
+
+  return TUSB_ERROR_NONE;
+}
+
+//--------------------------------------------------------------------+
+// BULK/INT/ISO PIPE API
+//--------------------------------------------------------------------+
+pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code)
+{
+  pipe_handle_t const null_handle = { .dev_addr = 0, .xfer_type = 0, .index = 0 };
+
+  ASSERT(dev_addr > 0, null_handle);
+
+  if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
+    return null_handle; // TODO not support ISO yet
+
+  //------------- Prepare Queue Head -------------//
+  ehci_qhd_t * const p_qhd = qhd_find_free(dev_addr);
+  ASSERT_PTR(p_qhd, null_handle);
+
+  qhd_init( p_qhd, dev_addr, p_endpoint_desc->wMaxPacketSize.size, p_endpoint_desc->bEndpointAddress,
+            p_endpoint_desc->bmAttributes.xfer, p_endpoint_desc->bInterval );
+  p_qhd->class_code = class_code;
+
+  //------------- Insert to Async List -------------//
+  ehci_link_t * list_head;
+
+  if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_BULK)
+  {
+    list_head = (ehci_link_t*) get_async_head(usbh_devices[dev_addr].core_id);
+  }
+  #if EHCI_PERIODIC_LIST // TODO refractor/group this together
+  else if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_INTERRUPT)
+  {
+    list_head = get_period_head(usbh_devices[dev_addr].core_id, p_qhd->interval_ms);
+  }
+  #endif
+
+  //------------- insert to async/period list TODO might need to disable async/period list -------------//
+  list_insert( list_head,
+               (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
+
+  return (pipe_handle_t) { .dev_addr = dev_addr, .xfer_type = p_endpoint_desc->bmAttributes.xfer, .index = qhd_get_index(p_qhd) };
+}
+
+tusb_error_t  hcd_pipe_queue_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes)
+{
+  //------------- TODO pipe handle validate -------------//
+
+  //------------- set up QTD -------------//
+  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(pipe_hdl);
+  ehci_qtd_t *p_qtd = qtd_find_free(pipe_hdl.dev_addr);
+
+  ASSERT_PTR(p_qtd, TUSB_ERROR_EHCI_NOT_ENOUGH_QTD);
+
+  qtd_init(p_qtd, (uint32_t) buffer, total_bytes);
+  p_qtd->pid = p_qhd->pid_non_control;
+
+  //------------- insert TD to TD list -------------//
+  qtd_insert_to_qhd(p_qhd, p_qtd);
+
+  return TUSB_ERROR_NONE;
+}
+
+tusb_error_t  hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete)
+{
+  ASSERT_STATUS ( hcd_pipe_queue_xfer(pipe_hdl, buffer, total_bytes) );
+
+  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(pipe_hdl);
+
+  if ( int_on_complete )
+  { // the just added qtd is pointed by list_tail
+    p_qhd->p_qtd_list_tail->int_on_complete = 1;
+  }
+  p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; // attach to queue head to start transferring
+
+  return TUSB_ERROR_NONE;
+}
+
+/// pipe_close should only be called as a part of unmount/safe-remove process
+tusb_error_t  hcd_pipe_close(pipe_handle_t pipe_hdl)
+{
+  ASSERT(pipe_hdl.dev_addr > 0, TUSB_ERROR_INVALID_PARA);
+
+  ASSERT(pipe_hdl.xfer_type != TUSB_XFER_ISOCHRONOUS, TUSB_ERROR_INVALID_PARA);
+
+  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+
+  // async list needs async advance handshake to make sure host controller has released cached data
+  // non-control does not use async advance, it will eventually free by control pipe close
+  // period list queue element is guarantee to be free in the next frame (1 ms)
+  p_qhd->is_removing = 1; // TODO redundant, only apply to control queue head
+
+  if ( pipe_hdl.xfer_type == TUSB_XFER_BULK )
+  {
+    ASSERT_STATUS( list_remove_qhd(
+        (ehci_link_t*) get_async_head( usbh_devices[pipe_hdl.dev_addr].core_id ),
+        (ehci_link_t*) p_qhd) );
+  }
+  #if EHCI_PERIODIC_LIST // TODO refractor/group this together
+  else
+  {
+    ASSERT_STATUS( list_remove_qhd(
+        get_period_head( usbh_devices[pipe_hdl.dev_addr].core_id, p_qhd->interval_ms ),
+        (ehci_link_t*) p_qhd) );
+  }
+  #endif
+
+  return TUSB_ERROR_NONE;
+}
+
+bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl)
+{
+  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+  return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL);
+}
+
+bool hcd_pipe_is_error(pipe_handle_t pipe_hdl)
+{
+  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+  return p_qhd->qtd_overlay.halted;
+}
+
+bool hcd_pipe_is_idle(pipe_handle_t pipe_hdl)
+{ // TODO to be remove
+  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+  return (p_qhd->p_qtd_list_head == NULL);
+}
+
+bool hcd_pipe_is_stalled(pipe_handle_t pipe_hdl)
+{
+  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+  return p_qhd->qtd_overlay.halted && !qhd_has_xact_error(p_qhd);
+}
+
+uint8_t hcd_pipe_get_endpoint_addr(pipe_handle_t pipe_hdl)
+{
+  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+  return p_qhd->endpoint_number + ( (p_qhd->pid_non_control == EHCI_PID_IN) ? 0x80 : 0);
+}
+
+tusb_error_t hcd_pipe_clear_stall(pipe_handle_t pipe_hdl)
+{
+  ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle( pipe_hdl );
+  p_qhd->qtd_overlay.halted = 0;
+
+  return TUSB_ERROR_NONE;
+}
+
+//--------------------------------------------------------------------+
+// EHCI Interrupt Handler
+//--------------------------------------------------------------------+
+
+// async_advance is handshake between sw stack & ehci controller where ehci free all memory from an deleted queue head.
+// In tinyusb, queue head is only removed when device is unplugged. So only control queue head is checked if removing
+static void async_advance_isr(ehci_qhd_t * const async_head)
+{
+  // TODO do we need to close addr0
+  if (async_head->is_removing) // closing control pipe of addr0
+  {
+    async_head->is_removing        = 0;
+    async_head->p_qtd_list_head    = async_head->p_qtd_list_tail = NULL;
+    async_head->qtd_overlay.halted = 1;
+
+    usbh_devices[0].state          = TUSB_DEVICE_STATE_UNPLUG;
+  }
+
+  for(uint8_t relative_dev_addr=0; relative_dev_addr < TUSB_CFG_HOST_DEVICE_MAX; relative_dev_addr++)
+  {
+    // check if control endpoint is removing
+    ehci_qhd_t *p_control_qhd = &ehci_data.device[relative_dev_addr].control.qhd;
+    if ( p_control_qhd->is_removing )
+    {
+      p_control_qhd->is_removing = 0;
+      p_control_qhd->used        = 0;
+
+      // Host Controller has cleaned up its cached data for this device, set state to unplug
+      usbh_devices[relative_dev_addr+1].state = TUSB_DEVICE_STATE_UNPLUG;
+
+      for (uint8_t i=0; i<EHCI_MAX_QHD; i++) // free all qhd
+      {
+        ehci_data.device[relative_dev_addr].qhd[i].used        = 0;
+        ehci_data.device[relative_dev_addr].qhd[i].is_removing = 0;
+      }
+      for (uint8_t i=0; i<EHCI_MAX_QTD; i++) // free all qtd
+      {
+        ehci_data.device[relative_dev_addr].qtd[i].used = 0;
+      }
+      // TODO free all itd & sitd
+    }
+  } // end for device[] loop
+}
+
+static void port_connect_status_change_isr(uint8_t hostid)
+{
+  ehci_registers_t* const regs = get_operational_register(hostid);
+
+  // NOTE There is an sequence plug->unplug->…..-> plug if device is powering with pre-plugged device
+  if (regs->portsc_bit.current_connect_status)
+  {
+    usbh_hcd_rhport_plugged_isr(hostid);
+  }else // device unplugged
+  {
+    usbh_hcd_rhport_unplugged_isr(hostid);
+//    regs->usb_cmd_bit.advacne_async = 1; // Async doorbell check EHCI 4.8.2 for operational details
+  }
+}
+
+// TODO refractor abtract later
+void hcd_port_unplug(uint8_t hostid)
+{
+	ehci_registers_t* const regs = get_operational_register(hostid);
+  regs->usb_cmd_bit.advacne_async = 1; // Async doorbell check EHCI 4.8.2 for operational details
+}
+
+static void qhd_xfer_complete_isr(ehci_qhd_t * p_qhd)
+{
+  uint8_t max_loop = 0;
+  tusb_xfer_type_t const xfer_type = qhd_get_xfer_type(p_qhd);
+
+  // free all TDs from the head td to the first active TD
+  while(p_qhd->p_qtd_list_head != NULL && !p_qhd->p_qtd_list_head->active
+      && max_loop < EHCI_MAX_QTD)
+  {
+    // TD need to be freed and removed from qhd, before invoking callback
+    bool is_ioc = (p_qhd->p_qtd_list_head->int_on_complete != 0);
+    p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes;
+
+    p_qhd->p_qtd_list_head->used = 0; // free QTD
+    qtd_remove_1st_from_qhd(p_qhd);
+
+    if (is_ioc) // end of request
+    { // call USBH callback
+      usbh_xfer_isr( qhd_create_pipe_handle(p_qhd, xfer_type),
+                     p_qhd->class_code, TUSB_EVENT_XFER_COMPLETE,
+                     p_qhd->total_xferred_bytes - (xfer_type == TUSB_XFER_CONTROL ? 8 : 0) ); // subtract setup packet size if control,
+      p_qhd->total_xferred_bytes = 0;
+    }
+
+    max_loop++;
+  }
+}
+
+static void async_list_xfer_complete_isr(ehci_qhd_t * const async_head)
+{
+  uint8_t max_loop = 0;
+  ehci_qhd_t *p_qhd = async_head;
+  do
+  {
+    if ( !p_qhd->qtd_overlay.halted ) // halted or error is processed in error isr
+    {
+      qhd_xfer_complete_isr(p_qhd);
+    }
+    p_qhd = qhd_next(p_qhd);
+    max_loop++;
+  }while(p_qhd != async_head && max_loop < EHCI_MAX_QHD); // async list traversal, stop if loop around
+  // TODO abstract max loop guard for async
+}
+
+#if EHCI_PERIODIC_LIST // TODO refractor/group this together
+static void period_list_xfer_complete_isr(uint8_t hostid, uint8_t interval_ms)
+{
+  uint8_t max_loop = 0;
+  uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
+  ehci_link_t next_item = * get_period_head(hostid, interval_ms);
+
+  // TODO abstract max loop guard for period
+  while( !next_item.terminate &&
+      !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) &&
+      max_loop < (EHCI_MAX_QHD + EHCI_MAX_ITD + EHCI_MAX_SITD))
+  {
+    switch ( next_item.type )
+    {
+      case EHCI_QUEUE_ELEMENT_QHD:
+      {
+        ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address);
+        if ( !p_qhd_int->qtd_overlay.halted )
+        {
+          qhd_xfer_complete_isr(p_qhd_int);
+        }
+      }
+      break;
+
+      case EHCI_QUEUE_ELEMENT_ITD:
+      case EHCI_QUEUE_ELEMENT_SITD:
+      case EHCI_QUEUE_ELEMENT_FSTN:
+      default:
+        ASSERT (false, VOID_RETURN); // TODO support hs/fs ISO
+      break;
+    }
+
+    next_item = *list_next(&next_item);
+    max_loop++;
+  }
+}
+#endif
+
+static void qhd_xfer_error_isr(ehci_qhd_t * p_qhd)
+{
+  if ( (p_qhd->device_address != 0 && p_qhd->qtd_overlay.halted) || // addr0 cannot be protocol STALL
+        qhd_has_xact_error(p_qhd) )
+  { // current qhd has error in transaction
+    tusb_xfer_type_t const xfer_type = qhd_get_xfer_type(p_qhd);
+    tusb_event_t error_event;
+
+    // no error bits are set, endpoint is halted due to STALL
+    error_event = qhd_has_xact_error(p_qhd) ? TUSB_EVENT_XFER_ERROR : TUSB_EVENT_XFER_STALLED;
+
+    p_qhd->total_xferred_bytes += p_qhd->p_qtd_list_head->expected_bytes - p_qhd->p_qtd_list_head->total_bytes;
+
+    // TODO skip unplugged device
+    if ( TUSB_EVENT_XFER_ERROR == error_event )    hal_debugger_breakpoint();
+
+    p_qhd->p_qtd_list_head->used = 0; // free QTD
+    qtd_remove_1st_from_qhd(p_qhd);
+
+    if ( TUSB_XFER_CONTROL == xfer_type )
+    {
+      p_qhd->total_xferred_bytes -= min8_of(8, p_qhd->total_xferred_bytes); // subtract setup size
+
+      // control cannot be halted --> clear all qtd list
+      p_qhd->p_qtd_list_head = NULL;
+      p_qhd->p_qtd_list_tail = NULL;
+
+      p_qhd->qtd_overlay.next.terminate      = 1;
+      p_qhd->qtd_overlay.alternate.terminate = 1;
+      p_qhd->qtd_overlay.halted              = 0;
+
+      ehci_qtd_t *p_setup  = get_control_qtds(p_qhd->device_address);
+      ehci_qtd_t *p_data   = p_setup + 1;
+      ehci_qtd_t *p_status = p_setup + 2;
+
+      p_setup->used = p_data->used = p_status->used = 0;
+    }
+
+    // call USBH callback
+    usbh_xfer_isr( qhd_create_pipe_handle(p_qhd, xfer_type),
+                   p_qhd->class_code, error_event,
+                   p_qhd->total_xferred_bytes);
+
+    p_qhd->total_xferred_bytes = 0;
+  }
+}
+
+static void xfer_error_isr(uint8_t hostid)
+{
+  //------------- async list -------------//
+  uint8_t max_loop = 0;
+  ehci_qhd_t * const async_head = get_async_head(hostid);
+  ehci_qhd_t *p_qhd = async_head;
+  do
+  {
+    qhd_xfer_error_isr( p_qhd );
+    p_qhd = qhd_next(p_qhd);
+    max_loop++;
+  }while(p_qhd != async_head && max_loop < EHCI_MAX_QHD); // async list traversal, stop if loop around
+
+  #if EHCI_PERIODIC_LIST
+  //------------- TODO refractor period list -------------//
+  uint32_t const period_1ms_addr = (uint32_t) get_period_head(hostid, 1);
+  for (uint8_t interval_ms=1; interval_ms <= EHCI_FRAMELIST_SIZE; interval_ms *= 2)
+  {
+    uint8_t period_max_loop = 0;
+    ehci_link_t next_item = * get_period_head(hostid, interval_ms);
+
+    // TODO abstract max loop guard for period
+    while( !next_item.terminate &&
+        !(interval_ms > 1 && period_1ms_addr == align32(next_item.address)) &&
+        period_max_loop < (EHCI_MAX_QHD + EHCI_MAX_ITD + EHCI_MAX_SITD))
+    {
+      switch ( next_item.type )
+      {
+        case EHCI_QUEUE_ELEMENT_QHD:
+        {
+          ehci_qhd_t *p_qhd_int = (ehci_qhd_t *) align32(next_item.address);
+          qhd_xfer_error_isr(p_qhd_int);
+        }
+        break;
+
+        case EHCI_QUEUE_ELEMENT_ITD:
+        case EHCI_QUEUE_ELEMENT_SITD:
+        case EHCI_QUEUE_ELEMENT_FSTN:
+        default:
+          ASSERT (false, VOID_RETURN); // TODO support hs/fs ISO
+        break;
+      }
+
+      next_item = *list_next(&next_item);
+      period_max_loop++;
+    }
+  }
+  #endif
+}
+
+//------------- Host Controller Driver's Interrupt Handler -------------//
+void hcd_isr(uint8_t hostid)
+{
+  ehci_registers_t* const regs = get_operational_register(hostid);
+
+  uint32_t int_status = regs->usb_sts;
+  int_status &= regs->usb_int_enable;
+  
+  regs->usb_sts |= int_status; // Acknowledge handled interrupt
+
+  if (int_status == 0)
+    return;
+
+  if (int_status & EHCI_INT_MASK_PORT_CHANGE)
+  {
+    uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL;
+
+    if (regs->portsc_bit.connect_status_change)
+    {
+      port_connect_status_change_isr(hostid);
+    }
+
+    regs->portsc |= port_status; // Acknowledge change bits in portsc
+  }
+
+  if (int_status & EHCI_INT_MASK_ERROR)
+  {
+    xfer_error_isr(hostid);
+  }
+
+  //------------- some QTD/SITD/ITD with IOC set is completed -------------//
+  if (int_status & EHCI_INT_MASK_NXP_ASYNC)
+  {
+    async_list_xfer_complete_isr( get_async_head(hostid) );
+  }
+
+#if EHCI_PERIODIC_LIST // TODO refractor/group this together
+  if (int_status & EHCI_INT_MASK_NXP_PERIODIC)
+  {
+    for (uint8_t i=1; i <= EHCI_FRAMELIST_SIZE; i *= 2)
+    {
+      period_list_xfer_complete_isr( hostid, i );
+    }
+  }
+#endif
+
+  //------------- There is some removed async previously -------------//
+  if (int_status & EHCI_INT_MASK_ASYNC_ADVANCE) // need to place after EHCI_INT_MASK_NXP_ASYNC
+  {
+    async_advance_isr( get_async_head(hostid) );
+  }
+}
+
+//--------------------------------------------------------------------+
+// HELPER
+//--------------------------------------------------------------------+
+STATIC_ INLINE_ ehci_registers_t* get_operational_register(uint8_t hostid)
+{
+  return (ehci_registers_t*) (hostid ? (&LPC_USB1->USBCMD_H) : (&LPC_USB0->USBCMD_H) );
+}
+
+#if EHCI_PERIODIC_LIST // TODO refractor/group this together
+STATIC_ INLINE_ ehci_link_t* get_period_frame_list(uint8_t hostid)
+{
+  switch(hostid)
+  {
+#if (TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_HOST)
+    case 0:
+      return period_frame_list0;
+#endif
+
+#if (TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST)
+    case 1:
+      return period_frame_list1;
+#endif
+	 
+    default: return NULL;
+  }
+}
+#endif
+
+STATIC_ INLINE_ uint8_t hostid_to_data_idx(uint8_t hostid)
+{
+  #if (CONTROLLER_HOST_NUMBER == 1) && (TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST)
+    (void) hostid;
+    return 0;
+  #else
+    return hostid;
+  #endif
+}
+
+//------------- queue head helper -------------//
+STATIC_ INLINE_ ehci_qhd_t* get_async_head(uint8_t hostid)
+{
+  return &ehci_data.async_head[ hostid_to_data_idx(hostid) ];
+}
+
+#if EHCI_PERIODIC_LIST // TODO refractor/group this together
+STATIC_ INLINE_ ehci_link_t* get_period_head(uint8_t hostid, uint8_t interval_ms)
+{
+  return (ehci_link_t*) (&ehci_data.period_head_arr[ hostid_to_data_idx(hostid) ]
+                                                    [ log2_of( min8_of(EHCI_FRAMELIST_SIZE, interval_ms) ) ] );
+}
+#endif
+
+STATIC_ INLINE_ ehci_qhd_t* get_control_qhd(uint8_t dev_addr)
+{
+  return (dev_addr == 0) ?
+      get_async_head( usbh_devices[dev_addr].core_id ) :
+      &ehci_data.device[dev_addr-1].control.qhd;
+}
+STATIC_ INLINE_ ehci_qtd_t* get_control_qtds(uint8_t dev_addr)
+{
+  return (dev_addr == 0) ?
+      ehci_data.addr0_qtd :
+      ehci_data.device[ dev_addr-1 ].control.qtd;
+
+}
+
+static inline ehci_qhd_t* qhd_find_free (uint8_t dev_addr)
+{
+  uint8_t relative_address = dev_addr-1;
+  uint8_t index=0;
+  while( index<EHCI_MAX_QHD && ehci_data.device[relative_address].qhd[index].used )
+  {
+    index++;
+  }
+  return (index < EHCI_MAX_QHD) ? &ehci_data.device[relative_address].qhd[index] : NULL;
+}
+
+static inline uint8_t qhd_get_index(ehci_qhd_t const * p_qhd)
+{
+  return p_qhd - ehci_data.device[p_qhd->device_address-1].qhd;
+}
+static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd)
+{
+  return  ( p_qhd->endpoint_number == 0 ) ? TUSB_XFER_CONTROL :
+          ( p_qhd->interrupt_smask != 0 ) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK;
+}
+
+static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd)
+{
+  return (ehci_qhd_t*) align32(p_qhd->next.address);
+}
+
+STATIC_ INLINE_ ehci_qhd_t* qhd_get_from_pipe_handle(pipe_handle_t pipe_hdl)
+{
+  return &ehci_data.device[ pipe_hdl.dev_addr-1 ].qhd[ pipe_hdl.index ];
+}
+
+static inline pipe_handle_t qhd_create_pipe_handle(ehci_qhd_t const * p_qhd, tusb_xfer_type_t xfer_type)
+{
+  pipe_handle_t pipe_hdl = {
+      .dev_addr  = p_qhd->device_address,
+      .xfer_type = xfer_type
+  };
+
+  // TODO Isochronous transfer support
+  if (TUSB_XFER_CONTROL != xfer_type) // qhd index for control is meaningless
+  {
+    pipe_hdl.index = qhd_get_index(p_qhd);
+  }
+
+  return pipe_hdl;
+}
+
+//------------- TD helper -------------//
+STATIC_ INLINE_ ehci_qtd_t* qtd_find_free(uint8_t dev_addr)
+{
+  uint8_t index=0;
+  while( index<EHCI_MAX_QTD && ehci_data.device[dev_addr-1].qtd[index].used )
+  {
+    index++;
+  }
+
+  return (index < EHCI_MAX_QTD) ? &ehci_data.device[dev_addr-1].qtd[index] : NULL;
+}
+
+static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd )
+{
+  return (ehci_qtd_t*) align32(p_qtd->next.address);
+}
+
+static inline void qtd_remove_1st_from_qhd(ehci_qhd_t *p_qhd)
+{
+  if (p_qhd->p_qtd_list_head == p_qhd->p_qtd_list_tail) // last TD --> make it NULL
+  {
+    p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = NULL;
+  }else
+  {
+    p_qhd->p_qtd_list_head = qtd_next( p_qhd->p_qtd_list_head );
+  }
+}
+
+static inline void qtd_insert_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new)
+{
+  if (p_qhd->p_qtd_list_head == NULL) // empty list
+  {
+    p_qhd->p_qtd_list_head               = p_qhd->p_qtd_list_tail = p_qtd_new;
+  }else
+  {
+    p_qhd->p_qtd_list_tail->next.address = (uint32_t) p_qtd_new;
+    p_qhd->p_qtd_list_tail               = p_qtd_new;
+  }
+}
+
+static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval)
+{
+  // address 0 uses async head, which always on the list --> cannot be cleared (ehci halted otherwise)
+  if (dev_addr != 0)
+  {
+    memclr_(p_qhd, sizeof(ehci_qhd_t));
+  }
+
+  p_qhd->device_address                   = dev_addr;
+  p_qhd->non_hs_period_inactive_next_xact = 0;
+  p_qhd->endpoint_number                  = endpoint_addr & 0x0F;
+  p_qhd->endpoint_speed                   = usbh_devices[dev_addr].speed;
+  p_qhd->data_toggle_control              = (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0;
+  p_qhd->head_list_flag                   = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head
+  p_qhd->max_package_size                 = max_packet_size;
+  p_qhd->non_hs_control_endpoint          = ((TUSB_XFER_CONTROL == xfer_type) && (p_qhd->endpoint_speed != TUSB_SPEED_HIGH))  ? 1 : 0;
+  p_qhd->nak_count_reload                 = 0;
+
+  // Bulk/Control -> smask = cmask = 0
+  // TODO Isochronous
+  if (TUSB_XFER_INTERRUPT == xfer_type)
+  {
+    if (TUSB_SPEED_HIGH == p_qhd->endpoint_speed)
+    {
+      ASSERT_INT_WITHIN(1, 16, interval, VOID_RETURN);
+      if ( interval < 4) // sub milisecond interval
+      {
+        p_qhd->interval_ms     = 0;
+        p_qhd->interrupt_smask = (interval == 1) ? BIN8(11111111) :
+                                 (interval == 2) ? BIN8(10101010) : BIN8(01000100);
+      }else
+      {
+        p_qhd->interval_ms     = (uint8_t) min16_of( 1 << (interval-4), 255 );
+        p_qhd->interrupt_smask = BIT_(interval % 8);
+      }
+    }else
+    {
+      ASSERT( 0 != interval, VOID_RETURN);
+      // Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes
+      p_qhd->interrupt_smask        = 0x01;
+      p_qhd->non_hs_interrupt_cmask = BIN8(11100);
+      p_qhd->interval_ms            = interval;
+    }
+  }else
+  {
+    p_qhd->interrupt_smask = p_qhd->non_hs_interrupt_cmask = 0;
+  }
+
+  p_qhd->hub_address             = usbh_devices[dev_addr].hub_addr;
+  p_qhd->hub_port                = usbh_devices[dev_addr].hub_port;
+  p_qhd->mult                    = 1; // TODO not use high bandwidth/park mode yet
+
+  //------------- HCD Management Data -------------//
+  p_qhd->used            = 1;
+  p_qhd->is_removing     = 0;
+  p_qhd->p_qtd_list_head = NULL;
+  p_qhd->p_qtd_list_tail = NULL;
+  p_qhd->pid_non_control = (endpoint_addr & 0x80) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint
+
+  //------------- active, but no TD list -------------//
+  p_qhd->qtd_overlay.halted              = 0;
+  p_qhd->qtd_overlay.next.terminate      = 1;
+  p_qhd->qtd_overlay.alternate.terminate = 1;
+  if (TUSB_XFER_BULK == xfer_type && p_qhd->endpoint_speed == TUSB_SPEED_HIGH && p_qhd->pid_non_control == EHCI_PID_OUT)
+  {
+    p_qhd->qtd_overlay.pingstate_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11
+  }
+}
+
+static void qtd_init(ehci_qtd_t* p_qtd, uint32_t data_ptr, uint16_t total_bytes)
+{
+  memclr_(p_qtd, sizeof(ehci_qtd_t));
+
+  p_qtd->used                = 1;
+
+  p_qtd->next.terminate      = 1; // init to null
+  p_qtd->alternate.terminate = 1; // not used, always set to terminated
+  p_qtd->active              = 1;
+  p_qtd->cerr                = 3; // TODO 3 consecutive errors tolerance
+  p_qtd->data_toggle         = 0;
+  p_qtd->total_bytes         = total_bytes;
+  p_qtd->expected_bytes      = total_bytes;
+
+  p_qtd->buffer[0]           = data_ptr;
+  for(uint8_t i=1; i<5; i++)
+  {
+    p_qtd->buffer[i] |= align4k( p_qtd->buffer[i-1] ) + 4096;
+  }
+}
+
+//------------- List Managing Helper -------------//
+static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type)
+{
+  new->address = current->address;
+  current->address = ((uint32_t) new) | (new_type << 1);
+}
+
+static inline ehci_link_t* list_next(ehci_link_t *p_link_pointer)
+{
+  return (ehci_link_t*) align32(p_link_pointer->address);
+}
+
+static ehci_link_t* list_find_previous_item(ehci_link_t* p_head, ehci_link_t* p_current)
+{
+  ehci_link_t *p_prev = p_head;
+  uint32_t max_loop = 0;
+  while( (align32(p_prev->address) != (uint32_t) p_head)    && // not loop around
+         (align32(p_prev->address) != (uint32_t) p_current) && // not found yet
+         !p_prev->terminate                                 && // not advanceable
+         max_loop < EHCI_MAX_QHD)
+  {
+    p_prev = list_next(p_prev);
+    max_loop++;
+  }
+
+  return  (align32(p_prev->address) != (uint32_t) p_head) ? p_prev : NULL;
+}
+
+static tusb_error_t list_remove_qhd(ehci_link_t* p_head, ehci_link_t* p_remove)
+{
+  ehci_link_t *p_prev = list_find_previous_item(p_head, p_remove);
+
+  ASSERT_PTR(p_prev, TUSB_ERROR_INVALID_PARA);
+
+  p_prev->address   = p_remove->address;
+  // EHCI 4.8.2 link the removing queue head to async/period head (which always reachable by Host Controller)
+  p_remove->address = ((uint32_t) p_head) | (EHCI_QUEUE_ELEMENT_QHD << 1);
+
+  return TUSB_ERROR_NONE;
+}
+
+#endif

+ 98 - 98
tinyusb/mcu_capacity.h

@@ -1,98 +1,98 @@
-/**************************************************************************/
-/*!
-    @file     mcu_capacity.h
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \file
- *  \brief TBD
- *
- *  \note TBD
- */
-
-/** \ingroup TBD
- *  \defgroup TBD
- *  \brief TBD
- *
- *  @{
- */
-
-#ifndef _TUSB_MCU_CAPACITY_H_
-#define _TUSB_MCU_CAPACITY_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-// CAP is abbreviation for Capacity
-
-//--------------------------------------------------------------------+
-// ARCHTECTURE
-//--------------------------------------------------------------------+
-
-
-
-//--------------------------------------------------------------------+
-// Controller
-//--------------------------------------------------------------------+
-#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX
-  #define CAP_CONTROLLER_NUMBER 2
-#else
-  #define CAP_CONTROLLER_NUMBER 1
-#endif
-
-#define CAP_MODE_DEVICE
-#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX || MCU == MCU_LPC175X_6X
-  #define CAP_MODE_HOST
-#endif
-
-#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX || MCU == MCU_LPC11UXX || MCU == MCU_LPC13UXX
-  #define CAP_DEVICE_ROMDRIVER
-#endif
-
-//--------------------------------------------------------------------+
-// Validation
-//--------------------------------------------------------------------+
-#if (CAP_CONTROLLER_NUMBER == 1) && ( defined TUSB_CFG_CONTROLLER1_MODE)
- #error current MCU does not have the required number of controllers
-#endif
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_MCU_CAPACITY_H_ */
-
-/** @} */
+/**************************************************************************/
+/*!
+    @file     mcu_capacity.h
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/** \file
+ *  \brief TBD
+ *
+ *  \note TBD
+ */
+
+/** \ingroup TBD
+ *  \defgroup TBD
+ *  \brief TBD
+ *
+ *  @{
+ */
+
+#ifndef _TUSB_MCU_CAPACITY_H_
+#define _TUSB_MCU_CAPACITY_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// CAP is abbreviation for Capacity
+
+//--------------------------------------------------------------------+
+// ARCHTECTURE
+//--------------------------------------------------------------------+
+
+
+
+//--------------------------------------------------------------------+
+// Controller
+//--------------------------------------------------------------------+
+#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX
+  #define CAP_CONTROLLER_NUMBER 2
+#else
+  #define CAP_CONTROLLER_NUMBER 1
+#endif
+
+#define CAP_MODE_DEVICE
+#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX || MCU == MCU_LPC175X_6X
+  #define CAP_MODE_HOST
+#endif
+
+#if MCU == MCU_LPC43XX || MCU == MCU_LPC18XX || MCU == MCU_LPC11UXX || MCU == MCU_LPC13UXX
+  #define CAP_DEVICE_ROMDRIVER
+#endif
+
+//--------------------------------------------------------------------+
+// Validation
+//--------------------------------------------------------------------+
+#if (CAP_CONTROLLER_NUMBER == 1) && ( defined TUSB_CFG_CONTROLLER_1_MODE)
+ #error current MCU does not have the required number of controllers
+#endif
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_MCU_CAPACITY_H_ */
+
+/** @} */

+ 209 - 204
tinyusb/osal/osal.h

@@ -1,204 +1,209 @@
-/**************************************************************************/
-/*!
-    @file     osal.h
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \file
- *  \brief TBD
- *
- *  \note TBD
- */
-
-/** \ingroup TBD
- *  \defgroup TBD
- *  \brief TBD
- *
- *  @{
- */
-
-#ifndef _TUSB_OSAL_H_
-#define _TUSB_OSAL_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-#include "tusb_option.h"
-
-#define TUSB_OS_NONE       1
-#define TUSB_OS_FREERTOS   2
-#define TUSB_OS_CMSIS_RTX  3
-#define TUSB_OS_UCOS2      4
-#define TUSB_OS_UCOS3      5
-
-#ifndef _TEST_
-
-#if TUSB_CFG_OS == TUSB_OS_NONE
-  #include "osal_none.h"
-#else
-  #define OSAL_VAR
-  #if TUSB_CFG_OS == TUSB_OS_FREERTOS
-    #include "osal_freeRTOS.h"
-  #elif TUSB_CFG_OS == TUSB_OS_CMSIS_RTX
-    #include "osal_cmsis_rtx.h"
-  #else
-    #error TUSB_CFG_OS is not defined or OS is not supported yet
-  #endif
-#endif
-
-#else // OSAL API for cmock
-
-#define OSAL_VAR
-#include "osal_common.h"
-
-//------------- Tick -------------//
-uint32_t osal_tick_get(void);
-
-//--------------------------------------------------------------------+
-// TASK API
-//--------------------------------------------------------------------+
-typedef uint32_t osal_task_t;
-tusb_error_t osal_task_create(osal_task_t *task);
-
-#define OSAL_TASK_DEF(code, stack_depth, prio) \
-    osal_task_t variable
-
-#define OSAL_TASK_REF(name) (&name)
-
-#define OSAL_TASK_FUNCTION(task_name) \
-    void task_name
-
-void osal_task_delay(uint32_t msec);
-
-#define OSAL_TASK_LOOP_BEGIN
-#define OSAL_TASK_LOOP_END
-
-#define SUBTASK_EXIT(error)   return error;
-
-//------------- Sub Task -------------//
-#define OSAL_SUBTASK_INVOKED_AND_WAIT(subtask, status) \
-  status = subtask
-
-#define OSAL_SUBTASK_BEGIN
-#define OSAL_SUBTASK_END \
-  return TUSB_ERROR_NONE;
-
-//------------- Sub Task Assert -------------//
-#define _SUBTASK_ASSERT_ERROR_HANDLER(error, func_call)\
-    func_call; return error
-
-#define SUBTASK_ASSERT_STATUS(sts) ASSERT_STATUS(sts)
-
-#define SUBTASK_ASSERT_STATUS_WITH_HANDLER(sts, func_call) \
-    ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, func_call, tusb_error_t status = (tusb_error_t)(sts),\
-                               TUSB_ERROR_NONE == status, status, "%s", TUSB_ErrorStr[status])
-
-#define SUBTASK_ASSERT(condition)  ASSERT(condition, TUSB_ERROR_OSAL_TASK_FAILED)
-
-#define SUBTASK_ASSERT_WITH_HANDLER(condition, func_call) \
-    ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, func_call, ,\
-                               condition, TUSB_ERROR_OSAL_TASK_FAILED, "%s", "evaluated to false")
-
-
-//--------------------------------------------------------------------+
-// Semaphore API
-//--------------------------------------------------------------------+
-typedef volatile uint8_t osal_semaphore_t;
-typedef osal_semaphore_t * osal_semaphore_handle_t;
-
-#define OSAL_SEM_DEF(name)\
-  osal_semaphore_t name
-
-#define OSAL_SEM_REF(name)\
-  &name
-
-osal_semaphore_handle_t osal_semaphore_create(osal_semaphore_t * p_sem);
-void osal_semaphore_wait(osal_semaphore_handle_t sem_hdl, uint32_t msec, tusb_error_t *p_error);
-tusb_error_t osal_semaphore_post(osal_semaphore_handle_t sem_hdl);
-void osal_semaphore_reset(osal_semaphore_handle_t sem_hdl);
-
-//--------------------------------------------------------------------+
-// MUTEX API (priority inheritance)
-//--------------------------------------------------------------------+
-#define OSAL_MUTEX_DEF(name)\
-  osal_mutex_t name
-
-#define OSAL_MUTEX_REF(name)\
-  &name
-
-typedef osal_semaphore_t        osal_mutex_t;
-typedef osal_semaphore_handle_t osal_mutex_handle_t;
-
-osal_mutex_handle_t osal_mutex_create(osal_mutex_t * p_mutex);
-void osal_mutex_wait(osal_mutex_handle_t mutex_hdl, uint32_t msec, tusb_error_t *p_error);
-tusb_error_t osal_mutex_release(osal_mutex_handle_t mutex_hdl);
-void osal_mutex_reset(osal_mutex_handle_t mutex_hdl);
-//--------------------------------------------------------------------+
-// QUEUE API
-//--------------------------------------------------------------------+
-typedef struct{
-           uint32_t * const buffer ; ///< buffer pointer
-           uint8_t const depth     ; ///< buffer size
-  volatile uint8_t count           ; ///< bytes in fifo
-  volatile uint8_t wr_idx          ; ///< write pointer
-  volatile uint8_t rd_idx          ; ///< read pointer
-} osal_queue_t;
-
-typedef osal_queue_t * osal_queue_handle_t;
-
-#define OSAL_QUEUE_DEF(name, queue_depth, type) \
-  osal_queue_t name
-
-#define OSAL_QUEUE_REF(name)  (&name)
-
-osal_queue_handle_t  osal_queue_create  (osal_queue_t *p_queue);
-void                 osal_queue_receive (osal_queue_handle_t const queue_hdl, void *p_data, uint32_t msec, tusb_error_t *p_error);
-tusb_error_t         osal_queue_send    (osal_queue_handle_t const queue_hdl, const void * data);
-void osal_queue_flush(osal_queue_handle_t const queue_hdl);
-
-//--------------------------------------------------------------------+
-// TICK API
-//--------------------------------------------------------------------+
-uint32_t osal_tick_get(void);
-#endif
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_OSAL_H_ */
-
-/** @} */
+/**************************************************************************/
+/*!
+    @file     osal.h
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+/** \file
+ *  \brief TBD
+ *
+ *  \note TBD
+ */
+
+/** \ingroup TBD
+ *  \defgroup TBD
+ *  \brief TBD
+ *
+ *  @{
+ */
+
+#ifndef _TUSB_OSAL_H_
+#define _TUSB_OSAL_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "tusb_option.h"
+
+/** \ingroup group_configuration
+ *  \defgroup TUSB_OS RTOS Integration Selection
+ * \brief TUSB_CFG_OS must be defined to one of these
+ *  @{ */
+#define TUSB_OS_NONE       1 ///< No RTOS is used
+#define TUSB_OS_FREERTOS   2 ///< FreeRTOS is used
+#define TUSB_OS_CMSIS_RTX  3 ///< CMSIS RTX is used
+#define TUSB_OS_UCOS2      4 ///< MicroC OS II is used (not supported yet)
+#define TUSB_OS_UCOS3      5 ///< MicroC OS III is used (not supported yet)
+/** @} */
+
+#ifndef _TEST_
+
+#if TUSB_CFG_OS == TUSB_OS_NONE
+  #include "osal_none.h"
+#else
+  #define OSAL_VAR
+  #if TUSB_CFG_OS == TUSB_OS_FREERTOS
+    #include "osal_freeRTOS.h"
+  #elif TUSB_CFG_OS == TUSB_OS_CMSIS_RTX
+    #include "osal_cmsis_rtx.h"
+  #else
+    #error TUSB_CFG_OS is not defined or OS is not supported yet
+  #endif
+#endif
+
+#else // OSAL API for cmock
+
+#define OSAL_VAR
+#include "osal_common.h"
+
+//------------- Tick -------------//
+uint32_t osal_tick_get(void);
+
+//--------------------------------------------------------------------+
+// TASK API
+//--------------------------------------------------------------------+
+typedef uint32_t osal_task_t;
+tusb_error_t osal_task_create(osal_task_t *task);
+
+#define OSAL_TASK_DEF(code, stack_depth, prio) \
+    osal_task_t variable
+
+#define OSAL_TASK_REF(name) (&name)
+
+#define OSAL_TASK_FUNCTION(task_name) \
+    void task_name
+
+void osal_task_delay(uint32_t msec);
+
+#define OSAL_TASK_LOOP_BEGIN
+#define OSAL_TASK_LOOP_END
+
+#define SUBTASK_EXIT(error)   return error;
+
+//------------- Sub Task -------------//
+#define OSAL_SUBTASK_INVOKED_AND_WAIT(subtask, status) \
+  status = subtask
+
+#define OSAL_SUBTASK_BEGIN
+#define OSAL_SUBTASK_END \
+  return TUSB_ERROR_NONE;
+
+//------------- Sub Task Assert -------------//
+#define _SUBTASK_ASSERT_ERROR_HANDLER(error, func_call)\
+    func_call; return error
+
+#define SUBTASK_ASSERT_STATUS(sts) ASSERT_STATUS(sts)
+
+#define SUBTASK_ASSERT_STATUS_WITH_HANDLER(sts, func_call) \
+    ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, func_call, tusb_error_t status = (tusb_error_t)(sts),\
+                               TUSB_ERROR_NONE == status, status, "%s", TUSB_ErrorStr[status])
+
+#define SUBTASK_ASSERT(condition)  ASSERT(condition, TUSB_ERROR_OSAL_TASK_FAILED)
+
+#define SUBTASK_ASSERT_WITH_HANDLER(condition, func_call) \
+    ASSERT_DEFINE_WITH_HANDLER(_SUBTASK_ASSERT_ERROR_HANDLER, func_call, ,\
+                               condition, TUSB_ERROR_OSAL_TASK_FAILED, "%s", "evaluated to false")
+
+
+//--------------------------------------------------------------------+
+// Semaphore API
+//--------------------------------------------------------------------+
+typedef volatile uint8_t osal_semaphore_t;
+typedef osal_semaphore_t * osal_semaphore_handle_t;
+
+#define OSAL_SEM_DEF(name)\
+  osal_semaphore_t name
+
+#define OSAL_SEM_REF(name)\
+  &name
+
+osal_semaphore_handle_t osal_semaphore_create(osal_semaphore_t * p_sem);
+void osal_semaphore_wait(osal_semaphore_handle_t sem_hdl, uint32_t msec, tusb_error_t *p_error);
+tusb_error_t osal_semaphore_post(osal_semaphore_handle_t sem_hdl);
+void osal_semaphore_reset(osal_semaphore_handle_t sem_hdl);
+
+//--------------------------------------------------------------------+
+// MUTEX API (priority inheritance)
+//--------------------------------------------------------------------+
+#define OSAL_MUTEX_DEF(name)\
+  osal_mutex_t name
+
+#define OSAL_MUTEX_REF(name)\
+  &name
+
+typedef osal_semaphore_t        osal_mutex_t;
+typedef osal_semaphore_handle_t osal_mutex_handle_t;
+
+osal_mutex_handle_t osal_mutex_create(osal_mutex_t * p_mutex);
+void osal_mutex_wait(osal_mutex_handle_t mutex_hdl, uint32_t msec, tusb_error_t *p_error);
+tusb_error_t osal_mutex_release(osal_mutex_handle_t mutex_hdl);
+void osal_mutex_reset(osal_mutex_handle_t mutex_hdl);
+//--------------------------------------------------------------------+
+// QUEUE API
+//--------------------------------------------------------------------+
+typedef struct{
+           uint32_t * const buffer ; ///< buffer pointer
+           uint8_t const depth     ; ///< buffer size
+  volatile uint8_t count           ; ///< bytes in fifo
+  volatile uint8_t wr_idx          ; ///< write pointer
+  volatile uint8_t rd_idx          ; ///< read pointer
+} osal_queue_t;
+
+typedef osal_queue_t * osal_queue_handle_t;
+
+#define OSAL_QUEUE_DEF(name, queue_depth, type) \
+  osal_queue_t name
+
+#define OSAL_QUEUE_REF(name)  (&name)
+
+osal_queue_handle_t  osal_queue_create  (osal_queue_t *p_queue);
+void                 osal_queue_receive (osal_queue_handle_t const queue_hdl, void *p_data, uint32_t msec, tusb_error_t *p_error);
+tusb_error_t         osal_queue_send    (osal_queue_handle_t const queue_hdl, const void * data);
+void osal_queue_flush(osal_queue_handle_t const queue_hdl);
+
+//--------------------------------------------------------------------+
+// TICK API
+//--------------------------------------------------------------------+
+uint32_t osal_tick_get(void);
+#endif
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_OSAL_H_ */
+
+/** @} */

+ 195 - 192
tinyusb/tusb_option.h

@@ -1,192 +1,195 @@
-/**************************************************************************/
-/*!
-    @file     tusb_option.h
-    @author   hathach (tinyusb.org)
-
-    @section LICENSE
-
-    Software License Agreement (BSD License)
-
-    Copyright (c) 2013, hathach (tinyusb.org)
-    All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions are met:
-    1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    2. 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.
-    3. Neither the name of the copyright holders nor the
-    names of its 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 ''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 HOLDER 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.
-
-    This file is part of the tinyusb stack.
-*/
-/**************************************************************************/
-
-/** \file
- *  \brief Configure File
- *
- *  \note TBD
- */
-
-/** 
- *  \defgroup Group_TinyUSB_Configure Configuration tusb_option.h
- *  @{
- */
-
-#ifndef _TUSB_TUSB_OPTION_H_
-#define _TUSB_TUSB_OPTION_H_
-
-#define TUSB_VERSION_YEAR   00
-#define TUSB_VERSION_MONTH  00
-#define TUSB_VERSION_WEEK   0
-#define TUSB_VERSION_NAME   "alpha"
-#define TUSB_VERSION        XSTRING_(TUSB_VERSION_YEAR) "." XSTRING_(TUSB_VERSION_MONTH)
-
-#define MCU_LPC13UXX    1
-#define MCU_LPC11UXX    2
-#define MCU_LPC43XX     3
-#define MCU_LPC18XX     4
-#define MCU_LPC175X_6X  5
-#define MCU_LPC177X_8X  6
-
-/// define this symbol will make tinyusb look for external configure file
-#include "mcu_capacity.h"
-
-#ifdef TUSB_CFG_CONFIG_FILE
-  #include TUSB_CFG_CONFIG_FILE
-#else
-  #include "tusb_config.h"
-#endif
-
-//--------------------------------------------------------------------+
-// CONTROLLER
-//--------------------------------------------------------------------+
-#define TUSB_MODE_HOST    0x02
-#define TUSB_MODE_DEVICE  0x01
-#define TUSB_MODE_NONE    0x00
-
-#define CONTROLLER_HOST_NUMBER (\
-    ((TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_HOST) ? 1 : 0) + \
-    ((TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_HOST) ? 1 : 0))
-
-#define CONTROLLER_DEVICE_NUMBER (\
-    ((TUSB_CFG_CONTROLLER0_MODE & TUSB_MODE_DEVICE) ? 1 : 0) + \
-    ((TUSB_CFG_CONTROLLER1_MODE & TUSB_MODE_DEVICE) ? 1 : 0))
-
-#define MODE_HOST_SUPPORTED   (CONTROLLER_HOST_NUMBER > 0)
-#define MODE_DEVICE_SUPPORTED (CONTROLLER_DEVICE_NUMBER > 0)
-
-#if !MODE_HOST_SUPPORTED && !MODE_DEVICE_SUPPORTED
-  #error please configure at least 1 TUSB_CFG_CONTROLLERn_MODE to TUSB_MODE_HOST and/or TUSB_MODE_DEVICE
-#endif
-
-//--------------------------------------------------------------------+
-// COMMON OPTIONS
-//--------------------------------------------------------------------+
-
-// level 3: ATTR_ALWAYS_INLINE is null, ASSERT has text, Error has its String, STATIC_VAR is NULL
-// level 2: ATTR_ALWAYS_INLINE is attribute, ASSERT has no text, Error has no strings
-/// 0: no debug information 3: most debug information provided
-#ifndef TUSB_CFG_DEBUG
-  #define TUSB_CFG_DEBUG 2
-  #warning TUSB_CFG_DEBUG is not defined, default value is 3
-#endif
-
-/// USB RAM Section Placement, MCU's usb controller often has limited access to specific RAM region. This will be used to declare internal variables as follow:
-/// uint8_t tinyusb_data[10] TUSB_CFG_ATTR_USBRAM;
-/// if your mcu's usb controller has no such limit, define TUSB_CFG_ATTR_USBRAM as empty macro.
-#ifndef TUSB_CFG_ATTR_USBRAM
- #error TUSB_CFG_ATTR_USBRAM is not defined, please help me know how to place data in accessible RAM for usb controller
-#endif
-
-#if TUSB_CFG_OS == TUSB_OS_NONE
-  #ifndef TUSB_CFG_OS_TICKS_PER_SECOND
-    #error TUSB_CFG_OS_TICKS_PER_SECOND is required to use with OS_NONE
-  #endif
-#else
-  #ifndef TUSB_CFG_OS_TASK_PRIO
-    #error TUSB_CFG_OS_TASK_PRIO need to be defined (hint: use the highest if possible)
-  #endif
-#endif
-
-#ifndef TUSB_CFG_CONFIGURATION_MAX
-  #define TUSB_CFG_CONFIGURATION_MAX 1
-  #warning TUSB_CFG_CONFIGURATION_MAX is not defined, default value is 1
-#endif
-
-//--------------------------------------------------------------------+
-// HOST OPTIONS
-//--------------------------------------------------------------------+
-#if MODE_HOST_SUPPORTED
-  #ifndef TUSB_CFG_HOST_DEVICE_MAX
-    #define TUSB_CFG_HOST_DEVICE_MAX 1
-    #warning TUSB_CFG_HOST_DEVICE_MAX is not defined, default value is 1
-  #endif
-
-  //------------- HUB CLASS -------------//
-  #if TUSB_CFG_HOST_HUB && (TUSB_CFG_HOST_DEVICE_MAX == 1)
-    #error there is no benefit enable hub with max device is 1. Please disable hub or increase TUSB_CFG_HOST_DEVICE_MAX
-  #endif
-
-  //------------- HID CLASS -------------//
-  #define HOST_CLASS_HID   ( TUSB_CFG_HOST_HID_KEYBOARD + TUSB_CFG_HOST_HID_MOUSE + TUSB_CFG_HOST_HID_GENERIC )
-  #if HOST_CLASS_HID
-    #define HOST_HCD_XFER_INTERRUPT
-  #endif
-
-  #ifndef TUSB_CFG_HOST_ENUM_BUFFER_SIZE
-    #define TUSB_CFG_HOST_ENUM_BUFFER_SIZE 256
-    #warning TUSB_CFG_HOST_ENUM_BUFFER_SIZE is not defined, default value is 256
-  #endif
-
-  //------------- CLASS -------------//
-#endif // end TUSB_CFG_HOST
-
-//--------------------------------------------------------------------+
-// DEVICE OPTIONS
-//--------------------------------------------------------------------+
-#if MODE_DEVICE_SUPPORTED
-
-#if defined(CAP_DEVICE_ROMDRIVER) && !TUSB_CFG_DEVICE_USE_ROM_DRIVER
-  #error only rom driver for these mcu are supported now
-#endif
-
-#define DEVICE_CLASS_HID ( TUSB_CFG_DEVICE_HID_KEYBOARD + TUSB_CFG_DEVICE_HID_MOUSE + TUSB_CFG_DEVICE_HID_GENERIC )
-
-
-#endif
-
-
-
-#define USB_FS_MAX_BULK_PACKET  64
-#define USB_HS_MAX_BULK_PACKET  USB_FS_MAX_BULK_PACKET /* Full speed device only */
-
-/* HID In/Out Endpoint Address */
-#define    HID_KEYBOARD_EP_IN       ENDPOINT_IN_LOGICAL_TO_PHYSICAL(1)
-#define    HID_MOUSE_EP_IN          ENDPOINT_IN_LOGICAL_TO_PHYSICAL(4)
-
-/* CDC Endpoint Address */
-#define  CDC_NOTIFICATION_EP                ENDPOINT_IN_LOGICAL_TO_PHYSICAL(2)
-#define  CDC_DATA_EP_OUT                    ENDPOINT_OUT_LOGICAL_TO_PHYSICAL(3)
-#define  CDC_DATA_EP_IN                     ENDPOINT_IN_LOGICAL_TO_PHYSICAL(3)
-
-#define  CDC_NOTIFICATION_EP_MAXPACKETSIZE  8
-#define  CDC_DATA_EP_MAXPACKET_SIZE         16
-
-#endif /* _TUSB_TUSB_OPTION_H_ */
-
-/** @} */
+/**************************************************************************/
+/*!
+    @file     tusb_option.h
+    @author   hathach (tinyusb.org)
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2013, hathach (tinyusb.org)
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. 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.
+    3. Neither the name of the copyright holders nor the
+    names of its 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 ''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 HOLDER 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.
+
+    This file is part of the tinyusb stack.
+*/
+/**************************************************************************/
+
+#ifndef _TUSB_TUSB_OPTION_H_
+#define _TUSB_TUSB_OPTION_H_
+
+/** \defgroup group_configuration Configuration tusb_config.h
+ *  @{ */
+
+#define TUSB_VERSION_YEAR   00
+#define TUSB_VERSION_MONTH  00
+#define TUSB_VERSION_WEEK   0
+#define TUSB_VERSION_NAME   "alpha"
+#define TUSB_VERSION        XSTRING_(TUSB_VERSION_YEAR) "." XSTRING_(TUSB_VERSION_MONTH)
+
+/** \defgroup MCU_ MCU Selection
+ * \brief TUSB_CFG_MCU must be defined to one of these
+ *  @{ */
+#define MCU_LPC13XX_12ADC  1 ///< NXP LPC13xx 12 bit ADC family with USB on-chip Rom Driver (not supported yet)
+#define MCU_LPC13XX_10ADC  2 ///< NXP LPC13xx 10 bit ADC family (not supported yet)
+#define MCU_LPC11UXX       3 ///< NXP LPC11Uxx family (not supported yet)
+#define MCU_LPC43XX        4 ///< NXP LPC43xx family
+#define MCU_LPC18XX        5 ///< NXP LPC18xx family (not supported yet)
+#define MCU_LPC175X_6X     6 ///< NXP LPC175x, LPC176x family (not supported yet)
+#define MCU_LPC177X_8X     7 ///< NXP LPC177x, LPC178x family (not supported yet)
+/** @} */
+
+#include "mcu_capacity.h"
+
+#ifdef TUSB_CFG_CONFIG_FILE
+  #include TUSB_CFG_CONFIG_FILE
+#else
+  #include "tusb_config.h"
+#endif
+
+//--------------------------------------------------------------------+
+// CONTROLLER
+//--------------------------------------------------------------------+
+/** \defgroup TUSB_MODE Host/Device Mode Selection
+ * \brief TUSB_CFG_CONTROLLER_N_MODE must be defined with these
+ *  @{ */
+#define TUSB_MODE_HOST    0x02 ///< Host Mode
+#define TUSB_MODE_DEVICE  0x01 ///< Device Mode
+#define TUSB_MODE_NONE    0x00 ///< Disabled
+/** @} */
+
+#define CONTROLLER_HOST_NUMBER (\
+    ((TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_HOST) ? 1 : 0) + \
+    ((TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_HOST) ? 1 : 0))
+
+#define CONTROLLER_DEVICE_NUMBER (\
+    ((TUSB_CFG_CONTROLLER_0_MODE & TUSB_MODE_DEVICE) ? 1 : 0) + \
+    ((TUSB_CFG_CONTROLLER_1_MODE & TUSB_MODE_DEVICE) ? 1 : 0))
+
+#define MODE_HOST_SUPPORTED   (CONTROLLER_HOST_NUMBER > 0)
+#define MODE_DEVICE_SUPPORTED (CONTROLLER_DEVICE_NUMBER > 0)
+
+#if !MODE_HOST_SUPPORTED && !MODE_DEVICE_SUPPORTED
+  #error please configure at least 1 TUSB_CFG_CONTROLLER_N_MODE to TUSB_MODE_HOST and/or TUSB_MODE_DEVICE
+#endif
+
+//--------------------------------------------------------------------+
+// COMMON OPTIONS
+//--------------------------------------------------------------------+
+/**
+  determines the debug level for the stack
+  - Level 3: ATTR_ALWAYS_INLINE is null, ASSERT has text, Error has its String, STATIC_VAR is NULL
+  - Level 2: ATTR_ALWAYS_INLINE is attribute, ASSERT has no text, Error has no strings
+  - Level 1: TBD
+  - Level 0: no debug information is generated
+*/
+#ifndef TUSB_CFG_DEBUG
+  #define TUSB_CFG_DEBUG 2
+  #warning TUSB_CFG_DEBUG is not defined, default value is 3
+#endif
+
+#ifndef TUSB_CFG_ATTR_USBRAM
+ #error TUSB_CFG_ATTR_USBRAM is not defined, please help me know how to place data in accessible RAM for usb controller
+#endif
+
+#if TUSB_CFG_OS == TUSB_OS_NONE
+  #ifndef TUSB_CFG_OS_TICKS_PER_SECOND
+    #error TUSB_CFG_OS_TICKS_PER_SECOND is required to use with OS_NONE
+  #endif
+#else
+  #ifndef TUSB_CFG_OS_TASK_PRIO
+    #error TUSB_CFG_OS_TASK_PRIO need to be defined (hint: use the highest if possible)
+  #endif
+#endif
+
+/**
+ * Maximum number of supported USB's configuration (currently only support only 1)
+ */
+#ifndef TUSB_CFG_CONFIGURATION_MAX
+  #define TUSB_CFG_CONFIGURATION_MAX 1
+  #warning TUSB_CFG_CONFIGURATION_MAX is not defined, default value is 1
+#endif
+
+//--------------------------------------------------------------------+
+// HOST OPTIONS
+//--------------------------------------------------------------------+
+#if MODE_HOST_SUPPORTED
+  #ifndef TUSB_CFG_HOST_DEVICE_MAX
+    #define TUSB_CFG_HOST_DEVICE_MAX 1
+    #warning TUSB_CFG_HOST_DEVICE_MAX is not defined, default value is 1
+  #endif
+
+  //------------- HUB CLASS -------------//
+  #if TUSB_CFG_HOST_HUB && (TUSB_CFG_HOST_DEVICE_MAX == 1)
+    #error there is no benefit enable hub with max device is 1. Please disable hub or increase TUSB_CFG_HOST_DEVICE_MAX
+  #endif
+
+  //------------- HID CLASS -------------//
+  #define HOST_CLASS_HID   ( TUSB_CFG_HOST_HID_KEYBOARD + TUSB_CFG_HOST_HID_MOUSE + TUSB_CFG_HOST_HID_GENERIC )
+  #if HOST_CLASS_HID
+    #define HOST_HCD_XFER_INTERRUPT
+  #endif
+
+  #ifndef TUSB_CFG_HOST_ENUM_BUFFER_SIZE
+    #define TUSB_CFG_HOST_ENUM_BUFFER_SIZE 256
+    #warning TUSB_CFG_HOST_ENUM_BUFFER_SIZE is not defined, default value is 256
+  #endif
+
+  //------------- CLASS -------------//
+#endif // MODE_HOST_SUPPORTED
+
+//--------------------------------------------------------------------+
+// DEVICE OPTIONS
+//--------------------------------------------------------------------+
+#if MODE_DEVICE_SUPPORTED
+
+#if defined(CAP_DEVICE_ROMDRIVER) && !TUSB_CFG_DEVICE_USE_ROM_DRIVER
+  #error only rom driver for these mcu are supported now
+#endif
+
+#define DEVICE_CLASS_HID ( TUSB_CFG_DEVICE_HID_KEYBOARD + TUSB_CFG_DEVICE_HID_MOUSE + TUSB_CFG_DEVICE_HID_GENERIC )
+
+
+#endif // MODE_DEVICE_SUPPORTED
+
+
+
+#define USB_FS_MAX_BULK_PACKET  64
+#define USB_HS_MAX_BULK_PACKET  USB_FS_MAX_BULK_PACKET /* Full speed device only */
+
+/* HID In/Out Endpoint Address */
+#define    HID_KEYBOARD_EP_IN       ENDPOINT_IN_LOGICAL_TO_PHYSICAL(1)
+#define    HID_MOUSE_EP_IN          ENDPOINT_IN_LOGICAL_TO_PHYSICAL(4)
+
+/* CDC Endpoint Address */
+#define  CDC_NOTIFICATION_EP                ENDPOINT_IN_LOGICAL_TO_PHYSICAL(2)
+#define  CDC_DATA_EP_OUT                    ENDPOINT_OUT_LOGICAL_TO_PHYSICAL(3)
+#define  CDC_DATA_EP_IN                     ENDPOINT_IN_LOGICAL_TO_PHYSICAL(3)
+
+#define  CDC_NOTIFICATION_EP_MAXPACKETSIZE  8
+#define  CDC_DATA_EP_MAXPACKET_SIZE         16
+
+#endif /* _TUSB_TUSB_OPTION_H_ */
+
+/** @} */